Search code examples
pythoninheritanceinner-classes

Python behavior of classes that have nested classes


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.


Solution

  • 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.