Ejemplo n.º 1
0
    def __init__(self, to_register=DEFAULT_SORTERS):
        # self._sorters_4_modelfields = {}  # TODO: when order is kept (py3.6+)
        self._sorters_4_modelfields = OrderedDict()
        self._sorters_4_modelfieldtypes = ClassKeyedMap(default=None)

        for model_field_cls, sorter_cls in to_register:
            self.register_model_field_type(type=model_field_cls,
                                           sorter_cls=sorter_cls)
Ejemplo n.º 2
0
    def __init__(self,
                 to_register=DEFAULT_REGISTRATIONS,
                 choice_sfield_builder=lv_form.RegularChoiceField):
        self._builders_4_modelfields = {}
        self._builders_4_modelfieldtypes = ClassKeyedMap(default=None)
        self.register_choice_builder(choice_sfield_builder)

        for model_field_cls, builder in to_register:
            self.register_model_field_type(type=model_field_cls,
                                           sfield_builder=builder)
Ejemplo n.º 3
0
    def __init__(self,
                 models_to_register: Iterable[Tuple[
                     Type[Model], Type[AbstractCellSorter]]] = DEFAULT_MODELS):
        self._sorters: ClassKeyedMap = ClassKeyedMap(default=None)

        for model, sorter_cls in models_to_register:
            self.register(model=model, sorter_cls=sorter_cls)
Ejemplo n.º 4
0
    def __init__(self,
                 default=lv_form.RegularRelatedField,
                 models_to_register=DEFAULT_MODELS):
        self._builders_4_models = ClassKeyedMap(default=None)
        self.register_default(default)

        for model, builder in models_to_register:
            self.register_related_model(model=model, sfield_builder=builder)
Ejemplo n.º 5
0
    def test_main(self):
        class Klass1: pass
        class Klass2: pass
        class Klass3: pass

        ckm = ClassKeyedMap([(Klass1, 1), (Klass2, 2)])
        self.assertEqual(1, ckm[Klass1])
        self.assertEqual(2, ckm[Klass2])
        self.assertEqual(2, len(ckm))

        self.assertIsNone(ckm[Klass3])
        self.assertEqual(3, len(ckm))

        self.assertIsNone(ckm.default)

        self.assertTrue(hasattr(ckm, '__contains__'))
        self.assertIn(Klass1, ckm)

        empty = ClassKeyedMap()
        self.assertIs(True,  bool(ckm))
        self.assertIs(False, bool(empty))
        self.assertEqual(0, len(empty))
        self.assertNotIn(Klass1, empty)

        keys_set = {Klass1, Klass2, Klass3}
        self.assertEqual(keys_set, set(ckm))
        self.assertEqual(keys_set, set(ckm.keys()))

        self.assertEqual({1, 2, None}, set(ckm.values()))
        self.assertEqual({(Klass1, 1), (Klass2, 2), (Klass3, None)},
                         set(ckm.items())
                        )

        r = repr(ckm)
        self.assertTrue(r.startswith('ClassKeyedMap('))
Ejemplo n.º 6
0
    def test_inheritage03(self):
        "Inheritance order must be kept when cache is filled too"
        class Klass1: pass
        class Klass2(Klass1): pass
        class Klass3(Klass2): pass
        class Klass4(Klass3): pass

        ckm = ClassKeyedMap([(Klass1, 1), (Klass3, 3)],  # Not 2 & 4
                             default=0
                            )

        self.assertEqual(1, ckm[Klass2])
        self.assertEqual(3, ckm[Klass4])
Ejemplo n.º 7
0
    def __init__(self,
                 to_register: Iterable[
                     Tuple[Type[Field],
                           Type[AbstractCellSorter]]] = DEFAULT_SORTERS):
        # self._sorters_4_modelfields = {}  # TODO: when order is kept (py3.7)
        self._sorters_4_modelfields: Dict[Field,
                                          AbstractCellSorter] = OrderedDict()
        self._sorters_4_modelfieldtypes: ClassKeyedMap = ClassKeyedMap(
            default=None)

        for model_field_cls, sorter_cls in to_register:
            self.register_model_field_type(type=model_field_cls,
                                           sorter_cls=sorter_cls)
Ejemplo n.º 8
0
    def test_inheritage02(self):
        "Inheriting values: more complex case (the nearest parent should be found)"
        class Klass1: pass
        class Klass2(Klass1): pass
        class Klass3(Klass2): pass
        class Klass4(Klass3): pass

        ckm = ClassKeyedMap([(Klass1, 1), (Klass2, 2), (Klass3, 3), (Klass4, 4)],
                            default=0
                           )

        class Klass5(Klass4): pass

        self.assertEqual(4, ckm[Klass5])
Ejemplo n.º 9
0
    def test_inheritage01(self):
        "Inheriting values"
        class Klass1: pass
        class Klass2: pass
        class Klass3(Klass2): pass
        class Klass4(Klass3): pass

        ckm = ClassKeyedMap([(Klass1, 1), (Klass2, 2)])

        self.assertEqual(2, ckm[Klass3])
        self.assertEqual(2, ckm[Klass4])

        ckm[Klass3] = 3

        self.assertEqual(3, ckm[Klass3])
        self.assertEqual(3, ckm[Klass4])  # Cache must be updated
