diff options
author | Colin Watson <cjwatson@debian.org> | 2021-01-04 16:04:03 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-04 16:04:03 +0000 |
commit | 69527f91b21881a92575b7e96fc4aba40a4dea4d (patch) | |
tree | 8a082e9964ffb595172a26a1d0d84af5e4c5873f | |
parent | 798bca0ab2b2044ee16cde90c8b37f6edfe2f052 (diff) | |
parent | d0be1a20bd2f512b3cabe182f617b87f6d20619a (diff) | |
download | zope-schema-69527f91b21881a92575b7e96fc4aba40a4dea4d.tar.gz |
Merge pull request #97 from cjwatson/flake8
Add a tox lint environment, and make it pass
-rw-r--r-- | .coveragerc | 1 | ||||
-rw-r--r-- | src/zope/schema/_bootstrapfields.py | 134 | ||||
-rw-r--r-- | src/zope/schema/_bootstrapinterfaces.py | 12 | ||||
-rw-r--r-- | src/zope/schema/_compat.py | 12 | ||||
-rw-r--r-- | src/zope/schema/_field.py | 69 | ||||
-rw-r--r-- | src/zope/schema/_schema.py | 5 | ||||
-rw-r--r-- | src/zope/schema/accessors.py | 11 | ||||
-rw-r--r-- | src/zope/schema/interfaces.py | 28 | ||||
-rw-r--r-- | src/zope/schema/tests/__init__.py | 84 | ||||
-rw-r--r-- | src/zope/schema/tests/states.py | 2 | ||||
-rw-r--r-- | src/zope/schema/tests/test__bootstrapfields.py | 43 | ||||
-rw-r--r-- | src/zope/schema/tests/test__bootstrapinterfaces.py | 1 | ||||
-rw-r--r-- | src/zope/schema/tests/test__field.py | 48 | ||||
-rw-r--r-- | src/zope/schema/tests/test_accessors.py | 5 | ||||
-rw-r--r-- | src/zope/schema/tests/test_fieldproperty.py | 10 | ||||
-rw-r--r-- | src/zope/schema/tests/test_schema.py | 3 | ||||
-rw-r--r-- | src/zope/schema/tests/test_vocabulary.py | 15 | ||||
-rw-r--r-- | src/zope/schema/vocabulary.py | 9 | ||||
-rw-r--r-- | tox.ini | 13 |
19 files changed, 310 insertions, 195 deletions
diff --git a/.coveragerc b/.coveragerc index 953ece6..617e435 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,4 +1,5 @@ [run] +plugins = coverage_python_version source = zope.schema [report] diff --git a/src/zope/schema/_bootstrapfields.py b/src/zope/schema/_bootstrapfields.py index 9a64a2d..6f2906b 100644 --- a/src/zope/schema/_bootstrapfields.py +++ b/src/zope/schema/_bootstrapfields.py @@ -62,7 +62,7 @@ from zope.schema._compat import PY2 class _NotGiven(object): - def __repr__(self): # pragma: no cover + def __repr__(self): # pragma: no cover return "<Not Given>" @@ -77,7 +77,10 @@ class ValidatedProperty(object): self._allow_none = allow_none def __set__(self, inst, value): - bypass_validation = (value is None and self._allow_none) or value == inst.missing_value + bypass_validation = ( + (value is None and self._allow_none) + or value == inst.missing_value + ) if not bypass_validation: if self._check is not None: self._check(inst, value) @@ -124,6 +127,7 @@ def getFields(schema): fields[name] = attr return fields + class _DocStringHelpers(object): # Namespace object to hold methods related to ReST formatting # docstrings @@ -286,7 +290,9 @@ class Field(Attribute): def validate(self, value): if value == self.missing_value: if self.required: - raise RequiredMissing(self.__name__).with_field_and_value(self, value) + raise RequiredMissing( + self.__name__ + ).with_field_and_value(self, value) else: try: self._validate(value) @@ -307,18 +313,21 @@ class Field(Attribute): def __hash__(self): # Equal objects should have equal hashes; # equal hashes does not imply equal objects. - value = (type(self), self.interface) + tuple(self.__get_property_names_to_compare()) + value = ( + (type(self), self.interface) + + tuple(self.__get_property_names_to_compare()) + ) return hash(value) def __eq__(self, other): - # should be the same type and in the same interface (or no interface at all) + # should be the same type and in the same interface (or no interface + # at all) if self is other: return True if type(self) != type(other) or self.interface != other.interface: return False - # should have the same properties names = self.__get_property_names_to_compare() # XXX: What about the property names of the other object? Even @@ -335,7 +344,9 @@ class Field(Attribute): def _validate(self, value): if self._type is not None and not isinstance(value, self._type): - raise WrongType(value, self._type, self.__name__).with_field_and_value(self, value) + raise WrongType( + value, self._type, self.__name__ + ).with_field_and_value(self, value) try: constraint = self.constraint(value) @@ -346,7 +357,9 @@ class Field(Attribute): e.value = value raise if not constraint: - raise ConstraintNotSatisfied(value, self.__name__).with_field_and_value(self, value) + raise ConstraintNotSatisfied( + value, self.__name__ + ).with_field_and_value(self, value) def get(self, object): return getattr(object, self.__name__) @@ -380,16 +393,20 @@ class Field(Attribute): """ lines = [] - lines.append(_DocStringHelpers.make_class_field('Implementation', type(self))) + lines.append(_DocStringHelpers.make_class_field( + 'Implementation', type(self))) lines.append(_DocStringHelpers.make_field("Read Only", self.readonly)) lines.append(_DocStringHelpers.make_field("Required", self.required)) if self.defaultFactory: - lines.append(_DocStringHelpers.make_field("Default Factory", repr(self.defaultFactory))) + lines.append(_DocStringHelpers.make_field( + "Default Factory", repr(self.defaultFactory))) else: - lines.append(_DocStringHelpers.make_field("Default Value", repr(self.default))) + lines.append(_DocStringHelpers.make_field( + "Default Value", repr(self.default))) if self._type: - lines.append(_DocStringHelpers.make_class_field("Allowed Type", self._type)) + lines.append(_DocStringHelpers.make_class_field( + "Allowed Type", self._type)) # key_type and value_type are commonly used, but don't # have a common superclass to add them, so we do it here. @@ -413,6 +430,7 @@ class Field(Attribute): return '\n'.join(lines) + class Container(Field): def _validate(self, value): @@ -495,10 +513,12 @@ class MinMaxLen(object): super(MinMaxLen, self)._validate(value) if self.min_length is not None and len(value) < self.min_length: - raise TooShort(value, self.min_length).with_field_and_value(self, value) + raise TooShort(value, self.min_length).with_field_and_value( + self, value) if self.max_length is not None and len(value) > self.max_length: - raise TooLong(value, self.max_length).with_field_and_value(self, value) + raise TooLong(value, self.max_length).with_field_and_value( + self, value) @implementer(IFromUnicode) @@ -514,15 +534,13 @@ class Text(MinMaxLen, Field): def fromUnicode(self, value): """ - >>> from zope.schema.interfaces import WrongType - >>> from zope.schema.interfaces import ConstraintNotSatisfied >>> from zope.schema import Text - >>> from zope.schema._compat import text_type >>> t = Text(constraint=lambda v: 'x' in v) >>> t.fromUnicode(b"foo x spam") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - zope.schema._bootstrapinterfaces.WrongType: ('foo x spam', <type 'unicode'>, '') + zope.schema._bootstrapinterfaces.WrongType: + ('foo x spam', <type 'unicode'>, '') >>> result = t.fromUnicode(u"foo x spam") >>> isinstance(result, bytes) False @@ -531,11 +549,13 @@ class Text(MinMaxLen, Field): >>> t.fromUnicode(u"foo spam") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - zope.schema._bootstrapinterfaces.ConstraintNotSatisfied: (u'foo spam', '') + zope.schema._bootstrapinterfaces.ConstraintNotSatisfied: + (u'foo spam', '') """ if isinstance(value, text_type): if self.unicode_normalization: - value = unicodedata.normalize(self.unicode_normalization, value) + value = unicodedata.normalize( + self.unicode_normalization, value) self.validate(value) return value @@ -669,7 +689,8 @@ class Number(Orderable, Field): (1+0j) >>> f.fromUnicode(u"1/2") Fraction(1, 2) - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS Decimal('234...936') >>> f.fromUnicode(u"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -688,7 +709,8 @@ class Number(Orderable, Field): (1+0j) >>> f.fromBytes(b"1/2") Fraction(1, 2) - >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) # doctest: +ELLIPSIS + >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) + ... # doctest: +ELLIPSIS Decimal('234...936') >>> f.fromBytes(b"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -702,14 +724,16 @@ class Number(Orderable, Field): """ _type = numbers.Number - # An ordered sequence of conversion routines. These should accept - # a native string and produce an object that is an instance of `_type`, or raise - # a ValueError. The order should be most specific/strictest towards least - # restrictive (in other words, lowest in the numeric tower towards highest). - # We break this rule with fractions, though: a floating point number is - # more generally useful and expected than a fraction, so we attempt to parse - # as a float before a fraction. - _unicode_converters = (int, float, fractions.Fraction, complex, decimal.Decimal) + # An ordered sequence of conversion routines. These should accept a + # native string and produce an object that is an instance of `_type`, or + # raise a ValueError. The order should be most specific/strictest + # towards least restrictive (in other words, lowest in the numeric tower + # towards highest). We break this rule with fractions, though: a + # floating point number is more generally useful and expected than a + # fraction, so we attempt to parse as a float before a fraction. + _unicode_converters = ( + int, float, fractions.Fraction, complex, decimal.Decimal, + ) # The type of error we will raise if all conversions fail. _validation_error = InvalidNumberLiteral @@ -719,7 +743,9 @@ class Number(Orderable, Field): for converter in self._unicode_converters: try: val = converter(value) - if converter is float and isinf(val) and decimal.Decimal in self._unicode_converters: + if (converter is float + and isinf(val) + and decimal.Decimal in self._unicode_converters): # Pass this on to decimal, if we're allowed val = decimal.Decimal(value) except (ValueError, decimal.InvalidOperation) as e: @@ -728,15 +754,16 @@ class Number(Orderable, Field): self.validate(val) return val try: - raise self._validation_error(*last_exc.args).with_field_and_value(self, value) + raise self._validation_error(*last_exc.args).with_field_and_value( + self, value) finally: last_exc = None # On Python 2, native strings are byte strings, which is # what the converters expect, so we don't need to do any decoding. - if PY2: # pragma: no cover + if PY2: # pragma: PY2 fromBytes = fromUnicode - else: + else: # pragma: PY3 def fromBytes(self, value): return self.fromUnicode(value.decode('utf-8')) @@ -759,7 +786,8 @@ class Complex(Number): (1+0j) >>> f.fromUnicode(u"1/2") Fraction(1, 2) - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS inf >>> f.fromUnicode(u"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -778,7 +806,8 @@ class Complex(Number): (1+0j) >>> f.fromBytes(b"1/2") Fraction(1, 2) - >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) # doctest: +ELLIPSIS + >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) + ... # doctest: +ELLIPSIS inf >>> f.fromBytes(b"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -811,7 +840,8 @@ class Real(Complex): InvalidNumberLiteral: Invalid literal for Fraction: '1+0j' >>> f.fromUnicode("1/2") Fraction(1, 2) - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS inf >>> f.fromUnicode("not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -844,7 +874,8 @@ class Rational(Real): Traceback (most recent call last): ... InvalidNumberLiteral: Invalid literal for Fraction: '1+0j' - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS Fraction(777..., 330...) >>> f.fromUnicode("not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -929,7 +960,8 @@ class Decimal(Number): Traceback (most recent call last): ... InvalidDecimalLiteral: Invalid literal for Decimal(): 1/2 - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS Decimal('2349...936') >>> f.fromUnicode("not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -952,7 +984,8 @@ class Decimal(Number): Traceback (most recent call last): ... InvalidDecimalLiteral: Invalid literal for Decimal(): 1/2 - >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode("ascii")) # doctest: +ELLIPSIS + >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode("ascii")) + ... # doctest: +ELLIPSIS Decimal('2349...936') >>> f.fromBytes(b"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -1010,7 +1043,7 @@ def get_schema_validation_errors(schema, value, for name in schema.names(all=True): attribute = schema[name] if IMethod.providedBy(attribute): - continue # pragma: no cover + continue # pragma: no cover try: if IValidatable.providedBy(attribute): @@ -1022,7 +1055,9 @@ def get_schema_validation_errors(schema, value, 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) + errors[name] = SchemaNotFullyImplemented( + error + ).with_field_and_value(attribute, None) finally: ids_being_validated.remove(id_value) return errors @@ -1074,12 +1109,13 @@ class Object(Field): """ Object(schema=<Not Given>, *, validate_invariants=True, **kwargs) - Create an `~.IObject` field. The keyword arguments are as for `~.Field`. + 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. + 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. @@ -1099,7 +1135,8 @@ class Object(Field): def getExtraDocLines(self): lines = super(Object, self).getExtraDocLines() - lines.append(_DocStringHelpers.make_class_field("Must Provide", self.schema)) + lines.append(_DocStringHelpers.make_class_field( + "Must Provide", self.schema)) return lines def _validate(self, value): @@ -1107,7 +1144,8 @@ class Object(Field): # schema has to be provided by value if not self.schema.providedBy(value): - raise SchemaNotProvided(self.schema, value).with_field_and_value(self, 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( diff --git a/src/zope/schema/_bootstrapinterfaces.py b/src/zope/schema/_bootstrapinterfaces.py index 79f9c49..8bddae1 100644 --- a/src/zope/schema/_bootstrapinterfaces.py +++ b/src/zope/schema/_bootstrapinterfaces.py @@ -24,6 +24,7 @@ from zope.schema._messageid import _ # pylint:disable=inherit-non-class,keyword-arg-before-vararg, # pylint:disable=no-self-argument + class StopValidation(Exception): """Raised if the validation is completed early. @@ -219,14 +220,17 @@ class SchemaNotCorrectlyImplemented(WrongContainedType): #: of the schema. invariant_errors = () - def __init__(self, errors=None, name=None, schema_errors=None, invariant_errors=(), *args): + def __init__(self, errors=None, name=None, schema_errors=None, + invariant_errors=(), *args): """ - SchemaNotCorrectlyImplemented(errors, name, schema_errors, invariant_errors) + SchemaNotCorrectlyImplemented(errors, name, schema_errors, + invariant_errors) .. versionchanged:: 4.7.0 Added named arguments to the constructor. """ - super(SchemaNotCorrectlyImplemented, self).__init__(errors, name, *args) + super(SchemaNotCorrectlyImplemented, self).__init__( + errors, name, *args) self.schema_errors = schema_errors self.invariant_errors = invariant_errors @@ -344,7 +348,7 @@ class IValidatable(zope.interface.Interface): class NO_VALUE(object): - def __repr__(self): # pragma: no cover + def __repr__(self): # pragma: no cover return '<NO_VALUE>' diff --git a/src/zope/schema/_compat.py b/src/zope/schema/_compat.py index 239c8d6..51a4716 100644 --- a/src/zope/schema/_compat.py +++ b/src/zope/schema/_compat.py @@ -22,15 +22,15 @@ if PY3: # pragma: no cover else: # pragma: no cover - string_types = basestring, - text_type = unicode - binary_type = str - integer_types = (int, long) + string_types = (basestring, ) # noqa: F821 + text_type = unicode # noqa: F821 + binary_type = str # noqa: F821 + integer_types = (int, long) # noqa: F821 def non_native_string(x): - if isinstance(x, unicode): + if isinstance(x, unicode): # noqa: F821 return x - return unicode(x, 'unicode_escape') + return unicode(x, 'unicode_escape') # noqa: F821 def make_binary(x): if isinstance(x, str): diff --git a/src/zope/schema/_field.py b/src/zope/schema/_field.py index aab68ec..3e42f67 100644 --- a/src/zope/schema/_field.py +++ b/src/zope/schema/_field.py @@ -17,7 +17,7 @@ __docformat__ = 'restructuredtext' try: from collections import abc -except ImportError: # pragma: no cover +except ImportError: # pragma: PY2 # Python 2 import collections as abc @@ -107,7 +107,7 @@ from zope.schema._bootstrapfields import Bool from zope.schema._bootstrapfields import Int from zope.schema._bootstrapfields import Integral from zope.schema._bootstrapfields import Number -from zope.schema._bootstrapfields import InvalidDecimalLiteral # reimport +from zope.schema._bootstrapfields import InvalidDecimalLiteral # noqa: reexport from zope.schema._bootstrapfields import Decimal from zope.schema._bootstrapfields import Password from zope.schema._bootstrapfields import Rational @@ -207,8 +207,8 @@ class NativeString(Text if PY3 else Bytes): :class:`~zope.schema.interfaces.IFromBytes`. .. versionchanged:: 4.9.0 - This is now a distinct type instead of an alias for either `Text` or `Bytes`, - depending on the platform. + This is now a distinct type instead of an alias for either `Text` or + `Bytes`, depending on the platform. """ _type = str @@ -302,7 +302,8 @@ class Float(Real): Traceback (most recent call last): ... InvalidFloatLiteral: invalid literal for float(): 1/2 - >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) # doctest: +ELLIPSIS + >>> f.fromUnicode(str(2**31234) + '.' + str(2**256)) + ... # doctest: +ELLIPSIS inf >>> f.fromUnicode("not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -325,7 +326,8 @@ class Float(Real): Traceback (most recent call last): ... InvalidFloatLiteral: invalid literal for float(): 1/2 - >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) # doctest: +ELLIPSIS + >>> f.fromBytes((str(2**31234) + '.' + str(2**256)).encode('ascii')) + ... # doctest: +ELLIPSIS inf >>> f.fromBytes(b"not a number") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): @@ -355,7 +357,9 @@ class Date(Orderable, Field): def _validate(self, value): super(Date, self)._validate(value) if isinstance(value, datetime): - raise WrongType(value, self._type, self.__name__).with_field_and_value(self, value) + raise WrongType( + value, self._type, self.__name__ + ).with_field_and_value(self, value) @implementer(ITimedelta) @@ -376,6 +380,7 @@ class MissingVocabularyError(ValidationError, """Raised when a named vocabulary cannot be found.""" # Subclasses ValueError and LookupError for backwards compatibility + class InvalidVocabularyError(ValidationError, ValueError, TypeError): @@ -383,7 +388,8 @@ class InvalidVocabularyError(ValidationError, # Subclasses TypeError and ValueError for backwards compatibility def __init__(self, vocabulary): - super(InvalidVocabularyError, self).__init__("Invalid vocabulary %r" % (vocabulary,)) + super(InvalidVocabularyError, self).__init__( + "Invalid vocabulary %r" % (vocabulary,)) @implementer(IChoice, IFromUnicode) @@ -442,7 +448,8 @@ class Choice(Field): # an exception if this isn't possible, and returning # an ISource otherwise. vocabulary = self.vocabulary - if IContextSourceBinder.providedBy(vocabulary) and self.context is not None: + if (IContextSourceBinder.providedBy(vocabulary) + and self.context is not None): vocabulary = vocabulary(self.context) elif vocabulary is None and self.vocabularyName is not None: vr = getVocabularyRegistry() @@ -450,11 +457,13 @@ class Choice(Field): vocabulary = vr.get(self.context, self.vocabularyName) except LookupError: raise MissingVocabularyError( - "Can't validate value without vocabulary named %r" % (self.vocabularyName,) + "Can't validate value without vocabulary named %r" % ( + self.vocabularyName,) ).with_field_and_value(self, value) if not ISource.providedBy(vocabulary): - raise InvalidVocabularyError(vocabulary).with_field_and_value(self, value) + raise InvalidVocabularyError(vocabulary).with_field_and_value( + self, value) return vocabulary @@ -480,7 +489,9 @@ class Choice(Field): super(Choice, self)._validate(value) vocabulary = self._resolve_vocabulary(value) if value not in vocabulary: - raise ConstraintNotSatisfied(value, self.__name__).with_field_and_value(self, value) + raise ConstraintNotSatisfied( + value, self.__name__ + ).with_field_and_value(self, value) # Both of these are inherited from the parent; re-declaring them @@ -498,9 +509,10 @@ class _StrippedNativeStringLine(NativeStringLine): # unicode, but we don't want to allow non-ASCII values, to match # Python 2 (our regexs would reject that anyway.) try: - v = v.encode('ascii') # bytes + v = v.encode('ascii') # bytes except UnicodeEncodeError: - raise self._invalid_exc_type(value).with_field_and_value(self, value) + raise self._invalid_exc_type(value).with_field_and_value( + self, value) if not isinstance(v, self._type): v = v.decode('ascii') self.validate(v) @@ -636,9 +648,9 @@ class DottedName(_StrippedNativeStringLine): "too few dots; %d required" % self.min_dots, value ).with_field_and_value(self, value) if self.max_dots is not None and dots > self.max_dots: - raise InvalidDottedName("too many dots; no more than %d allowed" % - self.max_dots, value).with_field_and_value(self, value) - + raise InvalidDottedName( + "too many dots; no more than %d allowed" % self.max_dots, value + ).with_field_and_value(self, value) @implementer(IId) @@ -691,7 +703,6 @@ def _validate_sequence(value_type, value, errors=None): To validate a sequence of various values: - >>> from zope.schema._compat import text_type >>> errors = _validate_sequence(field, (bytearray(b'foo'), u'bar', 1)) >>> errors [WrongType(bytearray(b'foo'), <...>, ''), WrongType(1, <...>, '')] @@ -703,8 +714,10 @@ def _validate_sequence(value_type, value, errors=None): for a new sequence: >>> errors = _validate_sequence(field, (2, u'baz'), errors) - >>> errors - [WrongType(bytearray(b'foo'), <...>, ''), WrongType(1, <...>, ''), WrongType(2, <...>, '')] + >>> errors # doctest: +NORMALIZE_WHITESPACE + [WrongType(bytearray(b'foo'), <...>, ''), + WrongType(1, <...>, ''), + WrongType(2, <...>, '')] """ if errors is None: @@ -731,7 +744,8 @@ def _validate_uniqueness(self, value): @implementer(ICollection) class Collection(MinMaxLen, Iterable): """ - A generic collection implementing :class:`zope.schema.interfaces.ICollection`. + A generic collection implementing + :class:`zope.schema.interfaces.ICollection`. Subclasses can define the attribute ``value_type`` to be a field such as an :class:`Object` that will be checked for each member of @@ -754,7 +768,8 @@ class Collection(MinMaxLen, Iterable): if value_type is not _NotGiven: self.value_type = value_type - if self.value_type is not None and not IField.providedBy(self.value_type): + if (self.value_type is not None + and not IField.providedBy(self.value_type)): raise ValueError("'value_type' must be field instance.") if unique is not _NotGiven: self.unique = unique @@ -773,7 +788,9 @@ class Collection(MinMaxLen, Iterable): errors = _validate_sequence(self.value_type, value) if errors: try: - raise WrongContainedType(errors, self.__name__).with_field_and_value(self, value) + raise WrongContainedType( + errors, self.__name__ + ).with_field_and_value(self, value) finally: # Break cycles del errors @@ -825,7 +842,7 @@ class _AbstractSet(Collection): def __init__(self, *args, **kwargs): super(_AbstractSet, self).__init__(*args, **kwargs) - if not self.unique: # set members are always unique + if not self.unique: # set members are always unique raise TypeError( "__init__() got an unexpected keyword argument 'unique'") @@ -872,7 +889,9 @@ class Mapping(MinMaxLen, Iterable): if errors: try: - raise WrongContainedType(errors, self.__name__).with_field_and_value(self, value) + raise WrongContainedType( + errors, self.__name__ + ).with_field_and_value(self, value) finally: # Break cycles del errors diff --git a/src/zope/schema/_schema.py b/src/zope/schema/_schema.py index b64b7b6..bd9d780 100644 --- a/src/zope/schema/_schema.py +++ b/src/zope/schema/_schema.py @@ -70,7 +70,10 @@ def getValidationErrors(schema, value): # Valid! Yay! return [] - return list(schema_error_dict.items()) + [(None, e) for e in invariant_errors] + return ( + list(schema_error_dict.items()) + + [(None, e) for e in invariant_errors] + ) def getSchemaValidationErrors(schema, value): diff --git a/src/zope/schema/accessors.py b/src/zope/schema/accessors.py index decf3aa..257eb7b 100644 --- a/src/zope/schema/accessors.py +++ b/src/zope/schema/accessors.py @@ -76,17 +76,18 @@ class FieldReadAccessor(Method): if iface in provided_list: provided_list.remove(iface) provided = Declaration(*provided_list) + # pylint:disable=broad-except try: return provided + implemented - except BaseException as e: # pragma: no cover pylint:disable=broad-except + except BaseException as e: # pragma: no cover # Sadly, zope.interface catches and silently ignores # any exceptions raised in ``__providedBy__``, # which is the class descriptor that invokes ``__provides__``. # So, for example, if we're in strict C3 mode and fail to produce - # a resolution order, that gets ignored and we fallback to just what's - # implemented by the class. - # That's not good. Do our best to propagate the exception by returning it. - # There will be downstream errors later. + # a resolution order, that gets ignored and we fallback to just + # what's implemented by the class. + # That's not good. Do our best to propagate the exception by + # returning it. There will be downstream errors later. return e def getSignatureString(self): diff --git a/src/zope/schema/interfaces.py b/src/zope/schema/interfaces.py index 303380a..c18e54c 100644 --- a/src/zope/schema/interfaces.py +++ b/src/zope/schema/interfaces.py @@ -463,7 +463,8 @@ class INativeStringLine(ITextLine if PY3 else IBytesLine): class IPassword(ITextLine): - "Field containing a unicode string without newlines that is a password." + """Field containing a unicode password string without newlines.""" + ### # Numbers @@ -550,6 +551,7 @@ class IReal(IComplex): field value""") ) + class IRational(IReal): """ Field containing a rational number: :class:`numbers.IRational`. @@ -576,6 +578,7 @@ class IRational(IReal): field value""") ) + class IIntegral(IRational): """ Field containing an integral number: class:`numbers.Integral`. @@ -600,6 +603,8 @@ class IIntegral(IRational): description=_("""The field default value may be None or a legal field value""") ) + + ## # Concrete numbers ## @@ -667,6 +672,7 @@ class IDecimal(INumber): # End numbers ### + class IDatetime(IMinMax, IField): """Field containing a datetime.""" @@ -757,6 +763,7 @@ class IChoice(IField): default=None ) + # Collections: # Abstract @@ -792,6 +799,7 @@ class IMutableSequence(ISequence): .. versionadded:: 4.6.0 """ + class IUnorderedCollection(ICollection): """Abstract interface specifying that the value cannot be ordered""" @@ -799,14 +807,16 @@ class IUnorderedCollection(ICollection): class IAbstractSet(IUnorderedCollection): """An unordered collection of unique values.""" - unique = Bool(description="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 = Bool(description="This ICollection interface attribute must be False") + unique = Bool( + description="This ICollection interface attribute must be False") # Concrete @@ -844,18 +854,19 @@ class IObject(IField): schema = Object( IInterface, - description=_("The Interface that defines the Fields comprising the Object.") + description=_("The Interface that defines the Fields comprising the " + "Object.") ) validate_invariants = Bool( title=_("Validate Invariants"), - description=_("A boolean that says whether ``schema.validateInvariants`` " - "is called from ``self.validate()``. The default is true."), + description=_("A boolean that says whether " + "``schema.validateInvariants`` is called from " + "``self.validate()``. The default is true."), default=True, ) - class IMapping(IMinMaxLen, IIterable, IContainer): """ Field containing an instance of :class:`collections.Mapping`. @@ -866,7 +877,8 @@ class IMapping(IMinMaxLen, IIterable, IContainer): """ key_type = Object( IField, - description=_("Field keys must conform to the given type, expressed via a Field.") + description=_("Field keys must conform to the given type, expressed " + "via a Field.") ) value_type = Object( diff --git a/src/zope/schema/tests/__init__.py b/src/zope/schema/tests/__init__.py index b7d1a56..f6718f0 100644 --- a/src/zope/schema/tests/__init__.py +++ b/src/zope/schema/tests/__init__.py @@ -6,44 +6,46 @@ import re from zope.schema._compat import PY3 from zope.testing import renormalizing -if PY3: - py3_checker = renormalizing.RENormalizing([ - (re.compile(r"u'([^']*)'"), - r"'\1'"), - (re.compile(r"^b'([^']*)'"), - r"'\1'"), - (re.compile(r"([^'])b'([^']*)'"), - r"\1'\2'"), - (re.compile(r"<class 'bytes'>"), - r"<type 'str'>"), - (re.compile(r"<class 'str'>"), - r"<type 'unicode'>"), - (re.compile(r"zope.schema._bootstrapinterfaces.InvalidValue"), - r"InvalidValue"), - (re.compile(r"zope.schema.interfaces.InvalidId: '([^']*)'"), - r"InvalidId: \1"), - (re.compile(r"zope.schema.interfaces.InvalidId:"), - r"InvalidId:"), - (re.compile(r"zope.schema.interfaces.InvalidURI: '([^']*)'"), - r"InvalidURI: \1"), - (re.compile(r"zope.schema.interfaces.InvalidURI:"), - r"InvalidURI:"), - (re.compile(r"zope.schema.interfaces.InvalidDottedName: '([^']*)'"), - r"InvalidDottedName: \1"), - (re.compile(r"zope.schema.interfaces.InvalidDottedName:"), - r"InvalidDottedName:"), - (re.compile( - r"zope.schema._bootstrapinterfaces.ConstraintNotSatisfied: '([^']*)'" - ), - r"ConstraintNotSatisfied: \1"), - (re.compile( - r"zope.schema._bootstrapinterfaces.ConstraintNotSatisfied:"), - r"ConstraintNotSatisfied:"), - (re.compile(r"zope.schema._bootstrapinterfaces.WrongType:"), - r"WrongType:"), - ]) -else: # pragma: no cover - py3_checker = renormalizing.RENormalizing([ - (re.compile(r"([^'])b'([^']*)'"), - r"\1'\2'"), - ]) + +def _make_transforms(patterns): + return [(re.compile(pattern), repl) for pattern, repl in patterns] + + +if PY3: # pragma: PY3 + py3_checker = renormalizing.RENormalizing(_make_transforms([ + (r"u'([^']*)'", + r"'\1'"), + (r"^b'([^']*)'", + r"'\1'"), + (r"([^'])b'([^']*)'", + r"\1'\2'"), + (r"<class 'bytes'>", + r"<type 'str'>"), + (r"<class 'str'>", + r"<type 'unicode'>"), + (r"zope.schema._bootstrapinterfaces.InvalidValue", + r"InvalidValue"), + (r"zope.schema.interfaces.InvalidId: '([^']*)'", + r"InvalidId: \1"), + (r"zope.schema.interfaces.InvalidId:", + r"InvalidId:"), + (r"zope.schema.interfaces.InvalidURI: '([^']*)'", + r"InvalidURI: \1"), + (r"zope.schema.interfaces.InvalidURI:", + r"InvalidURI:"), + (r"zope.schema.interfaces.InvalidDottedName: '([^']*)'", + r"InvalidDottedName: \1"), + (r"zope.schema.interfaces.InvalidDottedName:", + r"InvalidDottedName:"), + (r"zope.schema._bootstrapinterfaces.ConstraintNotSatisfied: '([^']*)'", + r"ConstraintNotSatisfied: \1"), + (r"zope.schema._bootstrapinterfaces.ConstraintNotSatisfied:", + r"ConstraintNotSatisfied:"), + (r"zope.schema._bootstrapinterfaces.WrongType:", + r"WrongType:"), + ])) +else: # pragma: PY2 + py3_checker = renormalizing.RENormalizing(_make_transforms([ + (r"([^'])b'([^']*)'", + r"\1'\2'"), + ])) diff --git a/src/zope/schema/tests/states.py b/src/zope/schema/tests/states.py index 3507fb2..dc3ca70 100644 --- a/src/zope/schema/tests/states.py +++ b/src/zope/schema/tests/states.py @@ -16,7 +16,6 @@ from zope.interface import implementer from zope.schema import interfaces -from zope.schema import Choice # This table is based on information from the United States Postal Service: # http://www.usps.com/ncsc/lookups/abbreviations.html#states @@ -91,6 +90,7 @@ class State(object): self.value = value self.title = title + for v, p in _states.items(): _states[v] = State(v, p) diff --git a/src/zope/schema/tests/test__bootstrapfields.py b/src/zope/schema/tests/test__bootstrapfields.py index 58e7e31..3516bf6 100644 --- a/src/zope/schema/tests/test__bootstrapfields.py +++ b/src/zope/schema/tests/test__bootstrapfields.py @@ -19,6 +19,7 @@ import unicodedata # pylint:disable=protected-access,inherit-non-class,blacklisted-name # pylint:disable=attribute-defined-outside-init + class InterfaceConformanceTestsMixin(object): def _getTargetClass(self): @@ -66,13 +67,15 @@ class InterfaceConformanceTestsMixin(object): from zope.interface import ro from zope.interface import implementedBy __traceback_info__ = implementedBy(self._getTargetClass()).__sro__ - self.assertTrue(ro.is_consistent(implementedBy(self._getTargetClass()))) + self.assertTrue( + ro.is_consistent(implementedBy(self._getTargetClass()))) def test_iface_consistent_ro(self): from zope.interface import ro __traceback_info__ = self._getTargetInterface().__iro__ self.assertTrue(ro.is_consistent(self._getTargetInterface())) + class EqualityTestsMixin(InterfaceConformanceTestsMixin): def test_is_hashable(self): @@ -244,7 +247,8 @@ class LenTestsMixin(object): class WrongTypeTestsMixin(object): - def assertRaisesWrongType(self, field_or_meth, expected_type, *args, **kwargs): + def assertRaisesWrongType(self, field_or_meth, expected_type, + *args, **kwargs): from zope.schema.interfaces import WrongType field = None with self.assertRaises(WrongType) as exc: @@ -265,7 +269,6 @@ class WrongTypeTestsMixin(object): # A single keyword argument self.assertIs(ex.value, kwargs.popitem()[1]) - def assertAllRaiseWrongType(self, field, expected_type, *values): for value in values: __traceback_info__ = value @@ -986,7 +989,8 @@ class TextTests(EqualityTestsMixin, self.assertEqual(txt.fromUnicode(deadbeef), deadbeef) def test_normalization(self): - deadbeef = unicodedata.normalize('NFD', b'\xc3\x84\xc3\x96\xc3\x9c'.decode('utf-8')) + deadbeef = unicodedata.normalize( + 'NFD', b'\xc3\x84\xc3\x96\xc3\x9c'.decode('utf-8')) txt = self._makeOne() self.assertEqual(txt.unicode_normalization, 'NFC') self.assertEqual( @@ -1016,6 +1020,7 @@ class TextTests(EqualityTestsMixin, # see https://github.com/zopefoundation/zope.schema/issues/90 import pickle orig_makeOne = self._makeOne + def makeOne(**kwargs): result = orig_makeOne(**kwargs) if not kwargs: @@ -1209,7 +1214,8 @@ class NumberTests(EqualityTestsMixin, def test_instance_conforms_to_iface(self): from zope.schema._bootstrapinterfaces import IFromUnicode from zope.schema._bootstrapinterfaces import IFromBytes - verifyObject = super(NumberTests, self).test_instance_conforms_to_iface() + verifyObject = ( + super(NumberTests, self).test_instance_conforms_to_iface()) verifyObject(IFromUnicode, self._makeOne()) verifyObject(IFromBytes, self._makeOne()) @@ -1224,6 +1230,7 @@ class ComplexTests(NumberTests): from zope.schema.interfaces import IComplex return IComplex + class RealTests(WrongTypeTestsMixin, NumberTests): @@ -1238,8 +1245,10 @@ class RealTests(WrongTypeTestsMixin, def test_ctor_real_min_max(self): from fractions import Fraction - self.assertRaisesWrongType(self._makeOne, self._getTargetClass()._type, min='') - self.assertRaisesWrongType(self._makeOne, self._getTargetClass()._type, max='') + self.assertRaisesWrongType( + self._makeOne, self._getTargetClass()._type, min='') + self.assertRaisesWrongType( + self._makeOne, self._getTargetClass()._type, max='') field = self._makeOne(min=Fraction(1, 2), max=2) field.validate(1.0) @@ -1394,7 +1403,8 @@ class ObjectTests(EqualityTestsMixin, def _makeOneFromClass(self, cls, schema=None, *args, **kw): if schema is None: schema = self._makeSchema() - return super(ObjectTests, self)._makeOneFromClass(cls, schema, *args, **kw) + return super(ObjectTests, self)._makeOneFromClass( + cls, schema, *args, **kw) def _makeSchema(self, **kw): from zope.interface import Interface @@ -1749,13 +1759,12 @@ class ObjectTests(EqualityTestsMixin, raise Invalid("Bar is not valid") @implementer(ISchema) - class O(object): + class Obj(object): foo = u'' bar = b'' - field = self._makeOne(ISchema) - inst = O() + inst = Obj() # Fine at first field.validate(inst) @@ -1807,7 +1816,6 @@ class ObjectTests(EqualityTestsMixin, class ValueType(object): "The value type" - field.validate(ValueType()) def test_bound_field_of_collection_with_choice(self): @@ -1823,7 +1831,6 @@ class ObjectTests(EqualityTestsMixin, from zope.schema.interfaces import SchemaNotCorrectlyImplemented from zope.schema.vocabulary import SimpleVocabulary - @implementer(IContextSourceBinder) class EnumContext(object): def __call__(self, context): @@ -1832,7 +1839,8 @@ class ObjectTests(EqualityTestsMixin, 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. + # choke. NOTE: We don't actually verify the existence of this + # attribute. non_field = Attribute("An attribute") @implementer(IMultipleChoice) @@ -1843,14 +1851,13 @@ class ObjectTests(EqualityTestsMixin, def __iter__(self): # EnumContext calls this to make the vocabulary. - # Fields of the schema of the IObject are bound to the value being - # validated. + # 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']) @@ -1924,6 +1931,6 @@ def test_suite(): suite = unittest.defaultTestLoader.loadTestsFromName(__name__) suite.addTests(doctest.DocTestSuite( zope.schema._bootstrapfields, - optionflags=doctest.ELLIPSIS|IGNORE_EXCEPTION_MODULE_IN_PYTHON2 + optionflags=doctest.ELLIPSIS | IGNORE_EXCEPTION_MODULE_IN_PYTHON2 )) return suite diff --git a/src/zope/schema/tests/test__bootstrapinterfaces.py b/src/zope/schema/tests/test__bootstrapinterfaces.py index 77815c0..385fa1c 100644 --- a/src/zope/schema/tests/test__bootstrapinterfaces.py +++ b/src/zope/schema/tests/test__bootstrapinterfaces.py @@ -19,6 +19,7 @@ except NameError: def compare(a, b): return -1 if a < b else (0 if a == b else 1) + class ValidationErrorTests(unittest.TestCase): def _getTargetClass(self): diff --git a/src/zope/schema/tests/test__field.py b/src/zope/schema/tests/test__field.py index 13600d5..efbf152 100644 --- a/src/zope/schema/tests/test__field.py +++ b/src/zope/schema/tests/test__field.py @@ -29,6 +29,7 @@ from zope.schema.tests.test__bootstrapfields import NumberTests # pylint:disable=no-member # pylint:disable=blacklisted-name + class BytesTests(EqualityTestsMixin, WrongTypeTestsMixin, unittest.TestCase): @@ -274,7 +275,6 @@ class FloatTests(NumberTests): TOO_SMALL = tuple(float(x) for x in NumberTests.TOO_SMALL) TOO_BIG = tuple(float(x) for x in NumberTests.TOO_BIG) - def _getTargetClass(self): from zope.schema._field import Float return Float @@ -448,7 +448,8 @@ class TimedeltaTests(OrderableMissingValueMixin, MIN = datetime.timedelta(minutes=NumberTests.MIN) MAX = datetime.timedelta(minutes=NumberTests.MAX) VALID = tuple(datetime.timedelta(minutes=x) for x in NumberTests.VALID) - TOO_SMALL = tuple(datetime.timedelta(minutes=x) for x in NumberTests.TOO_SMALL) + TOO_SMALL = tuple( + datetime.timedelta(minutes=x) for x in NumberTests.TOO_SMALL) TOO_BIG = tuple(datetime.timedelta(x) for x in NumberTests.TOO_BIG) @@ -505,9 +506,9 @@ class ChoiceTests(EqualityTestsMixin, def _makeOneFromClass(self, cls, *args, **kwargs): if (not args - and 'vocabulary' not in kwargs - and 'values' not in kwargs - and 'source' not in kwargs): + and 'vocabulary' not in kwargs + and 'values' not in kwargs + and 'source' not in kwargs): from zope.schema.vocabulary import SimpleVocabulary kwargs['vocabulary'] = SimpleVocabulary.fromValues([1, 2, 3]) return super(ChoiceTests, self)._makeOneFromClass(cls, *args, **kwargs) @@ -516,12 +517,12 @@ class ChoiceTests(EqualityTestsMixin, from zope.schema.interfaces import IChoice return IChoice - def test_ctor_wo_values_vocabulary_or_source(self): self.assertRaises(ValueError, self._getTargetClass()) def test_ctor_invalid_vocabulary(self): - self.assertRaises(ValueError, self._getTargetClass(), vocabulary=object()) + self.assertRaises(ValueError, + self._getTargetClass(), vocabulary=object()) def test_ctor_invalid_source(self): self.assertRaises(ValueError, self._getTargetClass(), source=object()) @@ -552,8 +553,8 @@ class ChoiceTests(EqualityTestsMixin, sorted(values)) self.assertEqual( sorted(choose.vocabulary.by_token.keys()), - sorted([x.encode('ascii', 'backslashreplace').decode('ascii') for x in values])) - + sorted([x.encode('ascii', 'backslashreplace').decode('ascii') + for x in values])) def test_ctor_w_named_vocabulary(self): choose = self._makeOne(vocabulary="vocab") @@ -724,6 +725,7 @@ class ChoiceTests(EqualityTestsMixin, class Reg(object): called_with = () + def get(self, *args): self.called_with += args return _makeSampleVocabulary() @@ -1006,7 +1008,8 @@ class DottedNameTests(EqualityTestsMixin, # Underscores are allowed in any component self.assertEqual(field.fromUnicode(u'dotted._name'), 'dotted._name') - self.assertEqual(field.fromUnicode(u'_leading_underscore'), '_leading_underscore') + self.assertEqual(field.fromUnicode(u'_leading_underscore'), + '_leading_underscore') self.assertEqual(field.fromUnicode(u'_dotted.name'), '_dotted.name') self.assertEqual(field.fromUnicode(u'_dotted._name'), '_dotted._name') @@ -1181,7 +1184,6 @@ class CollectionTests(EqualityTestsMixin, _makeCollection = list - def test_schema_defined_by_subclass(self): from zope import interface from zope.schema import Object @@ -1217,7 +1219,6 @@ class CollectionTests(EqualityTestsMixin, class ValueType(object): "The value type" - field.validate(self._makeCollection([ValueType()])) def test_ctor_defaults(self): @@ -1358,6 +1359,7 @@ class SequenceTests(WrongTypeTestsMixin, class Sequence(abc.Sequence): def __getitem__(self, i): raise AssertionError("Not implemented") + def __len__(self): return 0 @@ -1371,16 +1373,20 @@ class SequenceTests(WrongTypeTestsMixin, class MutableSequence(abc.MutableSequence): def insert(self, index, value): raise AssertionError("not implemented") + def __getitem__(self, name): raise AssertionError("not implemented") + def __iter__(self): return iter(()) + def __setitem__(self, name, value): raise AssertionError("Not implemented") + def __len__(self): return 0 - __delitem__ = __getitem__ + __delitem__ = __getitem__ sequence = MutableSequence() field = self._makeOne() @@ -1479,7 +1485,7 @@ class SetTests(WrongTypeTestsMixin, def test_ctor_disallows_unique(self): self.assertRaises(TypeError, self._makeOne, unique=False) - self._makeOne(unique=True) # restating the obvious is allowed + self._makeOne(unique=True) # restating the obvious is allowed self.assertTrue(self._makeOne().unique) def test_validate_wrong_types(self): @@ -1599,7 +1605,6 @@ class MappingTests(EqualityTestsMixin, self.assertIsInstance(wct.errors[0], WrongType) self.assertIs(field.value_type._type, wct.errors[0].expected_type) - def test_validate_min_length(self): field = self._makeOne(min_length=1) field.validate({1: 'a'}) @@ -1635,12 +1640,13 @@ class MappingTests(EqualityTestsMixin, def __getitem__(self, name): raise AssertionError("not implemented") + def __iter__(self): return iter(()) + def __len__(self): return 0 - mm = Mapping() field = self._makeOne() field.validate(mm) @@ -1652,12 +1658,16 @@ class MappingTests(EqualityTestsMixin, def __getitem__(self, name): raise AssertionError("not implemented") + def __iter__(self): return iter(()) + def __setitem__(self, name, value): raise AssertionError("Not implemented") + def __len__(self): return 0 + __delitem__ = __getitem__ mm = MutableMapping() @@ -1696,6 +1706,7 @@ class DictTests(MutableMappingTests): with self.assertRaises(WrongType): super(DictTests, self).test_mutable_mapping() + class NativeStringTests(EqualityTestsMixin, WrongTypeTestsMixin, unittest.TestCase): @@ -1766,7 +1777,8 @@ class StrippedNativeStringLineTests(NativeStringLineTests): self.assertEqual(field.fromUnicode(u' '), '') def test_iface_is_first_in_sro(self): - self.skipTest("Not applicable; we inherit implementation but have no interface") + self.skipTest("Not applicable; we inherit implementation but have no " + "interface") def _makeSampleVocabulary(): @@ -1782,7 +1794,7 @@ def _makeSampleVocabulary(): def __contains__(self, value): return 0 <= value < 10 - def __len__(self): # pragma: no cover + def __len__(self): # pragma: no cover return 10 def getTerm(self, value): diff --git a/src/zope/schema/tests/test_accessors.py b/src/zope/schema/tests/test_accessors.py index 2a6ceae..74bd0a2 100644 --- a/src/zope/schema/tests/test_accessors.py +++ b/src/zope/schema/tests/test_accessors.py @@ -17,6 +17,7 @@ import unittest # pylint:disable=inherit-non-class + class FieldReadAccessorTests(unittest.TestCase): def _getTargetClass(self): @@ -207,7 +208,9 @@ class FieldReadAccessorTests(unittest.TestCase): pass writer = Writer() - writer.__name__ = 'setMe' # pylint:disable=attribute-defined-outside-init + # pylint:disable=attribute-defined-outside-init + writer.__name__ = 'setMe' + # pylint:enable=attribute-defined-outside-init getter.writer = writer class Foo(object): diff --git a/src/zope/schema/tests/test_fieldproperty.py b/src/zope/schema/tests/test_fieldproperty.py index f319f55..fd2dd5a 100644 --- a/src/zope/schema/tests/test_fieldproperty.py +++ b/src/zope/schema/tests/test_fieldproperty.py @@ -288,7 +288,8 @@ class FieldPropertyTests(_Base, _Integration): self.assertEqual(event.new_value, 0) self.assertEqual( [ev.field.__name__ for ev in log], - ['min_length', 'max_length', 'title', 'description', 'required', 'readonly']) + ['min_length', 'max_length', 'title', 'description', 'required', + 'readonly']) def test_field_event_update(self): from zope.schema import Text @@ -517,7 +518,7 @@ class FieldPropertyStoredThroughFieldTests(_Base, _Integration): return default def set(self, inst, value): - if self.readonly: # pragma: no cover + if self.readonly: # pragma: no cover raise ValueError setattr(inst, 'faux', value) @@ -608,7 +609,8 @@ class FieldPropertyStoredThroughFieldTests(_Base, _Integration): # these are fieldproperties in the field self.assertEqual( [ev.field.__name__ for ev in log], - ['min_length', 'max_length', 'title', 'description', 'required', 'readonly']) + ['min_length', 'max_length', 'title', 'description', 'required', + 'readonly']) event = log[0] self.assertTrue(isinstance(event, FieldUpdatedEvent)) self.assertEqual(event.inst, field) @@ -622,8 +624,6 @@ def _getSchema(): from zope.schema import Float from zope.schema import Text - - class Schema(Interface): title = Text(description=u"Short summary", default=u'say something') diff --git a/src/zope/schema/tests/test_schema.py b/src/zope/schema/tests/test_schema.py index f64b5fe..d91452d 100644 --- a/src/zope/schema/tests/test_schema.py +++ b/src/zope/schema/tests/test_schema.py @@ -42,8 +42,8 @@ def _makeSchema(): def _makeDerivedSchema(base=None): - from zope.schema import Bytes + if base is None: base = _makeSchema() @@ -225,7 +225,6 @@ class Test_getSchemaValidationErrors(unittest.TestCase): from zope.interface import Interface from zope.schema import Text - class IWithFields(Interface): foo = Text() bar = Text() diff --git a/src/zope/schema/tests/test_vocabulary.py b/src/zope/schema/tests/test_vocabulary.py index 8dc17ea..eef246b 100644 --- a/src/zope/schema/tests/test_vocabulary.py +++ b/src/zope/schema/tests/test_vocabulary.py @@ -72,10 +72,7 @@ class SimpleTermTests(unittest.TestCase): self.assertEqual(term.token, 'Snowman \\u2603') self.assertFalse(ITitledTokenizedTerm.providedBy(term)) - def test__eq__and__hash__(self): - from zope import interface - term = self._makeOne('value') # Equal to itself self.assertEqual(term, term) @@ -387,10 +384,10 @@ class TreeVocabularyTests(unittest.TestCase): self.assertTrue(IStupid.providedBy(v)) def test_ordering(self): - #The TreeVocabulary makes use of an OrderedDict to store it's - #internal tree representation. + # The TreeVocabulary makes use of an OrderedDict to store its + # internal tree representation. # - #Check that they keys are indeed oredered. + # Check that the keys are indeed ordered. from collections import OrderedDict d = { @@ -648,7 +645,7 @@ class TreeVocabularyTests(unittest.TestCase): self.assertEqual(str(e), "Term tokens must be unique: 'one'") def test_recursive_methods(self): - #Test the _createTermTree and _getPathToTreeNode methods + # Test the _createTermTree and _getPathToTreeNode methods from zope.schema.vocabulary import _createTermTree tree = _createTermTree({}, self.business_tree()) vocab = self._getTargetClass().fromDict(self.business_tree()) @@ -681,7 +678,7 @@ class TreeVocabularyTests(unittest.TestCase): class RegistryTests(unittest.TestCase): - #Tests of the simple vocabulary and presentation registries. + # Tests of the simple vocabulary and presentation registries. def setUp(self): from zope.schema.vocabulary import _clear @@ -723,7 +720,7 @@ def _makeSampleVocabulary(): def __contains__(self, value): return 0 <= value < 10 - def __len__(self): # pragma: no cover + def __len__(self): # pragma: no cover return 10 def getTerm(self, value): diff --git a/src/zope/schema/vocabulary.py b/src/zope/schema/vocabulary.py index eba0d4b..bab9a67 100644 --- a/src/zope/schema/vocabulary.py +++ b/src/zope/schema/vocabulary.py @@ -217,7 +217,10 @@ class SimpleVocabulary(object): if not isinstance(other, SimpleVocabulary): return False - return self._terms == other._terms and providedBy(self) == providedBy(other) + return ( + self._terms == other._terms + and providedBy(self) == providedBy(other) + ) def __ne__(self, other): return not self.__eq__(other) @@ -329,7 +332,8 @@ class TreeVocabulary(object): The tuples should have either 2 or 3 values, i.e: (token, value, title) or (token, value). Only tuples that have - three values will create a :class:`zope.schema.interfaces.ITitledTokenizedTerm`. + three values will create a + :class:`zope.schema.interfaces.ITitledTokenizedTerm`. For example, a dict with 2-valued tuples:: @@ -473,6 +477,7 @@ class VocabularyRegistry(object): """Register a *factory* for the vocabulary with the given *name*.""" self._map[name] = factory + _vocabularies = None @@ -3,7 +3,7 @@ envlist = # Jython support pending 2.7 support, due 2012-07-15 or so. See: # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html # py27,jython,pypy,coverage - py27,py35,py36,py37,py38,pypy,pypy3,coverage,docs + lint,py27,py35,py36,py37,py38,pypy,pypy3,coverage,docs [testenv] deps = @@ -12,6 +12,16 @@ commands = zope-testrunner --test-path=src sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest +[testenv:lint] +usedevelop = true +basepython = + python3.6 +skip_install = true +deps = + flake8 +commands = + flake8 src setup.py + [testenv:coverage] usedevelop = true basepython = @@ -22,6 +32,7 @@ commands = deps = .[test] coverage + coverage-python-version [testenv:docs] basepython = |