diff --git a/CHANGES.rst b/CHANGES.rst
index 99b9c7c..9d29d73 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -115,6 +115,17 @@
 - Make ``SimpleVocabulary`` and ``SimpleTerm`` have value-based
   equality and hashing methods.
 
+- All fields of the schema of an ``Object`` field are bound to the
+  top-level value being validated before attempting validation of
+  their particular attribute. Previously only ``IChoice`` fields were
+  bound. See `issue 17
+  <https://github.com/zopefoundation/zope.schema/issues/17>`_.
+
+- Share the internal logic of ``Object`` field validation and
+  ``zope.schema.getValidationErrors``. See `issue 57
+  <https://github.com/zopefoundation/zope.schema/issues/57>`_.
+
+
 4.5.0 (2017-07-10)
 ==================
 
diff --git a/docs/api.rst b/docs/api.rst
index 7314f20..5a1b9b3 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -9,97 +9,97 @@ better guide to the intended usage.
 Interfaces
 ==========
 
-.. autoclass:: zope.schema.interfaces.IField
-.. autoclass:: zope.schema.interfaces.IFromUnicode
-.. autoclass:: zope.schema.interfaces.IChoice
-.. autoclass:: zope.schema.interfaces.IContextAwareDefaultFactory
-.. autoclass:: zope.schema.interfaces.IOrderable
-.. autoclass:: zope.schema.interfaces.ILen
-.. autoclass:: zope.schema.interfaces.IMinMax
-.. autoclass:: zope.schema.interfaces.IMinMaxLen
-.. autoclass:: zope.schema.interfaces.IInterfaceField
-.. autoclass:: zope.schema.interfaces.IBool
-.. autoclass:: zope.schema.interfaces.IObject
-.. autoclass:: zope.schema.interfaces.IDict
+.. autointerface:: zope.schema.interfaces.IField
+.. autointerface:: zope.schema.interfaces.IFromUnicode
+.. autointerface:: zope.schema.interfaces.IChoice
+.. autointerface:: zope.schema.interfaces.IContextAwareDefaultFactory
+.. autointerface:: zope.schema.interfaces.IOrderable
+.. autointerface:: zope.schema.interfaces.ILen
+.. autointerface:: zope.schema.interfaces.IMinMax
+.. autointerface:: zope.schema.interfaces.IMinMaxLen
+.. autointerface:: zope.schema.interfaces.IInterfaceField
+.. autointerface:: zope.schema.interfaces.IBool
+.. autointerface:: zope.schema.interfaces.IObject
+.. autointerface:: zope.schema.interfaces.IDict
 
 Strings
 -------
 
-.. autoclass:: zope.schema.interfaces.IBytes
-.. autoclass:: zope.schema.interfaces.IBytesLine
-.. autoclass:: zope.schema.interfaces.IText
-.. autoclass:: zope.schema.interfaces.ITextLine
-.. autoclass:: zope.schema.interfaces.IASCII
-.. autoclass:: zope.schema.interfaces.IASCIILine
+.. autointerface:: zope.schema.interfaces.IBytes
+.. autointerface:: zope.schema.interfaces.IBytesLine
+.. autointerface:: zope.schema.interfaces.IText
+.. autointerface:: zope.schema.interfaces.ITextLine
+.. autointerface:: zope.schema.interfaces.IASCII
+.. autointerface:: zope.schema.interfaces.IASCIILine
 
-.. autoclass:: zope.schema.interfaces.IPassword
-.. autoclass:: zope.schema.interfaces.IURI
-.. autoclass:: zope.schema.interfaces.IId
-.. autoclass:: zope.schema.interfaces.IDottedName
+.. autointerface:: zope.schema.interfaces.IPassword
+.. autointerface:: zope.schema.interfaces.IURI
+.. autointerface:: zope.schema.interfaces.IId
+.. autointerface:: zope.schema.interfaces.IDottedName
 
 
 Numbers
 -------
 
-.. autoclass:: zope.schema.interfaces.INumber
-.. autoclass:: zope.schema.interfaces.IComplex
-.. autoclass:: zope.schema.interfaces.IReal
-.. autoclass:: zope.schema.interfaces.IRational
-.. autoclass:: zope.schema.interfaces.IIntegral
+.. autointerface:: zope.schema.interfaces.INumber
+.. autointerface:: zope.schema.interfaces.IComplex
+.. autointerface:: zope.schema.interfaces.IReal
+.. autointerface:: zope.schema.interfaces.IRational
+.. autointerface:: zope.schema.interfaces.IIntegral
 
-.. autoclass:: zope.schema.interfaces.IInt
-.. autoclass:: zope.schema.interfaces.IFloat
-.. autoclass:: zope.schema.interfaces.IDecimal
+.. autointerface:: zope.schema.interfaces.IInt
+.. autointerface:: zope.schema.interfaces.IFloat
+.. autointerface:: zope.schema.interfaces.IDecimal
 
 Date/Time
 ---------
 
-.. autoclass:: zope.schema.interfaces.IDatetime
-.. autoclass:: zope.schema.interfaces.IDate
-.. autoclass:: zope.schema.interfaces.ITimedelta
-.. autoclass:: zope.schema.interfaces.ITime
+.. autointerface:: zope.schema.interfaces.IDatetime
+.. autointerface:: zope.schema.interfaces.IDate
+.. autointerface:: zope.schema.interfaces.ITimedelta
+.. autointerface:: zope.schema.interfaces.ITime
 
 
 Collections
 -----------
-.. autoclass:: zope.schema.interfaces.IIterable
-.. autoclass:: zope.schema.interfaces.IContainer
-.. autoclass:: zope.schema.interfaces.ICollection
-.. autoclass:: zope.schema.interfaces.ISequence
-.. autoclass:: zope.schema.interfaces.IMutableSequence
-.. autoclass:: zope.schema.interfaces.IUnorderedCollection
-.. autoclass:: zope.schema.interfaces.IAbstractSet
-.. autoclass:: zope.schema.interfaces.IAbstractBag
-
-.. autoclass:: zope.schema.interfaces.ITuple
-.. autoclass:: zope.schema.interfaces.IList
-.. autoclass:: zope.schema.interfaces.ISet
-.. autoclass:: zope.schema.interfaces.IFrozenSet
+.. autointerface:: zope.schema.interfaces.IIterable
+.. autointerface:: zope.schema.interfaces.IContainer
+.. autointerface:: zope.schema.interfaces.ICollection
+.. autointerface:: zope.schema.interfaces.ISequence
+.. autointerface:: zope.schema.interfaces.IMutableSequence
+.. autointerface:: zope.schema.interfaces.IUnorderedCollection
+.. autointerface:: zope.schema.interfaces.IAbstractSet
+.. autointerface:: zope.schema.interfaces.IAbstractBag
+
+.. autointerface:: zope.schema.interfaces.ITuple
+.. autointerface:: zope.schema.interfaces.IList
+.. autointerface:: zope.schema.interfaces.ISet
+.. autointerface:: zope.schema.interfaces.IFrozenSet
 
 Events
 ------
 
-.. autoclass:: zope.schema.interfaces.IBeforeObjectAssignedEvent
-.. autoclass:: zope.schema.interfaces.IFieldEvent
-.. autoclass:: zope.schema.interfaces.IFieldUpdatedEvent
+.. autointerface:: zope.schema.interfaces.IBeforeObjectAssignedEvent
+.. autointerface:: zope.schema.interfaces.IFieldEvent
+.. autointerface:: zope.schema.interfaces.IFieldUpdatedEvent
 
 Vocabularies
 ------------
 
-.. autoclass:: zope.schema.interfaces.ITerm
-.. autoclass:: zope.schema.interfaces.ITokenizedTerm
-.. autoclass:: zope.schema.interfaces.ITitledTokenizedTerm
-.. autoclass:: zope.schema.interfaces.ISource
-.. autoclass:: zope.schema.interfaces.ISourceQueriables
-.. autoclass:: zope.schema.interfaces.IContextSourceBinder
-.. autoclass:: zope.schema.interfaces.IBaseVocabulary
-.. autoclass:: zope.schema.interfaces.IIterableVocabulary
-.. autoclass:: zope.schema.interfaces.IIterableSource
-.. autoclass:: zope.schema.interfaces.IVocabulary
-.. autoclass:: zope.schema.interfaces.IVocabularyTokenized
-.. autoclass:: zope.schema.interfaces.ITreeVocabulary
-.. autoclass:: zope.schema.interfaces.IVocabularyRegistry
-.. autoclass:: zope.schema.interfaces.IVocabularyFactory
+.. autointerface:: zope.schema.interfaces.ITerm
+.. autointerface:: zope.schema.interfaces.ITokenizedTerm
+.. autointerface:: zope.schema.interfaces.ITitledTokenizedTerm
+.. autointerface:: zope.schema.interfaces.ISource
+.. autointerface:: zope.schema.interfaces.ISourceQueriables
+.. autointerface:: zope.schema.interfaces.IContextSourceBinder
+.. autointerface:: zope.schema.interfaces.IBaseVocabulary
+.. autointerface:: zope.schema.interfaces.IIterableVocabulary
+.. autointerface:: zope.schema.interfaces.IIterableSource
+.. autointerface:: zope.schema.interfaces.IVocabulary
+.. autointerface:: zope.schema.interfaces.IVocabularyTokenized
+.. autointerface:: zope.schema.interfaces.ITreeVocabulary
+.. autointerface:: zope.schema.interfaces.IVocabularyRegistry
+.. autointerface:: zope.schema.interfaces.IVocabularyFactory
 
 Exceptions
 ----------
diff --git a/docs/validation.rst b/docs/validation.rst
index 01e4e68..0771b07 100644
--- a/docs/validation.rst
+++ b/docs/validation.rst
@@ -4,13 +4,11 @@ Schema Validation
 
 There are two helper methods to verify schemas and interfaces:
 
-:func:`~.getValidationErrors`
-    first validates via the zope.schema field validators. If that succeeds the
-    invariants are checked.
-:func:`~.getSchemaValidationErrors`
-    *only* validates via the zope.schema field validators. The invariants are
-    *not* checked.
+.. autofunction:: zope.schema.getValidationErrors
+.. autofunction:: zope.schema.getSchemaValidationErrors
 
+Invariants are `documented by zope.interface
+<https://zopeinterface.readthedocs.io/en/latest/README.html#invariants>`_.
 
 Create an interface to validate against:
 
diff --git a/src/zope/schema/_bootstrapfields.py b/src/zope/schema/_bootstrapfields.py
index 5904068..cde9df0 100644
--- a/src/zope/schema/_bootstrapfields.py
+++ b/src/zope/schema/_bootstrapfields.py
@@ -18,31 +18,41 @@ __docformat__ = 'restructuredtext'
 import decimal
 import fractions
 import numbers
+import threading
 from math import isinf
 
 from zope.interface import Attribute
+from zope.interface import Invalid
+from zope.interface import Interface
 from zope.interface import providedBy
 from zope.interface import implementer
+from zope.interface.interfaces import IInterface
+from zope.interface.interfaces import IMethod
+
+from zope.event import notify
 
-from zope.schema._bootstrapinterfaces import ValidationError
 from zope.schema._bootstrapinterfaces import ConstraintNotSatisfied
+from zope.schema._bootstrapinterfaces import IBeforeObjectAssignedEvent
 from zope.schema._bootstrapinterfaces import IContextAwareDefaultFactory
 from zope.schema._bootstrapinterfaces import IFromUnicode
+from zope.schema._bootstrapinterfaces import IValidatable
 from zope.schema._bootstrapinterfaces import NotAContainer
 from zope.schema._bootstrapinterfaces import NotAnIterator
 from zope.schema._bootstrapinterfaces import RequiredMissing
+from zope.schema._bootstrapinterfaces import SchemaNotCorrectlyImplemented
+from zope.schema._bootstrapinterfaces import SchemaNotFullyImplemented
+from zope.schema._bootstrapinterfaces import SchemaNotProvided
 from zope.schema._bootstrapinterfaces import StopValidation
 from zope.schema._bootstrapinterfaces import TooBig
 from zope.schema._bootstrapinterfaces import TooLong
 from zope.schema._bootstrapinterfaces import TooShort
 from zope.schema._bootstrapinterfaces import TooSmall
+from zope.schema._bootstrapinterfaces import ValidationError
 from zope.schema._bootstrapinterfaces import WrongType
 
 from zope.schema._compat import text_type
 from zope.schema._compat import integer_types
 
-from zope.schema._schema import getFields
-
 
 class _NotGiven(object):
 
@@ -98,6 +108,17 @@ class DefaultProperty(ValidatedProperty):
         return value
 
 
+def getFields(schema):
+    """Return a dictionary containing all the Fields in a schema.
+    """
+    fields = {}
+    for name in schema:
+        attr = schema[name]
+        if IValidatable.providedBy(attr):
+            fields[name] = attr
+    return fields
+
+
 class Field(Attribute):
 
     # Type restrictions, if any
@@ -187,10 +208,10 @@ class Field(Attribute):
     def constraint(self, value):
         return True
 
-    def bind(self, object):
+    def bind(self, context):
         clone = self.__class__.__new__(self.__class__)
         clone.__dict__.update(self.__dict__)
-        clone.context = object
+        clone.context = context
         return clone
 
     def validate(self, value):
