Open maxshilov opened 8 years ago
Indeed, you need to tell factory_boy
when to stop digging deeper ;)
The easiest way would be to specify it on call: MyModelFactory(next__next__next__next=None, previous__previous__previous=None)
.
thank you for a quick reply!
is it possible to specify maximum recursion depth inside the factory declaration?
It is not possible natively.
You could write a custom ComplexParameter
for this:
from factory import declarations
class RecursiveStopper(declarations.ComplexParameter):
def __init__(self, default_depth, recursive_field, stopper_value=None):
self.default_depth = default_depth
self.recursive_field = recursive_field
self.stopper_value = stopper_value
def compute(self, field_name, declarations):
depth = declarations.get(field_name) or self.default_depth
# use depth + 1: if depth is 0, we must stop now => set FIELD_NAME=None
override = '__'.join([self.recursive_field] * (depth + 1))
return {override: self.stopper_value}
With this, your factory would look like this:
class MyFactory(factory.django.DjangoModelFactory):
class Params:
next_depth = RecursiveStopper(10, 'next')
previous_depth = RecursiveStopper(5, 'previous')
Could you try this and let us know:
If it's useful, we'll add it to the core :)
@maxshilov does the proposed API look good to you?
The parameter method outlined above doesn't seem to work with newer version of factoryboy (I am on 2.11.1
). In particular, if you rename the compute
method to as_declarations
to fit in with the new way of declaring parameters the declaration
dictionary will not contain field_name
if you declare it as an argument.
In the example above, running MyFactory(next_depth=20)
will still give you a next depth of 10.
I had a go at getting a toy version of this working another way:
import factory
class RecursiveClass:
def __init__(self, child):
self.child = child
class RecursiveFactory(factory.Factory):
class Meta:
model = RecursiveClass
exclude = ('child_depth_temp', )
class Params:
child_depth = 10
child_depth_temp=factory.LazyAttribute(lambda o: o.child_depth-1)
child = factory.Maybe(
factory.LazyAttribute(lambda o: o.child_depth > 0),
yes_declaration=factory.SubFactory(
'tests.test_factories.RecursiveStopperFactory',
child_depth=factory.SelfAttribute('..child_depth_temp'),
),
no_declaration=None,
)
This seems to work - RecursiveFactory(20)
will give you a 20-deep recursion rather than 10-deep.
@rbarrois: Is there still a way to do this with a parameter or similar? It would be nice to be able to separate the logic for handling recursion depth from the actual factory declaration.
Guys, Please advise how can I make factory with FactoryBoy 2.6.0 and python 2.7 from django model below . Each object may have 'next' object, and if some object is the 'next' for another object, then it knows this object by 'previous' attribute.
I tried following Factory:
But, got the "RuntimeError: maximum recursion depth exceeded in cmp" error.