Ejemplo n.º 10
0
    def test_setitem(self):
        "Other default value + __setitem__"
        class Klass1: pass
        class Klass2: pass
        class Klass3: pass

        ckm = ClassKeyedMap(default=0)

        result = ckm[Klass1] = 1
        ckm[Klass2] = 2

        self.assertEqual(0, ckm[Klass3])
        self.assertEqual(1, ckm[Klass1])
        self.assertEqual(1, result)
        self.assertEqual(3, len(ckm))

        self.assertEqual(0, ckm[Klass3])  # 2nd access should hit the cache
        self.assertEqual(3, len(ckm))
Ejemplo n.º 11
0
class RegularFieldSearchRegistry(AbstractListViewSearchFieldRegistry):
    """Class of ListViewSearchFieldRegistry specialized for cells representing
    model fields (CharField, BooleanField, ForeignKey...).

    The returned search-field can be customised depending on (from greater priority to lesser):
      - A model-field (eg: the field "name" of your model <Book>).
      - The class of the model-field (eg: fields which have class inheriting CharField).

    There is a special case for model-fields which have choices.
    """
    DEFAULT_REGISTRATIONS = (
        (models.CharField, lv_form.RegularCharField),
        (models.TextField, lv_form.RegularCharField),
        (models.IntegerField, lv_form.RegularIntegerField),
        (models.PositiveIntegerField, lv_form.RegularPositiveIntegerField),
        (models.PositiveSmallIntegerField,
         lv_form.RegularPositiveIntegerField),
        (models.FloatField, lv_form.RegularFloatField),
        (models.DecimalField, lv_form.RegularDecimalField),
        (models.BooleanField, lv_form.RegularBooleanField),
        # (models.NullBooleanField, RegularBooleanField),
        (models.DateField, lv_form.RegularDateField),
        # (models.TimeField, ), TODO
        (models.ForeignKey, RegularRelatedFieldSearchRegistry),
        (models.ManyToManyField, RegularRelatedFieldSearchRegistry),
        # (models.OneToOneField, RegularRelatedFieldSearchRegistry), TODO

        # (models.IPAddressField, ...)  # TODO: what about ?

        # TODO: needs JSONField management in the RDBMS...
        # (fields.DurationField, ),
        # (fields.DatePeriodField, ),

        # No search
        # (models.FileField, ),
        # (models.ImageField, ),
    )

    def __init__(self,
                 to_register=DEFAULT_REGISTRATIONS,
                 choice_sfield_builder=lv_form.RegularChoiceField):
        self._builders_4_modelfields = {}
        self._builders_4_modelfieldtypes = ClassKeyedMap(default=None)
        self.register_choice_builder(choice_sfield_builder)

        for model_field_cls, builder in to_register:
            self.register_model_field_type(type=model_field_cls,
                                           sfield_builder=builder)

    def builder_4_model_field(self, *, model, field_name):
        field = model._meta.get_field(field_name)
        return self._builders_4_modelfields.get(field)

    def builder_4_model_field_type(self, model_field):
        return self._builders_4_modelfieldtypes[model_field]

    @property
    def choice_builder(self):
        return self._choice_builder

    def get_field(self, *, cell, user, **kwargs):
        model_field = cell.field_info[-1]

        return self._build_field(
            builder=self._builders_4_modelfields.get(model_field)
            or (self._choice_builder if model_field.choices else
                self._builders_4_modelfieldtypes[type(model_field)]),
            cell=cell,
            user=user,
            **kwargs)

    def pretty(self, indent=0):
        indent_str = ' ' * indent
        res = '{indent}{name}:\n{indent}  Choice:\n{choice}\n{indent}  Field types:'.format(
            indent=indent_str,
            name=type(self).__name__,
            choice=self._pretty_builder(self._choice_builder,
                                        indent=indent + 4),
        )

        for field_type, builder in self._builders_4_modelfieldtypes.items():
            res += '\n{}    [{}.{}]:\n{}'.format(
                indent_str,
                field_type.__module__,
                field_type.__name__,
                self._pretty_builder(builder, indent=indent + 6),
            )

        res += '\n{}  Fields:'.format(indent_str)
        modelfields = self._builders_4_modelfields
        if modelfields:
            for field, builder in modelfields.items():
                res += '\n{}    [{}]:\n{}'.format(
                    indent_str,
                    field,
                    self._pretty_builder(builder, indent=indent + 6),
                )
        else:
            res += '\n{}    (empty)'.format(indent_str)

        return res

    def register_choice_builder(self, sfield_builder):
        self._choice_builder = self._instantiate_builder(sfield_builder)

        return self

    def register_model_field(self, *, model, field_name, sfield_builder):
        field = model._meta.get_field(field_name)
        self._builders_4_modelfields[field] = self._instantiate_builder(
            sfield_builder)

        # TODO ?
        # if self._enums_4_fields.setdefault(field, enumerator_class) is not enumerator_class:
        #     raise self.RegistrationError(
        #         '_EnumerableRegistry: this field is already registered: {model}.{field}'.format(
        #             model=model.__name__, field=field_name,
        #         )
        #     )

        return self

    def register_model_field_type(self, *, type, sfield_builder):
        self._builders_4_modelfieldtypes[type] = self._instantiate_builder(
            sfield_builder)

        return self