@@ -655,3 +676,184 @@ class Int(Integral):
     """
     _type = integer_types
     _unicode_converters = (int,)
+
+
+class _ObjectsBeingValidated(threading.local):
+
+    def __init__(self):
+        super(_ObjectsBeingValidated, self).__init__()
+        self.ids_being_validated = set()
+
+
+def get_schema_validation_errors(schema, value,
+                                 _validating_objects=_ObjectsBeingValidated()):
+    """
+    Validate that *value* conforms to the schema interface *schema*.
+
+    All :class:`zope.schema.interfaces.IField` members of the *schema*
+    are validated after being bound to *value*. (Note that we do not check for
+    arbitrary :class:`zope.interface.Attribute` members being present.)
+
+    :return: A `dict` mapping field names to `ValidationError` subclasses.
+       A non-empty return value means that validation failed.
+    """
+    errors = {}
+    # Interface can be used as schema property for Object fields that plan to
+    # hold values of any type.
+    # Because Interface does not include any Attribute, it is obviously not
+    # worth looping on its methods and filter them all out.
+    if schema is Interface:
+        return errors
+    # if `value` is part of a cyclic graph, we need to break the cycle to avoid
+    # infinite recursion. Collect validated objects in a thread local dict by
+    # it's python represenation. A previous version was setting a volatile
+    # attribute which didn't work with security proxy
+    id_value = id(value)
+    ids_being_validated = _validating_objects.ids_being_validated
+    if id_value in ids_being_validated:
+        return errors
+    ids_being_validated.add(id_value)
+    # (If we have gotten here, we know that `value` provides an interface
+    # other than zope.interface.Interface;
+    # iow, we can rely on the fact that it is an instance
+    # that supports attribute assignment.)
+
+    try:
+        for name in schema.names(all=True):
+            attribute = schema[name]
+            if IMethod.providedBy(attribute):
+                continue # pragma: no cover
+
+            try:
+                if IValidatable.providedBy(attribute):
+                    # validate attributes that are fields
+                    field_value = getattr(value, name)
+                    attribute = attribute.bind(value)
+                    attribute.validate(field_value)
+            except ValidationError as error:
+                errors[name] = error
+            except AttributeError as error:
+                # property for the given name is not implemented
+                errors[name] = SchemaNotFullyImplemented(error).with_field_and_value(attribute, None)
+    finally:
+        ids_being_validated.remove(id_value)
+    return errors
+
+
+def get_validation_errors(schema, value, validate_invariants=True):
+    """
+    Validate that *value* conforms to the schema interface *schema*.
+
+    This includes checking for any schema validation errors (using
+    `get_schema_validation_errors`). If that succeeds, and
+    *validate_invariants* is true, then we proceed to check for any
+    declared invariants.
+
+    Note that this does not include a check to see if the *value*
+    actually provides the given *schema*.
+
+    :return: If there were any validation errors, either schema or
+             invariant, return a two tuple (schema_error_dict,
+             invariant_error_list). If there were no errors, returns a
+             two-tuple where both members are empty.
+    """
+    schema_error_dict = get_schema_validation_errors(schema, value)
+    invariant_errors = []
+    # Only validate invariants if there were no previous errors. Previous
+    # errors could be missing attributes which would most likely make an
+    # invariant raise an AttributeError.
+
+    if validate_invariants and not schema_error_dict:
+        try:
+            schema.validateInvariants(value, invariant_errors)
+        except Invalid:
+            # validateInvariants raises a wrapper error around
+            # all the errors it got if it got errors, in addition
+            # to appending them to the errors list. We don't want
+            # that, we raise our own error.
+            pass
+
+    return (schema_error_dict, invariant_errors)
+
+
+class Object(Field):
+    """
+    Implementation of :class:`zope.schema.interfaces.IObject`.
+    """
+    schema = None
+
+    def __init__(self, schema=_NotGiven, **kw):
+        """
+        Object(schema=<Not Given>, *, validate_invariants=True, **kwargs)
+
+        Create an `~.IObject` field. The keyword arguments are as for `~.Field`.
+
+        .. versionchanged:: 4.6.0
+           Add the keyword argument *validate_invariants*. When true (the default),
+           the schema's ``validateInvariants`` method will be invoked to check
+           the ``@invariant`` properties of the schema.
+        .. versionchanged:: 4.6.0
+           The *schema* argument can be ommitted in a subclass
+           that specifies a ``schema`` attribute.
+        """
+        if schema is _NotGiven:
+            schema = self.schema
+
+        if not IInterface.providedBy(schema):
+            raise WrongType
+
+        self.schema = schema
+        self.validate_invariants = kw.pop('validate_invariants', True)
+        super(Object, self).__init__(**kw)
+
+    def _validate(self, value):
+        super(Object, self)._validate(value)
+
+        # schema has to be provided by value
+        if not self.schema.providedBy(value):
+            raise SchemaNotProvided(self.schema, value).with_field_and_value(self, value)
+
+        # check the value against schema
+        schema_error_dict, invariant_errors = get_validation_errors(
+            self.schema,
+            value,
+            self.validate_invariants
+        )
+
+        if schema_error_dict or invariant_errors:
+            errors = list(schema_error_dict.values()) + invariant_errors
+            exception = SchemaNotCorrectlyImplemented(
+                errors,
+                self.__name__
+            ).with_field_and_value(self, value)
+            exception.schema_errors = schema_error_dict
+            exception.invariant_errors = invariant_errors
+            try:
+                raise exception
+            finally:
+                # Break cycles
+                del exception
+                del invariant_errors
+                del schema_error_dict
+                del errors
+
+    def set(self, object, value):
+        # Announce that we're going to assign the value to the object.
+        # Motivation: Widgets typically like to take care of policy-specific
+        # actions, like establishing location.
+        event = BeforeObjectAssignedEvent(value, self.__name__, object)
+        notify(event)
+        # The event subscribers are allowed to replace the object, thus we need
+        # to replace our previous value.
+        value = event.object
+        super(Object, self).set(object, value)
+
+
+@implementer(IBeforeObjectAssignedEvent)
+class BeforeObjectAssignedEvent(object):
+    """An object is going to be assigned to an attribute on another object."""
+
+    def __init__(self, object, name, context):
+        self.object = object
+        self.name = name
+        self.context = context
diff --git a/src/zope/schema/_bootstrapinterfaces.py b/src/zope/schema/_bootstrapinterfaces.py
index 40d85e2..eeb4f0e 100644
--- a/src/zope/schema/_bootstrapinterfaces.py
+++ b/src/zope/schema/_bootstrapinterfaces.py
@@ -16,6 +16,7 @@
 from functools import total_ordering
 
 import zope.interface
+from zope.interface import Attribute
 
 from zope.schema._messageid import _
 
@@ -108,6 +109,31 @@ class NotAnIterator(ValidationError):
     __doc__ = _("""Not an iterator""")
 
 
+
+class WrongContainedType(ValidationError):
+    __doc__ = _("""Wrong contained type""")
+
+
+class SchemaNotCorrectlyImplemented(WrongContainedType):
+    __doc__ = _("""An object failed schema or invariant validation.""")
+
+    #: A dictionary mapping failed attribute names of the
+    #: *value* to the underlying exception
+    schema_errors = None
+
+    #: A list of exceptions from validating the invariants
+    #: of the schema.
+    invariant_errors = ()
+
+
+class SchemaNotFullyImplemented(ValidationError):
+    __doc__ = _("""Schema not fully implemented""")
+
+
+class SchemaNotProvided(ValidationError):
+    __doc__ = _("""Schema not provided""")
+
+
 class IFromUnicode(zope.interface.Interface):
     """Parse a unicode string to a value
 
@@ -132,6 +158,36 @@ class IContextAwareDefaultFactory(zope.interface.Interface):
         """Returns a default value for the field."""
 
 
+class IBeforeObjectAssignedEvent(zope.interface.Interface):
+    """An object is going to be assigned to an attribute on another object.
+
+    Subscribers to this event can change the object on this event to change
+    what object is going to be assigned. This is useful, e.g. for wrapping
+    or replacing objects before they get assigned to conform to application
+    policy.
+    """
+
+    object = Attribute("The object that is going to be assigned.")
+
+    name = Attribute("The name of the attribute under which the object "
+                     "will be assigned.")
+
+    context = Attribute("The context object where the object will be "
+                        "assigned to.")
+
+
+class IValidatable(zope.interface.Interface):
+    # Internal interface, the base for IField, but used to prevent
+    # import recursion. This should *not* be implemented by anything
+    # other than IField.
+    def validate(value):
+        """Validate that the given value is a valid field value.
+
+        Returns nothing but raises an error if the value is invalid.
+        It checks everything specific to a Field and also checks
+        with the additional constraint.
+        """
+
 class NO_VALUE(object):
     def __repr__(self): # pragma: no cover
         return '<NO_VALUE>'
diff --git a/src/zope/schema/_field.py b/src/zope/schema/_field.py
index c9dcd4b..f659877 100644
--- a/src/zope/schema/_field.py
+++ b/src/zope/schema/_field.py
@@ -27,20 +27,16 @@ from datetime import timedelta
 from datetime import time
 import decimal
 import re
-import threading
 
-from zope.event import notify
+
 from zope.interface import classImplements
 from zope.interface import implementer
-from zope.interface import Interface
-from zope.interface import Invalid
 from zope.interface.interfaces import IInterface
-from zope.interface.interfaces import IMethod
+
 
 from zope.schema.interfaces import IASCII
 from zope.schema.interfaces import IASCIILine
 from zope.schema.interfaces import IBaseVocabulary
-from zope.schema.interfaces import IBeforeObjectAssignedEvent
 from zope.schema.interfaces import IBool
 from zope.schema.interfaces import IBytes
 from zope.schema.interfaces import IBytesLine
@@ -89,9 +85,6 @@ from zope.schema.interfaces import InvalidValue
 from zope.schema.interfaces import WrongType
 from zope.schema.interfaces import WrongContainedType
 from zope.schema.interfaces import NotUnique
-from zope.schema.interfaces import SchemaNotProvided
-from zope.schema.interfaces import SchemaNotCorrectlyImplemented
-from zope.schema.interfaces import SchemaNotFullyImplemented
 from zope.schema.interfaces import InvalidURI
 from zope.schema.interfaces import InvalidId
 from zope.schema.interfaces import InvalidDottedName
@@ -113,6 +106,7 @@ from zope.schema._bootstrapfields import Rational
 from zope.schema._bootstrapfields import Real
 from zope.schema._bootstrapfields import MinMaxLen
 from zope.schema._bootstrapfields import _NotGiven
+from zope.schema._bootstrapfields import Object
 from zope.schema.fieldproperty import FieldProperty
 from zope.schema.vocabulary import getVocabularyRegistry
 from zope.schema.vocabulary import SimpleVocabulary
@@ -150,6 +144,8 @@ classImplements(Rational, IRational)
 classImplements(Integral, IIntegral)
 classImplements(Int, IInt)
 
+classImplements(Object, IObject)
+
 
 
 @implementer(ISourceText)
@@ -646,13 +642,13 @@ class Collection(MinMaxLen, Iterable):
         if unique is not _NotGiven:
             self.unique = unique
 
-    def bind(self, object):
+    def bind(self, context):
         """See zope.schema._bootstrapinterfaces.IField."""
-        clone = super(Collection, self).bind(object)
+        clone = super(Collection, self).bind(context)
         # binding value_type is necessary for choices with named vocabularies,
         # and possibly also for other fields.
         if clone.value_type is not None:
-            clone.value_type = clone.value_type.bind(object)
+            clone.value_type = clone.value_type.bind(context)
         return clone
 
     def _validate(self, value):
@@ -728,141 +724,6 @@ class FrozenSet(_AbstractSet):
     _type = frozenset
 
 
