Наследование метакласса Python

#python-3.x #sqlalchemy #factory-boy

Вопрос:

Что я пытаюсь сделать?

Я пытаюсь создать базовый класс factory boy с набором метаданных класса следующим образом:

 class DBFactoryBase(factory.alchemy.SQLAlchemyModelFactory):

    class Meta:
        sqlalchemy_session = common_session
        sqlalchemy_session_persistence = 'flush'
 

Затем я хочу унаследовать это и использовать на своих заводах вместо factory.alchemy.SQLAlchemyModelFactory:

 class SomeFactory(DBFactoryBase):

    class Meta:
        model = AnSQLAlchemyModel

    fake_line_1 = "A'tuin"
    fake_line_2 = 'The currently untitled'
    fake_line_3 = '42'
 

По сути, я хочу иметь возможность расширять Мета-класс, а не переопределять его, и, обновляя сеанс базовой модели, я хочу, чтобы другие модели унаследовали этот сеанс.

Почему я пытаюсь это сделать?

Я делаю это для удобства, поэтому мне не нужно переопределять их со всеми моими заводскими классами. Я также делаю это для того, чтобы я мог переопределить сеанс во время выполнения pytest, используя приведенное ниже приспособление. Я не хочу, чтобы мои фабрики определялись внутри светильников, потому что я также хочу использовать те же фабрики для создания демонстрационных данных. Таким образом, мне нужно передать им сеанс БД без тестирования, и создание фабрик в качестве приспособлений помешает мне использовать их в обычных сценариях.

 @pytest.fixture(scope="function")
def test_db(engine_factory, enable_override):
    engine = engine_factory
    testing_session_local = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)
    api.dependency_overrides[get_db] = enable_override
    session: Session = testing_session_local()

    DBFactoryBase.sqlalchemy_session = session # <-- Please see here

    yield session
    # Rollback the session => no changes to the database
    session.rollback()
    # Remove it, so that the next test gets a new Session()
    Base.metadata.drop_all(bind=engine)
 

Если бы это была модель на основе Django, я мог бы получить доступ к мета-классу родительского класса в качестве атрибута с помощью DBFactoryBase.Мета и передайте это в мета-класс, как показано ниже. Я не совсем уверен, как это работает, и я не знаю, как это сделать, когда исходный класс не является моделью Django.

 class SomeFactory(DBFactoryBase):

    class Meta(DBFactoryBase.Meta):
        model = AnSQLAlchemyModel

    fake_line_1 = "A'tuin"
    fake_line_2 = 'The currently untitled'
    fake_line_3 = '42'
 

Комментарии:

1. Здесь много информации, но у меня нет четкого представления о том, каким должен быть вопрос.

2. Спасибо Snakecharmerb, я просто хочу обновить сеанс в одном месте, передав его в базовую модель.

3. И ты не можешь, потому что …?