Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.9', '3.10', '3.11', '3.12']
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI matrix removes Python 3.8 but setup.py classifiers also remove it while tox.ini still includes py38. For consistency, if Python 3.8 support is being dropped completely, it should be removed from tox.ini as well, or if it's being kept, it should remain in setup.py classifiers and the CI matrix.

Suggested change
python-version: ['3.9', '3.10', '3.11', '3.12']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

Copilot uses AI. Check for mistakes.
celery-version: ['5.2.*', '5.3.*', '5.4.*', '5.5.*']
tornado-version: ['6.0']
tornado-version: ['6.5']
exclude: # https://docs.celeryq.dev/en/v5.2.7/whatsnew-5.2.html#step-5-upgrade-to-celery-5-2
- python-version: '3.12'
celery-version: '5.2.*'
Expand Down
2 changes: 0 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# flower documentation build configuration file, created by
# sphinx-quickstart on Fri Apr 11 17:26:01 2014.
#
Expand Down
2 changes: 1 addition & 1 deletion examples/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def sleep(seconds):

@app.task
def echo(msg, timestamp=False):
return "%s: %s" % (datetime.now(), msg) if timestamp else msg
return f"{datetime.now()}: {msg}" if timestamp else msg


@app.task
Expand Down
2 changes: 1 addition & 1 deletion flower/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def apply_options(prog_name, argv):
try:
parse_config_file(os.path.abspath(options.conf), final=False)
parse_command_line([prog_name] + argv)
except IOError:
except OSError:
if os.path.basename(options.conf) != DEFAULT_CONFIG_FILE:
raise

Expand Down
2 changes: 1 addition & 1 deletion flower/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def bugreport(app=None):
app = app or celery.Celery()

# pylint: disable=consider-using-f-string
return 'flower -> flower:%s tornado:%s humanize:%s%s' % (
return 'flower -> flower:{} tornado:{} humanize:{}{}'.format(
__version__,
tornado.version,
getattr(humanize, '__version__', None) or getattr(humanize, 'VERSION'),
Expand Down
7 changes: 3 additions & 4 deletions flower/utils/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import json
import logging
import numbers
import socket
import sys
from urllib.parse import quote, unquote, urljoin, urlparse

Expand Down Expand Up @@ -67,7 +66,7 @@ async def queues(self, names):
url, auth_username=username, auth_password=password,
connect_timeout=1.0, request_timeout=2.0,
validate_cert=False)
except (socket.error, httpclient.HTTPError) as e:
except (OSError, httpclient.HTTPError) as e:
logger.error("RabbitMQ management API call failed: %s", e)
return []
finally:
Expand Down Expand Up @@ -106,7 +105,7 @@ def _q_for_pri(self, queue, pri):
if pri not in self.priority_steps:
raise ValueError('Priority not in priority steps')
# pylint: disable=consider-using-f-string
return '{0}{1}{2}'.format(*((queue, self.sep, pri) if pri else (queue, '', '')))
return '{}{}{}'.format(*((queue, self.sep, pri) if pri else (queue, '', '')))

async def queues(self, names):
queue_stats = []
Expand All @@ -115,7 +114,7 @@ async def queues(self, names):
name, pri) for pri in self.priority_steps]
queue_stats.append({
'name': name,
'messages': sum((self.redis.llen(x) for x in priority_names))
'messages': sum(self.redis.llen(x) for x in priority_names)
})
return queue_stats

Expand Down
2 changes: 1 addition & 1 deletion flower/utils/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def parse_search_terms(raw_search_value):
if 'kwargs'not in parsed_search:
parsed_search['kwargs'] = {}
try:
key, value = [p.strip() for p in query_part[len('kwargs:'):].split('=')]
key, value = (p.strip() for p in query_part[len('kwargs:'):].split('='))
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change from a list comprehension to a generator expression will break the unpacking operation. Python cannot unpack a generator directly with tuple unpacking syntax. The original [p.strip() for p in ...] returns a list that can be unpacked, but (p.strip() for p in ...) returns a generator object that cannot be unpacked this way.

To fix this while still using a generator-like approach, you should use: key, value = query_part[len('kwargs:'):].split('=') and then apply .strip() to each variable individually, or keep the list comprehension.

Suggested change
key, value = (p.strip() for p in query_part[len('kwargs:'):].split('='))
key, value = [p.strip() for p in query_part[len('kwargs:'):].split('=')]

Copilot uses AI. Check for mistakes.
except ValueError:
continue
parsed_search['kwargs'][key] = preprocess_search_value(value)
Expand Down
4 changes: 2 additions & 2 deletions flower/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ def format_task(self, task):
return task

def get_active_queue_names(self):
queues = set([])
queues = set()
for _, info in self.application.workers.items():
for queue in info.get('active_queues', []):
queues.add(queue['name'])