-VALIDATED_VALUES = threading.local()
-
-
-def _validate_fields(schema, value):
-    errors = {}
-    # Interface can be used as schema property for Object fields that plan to
-    # hold values of any type.
-    # Because Interface does not include any Attribute, it is obviously not
-    # worth looping on its methods and filter them all out.
-    if schema is Interface:
-        return errors
-    # if `value` is part of a cyclic graph, we need to break the cycle to avoid
-    # infinite recursion. Collect validated objects in a thread local dict by
-    # it's python represenation. A previous version was setting a volatile
-    # attribute which didn't work with security proxy
-    if id(value) in VALIDATED_VALUES.__dict__:
-        return errors
-    VALIDATED_VALUES.__dict__[id(value)] = True
-    # (If we have gotten here, we know that `value` provides an interface
-    # other than zope.interface.Interface;
-    # iow, we can rely on the fact that it is an instance
-    # that supports attribute assignment.)
-    try:
-        for name in schema.names(all=True):
-            attribute = schema[name]
-            if IMethod.providedBy(attribute):
-                continue # pragma: no cover
-
-            try:
-                if IChoice.providedBy(attribute):
-                    # Choice must be bound before validation otherwise
-                    # IContextSourceBinder is not iterable in validation
-                    bound = attribute.bind(value)
-                    bound.validate(getattr(value, name))
-                elif IField.providedBy(attribute):
-                    # validate attributes that are fields
-                    attribute.validate(getattr(value, name))
-            except ValidationError as error:
-                errors[name] = error
-            except AttributeError as error:
-                # property for the given name is not implemented
-                errors[name] = SchemaNotFullyImplemented(error).with_field_and_value(attribute, None)
-    finally:
-        del VALIDATED_VALUES.__dict__[id(value)]
-    return errors
-
-
-@implementer(IObject)
-class Object(Field):
-    __doc__ = IObject.__doc__
-    schema = None
-
-    def __init__(self, schema=_NotGiven, **kw):
-        """
-        Object(schema=<Not Given>, *, validate_invariants=True, **kwargs)
-
-        Create an `~.IObject` field. The keyword arguments are as for `~.Field`.
-
-        .. versionchanged:: 4.6.0
-           Add the keyword argument *validate_invariants*. When true (the default),
-           the schema's ``validateInvariants`` method will be invoked to check
-           the ``@invariant`` properties of the schema.
-        .. versionchanged:: 4.6.0
-           The *schema* argument can be ommitted in a subclass
-           that specifies a ``schema`` attribute.
-        """
-        if schema is _NotGiven:
-            schema = self.schema
-
-        if not IInterface.providedBy(schema):
-            raise WrongType
-
-        self.schema = schema
-        self.validate_invariants = kw.pop('validate_invariants', True)
-        super(Object, self).__init__(**kw)
-
-    def _validate(self, value):
-        super(Object, self)._validate(value)
-
-        # schema has to be provided by value
-        if not self.schema.providedBy(value):
-            raise SchemaNotProvided(self.schema, value).with_field_and_value(self, value)
-
-        # check the value against schema
-        schema_error_dict = _validate_fields(self.schema, value)
-        invariant_errors = []
-        if self.validate_invariants:
-            try:
-                self.schema.validateInvariants(value, invariant_errors)
-            except Invalid:
-                # validateInvariants raises a wrapper error around
-                # all the errors it got if it got errors, in addition
-                # to appending them to the errors list. We don't want
-                # that, we raise our own error.
-                pass
-
-        if schema_error_dict or invariant_errors:
-            errors = list(schema_error_dict.values()) + invariant_errors
-            exception = SchemaNotCorrectlyImplemented(
-                errors,
-                self.__name__
-            ).with_field_and_value(self, value)
-            exception.schema_errors = schema_error_dict
-            exception.invariant_errors = invariant_errors
-            try:
-                raise exception
-            finally:
-                # Break cycles
-                del exception
-                del invariant_errors
-                del schema_error_dict
-                del errors
-
-    def set(self, object, value):
-        # Announce that we're going to assign the value to the object.
-        # Motivation: Widgets typically like to take care of policy-specific
-        # actions, like establishing location.
-        event = BeforeObjectAssignedEvent(value, self.__name__, object)
-        notify(event)
-        # The event subscribers are allowed to replace the object, thus we need
-        # to replace our previous value.
-        value = event.object
-        super(Object, self).set(object, value)
-
-
-@implementer(IBeforeObjectAssignedEvent)
-class BeforeObjectAssignedEvent(object):
-    """An object is going to be assigned to an attribute on another object."""
-
-    def __init__(self, object, name, context):
-        self.object = object
-        self.name = name
-        self.context = context
-
-
 @implementer(IMapping)
 class Mapping(MinMaxLen, Iterable):
     """
diff --git a/src/zope/schema/_schema.py b/src/zope/schema/_schema.py
index 50b3a49..b64b7b6 100644
--- a/src/zope/schema/_schema.py
+++ b/src/zope/schema/_schema.py
@@ -14,26 +14,24 @@
 """Schema convenience functions
 """
 
-import zope.interface.verify
+from zope.schema._bootstrapfields import get_validation_errors
+from zope.schema._bootstrapfields import get_schema_validation_errors
+from zope.schema._bootstrapfields import getFields
+
+__all__ = [
+    'getFieldNames',
+    'getFields',
+    'getFieldsInOrder',
+    'getFieldNamesInOrder',
+    'getValidationErrors',
+    'getSchemaValidationErrors',
+]
 
 
 def getFieldNames(schema):
     """Return a list of all the Field names in a schema.
     """
-    from zope.schema.interfaces import IField
-    return [name for name in schema if IField.providedBy(schema[name])]
-
-
-def getFields(schema):
-    """Return a dictionary containing all the Fields in a schema.
-    """
-    from zope.schema.interfaces import IField
-    fields = {}
-    for name in schema:
-        attr = schema[name]
-        if IField.providedBy(attr):
-            fields[name] = attr
-    return fields
+    return list(getFields(schema).keys())
 
 
 def getFieldsInOrder(schema, _field_key=lambda x: x[1].order):
@@ -48,44 +46,43 @@ def getFieldNamesInOrder(schema):
     return [name for name, field in getFieldsInOrder(schema)]
 
 
-def getValidationErrors(schema, object):
-    """Return a list of all validation errors.
+def getValidationErrors(schema, value):
+    """
+    Validate that *value* conforms to the schema interface *schema*.
+
+    This includes checking for any schema validation errors (using
+    `getSchemaValidationErrors`). If that succeeds, then we proceed to
+    check for any declared invariants.
+
+    Note that this does not include a check to see if the *value*
+    actually provides the given *schema*.
+
+    :return: A sequence of (name, `zope.interface.Invalid`) tuples,
+       where *name* is None if the error was from an invariant.
+       If the sequence is empty, there were no errors.
+    """
+    schema_error_dict, invariant_errors = get_validation_errors(
+        schema,
+        value,
+        )
+
+    if not schema_error_dict and not invariant_errors:
+        # Valid! Yay!
+        return []
+
+    return list(schema_error_dict.items()) + [(None, e) for e in invariant_errors]
+
+
+def getSchemaValidationErrors(schema, value):
+    """
+    Validate that *value* conforms to the schema interface *schema*.
+
+    All :class:`zope.schema.interfaces.IField` members of the *schema*
+    are validated after being bound to *value*. (Note that we do not check for
+    arbitrary :class:`zope.interface.Attribute` members being present.)
+
+    :return: A sequence of (name, `ValidationError`) tuples. A non-empty
+        sequence indicates validation failed.
     """
-    errors = getSchemaValidationErrors(schema, object)
-    if errors:
-        return errors
-
-    # Only validate invariants if there were no previous errors. Previous
-    # errors could be missing attributes which would most likely make an
-    # invariant raise an AttributeError.
-    invariant_errors = []
-    try:
-        schema.validateInvariants(object, invariant_errors)
-    except zope.interface.exceptions.Invalid:
-        # Just collect errors
-        pass
-    errors = [(None, e) for e in invariant_errors]
-    return errors
-
-
-def getSchemaValidationErrors(schema, object):
-    errors = []
-    for name in schema.names(all=True):
-        if zope.interface.interfaces.IMethod.providedBy(schema[name]):
-            continue
-        attribute = schema[name]
-        if not zope.schema.interfaces.IField.providedBy(attribute):
-            continue
-        try:
-            value = getattr(object, name)
-        except AttributeError as error:
-            # property for the given name is not implemented
-            error = zope.schema.interfaces.SchemaNotFullyImplemented(error)
-            error = error.with_field_and_value(attribute, None)
-            errors.append((name, error))
-        else:
-            try:
-                attribute.bind(object).validate(value)
-            except zope.schema.ValidationError as e:
-                errors.append((name, e))
-    return errors
+    items = get_schema_validation_errors(schema, value).items()
+    return items if isinstance(items, list) else list(items)
diff --git a/src/zope/schema/interfaces.py b/src/zope/schema/interfaces.py
index 88988c4..26ddf5a 100644
--- a/src/zope/schema/interfaces.py
+++ b/src/zope/schema/interfaces.py
@@ -15,76 +15,151 @@
 """
 __docformat__ = "reStructuredText"
 
-from zope.interface import Interface, Attribute
+from zope.interface import Attribute
+from zope.interface import Interface
 from zope.interface.common.mapping import IEnumerableMapping
+from zope.interface.interfaces import IInterface
 
 
-# Import from _bootstrapinterfaces only because other packages will expect
-# to find these interfaces here.
-from zope.schema._bootstrapfields import Field
-from zope.schema._bootstrapfields import Text
-from zope.schema._bootstrapfields import TextLine
 from zope.schema._bootstrapfields import Bool
-from zope.schema._bootstrapfields import Number
 from zope.schema._bootstrapfields import Complex
+from zope.schema._bootstrapfields import Field
+from zope.schema._bootstrapfields import Int
+from zope.schema._bootstrapfields import Integral
+from zope.schema._bootstrapfields import Number
+from zope.schema._bootstrapfields import Object
 from zope.schema._bootstrapfields import Rational
 from zope.schema._bootstrapfields import Real
-from zope.schema._bootstrapfields import Integral
-from zope.schema._bootstrapfields import Int
-from zope.schema._bootstrapinterfaces import StopValidation
-from zope.schema._bootstrapinterfaces import ValidationError
-from zope.schema._bootstrapinterfaces import IFromUnicode
-from zope.schema._bootstrapinterfaces import RequiredMissing
-from zope.schema._bootstrapinterfaces import WrongType
+from zope.schema._bootstrapfields import Text
+from zope.schema._bootstrapfields import TextLine
+
+# Import from _bootstrapinterfaces only because other packages will expect
+# to find these interfaces here.
 from zope.schema._bootstrapinterfaces import ConstraintNotSatisfied
+from zope.schema._bootstrapinterfaces import IBeforeObjectAssignedEvent
+from zope.schema._bootstrapinterfaces import IContextAwareDefaultFactory
+from zope.schema._bootstrapinterfaces import IFromUnicode
+from zope.schema._bootstrapinterfaces import IValidatable
+from zope.schema._bootstrapinterfaces import InvalidValue
 from zope.schema._bootstrapinterfaces import NotAContainer
 from zope.schema._bootstrapinterfaces import NotAnIterator
-from zope.schema._bootstrapinterfaces import TooSmall
+from zope.schema._bootstrapinterfaces import RequiredMissing
+from zope.schema._bootstrapinterfaces import SchemaNotCorrectlyImplemented
+from zope.schema._bootstrapinterfaces import SchemaNotFullyImplemented
+from zope.schema._bootstrapinterfaces import SchemaNotProvided
+from zope.schema._bootstrapinterfaces import StopValidation
 from zope.schema._bootstrapinterfaces import TooBig
 from zope.schema._bootstrapinterfaces import TooLong
 from zope.schema._bootstrapinterfaces import TooShort
-from zope.schema._bootstrapinterfaces import InvalidValue
-from zope.schema._bootstrapinterfaces import IContextAwareDefaultFactory
+from zope.schema._bootstrapinterfaces import TooSmall
+from zope.schema._bootstrapinterfaces import ValidationError
+from zope.schema._bootstrapinterfaces import WrongContainedType
+from zope.schema._bootstrapinterfaces import WrongType
 
 from zope.schema._compat import PY3
 
 from zope.schema._messageid import _
 
-
-# pep 8 friendlyness
-StopValidation, ValidationError, IFromUnicode, RequiredMissing, WrongType
-ConstraintNotSatisfied, NotAContainer, NotAnIterator
-TooSmall, TooBig, TooLong, TooShort, InvalidValue, IContextAwareDefaultFactory
-
-
-class WrongContainedType(ValidationError):
-    __doc__ = _("""Wrong contained type""")
-
-
-class SchemaNotCorrectlyImplemented(WrongContainedType):
-    __doc__ = _("""An object failed schema or invariant validation.""")
-
-    #: A dictionary mapping failed attribute names of the
-    #: *value* to the underlying exception
-    schema_errors = None
-
-    #: A list of exceptions from validating the invariants
-    #: of the schema.
-    invariant_errors = ()
+__all__ = [
+    # Exceptions
+    'ConstraintNotSatisfied',
+    'InvalidDottedName',
+    'InvalidId',
+    'InvalidURI',
+    'InvalidValue',
+    'NotAContainer',
+    'NotAnIterator',
+    'NotUnique',
+    'RequiredMissing',
+    'SchemaNotCorrectlyImplemented',
+    'SchemaNotFullyImplemented',
+    'SchemaNotProvided',
+    'StopValidation',
+    'TooBig',
+    'TooLong',
+    'TooShort',
+    'TooSmall',
+    'Unbound',
+    'ValidationError',
+    'WrongContainedType',
+    'WrongType',
+
+    # Interfaces
+    'IASCII',
+    'IASCIILine',
+    'IAbstractBag',
+    'IAbstractSet',
+    'IBaseVocabulary',
+    'IBeforeObjectAssignedEvent',
+    'IBool',
+    'IBytes',
+    'IBytesLine',
+    'IChoice',
+    'ICollection',
+    'IComplex',
+    'IContainer',
+    'IContextAwareDefaultFactory',
+    'IContextSourceBinder',
+    'IDate',
+    'IDatetime',
+    'IDecimal',
+    'IDict',
+    'IDottedName',
+    'IField',
+    'IFieldEvent',
+    'IFieldUpdatedEvent',
+    'IFloat',
+    'IFromUnicode',
+    'IFrozenSet',
+    'IId',
+    'IInt',
+    'IIntegral',
+    'IInterfaceField',
+    'IIterable',
+    'IIterableSource',
+    'IIterableVocabulary',
+    'ILen',
+    'IList',
+    'IMapping',
+    'IMinMax',
+    'IMinMaxLen',
+    'IMutableMapping',
+    'IMutableSequence',
+    'INativeString',
+    'INativeStringLine',
+    'INumber',
+    'IObject',
+    'IOrderable',
+    'IPassword',
+    'IRational',
+    'IReal',
+    'ISequence',
+    'ISet',
+    'ISource',
+    'ISourceQueriables',
+    'ISourceText',
+    'ITerm',
+    'IText',
+    'ITextLine',
+    'ITime',
+    'ITimedelta',
+    'ITitledTokenizedTerm',
+    'ITokenizedTerm',
+    'ITreeVocabulary',
+    'ITuple',
+    'IURI',
+    'IUnorderedCollection',
+    'IVocabulary',
+    'IVocabularyFactory',
+    'IVocabularyRegistry',
+    'IVocabularyTokenized',
+]
 
 
 class NotUnique(ValidationError):
     __doc__ = _("""One or more entries of sequence are not unique.""")
 
 
-class SchemaNotFullyImplemented(ValidationError):
-    __doc__ = _("""Schema not fully implemented""")
-
-
-class SchemaNotProvided(ValidationError):
-    __doc__ = _("""Schema not provided""")
-
-
 class InvalidURI(ValidationError):
     __doc__ = _("""The specified URI is not valid.""")
 
@@ -101,7 +176,7 @@ class Unbound(Exception):
     __doc__ = _("""The field is not bound.""")
 
 
-class IField(Interface):
+class IField(IValidatable):
     """Basic Schema Field Interface.
 
     Fields are used for Interface specifications.  They at least provide
