def test_deferred_fields(self):
        pre_save_changed.connect(func, sender=DeferredModel)

        obj = DeferredModel()
        post_init.send(instance=obj, sender=DeferredModel)

        assert list(obj._fieldsignals_originals.values()) == [{'a': 1}]
    def test_deferred_fields(self):
        pre_save_changed.connect(func, sender=DeferredModel)

        obj = DeferredModel()
        post_init.send(instance=obj, sender=DeferredModel)

        assert list(obj._fieldsignals_originals.values()) == [{'a': 1}]
    def test_post_save_unchanged(self):
        with must_be_called(False) as func:
            post_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)
            # This *doesn't* call post_save_changed, because we haven't changed anything.
            post_save.send(instance=obj, sender=FakeModel)
    def test_post_save_unchanged(self):
        with must_be_called(False) as func:
            post_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)
            # This *doesn't* call post_save_changed, because we haven't changed anything.
            post_save.send(instance=obj, sender=FakeModel)
    def test_post_save_changed(self):
        with must_be_called(True) as func:
            post_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'another value'
            post_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_with_fields_changed(self):
        with must_be_called(True) as func:
            pre_save_changed.connect(func, sender=FakeModel, fields=('a_key',))

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'change a field that we care about'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_with_fields_unchanged(self):
        with must_be_called(False) as func:
            pre_save_changed.connect(func, sender=FakeModel, fields=('a_key',))

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.another = 'dont care about this field'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_post_save_changed(self):
        with must_be_called(True) as func:
            post_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'another value'
            post_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_with_fields_unchanged(self):
        with must_be_called(False) as func:
            pre_save_changed.connect(func,
                                     sender=FakeModel,
                                     fields=('a_key', ))

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.another = 'dont care about this field'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_with_fields_changed(self):
        with must_be_called(True) as func:
            pre_save_changed.connect(func,
                                     sender=FakeModel,
                                     fields=('a_key', ))

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'change a field that we care about'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_changed(self):
        with must_be_called(True) as func:
            pre_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()

            # post_init sets list of initial values
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'another value'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_pre_save_changed(self):
        with must_be_called(True) as func:
            pre_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()

            # post_init sets list of initial values
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = 'another value'
            pre_save.send(instance=obj, sender=FakeModel)
    def test_post_save_changed(self):
        with must_be_called(True) as func:
            post_save_changed.connect(func, sender=FakeModel)

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = "another value"
            post_save.send(instance=obj, sender=FakeModel)
        assert func.kwargs["changed_fields"] == {
            "a_key": ("a value", "another value")
        }
    def test_pre_save_with_fields_changed(self):
        with must_be_called(True) as func:
            pre_save_changed.connect(func,
                                     sender=FakeModel,
                                     fields=("a_key", ))

            obj = FakeModel()
            post_init.send(instance=obj, sender=FakeModel)

            obj.a_key = "change a field that we care about"
            pre_save.send(instance=obj, sender=FakeModel)
        assert func.kwargs["changed_fields"] == {
            "a_key": ("a value", "change a field that we care about")
        }
Example #15
0
    def __init__(self, *args, **kwargs):
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        self._dn = None

        pre_init.send(sender=cls, args=args, kwargs=kwargs)

        if len(args) > len(opts.fields):
            # Daft, but matches old exception sans the err msg.
            raise IndexError("Number of args exceeds number of fields")

        if not kwargs:
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                _setattr(self, field.name, val)
        else:
            # Slower, kwargs-ready version.
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                _setattr(self, field.name, val)
                kwargs.pop(field.name, None)

        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.

        for field in fields_iter:
            if kwargs:
                try:
                    val = kwargs.pop(field.name)
                except KeyError:
                    # This is done with an exception rather than the
                    # default argument on pop because we don't want
                    # get_default() to be evaluated, and then not used.
                    # Refs #12057.
                    val = field.get_default()
            else:
                val = field.get_default()
            _setattr(self, field.name, val)

        if kwargs and '_dn' in kwargs:
            _setattr(self, '_dn', kwargs['_dn'])
            kwargs.pop('_dn')

        if kwargs:
            for kwarg in kwargs:
                raise TypeError("'%s' is an invalid keyword argument for this function" % kwarg)
        super().__init__()
        post_init.send(sender=cls, instance=self)
Example #16
0
    def __init__(self, **kwargs):
        self.pk = getattr(self, 'pk', None)
        self._models.append(self)

        for key, value in kwargs.iteritems():
            setattr(self, key, value)

        def save_side_effect():
            if self.pk is None:
                self.pk = random.randint(1000, 10000)

        post_init.send(sender=self.__class__, instance=self)

        self.save = Mock(name='save', side_effect=save_side_effect)
        self.delete = Mock(name='delete')
