Skip to content

Commit

Permalink
Merge fa1f67e into e42c09f
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Sep 18, 2018
2 parents e42c09f + fa1f67e commit 60a3619
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 27 deletions.
4 changes: 3 additions & 1 deletion CHANGES.rst
Expand Up @@ -6,7 +6,9 @@
1.5.1 (unreleased)
==================

- Nothing changed yet.
- Adjust the deprecated ``zope.schema.interfaces.InvalidValue`` to be
a simple alias for ``zope.schema.interfaces.InvalidValue`` (while
preserving the constructor) for improved backwards compatibility.


1.5.0 (2018-09-11)
Expand Down
11 changes: 11 additions & 0 deletions docs/interfaces.rst
Expand Up @@ -5,3 +5,14 @@
.. automodule:: nti.schema.interfaces
:members:
:undoc-members:

.. exception:: InvalidValue(*args, field=None, value=None)

Adds a field specifically to carry the value that is invalid.

.. deprecated:: 1.4.0
This is now just a convenience wrapper around
:class:`zope.schema.interfaces.InvalidValue` that calls
:meth:`.zope.schema.interfaces.ValidationError.with_field_and_value`
before returning the exception. You should always catch
:class:`zope.schema.interfaces.InvalidValue`.
43 changes: 23 additions & 20 deletions src/nti/schema/interfaces.py
Expand Up @@ -45,7 +45,8 @@ class IBeforeSchemaFieldAssignedEvent(Interface):
context = Attribute(u"The context object where the object will be assigned to.")

# Make this a base of the zope interface so our handlers
# are compatible
# are compatible. This is dangerous if any lookups or registrations have already been done,
# as zope.interface maintains a cache of these things.
sch_interfaces.IBeforeObjectAssignedEvent.__bases__ = (IBeforeSchemaFieldAssignedEvent,)

@implementer(IBeforeSchemaFieldAssignedEvent)
Expand Down Expand Up @@ -135,28 +136,30 @@ class BeforeDictAssignedEvent(BeforeSchemaFieldAssignedEvent):

BeforeObjectAssignedEvent = BeforeObjectAssignedEvent

class InvalidValue(sch_interfaces.InvalidValue):
"""
InvalidValue(*args, field=None, value=None)

Adds a field specifically to carry the value that is invalid.
# Set up the alias for InvalidValue. We need to use an alias so that
# try/except and subclass works as expected. The unfortunate side
# effect is that to preserve the constructor we need to swizzle the
# __init__ of sch_interfaces.InvalidValue (the swizzling is harmless;
# in zope.schema 4.7, InvalidValue inherits the Exception constructor,
# which forbids any kwargs but allows arbitrary *args; we keep that
# behaviour). This is deprecated and will be removed in the future.
InvalidValue = sch_interfaces.InvalidValue

def _InvalidValue__init__(self, *args, **kwargs):
field = kwargs.pop('field', None)
value = kwargs.pop('value', None)
if kwargs:
raise TypeError("Too many kwargs for function InvalidValue")
# like normal
sch_interfaces.ValidationError.__init__(self, *args)
if field is not None or value is not None:
self.with_field_and_value(field, value)

.. deprecated:: 1.4.0
This is now just a convenience wrapper around
:class:`zope.schema.interfaces.InvalidValue` that calls
:meth:`.zope.schema.interfaces.ValidationError.with_field_and_value`
before returning the exception. You should always catch
:class:`zope.schema.interfaces.InvalidValue`.
"""
# We can't write the syntax we want to in Python 2.

def __init__(self, *args, **kwargs):
field = kwargs.pop('field', None)
value = kwargs.pop('value', None)
if kwargs:
raise TypeError("Too many kwargs for function InvalidValue")
super(InvalidValue, self).__init__(*args)
self.with_field_and_value(field, value)
sch_interfaces.InvalidValue.__init__ = _InvalidValue__init__

del _InvalidValue__init__

deprecated('InvalidValue',
"Use zope.schema.interfaces.InvalidValue.with_field_and_value.")
Expand Down
28 changes: 22 additions & 6 deletions src/nti/schema/tests/test_interfaces.py
Expand Up @@ -43,13 +43,29 @@ def test_construct(self):
InvalidValue(value=1, field=2, other=3)

def test_subclass(self):
type('subclass', (InvalidValue,), {})

def test_instance(self):
v = InvalidValue()
assert_that(v, is_(instance_of(InvalidValue)))

kind = type('subclass', (InvalidValue,), {})
self.test_instance(kind)
self.test_raise_except(kind)

def test_instance(self, kind=InvalidValue):
from zope.schema import interfaces as sch_interfaces
v = kind()
self.assertIsInstance(v, sch_interfaces.InvalidValue)
self.assertIsInstance(v, InvalidValue)

def test_raise_except(self, kind=InvalidValue):
# It can be caught by its own name
with self.assertRaises(kind):
raise kind()
# It can be caught by the zope.schema name
from zope.schema import interfaces as sch_interfaces
with self.assertRaises(sch_interfaces.InvalidValue):
raise InvalidValue()

def test_repr(self):
assert_that(repr(InvalidValue('foo')),
is_("InvalidValue('foo')"))

def test_alias(self):
from zope.schema import interfaces as sch_interfaces
self.assertIs(InvalidValue, sch_interfaces.InvalidValue)

0 comments on commit 60a3619

Please sign in to comment.