Ejemplo n.º 12
0
class RegularFieldSorterRegistry(AbstractCellSorter):
    """Class of sorter for all types of EntityCellRegularField.

    Sub-sorters can be registered to customise the behaviour for specific
    model-fields & model-field classes.
    """
    DEFAULT_SORTERS = (
        (models.AutoField, RegularFieldSorter),
        (models.BooleanField, RegularFieldSorter),
        (models.DecimalField, RegularFieldSorter),
        (models.FloatField, RegularFieldSorter),
        (models.IntegerField, RegularFieldSorter),
        (models.CharField, RegularFieldSorter),
        (models.TextField, RegularFieldSorter),
        (models.DateField, RegularFieldSorter),
        (models.TimeField, RegularFieldSorter),
        (models.ForeignKey, ForeignKeySorterRegistry),

        # No sorting
        #  models.ManyToManyField
        #  models.OneToOneField
        (models.CommaSeparatedIntegerField, VoidSorter),
        #  models.FilePathField
        #  models.BinaryField
        #  models.UUIDField
        #  (fields.DurationField, VoidSorter),  TODO ?
        (fields.DatePeriodField, VoidSorter
         ),  # TODO: needs JSONField management in the RDBMS...

        # TODO: what about ?
        # (models.DurationField, ...)
        # (models.IPAddressField, ...)
        # (models.GenericIPAddressField, ...)
        # (models.SlugField, ...)
        # (models.URLField, ...)
    )

    def __init__(self, to_register=DEFAULT_SORTERS):
        # self._sorters_4_modelfields = {}  # TODO: when order is kept (py3.6+)
        self._sorters_4_modelfields = OrderedDict()
        self._sorters_4_modelfieldtypes = ClassKeyedMap(default=None)

        for model_field_cls, sorter_cls in to_register:
            self.register_model_field_type(type=model_field_cls,
                                           sorter_cls=sorter_cls)

    def get_field_name(self, cell):
        field = cell.field_info[-1]
        sorter = self._sorters_4_modelfields.get(field) or \
                 self._sorters_4_modelfieldtypes[type(field)]

        return None if sorter is None else sorter.get_field_name(cell=cell)

    def pretty(self, indent=0):
        indent_str = ' ' * indent
        res = '{indent}{name}:\n{indent}  Field types:'.format(
            indent=indent_str,
            name=type(self).__name__,
        )

        for field_type, sorter in self._sorters_4_modelfieldtypes.items():
            res += '\n{}    [{}.{}]:\n{}'.format(
                indent_str,
                field_type.__module__,
                field_type.__name__,
                sorter.pretty(indent=indent + 6),
            )

        res += '\n{}  Fields:'.format(indent_str)
        modelfields = self._sorters_4_modelfields
        if modelfields:
            for field, sorter in modelfields.items():
                res += '\n{}    [{}]:\n{}'.format(
                    indent_str,
                    field,
                    sorter.pretty(indent=indent + 6),
                )
        else:
            res += '\n{}    (empty)'.format(indent_str)

        return res

    def register_model_field(self, *, model, field_name, sorter_cls):
        field = model._meta.get_field(field_name)
        self._sorters_4_modelfields[field] = sorter_cls()

        # TODO ?
        # if self._enums_4_fields.setdefault(field, enumerator_class) is not enumerator_class:
        #     raise self.RegistrationError(
        #         '_EnumerableRegistry: this field is already registered: {model}.{field}'.format(
        #             model=model.__name__, field=field_name,
        #         )
        #     )

        return self

    def register_model_field_type(self, *, type, sorter_cls):
        self._sorters_4_modelfieldtypes[type] = sorter_cls()

        return self

    def sorter_4_model_field(self, *, model, field_name):
        field = model._meta.get_field(field_name)
        return self._sorters_4_modelfields.get(field)

    def sorter_4_model_field_type(self, model_field):
        return self._sorters_4_modelfieldtypes[model_field]
Ejemplo n.º 13
0
    def __init__(self, models_to_register=DEFAULT_MODELS):
        self._sorters = ClassKeyedMap(default=None)

        for model, sorter_cls in models_to_register:
            self.register(model=model, sorter_cls=sorter_cls)
Ejemplo n.º 14
0
 def __init__(self, default_field_explainer_class=FieldChangeExplainer):
     self._line_explainer_classes = {}
     self._field_explainer_classes = ClassKeyedMap(
         default=default_field_explainer_class)