Как обеспечить соблюдение кода контракта на Pony Entity - PullRequest
0 голосов
/ 14 апреля 2020

Я стремлюсь разделить проблемы, используя многоуровневую архитектуру в моем дизайне. Чтобы добиться этого, я определяю основные свойства объекта, используя Абстрактные базовые классы (AB C), например ::

from abc import ABC, abstractmethod

class AbstractPerson(ABC):

    @property
    @abstractmethod
    def name(self):
        pass

, которые затем я использую на прикладном уровне:

class Person(AbstractPerson):

    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

Уровень персистентности должен быть отделен от приложения, поэтому я определяю Pony-классы:

from pony import orm

def define_pony_person(database):

    class PonyPerson(database.Entity, AbstractPerson):

        name = orm.Required(
            str,
            unique=True
        )

    return PonyPerson

Наследование от AbstractPerson предназначено для принудительного выполнения контракта Person через слои. Чем в коде клиента (например, бизнес-логи c) я мог бы создать экземпляр и использовать свой основной объект:

person = Person(
    name='Foo'
)

, а в какой-то другой части кода (например, в репозитории) я бы сохранил его:

db = orm.Database()
PonyPerson = define_pony_person(db)
db.bind('sqlite', ':memory:')
db.generate_mapping(create_tables=True)
pony_person = PonyPerson(
    name=person.name
)

Но когда я пытаюсь сделать это таким образом, оказывается, что Пони-сущность не смешивается с AB C плавно:

Traceback (most recent call last):
  File "./test.py", line 43, in <module>
    define_pony_person(db)
  File "./test.py", line 28, in define_pony_person
    class PonyPerson(database.Entity, AbstractPerson):
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Есть ли способ принудительного исполнения моего контракта с основным объектом на объекте Pony в соответствии с набросками, описанными выше?

...