Example #17
0
    def __init__(self, **kwargs):
        self.pk = getattr(self, 'pk', None)
        self._models.append(self)

        for key, value in kwargs.iteritems():
            setattr(self, key, value)

        def save_side_effect():
            if self.pk is None:
                self.pk = random.randint(1000, 10000)

        post_init.send(sender=self.__class__, instance=self)

        self.save = Mock(name='save', side_effect=save_side_effect)
        self.delete = Mock(name='delete')
    def test_compare_after_to_python(self):
        """
        Field values (e.g. datetimes) are equal even if set via string.
        Ensures that to_python() is called prior to comparison between old & new values.
        """
        with must_be_called(False) as func:
            pre_save_changed.connect(func, sender=FakeModel, fields=('a_datetime',))

            obj = FakeModel()
            obj.a_datetime = '2017-01-01T00:00:00.000000Z'
            post_init.send(instance=obj, sender=FakeModel)

            # This is identical to the above, even though the type is different,
            # so don't call the signal
            obj.a_datetime = datetime.datetime(2017, 1, 1, 0, 0, 0, 0, utc)
            pre_save.send(instance=obj, sender=FakeModel)
    def test_compare_after_to_python(self):
        """
        Field values (e.g. datetimes) are equal even if set via string.
        Ensures that to_python() is called prior to comparison between old & new values.
        """
        with must_be_called(False) as func:
            pre_save_changed.connect(func,
                                     sender=FakeModel,
                                     fields=('a_datetime', ))

            obj = FakeModel()
            obj.a_datetime = '2017-01-01T00:00:00.000000Z'
            post_init.send(instance=obj, sender=FakeModel)

            # This is identical to the above, even though the type is different,
            # so don't call the signal
            obj.a_datetime = datetime.datetime(2017, 1, 1, 0, 0, 0, 0, utc)
            pre_save.send(instance=obj, sender=FakeModel)
    def __init__(self, *args, **kwargs):
        cls = self.__class__

        pre_init.send(sender=cls, args=args, kwargs=kwargs)
        super().__init__(*args, **kwargs)
        post_init.send(sender=cls, instance=self)
Example #21
0
    def __init__(self, *args, **kwargs):
        # Alias some things as locals to avoid repeat global lookups
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        _DEFERRED = DEFERRED

        pre_init.send(sender=cls, args=args, kwargs=kwargs)

        # Set up the storage for instance state
        self._state = ModelState()

        # There is a rather weird disparity here; if kwargs, it's set, then args
        # overrides it. It should be one or the other; don't duplicate the work
        # The reason for the kwargs check is that standard iterator passes in by
        # args, and instantiation for iteration is 33% faster.
        if len(args) > len(opts.concrete_fields):
            # Daft, but matches old exception sans the err msg.
            raise IndexError("Number of args exceeds number of fields")

        if not kwargs:
            fields_iter = iter(opts.concrete_fields)
            # The ordering of the zip calls matter - zip throws StopIteration
            # when an iter throws it. So if the first iter throws it, the second
            # is *not* consumed. We rely on this, so don't change the order
            # without changing the logic.
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
        else:
            # Slower, kwargs-ready version.
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
                kwargs.pop(field.name, None)

        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.

        for field in fields_iter:
            is_related_object = False
            # Virtual field
            if field.attname not in kwargs and field.column is None:
                continue
            if kwargs:
                if isinstance(field.remote_field, ForeignObjectRel):
                    try:
                        # Assume object instance was passed in.
                        rel_obj = kwargs.pop(field.name)
                        is_related_object = True
                    except KeyError:
                        try:
                            # Object instance wasn't passed in -- must be an ID.
                            val = kwargs.pop(field.attname)
                        except KeyError:
                            val = field.get_default()
                    else:
                        # Object instance was passed in. Special case: You can
                        # pass in "None" for related objects if it's allowed.
                        if rel_obj is None and field.null:
                            val = None
                else:
                    try:
                        val = kwargs.pop(field.attname)
                    except KeyError:
                        # This is done with an exception rather than the
                        # default argument on pop because we don't want
                        # get_default() to be evaluated, and then not used.
                        # Refs #12057.
                        val = field.get_default()
            else:
                val = field.get_default()

            if is_related_object:
                # If we are passed a related instance, set it using the
                # field.name instead of field.attname (e.g. "user" instead of
                # "user_id") so that the object gets properly cached (and type
                # checked) by the RelatedObjectDescriptor.
                if rel_obj is not _DEFERRED:
                    _setattr(self, field.name, rel_obj)
            else:
                if val is not _DEFERRED:
                    _setattr(self, field.attname, val)

        if kwargs:
            property_names = opts._property_names
            for prop in tuple(kwargs):
                try:
                    # Any remaining kwargs must correspond to properties or
                    # virtual fields.
                    if prop in property_names or opts.get_field(prop):
                        if kwargs[prop] is not _DEFERRED:
                            _setattr(self, prop, kwargs[prop])
                        del kwargs[prop]
                except (AttributeError, FieldDoesNotExist):
                    pass
            if kwargs:
                for key, value in kwargs.items():
                    if hasattr(self, key):
                        raise TypeError(
                            "'%s' is an invalid keyword argument for this function"
                            % key)

                    setattr(self, key, value)
        super(Model, self).__init__()
        post_init.send(sender=cls, instance=self)