@@ -639,14 +714,14 @@ class IChoice(IField):
 
 # Abstract
 
-
 class ICollection(IMinMaxLen, IIterable, IContainer):
     """Abstract interface containing a collection value.
 
     The Value must be iterable and may have a min_length/max_length.
     """
 
-    value_type = Field(
+    value_type = Object(
+        IField,
         title=_("Value Type"),
         description=_("Field value items must conform to the given type, "
                       "expressed via a Field."))
@@ -677,14 +752,14 @@ class IUnorderedCollection(ICollection):
 class IAbstractSet(IUnorderedCollection):
     """An unordered collection of unique values."""
 
-    unique = Attribute("This ICollection interface attribute must be True")
+    unique = Bool(description="This ICollection interface attribute must be True")
 
 
 class IAbstractBag(IUnorderedCollection):
     """An unordered collection of values, with no limitations on whether
     members are unique"""
 
-    unique = Attribute("This ICollection interface attribute must be False")
+    unique = Bool(description="This ICollection interface attribute must be False")
 
 
 # Concrete
@@ -720,34 +795,19 @@ class IObject(IField):
        Add the *validate_invariants* attribute.
     """
 
-    schema = Attribute(
-        "schema",
-        _("The Interface that defines the Fields comprising the Object.")
+    schema = Object(
+        IInterface,
+        description=_("The Interface that defines the Fields comprising the Object.")
     )
 
-    validate_invariants = Attribute(
-        "validate_invariants",
-        _("A boolean that says whether ``schema.validateInvariants`` "
-          "is called from ``self.validate()``. The default is true.")
+    validate_invariants = Bool(
+        title="validate_invariants",
+        description=_("A boolean that says whether ``schema.validateInvariants`` "
+                      "is called from ``self.validate()``. The default is true."),
+        default=True,
     )
 
 
-class IBeforeObjectAssignedEvent(Interface):
-    """An object is going to be assigned to an attribute on another object.
-
-    Subscribers to this event can change the object on this event to change
-    what object is going to be assigned. This is useful, e.g. for wrapping
-    or replacing objects before they get assigned to conform to application
-    policy.
-    """
-
-    object = Attribute("The object that is going to be assigned.")
-
-    name = Attribute("The name of the attribute under which the object "
-                     "will be assigned.")
-
-    context = Attribute("The context object where the object will be "
-                        "assigned to.")
 
 class IMapping(IMinMaxLen, IIterable, IContainer):
     """
@@ -757,15 +817,15 @@ class IMapping(IMinMaxLen, IIterable, IContainer):
     of restrictions for keys and values contained in the dict.
 
     """
-    key_type = Attribute(
-        "key_type",
-        _("Field keys must conform to the given type, expressed via a Field.")
+    key_type = Object(
+        IField,
+        description=_("Field keys must conform to the given type, expressed via a Field.")
     )
 
-    value_type = Attribute(
-        "value_type",
-        _("Field values must conform to the given type, expressed "
-          "via a Field.")
+    value_type = Object(
+        IField,
+        description=_("Field values must conform to the given type, expressed "
+                      "via a Field.")
     )
 
 
@@ -973,7 +1033,9 @@ class IVocabularyFactory(Interface):
 
 class IFieldEvent(Interface):
 
-    field = Attribute("The field that has been changed")
+    field = Object(
+        IField,
+        description="The field that has been changed")
 
     object = Attribute("The object containing the field")
 

`getSchemaValidationErrors` is freakily similar to `_validate_fields` used by `Object`
There are two differences:

- `_validate_fields` correctly handles cycles; `gSVE` does not.
- `_validate_fields` returns a dictionary (now); `gSVE` returns a list of tuples.

On first blush, it appears that `gSVE` binds the field to the top-level object being validated, while `_validate_fields` does not. This is true, prior to #53. With that PR, they are bound to the same object.

It seems like we could and should share this code.

In addition, `getValidationErrors` is very similar to the internals of `Object._validate`. There may be some code sharing we can do there as well.
diff --git a/src/zope/schema/tests/test__bootstrapfields.py b/src/zope/schema/tests/test__bootstrapfields.py
index 419378a..733d5c9 100644
--- a/src/zope/schema/tests/test__bootstrapfields.py
+++ b/src/zope/schema/tests/test__bootstrapfields.py
@@ -14,7 +14,7 @@
 import doctest
 import unittest
 
-# pylint:disable=protected-access
+# pylint:disable=protected-access,inherit-non-class,blacklisted-name
 
 class EqualityTestsMixin(object):
 
@@ -991,6 +991,496 @@ class IntTests(IntegralTests):
         self.assertEqual(txt._type, integer_types)
 
 
+class ObjectTests(EqualityTestsMixin,
+                  unittest.TestCase):
+
+    def setUp(self):
+        from zope.event import subscribers
+        self._before = subscribers[:]
+
+    def tearDown(self):
+        from zope.event import subscribers
+        subscribers[:] = self._before
+
+    def _getTargetClass(self):
+        from zope.schema._field import Object
+        return Object
+
+    def _getTargetInterface(self):
+        from zope.schema.interfaces import IObject
+        return IObject
+
+    def _makeOneFromClass(self, cls, schema=None, *args, **kw):
+        if schema is None:
+            schema = self._makeSchema()
+        return super(ObjectTests, self)._makeOneFromClass(cls, schema, *args, **kw)
+
+    def _makeSchema(self, **kw):
+        from zope.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        return InterfaceClass('ISchema', (Interface,), kw)
+
+    def _getErrors(self, f, *args, **kw):
+        from zope.schema.interfaces import WrongContainedType
+        with self.assertRaises(WrongContainedType) as e:
+            f(*args, **kw)
+        return e.exception.args[0]
+
+    def _makeCycles(self):
+        from zope.interface import Interface
+        from zope.interface import implementer
+        from zope.schema import Object
+        from zope.schema import List
+        from zope.schema._messageid import _
+
+        class IUnit(Interface):
+            """A schema that participate to a cycle"""
+            boss = Object(
+                schema=Interface,
+                title=_("Boss"),
+                description=_("Boss description"),
+                required=False,
+                )
+            members = List(
+                value_type=Object(schema=Interface),
+                title=_("Member List"),
+                description=_("Member list description"),
+                required=False,
+                )
+
+        class IPerson(Interface):
+            """A schema that participate to a cycle"""
+            unit = Object(
+                schema=IUnit,
+                title=_("Unit"),
+                description=_("Unit description"),
+                required=False,
+                )
+
+        IUnit['boss'].schema = IPerson
+        IUnit['members'].value_type.schema = IPerson
+
+        @implementer(IUnit)
+        class Unit(object):
+            def __init__(self, person, person_list):
+                self.boss = person
+                self.members = person_list
+
+        @implementer(IPerson)
+        class Person(object):
+            def __init__(self, unit):
+                self.unit = unit
+
+        return IUnit, Person, Unit
+
+    def test_class_conforms_to_IObject(self):
+        from zope.interface.verify import verifyClass
+        from zope.schema.interfaces import IObject
+        verifyClass(IObject, self._getTargetClass())
+
+    def test_instance_conforms_to_IObject(self):
+        from zope.interface.verify import verifyObject
+        from zope.schema.interfaces import IObject
+        verifyObject(IObject, self._makeOne())
+
+    def test_ctor_w_bad_schema(self):
+        from zope.schema.interfaces import WrongType
+        self.assertRaises(WrongType, self._makeOne, object())
+
+    def test_validate_not_required(self):
+        schema = self._makeSchema()
+        objf = self._makeOne(schema, required=False)
+        objf.validate(None)  # doesn't raise
+
+    def test_validate_required(self):
+        from zope.schema.interfaces import RequiredMissing
+        field = self._makeOne(required=True)
+        self.assertRaises(RequiredMissing, field.validate, None)
+
+    def test__validate_w_empty_schema(self):
+        from zope.interface import Interface
+        objf = self._makeOne(Interface)
+        objf.validate(object())  # doesn't raise
+
+    def test__validate_w_value_not_providing_schema(self):
+        from zope.schema.interfaces import SchemaNotProvided
+        from zope.schema._bootstrapfields import Text
+        schema = self._makeSchema(foo=Text(), bar=Text())
+        objf = self._makeOne(schema)
+        bad_value = object()
+        with self.assertRaises(SchemaNotProvided) as exc:
+            objf.validate(bad_value)
+
+        not_provided = exc.exception
+        self.assertIs(not_provided.field, objf)
+        self.assertIs(not_provided.value, bad_value)
+        self.assertEqual(not_provided.args, (schema, bad_value), )
+
+    def test__validate_w_value_providing_schema_but_missing_fields(self):
+        from zope.interface import implementer
+        from zope.schema.interfaces import SchemaNotFullyImplemented
+        from zope.schema.interfaces import SchemaNotCorrectlyImplemented
+        from zope.schema._bootstrapfields import Text
+        schema = self._makeSchema(foo=Text(), bar=Text())
+
+        @implementer(schema)
+        class Broken(object):
+            pass
+
+        objf = self._makeOne(schema)
+        broken = Broken()
+        with self.assertRaises(SchemaNotCorrectlyImplemented) as exc:
+            objf.validate(broken)
+
+        wct = exc.exception
+        self.assertIs(wct.field, objf)
+        self.assertIs(wct.value, broken)
+        self.assertEqual(wct.invariant_errors, [])
+        self.assertEqual(
+            sorted(wct.schema_errors),
+            ['bar', 'foo']
+        )
+        for name in ('foo', 'bar'):
+            error = wct.schema_errors[name]
+            self.assertIsInstance(error,
+                                  SchemaNotFullyImplemented)
+            self.assertEqual(schema[name], error.field)
+            self.assertIsNone(error.value)
+
+        # The legacy arg[0] errors list
+        errors = self._getErrors(objf.validate, Broken())
+        self.assertEqual(len(errors), 2)
+        errors = sorted(errors,
+                        key=lambda x: (type(x).__name__, str(x.args[0])))
+        err = errors[0]
+        self.assertIsInstance(err, SchemaNotFullyImplemented)
+        nested = err.args[0]
+        self.assertIsInstance(nested, AttributeError)
+        self.assertIn("'bar'", str(nested))
+        err = errors[1]
+        self.assertIsInstance(err, SchemaNotFullyImplemented)
+        nested = err.args[0]
+        self.assertIsInstance(nested, AttributeError)
+        self.assertIn("'foo'", str(nested))
+
+    def test__validate_w_value_providing_schema_but_invalid_fields(self):
+        from zope.interface import implementer
+        from zope.schema.interfaces import SchemaNotCorrectlyImplemented
+        from zope.schema.interfaces import RequiredMissing
+        from zope.schema.interfaces import WrongType
+        from zope.schema._bootstrapfields import Text
+        from zope.schema._compat import text_type
+        schema = self._makeSchema(foo=Text(), bar=Text())
+
+        @implementer(schema)
+        class Broken(object):
+            foo = None
+            bar = 1
+
+        objf = self._makeOne(schema)
+        broken = Broken()
+        with self.assertRaises(SchemaNotCorrectlyImplemented) as exc:
+            objf.validate(broken)
+
+        wct = exc.exception
+        self.assertIs(wct.field, objf)
+        self.assertIs(wct.value, broken)
+        self.assertEqual(wct.invariant_errors, [])
+        self.assertEqual(
+            sorted(wct.schema_errors),
+            ['bar', 'foo']
+        )
+        self.assertIsInstance(wct.schema_errors['foo'], RequiredMissing)
+        self.assertIsInstance(wct.schema_errors['bar'], WrongType)
+
+        # The legacy arg[0] errors list
+        errors = self._getErrors(objf.validate, Broken())
+        self.assertEqual(len(errors), 2)
+        errors = sorted(errors, key=lambda x: type(x).__name__)
+        err = errors[0]
+        self.assertIsInstance(err, RequiredMissing)
+        self.assertEqual(err.args, ('foo',))
+        err = errors[1]
+        self.assertIsInstance(err, WrongType)
+        self.assertEqual(err.args, (1, text_type, 'bar'))
+
+    def test__validate_w_value_providing_schema(self):
+        from zope.interface import implementer
+        from zope.schema._bootstrapfields import Text
+        from zope.schema._field import Choice
+
+        schema = self._makeSchema(
+            foo=Text(),
+            bar=Text(),
+            baz=Choice(values=[1, 2, 3]),
+        )
+
+        @implementer(schema)
+        class OK(object):
+            foo = u'Foo'
+            bar = u'Bar'
+            baz = 2
+        objf = self._makeOne(schema)
+        objf.validate(OK())  # doesn't raise
+
+    def test_validate_w_cycles(self):
+        IUnit, Person, Unit = self._makeCycles()
+        field = self._makeOne(schema=IUnit)
+        person1 = Person(None)
+        person2 = Person(None)
+        unit = Unit(person1, [person1, person2])
+        person1.unit = unit
+        person2.unit = unit
+        field.validate(unit)  # doesn't raise
+
+    def test_validate_w_cycles_object_not_valid(self):
+        from zope.schema.interfaces import WrongContainedType
+        IUnit, Person, Unit = self._makeCycles()
+        field = self._makeOne(schema=IUnit)
+        person1 = Person(None)
+        person2 = Person(None)
+        person3 = Person(object())
+        unit = Unit(person3, [person1, person2])
+        person1.unit = unit
+        person2.unit = unit
+        self.assertRaises(WrongContainedType, field.validate, unit)
+
+    def test_validate_w_cycles_collection_not_valid(self):
+        from zope.schema.interfaces import WrongContainedType
+        IUnit, Person, Unit = self._makeCycles()
+        field = self._makeOne(schema=IUnit)
+        person1 = Person(None)
+        person2 = Person(None)
+        person3 = Person(object())
+        unit = Unit(person1, [person2, person3])
+        person1.unit = unit
+        person2.unit = unit
+        self.assertRaises(WrongContainedType, field.validate, unit)
+
+    def test_set_emits_IBOAE(self):
+        from zope.event import subscribers
+        from zope.interface import implementer
+        from zope.schema.interfaces import IBeforeObjectAssignedEvent
+        from zope.schema._bootstrapfields import Text
+        from zope.schema._field import Choice
+
+        schema = self._makeSchema(
+            foo=Text(),
+            bar=Text(),
+            baz=Choice(values=[1, 2, 3]),
+        )
+
+        @implementer(schema)
+        class OK(object):
+            foo = u'Foo'
+            bar = u'Bar'
+            baz = 2
+        log = []
+        subscribers.append(log.append)
+        objf = self._makeOne(schema, __name__='field')
+        inst = DummyInst()
+        value = OK()
+        objf.set(inst, value)
+        self.assertIs(inst.field, value)
+        self.assertEqual(len(log), 5)
+        self.assertEqual(IBeforeObjectAssignedEvent.providedBy(log[-1]), True)
+        self.assertEqual(log[-1].object, value)
+        self.assertEqual(log[-1].name, 'field')
+        self.assertEqual(log[-1].context, inst)
+
+    def test_set_allows_IBOAE_subscr_to_replace_value(self):
+        from zope.event import subscribers
+        from zope.interface import implementer
+        from zope.schema._bootstrapfields import Text
+        from zope.schema._field import Choice
+
+        schema = self._makeSchema(
+            foo=Text(),
+            bar=Text(),
+            baz=Choice(values=[1, 2, 3]),
+        )
+
+        @implementer(schema)
+        class OK(object):
+            def __init__(self, foo=u'Foo', bar=u'Bar', baz=2):
+                self.foo = foo
+                self.bar = bar
+                self.baz = baz
+        ok1 = OK()
+        ok2 = OK(u'Foo2', u'Bar2', 3)
+        log = []
+        subscribers.append(log.append)
+
+        def _replace(event):
+            event.object = ok2
+        subscribers.append(_replace)
+        objf = self._makeOne(schema, __name__='field')
+        inst = DummyInst()
+        self.assertEqual(len(log), 4)
+        objf.set(inst, ok1)
+        self.assertIs(inst.field, ok2)
+        self.assertEqual(len(log), 5)
+        self.assertEqual(log[-1].object, ok2)
+        self.assertEqual(log[-1].name, 'field')
+        self.assertEqual(log[-1].context, inst)
+
+    def test_validates_invariants_by_default(self):
+        from zope.interface import invariant
+        from zope.interface import Interface
+        from zope.interface import implementer
+        from zope.interface import Invalid
+        from zope.schema import Text
+        from zope.schema import Bytes
+
+        class ISchema(Interface):
+
+            foo = Text()
+            bar = Bytes()
+
+            @invariant
+            def check_foo(self):
+                if self.foo == u'bar':
+                    raise Invalid("Foo is not valid")
+
+            @invariant
+            def check_bar(self):
+                if self.bar == b'foo':
+                    raise Invalid("Bar is not valid")
+
+        @implementer(ISchema)
+        class O(object):
+            foo = u''
+            bar = b''
+
+
+        field = self._makeOne(ISchema)
+        inst = O()
+
+        # Fine at first
+        field.validate(inst)
+
+        inst.foo = u'bar'
+        errors = self._getErrors(field.validate, inst)
+        self.assertEqual(len(errors), 1)
+        self.assertEqual(errors[0].args[0], "Foo is not valid")
+
+        del inst.foo
+        inst.bar = b'foo'
+        errors = self._getErrors(field.validate, inst)
+        self.assertEqual(len(errors), 1)
+        self.assertEqual(errors[0].args[0], "Bar is not valid")
+
+        # Both invalid
+        inst.foo = u'bar'
+        errors = self._getErrors(field.validate, inst)
+        self.assertEqual(len(errors), 2)
+        errors.sort(key=lambda i: i.args)
+        self.assertEqual(errors[0].args[0], "Bar is not valid")
+        self.assertEqual(errors[1].args[0], "Foo is not valid")
+
+        # We can specifically ask for invariants to be turned off.
+        field = self._makeOne(ISchema, validate_invariants=False)
+        field.validate(inst)
+
+    def test_schema_defined_by_subclass(self):
+        from zope import interface
+        from zope.schema.interfaces import SchemaNotProvided
+
+        class IValueType(interface.Interface):
+            "The value type schema"
+
+        class Field(self._getTargetClass()):
+            schema = IValueType
+
+        field = Field()
+        self.assertIs(field.schema, IValueType)
+
+        # Non implementation is bad
+        self.assertRaises(SchemaNotProvided, field.validate, object())
+
+        # Actual implementation works
+        @interface.implementer(IValueType)
+        class ValueType(object):
+            "The value type"
+
+
+        field.validate(ValueType())
+
+    def test_bound_field_of_collection_with_choice(self):
+        # https://github.com/zopefoundation/zope.schema/issues/17
+        from zope.interface import Interface, implementer
+        from zope.interface import Attribute
+
+        from zope.schema import Choice, Object, Set
+        from zope.schema.fieldproperty import FieldProperty
+        from zope.schema.interfaces import IContextSourceBinder
+        from zope.schema.interfaces import WrongContainedType
+        from zope.schema.interfaces import SchemaNotCorrectlyImplemented
+        from zope.schema.vocabulary import SimpleVocabulary
+
+
+        @implementer(IContextSourceBinder)
+        class EnumContext(object):
+            def __call__(self, context):
+                return SimpleVocabulary.fromValues(list(context))
+
+        class IMultipleChoice(Interface):
+            choices = Set(value_type=Choice(source=EnumContext()))
+            # Provide a regular attribute to prove that binding doesn't
+            # choke. NOTE: We don't actually verify the existence of this attribute.
+            non_field = Attribute("An attribute")
+
+        @implementer(IMultipleChoice)
+        class Choices(object):
+
+            def __init__(self, choices):
+                self.choices = choices
+
+            def __iter__(self):
+                # EnumContext calls this to make the vocabulary.
+                # Fields of the schema of the IObject are bound to the value being
+                # validated.
+                return iter(range(5))
+
+        class IFavorites(Interface):
+            fav = Object(title=u"Favorites number", schema=IMultipleChoice)
+
+
+        @implementer(IFavorites)
+        class Favorites(object):
+            fav = FieldProperty(IFavorites['fav'])
+
+        # must not raise
+        good_choices = Choices({1, 3})
+        IFavorites['fav'].validate(good_choices)
+
+        # Ranges outside the context fail
+        bad_choices = Choices({1, 8})
+        with self.assertRaises(WrongContainedType) as exc:
+            IFavorites['fav'].validate(bad_choices)
+
+        e = exc.exception
+        self.assertEqual(IFavorites['fav'], e.field)
+        self.assertEqual(bad_choices, e.value)
+
+        # Validation through field property
+        favorites = Favorites()
+        favorites.fav = good_choices
+
+        # And validation through a field that wants IFavorites
+        favorites_field = Object(IFavorites)
+        favorites_field.validate(favorites)
+
+        # Check the field property error
+        with self.assertRaises(SchemaNotCorrectlyImplemented) as exc:
+            favorites.fav = bad_choices
+
+        e = exc.exception
+        self.assertEqual(IFavorites['fav'], e.field)
+        self.assertEqual(bad_choices, e.value)
+        self.assertEqual(['choices'], list(e.schema_errors))
+
+
 class DummyInst(object):
     missing_value = object()
 
diff --git a/src/zope/schema/tests/test__field.py b/src/zope/schema/tests/test__field.py
index e959688..c176326 100644
--- a/src/zope/schema/tests/test__field.py
+++ b/src/zope/schema/tests/test__field.py
@@ -796,9 +796,9 @@ class ChoiceTests(EqualityTestsMixin,
                 pass
 
         source = self._makeOne(vocabulary=Vocab())
-        instance = DummyInstance()
+        instance = object()
         target = source.bind(instance)
-        self.assertTrue(target.vocabulary is source.vocabulary)
+        self.assertIs(target.vocabulary, source.vocabulary)
 
     def test_bind_w_voc_is_ICSB(self):
         from zope.interface import implementer
@@ -818,9 +818,9 @@ class ChoiceTests(EqualityTestsMixin,
         source = self._makeOne(vocabulary='temp')
         source.vocabulary = Vocab(source)
         source.vocabularyName = None
-        instance = DummyInstance()
+        instance = object()
         target = source.bind(instance)
-        self.assertEqual(target.vocabulary.context, instance)
+        self.assertIs(target.vocabulary.context, instance)
 
     def test_bind_w_voc_is_ICSB_but_not_ISource(self):
         from zope.interface import implementer
@@ -838,7 +838,7 @@ class ChoiceTests(EqualityTestsMixin,
         source = self._makeOne(vocabulary='temp')
         source.vocabulary = Vocab(source)
         source.vocabularyName = None
-        instance = DummyInstance()
+        instance = object()
         self.assertRaises(ValueError, source.bind, instance)
 
     def test_fromUnicode_miss(self):
@@ -1630,422 +1630,6 @@ class FrozenSetTests(SetTests):
         return IFrozenSet
 
 
-class ObjectTests(EqualityTestsMixin,
-                  unittest.TestCase):
-
-    def setUp(self):
-        from zope.event import subscribers
-        self._before = subscribers[:]
-
-    def tearDown(self):
-        from zope.event import subscribers
-        subscribers[:] = self._before
-
-    def _getTargetClass(self):
-        from zope.schema._field import Object
-        return Object
-
-    def _getTargetInterface(self):
-        from zope.schema.interfaces import IObject
-        return IObject
-
-    def _makeOneFromClass(self, cls, schema=None, *args, **kw):
-        if schema is None:
-            schema = self._makeSchema()
-        return super(ObjectTests, self)._makeOneFromClass(cls, schema, *args, **kw)
-
-    def _makeSchema(self, **kw):
-        from zope.interface import Interface
-        from zope.interface.interface import InterfaceClass
-        return InterfaceClass('ISchema', (Interface,), kw)
-
-    def _getErrors(self, f, *args, **kw):
-        from zope.schema.interfaces import WrongContainedType
-        with self.assertRaises(WrongContainedType) as e:
-            f(*args, **kw)
-        return e.exception.args[0]
-
-    def _makeCycles(self):
-        from zope.interface import Interface
-        from zope.interface import implementer
-        from zope.schema import Object
-        from zope.schema import List
-        from zope.schema._messageid import _
-
-        class IUnit(Interface):
-            """A schema that participate to a cycle"""
-            boss = Object(
-                schema=Interface,
-                title=_("Boss"),
-                description=_("Boss description"),
-                required=False,
-                )
-            members = List(
-                value_type=Object(schema=Interface),
-                title=_("Member List"),
-                description=_("Member list description"),
-                required=False,
-                )
-
-        class IPerson(Interface):
-            """A schema that participate to a cycle"""
-            unit = Object(
-                schema=IUnit,
-                title=_("Unit"),
-                description=_("Unit description"),
-                required=False,
-                )
-
-        IUnit['boss'].schema = IPerson
-        IUnit['members'].value_type.schema = IPerson
-
-        @implementer(IUnit)
-        class Unit(object):
-            def __init__(self, person, person_list):
-                self.boss = person
-                self.members = person_list
-
-        @implementer(IPerson)
-        class Person(object):
-            def __init__(self, unit):
-                self.unit = unit
-
-        return IUnit, Person, Unit
-
-    def test_class_conforms_to_IObject(self):
-        from zope.interface.verify import verifyClass
-        from zope.schema.interfaces import IObject
-        verifyClass(IObject, self._getTargetClass())
-
-    def test_instance_conforms_to_IObject(self):
-        from zope.interface.verify import verifyObject
-        from zope.schema.interfaces import IObject
-        verifyObject(IObject, self._makeOne())
-
-    def test_ctor_w_bad_schema(self):
-        from zope.schema.interfaces import WrongType
-        self.assertRaises(WrongType, self._makeOne, object())
-
-    def test_validate_not_required(self):
-        schema = self._makeSchema()
-        objf = self._makeOne(schema, required=False)
-        objf.validate(None)  # doesn't raise
-
-    def test_validate_required(self):
-        from zope.schema.interfaces import RequiredMissing
-        field = self._makeOne(required=True)
-        self.assertRaises(RequiredMissing, field.validate, None)
-
-    def test__validate_w_empty_schema(self):
-        from zope.interface import Interface
-        objf = self._makeOne(Interface)
-        objf.validate(object())  # doesn't raise
-
-    def test__validate_w_value_not_providing_schema(self):
-        from zope.schema.interfaces import SchemaNotProvided
-        from zope.schema._bootstrapfields import Text
-        schema = self._makeSchema(foo=Text(), bar=Text())
-        objf = self._makeOne(schema)
-        bad_value = object()
-        with self.assertRaises(SchemaNotProvided) as exc:
-            objf.validate(bad_value)
-
-        not_provided = exc.exception
-        self.assertIs(not_provided.field, objf)
-        self.assertIs(not_provided.value, bad_value)
-        self.assertEqual(not_provided.args, (schema, bad_value), )
-
-    def test__validate_w_value_providing_schema_but_missing_fields(self):
-        from zope.interface import implementer
-        from zope.schema.interfaces import SchemaNotFullyImplemented
-        from zope.schema.interfaces import SchemaNotCorrectlyImplemented
-        from zope.schema._bootstrapfields import Text
-        schema = self._makeSchema(foo=Text(), bar=Text())
-
-        @implementer(schema)
-        class Broken(object):
-            pass
-
-        objf = self._makeOne(schema)
-        broken = Broken()
-        with self.assertRaises(SchemaNotCorrectlyImplemented) as exc:
-            objf.validate(broken)
-
-        wct = exc.exception
-        self.assertIs(wct.field, objf)
-        self.assertIs(wct.value, broken)
-        self.assertEqual(wct.invariant_errors, [])
-        self.assertEqual(
-            sorted(wct.schema_errors),
-            ['bar', 'foo']
-        )
-        for name in ('foo', 'bar'):
-            error = wct.schema_errors[name]
-            self.assertIsInstance(error,
-                                  SchemaNotFullyImplemented)
-            self.assertEqual(schema[name], error.field)
-            self.assertIsNone(error.value)
-
-        # The legacy arg[0] errors list
-        errors = self._getErrors(objf.validate, Broken())
-        self.assertEqual(len(errors), 2)
-        errors = sorted(errors,
-                        key=lambda x: (type(x).__name__, str(x.args[0])))
-        err = errors[0]
-        self.assertIsInstance(err, SchemaNotFullyImplemented)
-        nested = err.args[0]
-        self.assertIsInstance(nested, AttributeError)
-        self.assertIn("'bar'", str(nested))
-        err = errors[1]
-        self.assertIsInstance(err, SchemaNotFullyImplemented)
-        nested = err.args[0]
-        self.assertIsInstance(nested, AttributeError)
-        self.assertIn("'foo'", str(nested))
-
-    def test__validate_w_value_providing_schema_but_invalid_fields(self):
-        from zope.interface import implementer
-        from zope.schema.interfaces import SchemaNotCorrectlyImplemented
-        from zope.schema.interfaces import RequiredMissing
-        from zope.schema.interfaces import WrongType
-        from zope.schema._bootstrapfields import Text
-        from zope.schema._compat import text_type
-        schema = self._makeSchema(foo=Text(), bar=Text())
-
-        @implementer(schema)
-        class Broken(object):
-            foo = None
-            bar = 1
-
-        objf = self._makeOne(schema)
-        broken = Broken()
-        with self.assertRaises(SchemaNotCorrectlyImplemented) as exc:
-            objf.validate(broken)
-
-        wct = exc.exception
-        self.assertIs(wct.field, objf)
-        self.assertIs(wct.value, broken)
-        self.assertEqual(wct.invariant_errors, [])
-        self.assertEqual(
-            sorted(wct.schema_errors),
-            ['bar', 'foo']
-        )
-        self.assertIsInstance(wct.schema_errors['foo'], RequiredMissing)
-        self.assertIsInstance(wct.schema_errors['bar'], WrongType)
-
-        # The legacy arg[0] errors list
-        errors = self._getErrors(objf.validate, Broken())
-        self.assertEqual(len(errors), 2)
-        errors = sorted(errors, key=lambda x: type(x).__name__)
-        err = errors[0]
-        self.assertIsInstance(err, RequiredMissing)
-        self.assertEqual(err.args, ('foo',))
-        err = errors[1]
-        self.assertIsInstance(err, WrongType)
-        self.assertEqual(err.args, (1, text_type, 'bar'))
-
-    def test__validate_w_value_providing_schema(self):
-        from zope.interface import implementer
-        from zope.schema._bootstrapfields import Text
-        from zope.schema._field import Choice
-
-        schema = self._makeSchema(
-            foo=Text(),
-            bar=Text(),
-            baz=Choice(values=[1, 2, 3]),
-        )
-
-        @implementer(schema)
-        class OK(object):
-            foo = u'Foo'
-            bar = u'Bar'
-            baz = 2
-        objf = self._makeOne(schema)
-        objf.validate(OK())  # doesn't raise
-
-    def test_validate_w_cycles(self):
-        IUnit, Person, Unit = self._makeCycles()
-        field = self._makeOne(schema=IUnit)
-        person1 = Person(None)
-        person2 = Person(None)
-        unit = Unit(person1, [person1, person2])
-        person1.unit = unit
-        person2.unit = unit
-        field.validate(unit)  # doesn't raise
-
-    def test_validate_w_cycles_object_not_valid(self):
-        from zope.schema.interfaces import WrongContainedType
-        IUnit, Person, Unit = self._makeCycles()
-        field = self._makeOne(schema=IUnit)
-        person1 = Person(None)
-        person2 = Person(None)
-        person3 = Person(DummyInstance())
-        unit = Unit(person3, [person1, person2])
-        person1.unit = unit
-        person2.unit = unit
-        self.assertRaises(WrongContainedType, field.validate, unit)
-
-    def test_validate_w_cycles_collection_not_valid(self):
-        from zope.schema.interfaces import WrongContainedType
-        IUnit, Person, Unit = self._makeCycles()
-        field = self._makeOne(schema=IUnit)
-        person1 = Person(None)
-        person2 = Person(None)
-        person3 = Person(DummyInstance())
-        unit = Unit(person1, [person2, person3])
-        person1.unit = unit
-        person2.unit = unit
-        self.assertRaises(WrongContainedType, field.validate, unit)
-
-    def test_set_emits_IBOAE(self):
-        from zope.event import subscribers
-        from zope.interface import implementer
-        from zope.schema.interfaces import IBeforeObjectAssignedEvent
-        from zope.schema._bootstrapfields import Text
-        from zope.schema._field import Choice
-
-        schema = self._makeSchema(
-            foo=Text(),
-            bar=Text(),
-            baz=Choice(values=[1, 2, 3]),
-        )
-
-        @implementer(schema)
-        class OK(object):
-            foo = u'Foo'
-            bar = u'Bar'
-            baz = 2
-        log = []
-        subscribers.append(log.append)
-        objf = self._makeOne(schema, __name__='field')
-        inst = DummyInstance()
-        value = OK()
-        objf.set(inst, value)
-        self.assertEqual(inst.field is value, True)
-        self.assertEqual(len(log), 5)
-        self.assertEqual(IBeforeObjectAssignedEvent.providedBy(log[-1]), True)
-        self.assertEqual(log[-1].object, value)
-        self.assertEqual(log[-1].name, 'field')
-        self.assertEqual(log[-1].context, inst)
-
-    def test_set_allows_IBOAE_subscr_to_replace_value(self):
-        from zope.event import subscribers
-        from zope.interface import implementer
-        from zope.schema._bootstrapfields import Text
-        from zope.schema._field import Choice
-
-        schema = self._makeSchema(
-            foo=Text(),
-            bar=Text(),
-            baz=Choice(values=[1, 2, 3]),
-        )
-
-        @implementer(schema)
-        class OK(object):
-            def __init__(self, foo=u'Foo', bar=u'Bar', baz=2):
-                self.foo = foo
-                self.bar = bar
-                self.baz = baz
-        ok1 = OK()
-        ok2 = OK(u'Foo2', u'Bar2', 3)
-        log = []
-        subscribers.append(log.append)
-
-        def _replace(event):
-            event.object = ok2
-        subscribers.append(_replace)
-        objf = self._makeOne(schema, __name__='field')
-        inst = DummyInstance()
-        self.assertEqual(len(log), 4)
-        objf.set(inst, ok1)
-        self.assertEqual(inst.field is ok2, True)
-        self.assertEqual(len(log), 5)
-        self.assertEqual(log[-1].object, ok2)
-        self.assertEqual(log[-1].name, 'field')
-        self.assertEqual(log[-1].context, inst)
-
-    def test_validates_invariants_by_default(self):
-        from zope.interface import invariant
-        from zope.interface import Interface
-        from zope.interface import implementer
-        from zope.interface import Invalid
-        from zope.schema import Text
-        from zope.schema import Bytes
-
-        class ISchema(Interface):
-
-            foo = Text()
-            bar = Bytes()
-
-            @invariant
-            def check_foo(self):
-                if self.foo == u'bar':
-                    raise Invalid("Foo is not valid")
-
-            @invariant
-            def check_bar(self):
-                if self.bar == b'foo':
-                    raise Invalid("Bar is not valid")
-
-        @implementer(ISchema)
-        class O(object):
-            foo = u''
-            bar = b''
-
-
-        field = self._makeOne(ISchema)
-        inst = O()
-
-        # Fine at first
-        field.validate(inst)
-
-        inst.foo = u'bar'
-        errors = self._getErrors(field.validate, inst)
-        self.assertEqual(len(errors), 1)
-        self.assertEqual(errors[0].args[0], "Foo is not valid")
-
-        del inst.foo
-        inst.bar = b'foo'
-        errors = self._getErrors(field.validate, inst)
-        self.assertEqual(len(errors), 1)
-        self.assertEqual(errors[0].args[0], "Bar is not valid")
-
-        # Both invalid
-        inst.foo = u'bar'
-        errors = self._getErrors(field.validate, inst)
-        self.assertEqual(len(errors), 2)
-        errors.sort(key=lambda i: i.args)
-        self.assertEqual(errors[0].args[0], "Bar is not valid")
-        self.assertEqual(errors[1].args[0], "Foo is not valid")
-
-        # We can specifically ask for invariants to be turned off.
-        field = self._makeOne(ISchema, validate_invariants=False)
-        field.validate(inst)
-
-    def test_schema_defined_by_subclass(self):
-        from zope import interface
-        from zope.schema.interfaces import SchemaNotProvided
-
-        class IValueType(interface.Interface):
-            "The value type schema"
-
-        class Field(self._getTargetClass()):
-            schema = IValueType
-
-        field = Field()
-        self.assertIs(field.schema, IValueType)
-
-        # Non implementation is bad
-        self.assertRaises(SchemaNotProvided, field.validate, object())
-
-        # Actual implementation works
-        @interface.implementer(IValueType)
-        class ValueType(object):
-            "The value type"
-
-
-        field.validate(ValueType())
-
-
 class MappingTests(EqualityTestsMixin,
                    unittest.TestCase):
 
@@ -2147,7 +1731,7 @@ class MappingTests(EqualityTestsMixin,
     def test_bind_binds_key_and_value_types(self):
         from zope.schema import Int
         field = self._makeOne(key_type=Int(), value_type=Int())
-        context = DummyInstance()
+        context = object()
         field2 = field.bind(context)
         self.assertEqual(field2.key_type.context, context)
         self.assertEqual(field2.value_type.context, context)
@@ -2221,10 +1805,6 @@ class DictTests(MutableMappingTests):
             super(DictTests, self).test_mutable_mapping()
 
 
-class DummyInstance(object):
-    pass
-
-
 def _makeSampleVocabulary():
     from zope.interface import implementer
     from zope.schema.interfaces import IVocabulary

pip install -e .[test]
parse_log_pytest
pytest
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pytest==7.1.2
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work
zope.event==5.0
zope.exceptions==5.1
zope.interface==6.4.post2
-e git+https://github.com/zopefoundation/zope.schema.git@a409cbf2f88a19f9d4fc1bb0b8510634044bcc8c#egg=zope.schema
zope.testing==5.0.1
zope.testrunner==6.5

name: zope.schema
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - zope-event==5.0
      - zope-exceptions==5.1
      - zope-interface==6.4.post2
      - zope-testing==5.0.1
      - zope-testrunner==6.5
prefix: /opt/conda/envs/zope.schema

src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_bound_field_of_collection_with_choice
src/zope/schema/tests/test__bootstrapfields.py::test_suite
src/zope/schema/tests/test__bootstrapfields.py::ValidatedPropertyTests::test___get__ src/zope/schema/tests/test__bootstrapfields.py::ValidatedPropertyTests::test___set___not_missing_w_check src/zope/schema/tests/test__bootstrapfields.py::ValidatedPropertyTests::test___set___not_missing_wo_check src/zope/schema/tests/test__bootstrapfields.py::ValidatedPropertyTests::test___set___w_missing_wo_check src/zope/schema/tests/test__bootstrapfields.py::DefaultPropertyTests::test___get___w_defaultFactory_not_ICAF_no_check src/zope/schema/tests/test__bootstrapfields.py::DefaultPropertyTests::test___get___w_defaultFactory_w_ICAF_w_check src/zope/schema/tests/test__bootstrapfields.py::DefaultPropertyTests::test___get___wo_defaultFactory_hit src/zope/schema/tests/test__bootstrapfields.py::DefaultPropertyTests::test___get___wo_defaultFactory_miss src/zope/schema/tests/test__bootstrapfields.py::DefaultPropertyTests::test__get___wo_defaultFactory_in_dict src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_bind src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_ctor_order_madness src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_ctor_w_both_title_and_description src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_ctor_w_title_wo_description src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_ctor_wo_title_w_description src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_explicit_constraint_default src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_explicit_defaultFactory src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_explicit_defaultFactory_returning_missing_value src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_explicit_required_readonly_missingValue src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_get_hit src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_get_miss src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_query_hit src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_query_miss_no_default src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_query_miss_w_default src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_set_hit src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_set_readonly src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_validate_constraint_fails src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_validate_constraint_raises_StopValidation src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_validate_missing_and_required src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_validate_missing_not_required src/zope/schema/tests/test__bootstrapfields.py::FieldTests::test_validate_wrong_type src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test__validate_collection_but_not_iterable src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test__validate_not_collection_but_iterable src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test__validate_not_collection_not_iterable src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test__validate_w_collections src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::ContainerTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test__validate_collection_but_not_iterable src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test__validate_not_collection_but_iterable src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test__validate_not_collection_not_iterable src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test__validate_w_collections src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::IterableTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::OrderableTests::test_ctor_default_too_large src/zope/schema/tests/test__bootstrapfields.py::OrderableTests::test_ctor_default_too_small src/zope/schema/tests/test__bootstrapfields.py::OrderableTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::MinMaxLenTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::MinMaxLenTests::test_validate_too_long src/zope/schema/tests/test__bootstrapfields.py::MinMaxLenTests::test_validate_too_short src/zope/schema/tests/test__bootstrapfields.py::TextTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::TextTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::TextTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_fromUnicode_hit src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_fromUnicode_miss src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_validate_w_invalid_default src/zope/schema/tests/test__bootstrapfields.py::TextTests::test_validate_wrong_types src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_constraint src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::TextLineTests::test_validate_wrong_types src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_constraint src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_set_normal src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_set_unchanged src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_validate_unchanged_already_set src/zope/schema/tests/test__bootstrapfields.py::PasswordTests::test_validate_unchanged_not_already_set src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test__validate_w_int src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_fromUnicode_hit src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_fromUnicode_miss src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::BoolTests::test_set_w_int src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::NumberTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::ComplexTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::RealTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::RealTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::RealTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_ctor_real_min_max src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::RealTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::RationalTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_fromUnicode_hit src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_fromUnicode_miss src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_validate_max src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_validate_min src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_validate_min_and_max src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::IntegralTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::IntTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::IntTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::IntTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_ctor_defaults src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_fromUnicode_hit src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_fromUnicode_miss src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_validate_max src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_validate_min src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_validate_min_and_max src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::IntTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test___eq___different_type src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test__validate_w_empty_schema src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test__validate_w_value_not_providing_schema src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test__validate_w_value_providing_schema src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test__validate_w_value_providing_schema_but_invalid_fields src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test__validate_w_value_providing_schema_but_missing_fields src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_class_conforms_to_IObject src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_class_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_ctor_w_bad_schema src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_hash_across_unequal_instances src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_instance_conforms_to_IObject src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_instance_conforms_to_iface src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_is_hashable src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_schema_defined_by_subclass src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_set_allows_IBOAE_subscr_to_replace_value src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_set_emits_IBOAE src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validate_not_required src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validate_required src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validate_w_cycles src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validate_w_cycles_collection_not_valid src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validate_w_cycles_object_not_valid src/zope/schema/tests/test__bootstrapfields.py::ObjectTests::test_validates_invariants_by_default src/zope/schema/tests/test__field.py::BytesTests::test___eq___different_type src/zope/schema/tests/test__field.py::BytesTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::BytesTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::BytesTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::BytesTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::BytesTests::test_fromUnicode_hit src/zope/schema/tests/test__field.py::BytesTests::test_fromUnicode_miss src/zope/schema/tests/test__field.py::BytesTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::BytesTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::BytesTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::BytesTests::test_is_hashable src/zope/schema/tests/test__field.py::BytesTests::test_validate_not_required src/zope/schema/tests/test__field.py::BytesTests::test_validate_required src/zope/schema/tests/test__field.py::BytesTests::test_validate_w_invalid_default src/zope/schema/tests/test__field.py::BytesTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::ASCIITests::test___eq___different_type src/zope/schema/tests/test__field.py::ASCIITests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::ASCIITests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::ASCIITests::test__validate_empty src/zope/schema/tests/test__field.py::ASCIITests::test__validate_non_empty_hit src/zope/schema/tests/test__field.py::ASCIITests::test__validate_non_empty_miss src/zope/schema/tests/test__field.py::ASCIITests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::ASCIITests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::ASCIITests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::ASCIITests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::ASCIITests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::ASCIITests::test_is_hashable src/zope/schema/tests/test__field.py::ASCIITests::test_validate_wrong_types src/zope/schema/tests/test__field.py::BytesLineTests::test___eq___different_type src/zope/schema/tests/test__field.py::BytesLineTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::BytesLineTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::BytesLineTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::BytesLineTests::test_constraint src/zope/schema/tests/test__field.py::BytesLineTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::BytesLineTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::BytesLineTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::BytesLineTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::BytesLineTests::test_is_hashable src/zope/schema/tests/test__field.py::BytesLineTests::test_validate_not_required src/zope/schema/tests/test__field.py::BytesLineTests::test_validate_required src/zope/schema/tests/test__field.py::BytesLineTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::ASCIILineTests::test___eq___different_type src/zope/schema/tests/test__field.py::ASCIILineTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::ASCIILineTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::ASCIILineTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::ASCIILineTests::test_constraint src/zope/schema/tests/test__field.py::ASCIILineTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::ASCIILineTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::ASCIILineTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::ASCIILineTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::ASCIILineTests::test_is_hashable src/zope/schema/tests/test__field.py::ASCIILineTests::test_validate_not_required src/zope/schema/tests/test__field.py::ASCIILineTests::test_validate_required src/zope/schema/tests/test__field.py::ASCIILineTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::FloatTests::test___eq___different_type src/zope/schema/tests/test__field.py::FloatTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::FloatTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::FloatTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::FloatTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::FloatTests::test_fromUnicode_hit src/zope/schema/tests/test__field.py::FloatTests::test_fromUnicode_miss src/zope/schema/tests/test__field.py::FloatTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::FloatTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::FloatTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::FloatTests::test_is_hashable src/zope/schema/tests/test__field.py::FloatTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::FloatTests::test_validate_max src/zope/schema/tests/test__field.py::FloatTests::test_validate_min src/zope/schema/tests/test__field.py::FloatTests::test_validate_min_and_max src/zope/schema/tests/test__field.py::FloatTests::test_validate_not_required src/zope/schema/tests/test__field.py::FloatTests::test_validate_required src/zope/schema/tests/test__field.py::DecimalTests::test___eq___different_type src/zope/schema/tests/test__field.py::DecimalTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::DecimalTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::DecimalTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::DecimalTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::DecimalTests::test_fromUnicode_hit src/zope/schema/tests/test__field.py::DecimalTests::test_fromUnicode_miss src/zope/schema/tests/test__field.py::DecimalTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::DecimalTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::DecimalTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::DecimalTests::test_is_hashable src/zope/schema/tests/test__field.py::DecimalTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::DecimalTests::test_validate_max src/zope/schema/tests/test__field.py::DecimalTests::test_validate_min src/zope/schema/tests/test__field.py::DecimalTests::test_validate_min_and_max src/zope/schema/tests/test__field.py::DecimalTests::test_validate_not_required src/zope/schema/tests/test__field.py::DecimalTests::test_validate_required src/zope/schema/tests/test__field.py::DatetimeTests::test___eq___different_type src/zope/schema/tests/test__field.py::DatetimeTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::DatetimeTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::DatetimeTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::DatetimeTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::DatetimeTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::DatetimeTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::DatetimeTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::DatetimeTests::test_is_hashable src/zope/schema/tests/test__field.py::DatetimeTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_not_required src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_required src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_w_max src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_w_min src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_w_min_and_max src/zope/schema/tests/test__field.py::DatetimeTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::DateTests::test___eq___different_type src/zope/schema/tests/test__field.py::DateTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::DateTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::DateTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::DateTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::DateTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::DateTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::DateTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::DateTests::test_is_hashable src/zope/schema/tests/test__field.py::DateTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::DateTests::test_validate_not_required src/zope/schema/tests/test__field.py::DateTests::test_validate_required src/zope/schema/tests/test__field.py::DateTests::test_validate_w_max src/zope/schema/tests/test__field.py::DateTests::test_validate_w_min src/zope/schema/tests/test__field.py::DateTests::test_validate_w_min_and_max src/zope/schema/tests/test__field.py::DateTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::TimedeltaTests::test___eq___different_type src/zope/schema/tests/test__field.py::TimedeltaTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::TimedeltaTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::TimedeltaTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::TimedeltaTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::TimedeltaTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::TimedeltaTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::TimedeltaTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::TimedeltaTests::test_is_hashable src/zope/schema/tests/test__field.py::TimedeltaTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::TimedeltaTests::test_validate_max src/zope/schema/tests/test__field.py::TimedeltaTests::test_validate_min src/zope/schema/tests/test__field.py::TimedeltaTests::test_validate_min_and_max src/zope/schema/tests/test__field.py::TimedeltaTests::test_validate_not_required src/zope/schema/tests/test__field.py::TimedeltaTests::test_validate_required src/zope/schema/tests/test__field.py::TimeTests::test___eq___different_type src/zope/schema/tests/test__field.py::TimeTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::TimeTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::TimeTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::TimeTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::TimeTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::TimeTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::TimeTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::TimeTests::test_is_hashable src/zope/schema/tests/test__field.py::TimeTests::test_missing_value_no_min_or_max src/zope/schema/tests/test__field.py::TimeTests::test_validate_max src/zope/schema/tests/test__field.py::TimeTests::test_validate_min src/zope/schema/tests/test__field.py::TimeTests::test_validate_min_and_max src/zope/schema/tests/test__field.py::TimeTests::test_validate_not_required src/zope/schema/tests/test__field.py::TimeTests::test_validate_required src/zope/schema/tests/test__field.py::ChoiceTests::test___eq___different_type src/zope/schema/tests/test__field.py::ChoiceTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::ChoiceTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_int src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_mixed src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_source_is_ICSB_bound src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_source_is_ICSB_unbound src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_string src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_tuple src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_w_named_vocabulary src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_w_named_vocabulary_invalid src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_w_named_vocabulary_passes_context src/zope/schema/tests/test__field.py::ChoiceTests::test__validate_w_named_vocabulary_raises_LookupError src/zope/schema/tests/test__field.py::ChoiceTests::test_bind_w_preconstructed_vocabulary src/zope/schema/tests/test__field.py::ChoiceTests::test_bind_w_voc_is_ICSB src/zope/schema/tests/test__field.py::ChoiceTests::test_bind_w_voc_is_ICSB_but_not_ISource src/zope/schema/tests/test__field.py::ChoiceTests::test_bind_w_voc_not_ICSB src/zope/schema/tests/test__field.py::ChoiceTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_both_vocabulary_and_source src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_both_vocabulary_and_values src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_invalid_source src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_invalid_vocabulary src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_w_named_vocabulary src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_w_preconstructed_vocabulary src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_w_unicode_non_ascii_values src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_w_values src/zope/schema/tests/test__field.py::ChoiceTests::test_ctor_wo_values_vocabulary_or_source src/zope/schema/tests/test__field.py::ChoiceTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::ChoiceTests::test_fromUnicode_hit src/zope/schema/tests/test__field.py::ChoiceTests::test_fromUnicode_miss src/zope/schema/tests/test__field.py::ChoiceTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::ChoiceTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::ChoiceTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::ChoiceTests::test_is_hashable src/zope/schema/tests/test__field.py::URITests::test___eq___different_type src/zope/schema/tests/test__field.py::URITests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::URITests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::URITests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::URITests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::URITests::test_fromUnicode_invalid src/zope/schema/tests/test__field.py::URITests::test_fromUnicode_ok src/zope/schema/tests/test__field.py::URITests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::URITests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::URITests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::URITests::test_is_hashable src/zope/schema/tests/test__field.py::URITests::test_validate_not_a_uri src/zope/schema/tests/test__field.py::URITests::test_validate_not_required src/zope/schema/tests/test__field.py::URITests::test_validate_required src/zope/schema/tests/test__field.py::URITests::test_validate_wrong_types src/zope/schema/tests/test__field.py::DottedNameTests::test___eq___different_type src/zope/schema/tests/test__field.py::DottedNameTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::DottedNameTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::DottedNameTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::DottedNameTests::test_ctor_defaults src/zope/schema/tests/test__field.py::DottedNameTests::test_ctor_max_dots_invalid src/zope/schema/tests/test__field.py::DottedNameTests::test_ctor_max_dots_valid src/zope/schema/tests/test__field.py::DottedNameTests::test_ctor_min_dots_invalid src/zope/schema/tests/test__field.py::DottedNameTests::test_ctor_min_dots_valid src/zope/schema/tests/test__field.py::DottedNameTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::DottedNameTests::test_fromUnicode_dotted_name_ok src/zope/schema/tests/test__field.py::DottedNameTests::test_fromUnicode_invalid src/zope/schema/tests/test__field.py::DottedNameTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::DottedNameTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::DottedNameTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::DottedNameTests::test_is_hashable src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_not_a_dotted_name src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_not_required src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_required src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_w_max_dots src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_w_min_dots src/zope/schema/tests/test__field.py::DottedNameTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::IdTests::test___eq___different_type src/zope/schema/tests/test__field.py::IdTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::IdTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::IdTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::IdTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::IdTests::test_fromUnicode_dotted_name_ok src/zope/schema/tests/test__field.py::IdTests::test_fromUnicode_invalid src/zope/schema/tests/test__field.py::IdTests::test_fromUnicode_url_ok src/zope/schema/tests/test__field.py::IdTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::IdTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::IdTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::IdTests::test_is_hashable src/zope/schema/tests/test__field.py::IdTests::test_validate_not_a_uri src/zope/schema/tests/test__field.py::IdTests::test_validate_not_required src/zope/schema/tests/test__field.py::IdTests::test_validate_required src/zope/schema/tests/test__field.py::IdTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::InterfaceFieldTests::test___eq___different_type src/zope/schema/tests/test__field.py::InterfaceFieldTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::InterfaceFieldTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_is_hashable src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_validate_not_required src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_validate_required src/zope/schema/tests/test__field.py::InterfaceFieldTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::CollectionTests::test___eq___different_type src/zope/schema/tests/test__field.py::CollectionTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::CollectionTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::CollectionTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::CollectionTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::CollectionTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::CollectionTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::CollectionTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::CollectionTests::test_ctor_defaults src/zope/schema/tests/test__field.py::CollectionTests::test_ctor_explicit src/zope/schema/tests/test__field.py::CollectionTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::CollectionTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::CollectionTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::CollectionTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::CollectionTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::CollectionTests::test_is_hashable src/zope/schema/tests/test__field.py::CollectionTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::CollectionTests::test_validate_max_length src/zope/schema/tests/test__field.py::CollectionTests::test_validate_min_length src/zope/schema/tests/test__field.py::CollectionTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::CollectionTests::test_validate_not_required src/zope/schema/tests/test__field.py::CollectionTests::test_validate_required src/zope/schema/tests/test__field.py::SequenceTests::test___eq___different_type src/zope/schema/tests/test__field.py::SequenceTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::SequenceTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::SequenceTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::SequenceTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::SequenceTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::SequenceTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::SequenceTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::SequenceTests::test_ctor_defaults src/zope/schema/tests/test__field.py::SequenceTests::test_ctor_explicit src/zope/schema/tests/test__field.py::SequenceTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::SequenceTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::SequenceTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::SequenceTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::SequenceTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::SequenceTests::test_is_hashable src/zope/schema/tests/test__field.py::SequenceTests::test_mutable_sequence src/zope/schema/tests/test__field.py::SequenceTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::SequenceTests::test_sequence src/zope/schema/tests/test__field.py::SequenceTests::test_validate_max_length src/zope/schema/tests/test__field.py::SequenceTests::test_validate_min_length src/zope/schema/tests/test__field.py::SequenceTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::SequenceTests::test_validate_not_required src/zope/schema/tests/test__field.py::SequenceTests::test_validate_required src/zope/schema/tests/test__field.py::SequenceTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::TupleTests::test___eq___different_type src/zope/schema/tests/test__field.py::TupleTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::TupleTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::TupleTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::TupleTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::TupleTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::TupleTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::TupleTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::TupleTests::test_ctor_defaults src/zope/schema/tests/test__field.py::TupleTests::test_ctor_explicit src/zope/schema/tests/test__field.py::TupleTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::TupleTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::TupleTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::TupleTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::TupleTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::TupleTests::test_is_hashable src/zope/schema/tests/test__field.py::TupleTests::test_mutable_sequence src/zope/schema/tests/test__field.py::TupleTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::TupleTests::test_sequence src/zope/schema/tests/test__field.py::TupleTests::test_validate_max_length src/zope/schema/tests/test__field.py::TupleTests::test_validate_min_length src/zope/schema/tests/test__field.py::TupleTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::TupleTests::test_validate_not_required src/zope/schema/tests/test__field.py::TupleTests::test_validate_required src/zope/schema/tests/test__field.py::TupleTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::MutableSequenceTests::test___eq___different_type src/zope/schema/tests/test__field.py::MutableSequenceTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::MutableSequenceTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::MutableSequenceTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::MutableSequenceTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::MutableSequenceTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::MutableSequenceTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::MutableSequenceTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::MutableSequenceTests::test_ctor_defaults src/zope/schema/tests/test__field.py::MutableSequenceTests::test_ctor_explicit src/zope/schema/tests/test__field.py::MutableSequenceTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::MutableSequenceTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::MutableSequenceTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::MutableSequenceTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::MutableSequenceTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::MutableSequenceTests::test_is_hashable src/zope/schema/tests/test__field.py::MutableSequenceTests::test_mutable_sequence src/zope/schema/tests/test__field.py::MutableSequenceTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::MutableSequenceTests::test_sequence src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_max_length src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_min_length src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_not_required src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_required src/zope/schema/tests/test__field.py::MutableSequenceTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::ListTests::test___eq___different_type src/zope/schema/tests/test__field.py::ListTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::ListTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::ListTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::ListTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::ListTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::ListTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::ListTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::ListTests::test_ctor_defaults src/zope/schema/tests/test__field.py::ListTests::test_ctor_explicit src/zope/schema/tests/test__field.py::ListTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::ListTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::ListTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::ListTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::ListTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::ListTests::test_is_hashable src/zope/schema/tests/test__field.py::ListTests::test_mutable_sequence src/zope/schema/tests/test__field.py::ListTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::ListTests::test_sequence src/zope/schema/tests/test__field.py::ListTests::test_validate_max_length src/zope/schema/tests/test__field.py::ListTests::test_validate_min_length src/zope/schema/tests/test__field.py::ListTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::ListTests::test_validate_not_required src/zope/schema/tests/test__field.py::ListTests::test_validate_required src/zope/schema/tests/test__field.py::ListTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::SetTests::test___eq___different_type src/zope/schema/tests/test__field.py::SetTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::SetTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::SetTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::SetTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::SetTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::SetTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::SetTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::SetTests::test_ctor_defaults src/zope/schema/tests/test__field.py::SetTests::test_ctor_disallows_unique src/zope/schema/tests/test__field.py::SetTests::test_ctor_explicit src/zope/schema/tests/test__field.py::SetTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::SetTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::SetTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::SetTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::SetTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::SetTests::test_is_hashable src/zope/schema/tests/test__field.py::SetTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::SetTests::test_validate_max_length src/zope/schema/tests/test__field.py::SetTests::test_validate_min_length src/zope/schema/tests/test__field.py::SetTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::SetTests::test_validate_not_required src/zope/schema/tests/test__field.py::SetTests::test_validate_required src/zope/schema/tests/test__field.py::SetTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::FrozenSetTests::test___eq___different_type src/zope/schema/tests/test__field.py::FrozenSetTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::FrozenSetTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::FrozenSetTests::test__validate_miss_uniqueness src/zope/schema/tests/test__field.py::FrozenSetTests::test__validate_wrong_contained_type src/zope/schema/tests/test__field.py::FrozenSetTests::test_bind_w_value_Type src/zope/schema/tests/test__field.py::FrozenSetTests::test_bind_wo_value_Type src/zope/schema/tests/test__field.py::FrozenSetTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::FrozenSetTests::test_ctor_defaults src/zope/schema/tests/test__field.py::FrozenSetTests::test_ctor_disallows_unique src/zope/schema/tests/test__field.py::FrozenSetTests::test_ctor_explicit src/zope/schema/tests/test__field.py::FrozenSetTests::test_ctor_w_non_field_value_type src/zope/schema/tests/test__field.py::FrozenSetTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::FrozenSetTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::FrozenSetTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::FrozenSetTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::FrozenSetTests::test_is_hashable src/zope/schema/tests/test__field.py::FrozenSetTests::test_schema_defined_by_subclass src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_max_length src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_min_length src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_not_required src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_required src/zope/schema/tests/test__field.py::FrozenSetTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::MappingTests::test___eq___different_type src/zope/schema/tests/test__field.py::MappingTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::MappingTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::MappingTests::test_bind_binds_key_and_value_types src/zope/schema/tests/test__field.py::MappingTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::MappingTests::test_ctor_key_type_not_IField src/zope/schema/tests/test__field.py::MappingTests::test_ctor_value_type_not_IField src/zope/schema/tests/test__field.py::MappingTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::MappingTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::MappingTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::MappingTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::MappingTests::test_is_hashable src/zope/schema/tests/test__field.py::MappingTests::test_mapping src/zope/schema/tests/test__field.py::MappingTests::test_mutable_mapping src/zope/schema/tests/test__field.py::MappingTests::test_validate_invalid_key_type src/zope/schema/tests/test__field.py::MappingTests::test_validate_invalid_value_type src/zope/schema/tests/test__field.py::MappingTests::test_validate_max_length src/zope/schema/tests/test__field.py::MappingTests::test_validate_min_length src/zope/schema/tests/test__field.py::MappingTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::MappingTests::test_validate_not_required src/zope/schema/tests/test__field.py::MappingTests::test_validate_required src/zope/schema/tests/test__field.py::MappingTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::MutableMappingTests::test___eq___different_type src/zope/schema/tests/test__field.py::MutableMappingTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::MutableMappingTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::MutableMappingTests::test_bind_binds_key_and_value_types src/zope/schema/tests/test__field.py::MutableMappingTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::MutableMappingTests::test_ctor_key_type_not_IField src/zope/schema/tests/test__field.py::MutableMappingTests::test_ctor_value_type_not_IField src/zope/schema/tests/test__field.py::MutableMappingTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::MutableMappingTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::MutableMappingTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::MutableMappingTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::MutableMappingTests::test_is_hashable src/zope/schema/tests/test__field.py::MutableMappingTests::test_mapping src/zope/schema/tests/test__field.py::MutableMappingTests::test_mutable_mapping src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_invalid_key_type src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_invalid_value_type src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_max_length src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_min_length src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_not_required src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_required src/zope/schema/tests/test__field.py::MutableMappingTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::DictTests::test___eq___different_type src/zope/schema/tests/test__field.py::DictTests::test___eq___same_type_different_attrs src/zope/schema/tests/test__field.py::DictTests::test___eq___same_type_same_attrs src/zope/schema/tests/test__field.py::DictTests::test_bind_binds_key_and_value_types src/zope/schema/tests/test__field.py::DictTests::test_class_conforms_to_iface src/zope/schema/tests/test__field.py::DictTests::test_ctor_key_type_not_IField src/zope/schema/tests/test__field.py::DictTests::test_ctor_value_type_not_IField src/zope/schema/tests/test__field.py::DictTests::test_equal_instances_have_same_hash src/zope/schema/tests/test__field.py::DictTests::test_hash_across_unequal_instances src/zope/schema/tests/test__field.py::DictTests::test_instance_conforms_to_iface src/zope/schema/tests/test__field.py::DictTests::test_instances_in_different_interfaces_not_equal src/zope/schema/tests/test__field.py::DictTests::test_is_hashable src/zope/schema/tests/test__field.py::DictTests::test_mapping src/zope/schema/tests/test__field.py::DictTests::test_mutable_mapping src/zope/schema/tests/test__field.py::DictTests::test_validate_invalid_key_type src/zope/schema/tests/test__field.py::DictTests::test_validate_invalid_value_type src/zope/schema/tests/test__field.py::DictTests::test_validate_max_length src/zope/schema/tests/test__field.py::DictTests::test_validate_min_length src/zope/schema/tests/test__field.py::DictTests::test_validate_min_length_and_max_length src/zope/schema/tests/test__field.py::DictTests::test_validate_not_required src/zope/schema/tests/test__field.py::DictTests::test_validate_required src/zope/schema/tests/test__field.py::DictTests::test_validate_wrong_types src/zope/schema/tests/test__field.py::test_suite
src/zope/schema/_field.py src/zope/schema/_bootstrapfields.py src/zope/schema/_bootstrapinterfaces.py docs/validation.rst CHANGES.rst docs/api.rst src/zope/schema/interfaces.py src/zope/schema/_schema.py
src/zope/schema/_field.py src/zope/schema/_bootstrapfields.py src/zope/schema/_bootstrapinterfaces.py docs/validation.rst CHANGES.rst docs/api.rst src/zope/schema/interfaces.py src/zope/schema/_schema.py