Skip to content

Conversation

@maycuatroi1
Copy link
Contributor

@maycuatroi1 maycuatroi1 commented Dec 31, 2025

Summary

Fix AttributeError: 'str' object has no attribute '__module__' when running Flower with Celery 5.6.1.
image

Changes

  • Modified celery/fixups/django.py to check if pool_cls is a string before accessing .__module__
  • Added test case test_close_database_pool_cls_as_string to cover this scenario

Root Cause

In _close_database() method at line 220, the code assumes pool_cls is a class with a __module__ attribute:

is_prefork = "prefork" in self.worker.pool_cls.__module__

However, when Flower initializes, pool_cls can still be a string (e.g., 'prefork') instead of the resolved class object.

Fix

pool_cls = self.worker.pool_cls
if isinstance(pool_cls, str):
    is_prefork = "prefork" in pool_cls
else:
    is_prefork = "prefork" in pool_cls.__module__

Error Traceback (before fix)

File "/usr/local/lib/python3.12/site-packages/celery/fixups/django.py", line 220, in _close_database
    is_prefork = "prefork" in self.worker.pool_cls.__module__
                              │    │      └ 'prefork'
                              │    └ <Worker: celery@75efc8aa2596 (INIT)>
                              └ <celery.fixups.django.DjangoWorkerFixup object>

AttributeError: 'str' object has no attribute '__module__'

Test Plan

  • Added unit test test_close_database_pool_cls_as_string
  • Existing tests pass

Fixes #10042

When running Flower with Celery 5.6.1, an AttributeError is raised in
celery/fixups/django.py because pool_cls can be a string (e.g., 'prefork')
instead of a class object, and strings don't have a __module__ attribute.

This fix checks if pool_cls is a string before accessing __module__,
handling both cases correctly.

Fixes celery#10042
@codecov
Copy link

codecov bot commented Dec 31, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.41%. Comparing base (21dbc73) to head (a321252).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #10043   +/-   ##
=======================================
  Coverage   88.41%   88.41%           
=======================================
  Files         153      153           
  Lines       19363    19366    +3     
  Branches     2226     2227    +1     
=======================================
+ Hits        17120    17123    +3     
  Misses       1943     1943           
  Partials      300      300           
Flag Coverage Δ
unittests 88.38% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an AttributeError that occurs when Flower (or other tools) initialize Celery workers where pool_cls is still a string (e.g., 'prefork') instead of a resolved class object. The error occurred in the Django fixup when attempting to access the __module__ attribute on the string.

Key Changes

  • Modified _close_database() in celery/fixups/django.py to check if pool_cls is a string before accessing .__module__
  • Added comprehensive test coverage for string and class types of pool_cls

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
celery/fixups/django.py Added type checking for pool_cls to handle both string and class types when determining if the pool is prefork
t/unit/fixups/test_django.py Added test case covering string pool_cls scenarios including 'prefork', 'threads', and module paths

Comment on lines +220 to +224
pool_cls = self.worker.pool_cls
if isinstance(pool_cls, str):
is_prefork = "prefork" in pool_cls
else:
is_prefork = "prefork" in pool_cls.__module__
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

The fix correctly handles the case where pool_cls is a string. However, similar code exists in other files that may have the same issue. Were those locations reviewed?

  • celery/contrib/testing/worker.py line 45: if self.pool_cls.__module__.split('.')[-1] == 'prefork':
  • celery/worker/components.py line 197: if w.pool_cls.__module__.endswith(('gevent', 'eventlet')):

Should we apply the same fix to those locations in this PR or in a follow-up?

Copilot generated this review using guidance from repository custom instructions.
@maycuatroi1
Copy link
Contributor Author

Closing in favor of #10045 which fixes the root cause (recursive WorkController instantiation). My PR only addressed the symptom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AttributeError: 'str' object has no attribute '__module__' in django.py fixups when using Flower

1 participant