if not queues:
queues = set([self.capp.conf.task_default_queue]) |\
queues = {self.capp.conf.task_default_queue} |\
{q.name for q in self.capp.conf.task_queues or [] if q.name}
return sorted(queues)
2 changes: 1 addition & 1 deletion flower/views/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async def get(self):
@classmethod
def _as_dict(cls, worker):
if hasattr(worker, '_fields'):
return dict((k, getattr(worker, k)) for k in worker._fields)
return {k: getattr(worker, k) for k in worker._fields}
return cls._info(worker)

@classmethod
Expand Down
2 changes: 1 addition & 1 deletion requirements/default.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
celery>=5.0.5
tornado>=5.0.0,<7.0.0
tornado>=6.5.0,<7.0.0
prometheus_client>=0.8.0
humanize
pytz
2 changes: 0 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ def get_requirements(filename):
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Comment on lines 33 to 36
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The python_requires field in setup.py still specifies ">=3.7", but the PR removes Python 3.7 and 3.8 from the classifiers and the tox.ini still tests Python 3.8. This creates an inconsistency - either python_requires should be updated to ">=3.8" (if Python 3.8 is the new minimum as tested in tox.ini) or ">=3.9" (if dropping 3.8 support as indicated by the removed classifiers).

Copilot uses AI. Check for mistakes.
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def test_empty_conf(self):
def test_conf_abs(self):
with tempfile.NamedTemporaryFile() as cf:
with self.mock_option('conf', cf.name), self.mock_option('debug', False):
cf.write('debug=True\n'.encode('utf-8'))
cf.write(b'debug=True\n')
cf.flush()
apply_options('flower', argv=['--conf=%s' % cf.name])
self.assertEqual(cf.name, options.conf)
Expand All @@ -175,7 +175,7 @@ def test_conf_abs(self):
def test_conf_relative(self):
with tempfile.NamedTemporaryFile(dir='.') as cf:
with self.mock_option('conf', cf.name), self.mock_option('debug', False):
cf.write('debug=True\n'.encode('utf-8'))
cf.write(b'debug=True\n')
cf.flush()
apply_options('flower', argv=['--conf=%s' % os.path.basename(cf.name)])
self.assertTrue(options.debug)
Expand All @@ -184,7 +184,7 @@ def test_conf_relative(self):
def test_all_options_documented(self):
def grep(patter, filename):
return int(subprocess.check_output(
'grep "%s" %s|wc -l' % (patter, filename), shell=True))
f'grep "{patter}" {filename}|wc -l', shell=True))

defined = grep('^define(', 'flower/options.py')
documented = grep('^~~', 'docs/config.rst')
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/views/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ def test_authenticate_wildcard_email(self):
self.assertTrue(authenticate("one.*@example.com", "[email protected]"))
self.assertFalse(authenticate(".*@example.com", "[email protected]"))
self.assertFalse(authenticate(".*@corp.example.com", "[email protected]"))
self.assertFalse(authenticate(".*@corp\.example\.com", "[email protected]"))
self.assertFalse(authenticate(r".*@corp\.example\.com", "[email protected]"))
13 changes: 4 additions & 9 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[tox]
envlist =
# Celery 5.2: only py38–py311 (py312 excluded)
{py38,py39,py310,py311}-celery52-{tornado60,tornado61,tornado62,tornado63,tornado64,tornado65},
{py38,py39,py310,py311}-celery52-tornado65,
# Celery 5.3: py38–py312
{py38,py39,py310,py311,py312}-celery53-{tornado60,tornado61,tornado62,tornado63,tornado64,tornado65},
{py38,py39,py310,py311,py312}-celery53-tornado65,
# Celery 5.4: py38–py312
{py38,py39,py310,py311,py312}-celery54-{tornado60,tornado61,tornado62,tornado63,tornado64,tornado65},
{py38,py39,py310,py311,py312}-celery54-tornado65,
# Celery 5.5: py38–py312
{py38,py39,py310,py311,py312}-celery55-{tornado60,tornado61,tornado62,tornado63,tornado64,tornado65},
{py38,py39,py310,py311,py312}-celery55-tornado65,
Comment on lines +4 to +10
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tox.ini still includes Python 3.8 in the test matrix (py38), but setup.py removed the Python 3.8 classifier. This creates an inconsistency - if Python 3.8 support is being dropped, it should also be removed from the tox test matrix. If Python 3.8 is still supported, the classifier should remain in setup.py.

Copilot uses AI. Check for mistakes.
lint
skip_missing_interpreters = true

Expand All @@ -19,11 +19,6 @@ deps =
celery53: celery==5.3.*
celery54: celery==5.4.*
celery55: celery==5.5.*
tornado60: tornado==6.0.*
tornado61: tornado==6.1.*
tornado62: tornado==6.2.*
tornado63: tornado==6.3.*
tornado64: tornado==6.4.*
tornado65: tornado==6.5.*
commands =
python -m flower --version
Expand Down
Loading