pytest-dev / pytest-dev/pytest-factoryboy
@register decorator is incompatible with circular imports
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 400
- Forks
- 44
- Avg merge
- 6h 34m
- Merged PRs (30d)
- 1
Description
Factoryboy documents the creation of circular dependencies like this:
class UserFactory(factory.Factory):
class Meta:
model = User
username = 'john'
main_group = factory.SubFactory('users.factories.GroupFactory')
class GroupFactory(factory.Factory):
class Meta:
model = Group
name = "MyGroup"
owner = factory.SubFactory(UserFactory)
That example will not work with the @register decorator:
@register
class UserFactory(factory.Factory):
class Meta:
model = User
username = 'john'
main_group = factory.SubFactory('users.factories.GroupFactory')
@register
class GroupFactory(factory.Factory):
class Meta:
model = Group
name = "MyGroup"
owner = factory.SubFactory(UserFactory)
Throws:
ImportError while loading conftest '/app/_python/conftest.py'.
conftest.py:58: in <module>
class UserFactory(factory.Factory):
/usr/local/lib/python3.5/site-packages/pytest_factoryboy/fixture.py:91: in register
subfactory_class = value.get_factory()
/usr/local/lib/python3.5/site-packages/factory/declarations.py:647: in get_factory
return self.factory_wrapper.get()
/usr/local/lib/python3.5/site-packages/factory/declarations.py:363: in get
self.name,
/usr/local/lib/python3.5/site-packages/factory/utils.py:20: in import_object
return getattr(module, str(attribute_name))
E AttributeError: module 'conftest' has no attribute 'GroupFactory'
The issue seems to be that @register resolves the imports when applied, before the later classes are defined. So a workaround is to use the non-decorator version at the end of the file. This works:
# same as first code block, then ...
register(UserFactory)
register(GroupFactory)
Ideally the decorator form could Just Work, by delaying resolution of the imports until needed. Alternatively maybe the problem could be documented, and register() could detect what's happening and throw a more useful error?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at pytest_factoryboy/fixture.py, where register is applied in the traceback, and reproduce the UserFactory/GroupFactory example with the string SubFactory reference. Trace when the referenced factory is resolved and add coverage for the decorator form; done means circular registration works or the failure is reported and documented clearly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100