Home > front end >  Python behavior of classes that have nested classes
Python behavior of classes that have nested classes

Time:11-03

I have a number of factory objects that look like the following:

class OperatorFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = Operator
        sqlalchemy_session = Session()
        sqlalchemy_session_persistence = 'commit'

    operator = 'equals'

They all share that same Meta inner class and have distinct models, but they also share those sqlalchemy_session and sqlalchemy_session_persistence lines.

My question is, is it possible to write this object in a more DRY (don't repeat yourself) fashion where I don't have to constantly include the lines sqlalchemy_session = Session() and sqlalchemy_session_persistence = 'commit'?

So far I have at least a dozen factories and it's getting repetitive.

CodePudding user response:

Instead of having Meta as an inner-class you can make it a base class and just have factories inherit off it. As you've said they have distinct models you can simply provide a parameter for that to __init__. Take the following for example:

class Meta:
    def __init__(self, Operator):
        model = Operator
        sqlalchemy_session = Session()
        sqlalchemy_session_persistence = 'commit'

class Factory1(Meta, factory.alchemy.SQLAlchemyModelFactory):
    def __init__(self):
        op = 'equals'
        super.__init__(op)

class Factory2(Meta, factory.alchemy.SQLAlchemyModelFactory):
    def __init__(self):
        op = 'lessthan'
        super.__init__(op)

CodePudding user response:

I'm not 100% certain what sessions you want to be shared, the only documentation I could find talks about sharing sessions between all factories but you are generating a separate session for each factory class but not for every instance. (it is a class variable so it is shared between all instances)

Assuming this was an oversight and you actually want a single session for all Meta fields, you would create a base class for the Meta class:

class BaseMeta:
    # now this sessions is shared between ALL factories
    sqlalchemy_session = Session()
    sqlalchemy_session_persistence = 'commit'

class OperatorFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta(BaseMeta):
        model = Operator

    operator = 'equals'

alternatively if you want each class to have their own session then you may want a factory function for your meta class of your factory class.

def generate_meta_options(model_):
    class Meta:
        model = model_
        sqlalchemy_session = Session()
        sqlalchemy_session_persistence = 'commit'
    return Meta

class OperatorFactory(factory.alchemy.SQLAlchemyModelFactory):
    Meta = generate_meta_options(Operator)
    operator = 'equals'

If the intention is instead to have a separate session for every instance I'm not sure what should be done, I can't figure the relevant documentation on how the factory objects are instantiated.

  • Related