Как я могу обернуть не-черты модели для использования с чертами Python? - PullRequest
2 голосов
/ 24 мая 2011

Я хотел бы обернуть класс модели без черт для использования с чертами Python. Моя цель - написать интерфейс на основе Traits для манипулирования «внешним» классом модели. Класс внешней модели сгенерирован SWIG, и поэтому я не могу добавить enthought.traits.api.HasTraits в качестве предка (думаю, хотя я могу ошибаться).

Моя лучшая попытка на данный момент -

from enthought.traits.api import HasStrictTraits, Property, Instance

class ExternalModel():
    foo = 'foo'

class TraitsModel(HasStrictTraits):
    _e = Instance(ExternalModel)

    def __init__(self):
        self._e = ExternalModel()
        self.add_trait('foo', Property(lambda     :getattr(self._e,'foo'     ),
                                       lambda attr:setattr(self._e,'foo',attr)))

, что заставляет основанный на Traits класс TraitsModel иметь изменяемое свойство, которое делегирует содержавшемуся экземпляру Non-Traits ExternalModel. Однако TraitsModel.trait_names () не сообщает 'foo' как распознанную черту.

Есть какие-нибудь предложения, как заставить TraitsModel сообщать о черте 'foo', которая связана с ExternalModel? enthought.traits.api.DelegatesTo, кажется, требует, чтобы целью был класс Traits (хотя я, возможно, не нашел правильный вызов, и это возможно).

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

Обновление Я выяснил, как получить HasTraits в качестве суперкласса ExternalModel, используя подход на http://agentzlerich.blogspot.com/2011_05_01_archive.html, и, похоже, это была пустая трата времени. По-видимому, вуду SWIG и Худу Черты не джайв. Оборачивание ExternalModel в TraitsModel, поскольку этот вопрос задает, кажется наилучшим маршрутом.

1 Ответ

2 голосов
/ 18 июня 2011
from enthought.traits.api import HasStrictTraits, Instance, Property

class ExternalModel(object):
    foo = 'foo'

class TraitsModel(HasStrictTraits):
    _e = Instance(ExternalModel, ExternalModel())

    def __init__(self):
        '''
        >>> wrapper = TraitsModel()
        >>> wrapper.foo
        'foo'
        >>> wrapper._e.foo = 'bar'
        >>> wrapper.foo
        'bar'
        >>> wrapper.trait_names()
        ['trait_added', '_e', 'foo', 'trait_modified']
        '''
        HasStrictTraits.__init__(self)
        for trait in (name for name in dir(self._e) if not name.startswith('__')):
            self.__class__.add_class_trait(
                trait,
                Property(
                    lambda:getattr(self._e, trait),
                    lambda attr:setattr(self._e, trait, attr)
                )
            )


if __name__ == '__main__':
    import doctest
    doctest.testmod()

Довольно надежное решение заключается в использовании add_class_trait класса HasTraits в сочетании с dir(self._e) для получения имен атрибутов class ExternalModel и выражение выражения / списка генератора для фильтрации имен методов магического класса (filter с соответствующей функцией будет лучше работать для переноса более сложного класса).

Также:

  • ExternalModel должно наследоваться от object

  • __init__ должно вызывать HasStrictTraits.__init__ (или super(HasStrictTraits, self).__init__())

  • _e можно также создать в объявлении признака экземпляра в качестве второго аргумента, используя ExternalModel() или даже (), или в качестве метода TraitsModel, например:

    def __e_default(self): # note preceding underscore
        return ExternalModel()
    

Наконец, у меня есть немного старая копия API Enthought, включая Черты , которые могут быть очень удобными.

...