简体   繁体   中英

Inherit Params from parent factory with factory_boy

I'd like for a child factory to extend the Params of its parent. I think extending params is preferable to duplicating them. I've tried by making the Params in the subclass literally inherit from the parent Params , like so:

import factory


class BaseFactory(factory.Factory):
    class Params:
        configuration_one = True

class MyFactory(BaseFactory):
    class Params(BaseFactory.Params):
        configuration_two = False

This is failing with the exception:

AttributeError                            Traceback (most recent call last)
<ipython-input-5-cc609d2c781d> in <module>()
      6         configuration_one = True
      7
----> 8 class MyFactory(BaseFactory):
      9     class Params(BaseFactory.Params):
     10         configuration_two = False

<ipython-input-5-cc609d2c781d> in MyFactory()
      7
      8 class MyFactory(BaseFactory):
----> 9     class Params(BaseFactory.Params):
     10         configuration_two = False
     11

AttributeError: type object 'BaseFactory' has no attribute 'Params'

What is causing this error, and is there an idiomatic way to accomplish my goal?

Versions

Python - 2.7.12

factory_boy - 2.9.2

I'm working toward the same goal. I want to DRY up my factories since I'm using polymorphic models.

the bad news is the factoryboy DSL removes Meta and Params classes from the attributes. I'm not sure why they do this, possibly it simplifies how they inherit pre and post vars from parent factories? I think they are trying to emulate FactoryGirl from ruby, but don't have the ability to monkey-patch because python...

here is the relevant doc.

https://factoryboy.readthedocs.io/en/latest/internals.html?highlight=params

good luck.

PS. I got a little farther by putting the parent Param class outside the parent Factory, but it still doesn't work.

import factory 

class BaseParam:
  foo=True,
  bar=False 

class MyFactory(factory.Factory):
  class Meta:
    abstract=False
    model=Yolo

  class Params(BaseParam):
    baz=factory.Trait(
      foo=False
    )

MyFactory(baz=True)

gives me this

TypeError: 'foo' is an invalid keyword argument for this function

so Param is clearly not inheriting anything, and is not acting as a normal class.

I figured out a way using decorators

In [47]: import factory 
    ...: 
    ...:   
    ...: def with_base_params(target_factory):
    ...:   class NewClass(target_factory):
    ...:     class Params:
    ...:       baz=factory.Trait(
    ...:         name="chandeeland",
    ...:         address="123 fake st"
    ...:       )
    ...:   return NewClass
    ...: 
    ...: @with_base_params
    ...: class MyFactory(factory.Factory):
    ...:   class Meta:
    ...:     abstract=False
    ...:     model=Contact
    ...: 
    ...:   name = "someone else"
    ...: 
    ...: a = MyFactory()
    ...: a.name == "someone else"
    ...: a.address == None
    ...: 
    ...: b = MyFactory(name="another name")
    ...: b.name == "another name"
    ...: b.address == None
    ...: 
    ...: c = MyFactory(baz=True)
    ...: c.name == "chandeeland"
    ...: c.address == "123 fake st"
    ...: 
Out[47]: True

its not perfect, you cannot extend the params, but it serves

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM