Проверка двух полей одинаковых полей объекта с помощью атрибута - PullRequest
0 голосов
/ 22 февраля 2019

Я хочу проверить два поля объекта после инициализации.Я использую attrs для определения мета-класса PropertyMeta, а затем использую PropertyMeta в другом классе PropertyDescriptor.

class PropertyMeta(type):
        EXPECTED_VARS = ('PROPERTIES', 'PROPERTY_DEFAULTS',
                         'PROPERTY_VALIDATORS', 'PROPERTY_CONVERTERS')
        @classmethod
        def _get_attrib(mcs, property_name, attrs):
            kwargs = {}
            if property_name in attrs['PROPERTY_DEFAULTS']:
                kwargs.update(default=attrs['PROPERTY_DEFAULTS'][property_name])
            return attr.attrib(**kwargs)

    def __new__(mcs, name, bases, attrs):
        if 'PROPERTIES' not in attrs:
            attrs['PROPERTIES'] = []
        else:
            # For the defaults, converters, and validators ensure that extra attributes are not passed.
            # If they are defined, set the default value as an empty dict.
            for expected_attr in mcs.EXPECTED_VARS:
                if expected_attr == 'PROPERTIES':
                    continue

                if expected_attr in attrs:
                    for arg in attrs[expected_attr]:
                        if arg not in attrs['PROPERTIES']:
                            raise ValueError(
                                "Found a '%s' for an attribute '%s' in '%s' that doesn't belong to 'PROPERTIES';"
                                " ('PROPERTIES': %r, '%s': %r)" %
                                (arg, expected_attr, name,
                                 attrs['PROPERTIES'], expected_attr, attrs[expected_attr])
                            )
                else:
                    attrs[expected_attr] = {}

        # Create class from attr with all required attributes. This will set properties in same format as specified
        # by attr.
        new_cls = attr.make_class(name,
                                  {property_name: mcs._get_attrib(property_name, attrs) for property_name in
                                   attrs['PROPERTIES']})
        # Merge the attr class to present class.
        return super(PropertyMeta, mcs).__new__(mcs, name, (new_cls,) + bases, attrs)


@six.add_metaclass(PropertyMeta)
class PropertyDescriptor(object):
    def __init__(self):
        print("Not getting  called.")

    def __setattr__(self, property_name, property_value):
        # Convert properties to appropriate types if specified.
        if property_name in self.PROPERTY_CONVERTERS:
            property_value = self.PROPERTY_CONVERTERS[property_name](
                property_value)

        # Validate property values.
        if property_name in self.PROPERTY_VALIDATORS:
            try:
                validator = self.PROPERTY_VALIDATORS[property_name]
                validator(self, property_name, property_value)
            except Exception as err:
                raise err
        super(PropertyDescriptor, self).__setattr__(property_name, property_value)

Я пытаюсь создать экземпляр объекта, используя PropertyDescriptor в качестве базового класса.Всякий раз, когда создается экземпляр моего объекта, init PropertyDescriptor не вызывается.

Пример наследования от PropertyDescriptor.

class Example(PropertyDescriptor):
        def __init__(self, **kwargs):
            super(A, self).__init__(**kwargs)
            print(self.__dict__)

a = Example(start_time=1, end_time=2)

init класса Example вызывается.Поэтому я могу проверить поля, которые start_time всегда меньше, чем end_time

Два вопроса:

  1. Я хочу убедиться, что start_time всегда меньше, чем end_time.Есть ли лучший способ добиться этого?
  2. Почему init не вызывается в PropertyDescriptor?
...