mercurial/thirdparty/attr/validators.py
changeset 34397 765eb17a7eb8
child 49643 e1c586b9a43c
equal deleted inserted replaced
34396:9fb9f8440b71 34397:765eb17a7eb8
       
     1 """
       
     2 Commonly useful validators.
       
     3 """
       
     4 
       
     5 from __future__ import absolute_import, division, print_function
       
     6 
       
     7 from ._make import attr, attributes, and_, _AndValidator
       
     8 
       
     9 
       
    10 __all__ = [
       
    11     "and_",
       
    12     "in_",
       
    13     "instance_of",
       
    14     "optional",
       
    15     "provides",
       
    16 ]
       
    17 
       
    18 
       
    19 @attributes(repr=False, slots=True, hash=True)
       
    20 class _InstanceOfValidator(object):
       
    21     type = attr()
       
    22 
       
    23     def __call__(self, inst, attr, value):
       
    24         """
       
    25         We use a callable class to be able to change the ``__repr__``.
       
    26         """
       
    27         if not isinstance(value, self.type):
       
    28             raise TypeError(
       
    29                 "'{name}' must be {type!r} (got {value!r} that is a "
       
    30                 "{actual!r})."
       
    31                 .format(name=attr.name, type=self.type,
       
    32                         actual=value.__class__, value=value),
       
    33                 attr, self.type, value,
       
    34             )
       
    35 
       
    36     def __repr__(self):
       
    37         return (
       
    38             "<instance_of validator for type {type!r}>"
       
    39             .format(type=self.type)
       
    40         )
       
    41 
       
    42 
       
    43 def instance_of(type):
       
    44     """
       
    45     A validator that raises a :exc:`TypeError` if the initializer is called
       
    46     with a wrong type for this particular attribute (checks are perfomed using
       
    47     :func:`isinstance` therefore it's also valid to pass a tuple of types).
       
    48 
       
    49     :param type: The type to check for.
       
    50     :type type: type or tuple of types
       
    51 
       
    52     :raises TypeError: With a human readable error message, the attribute
       
    53         (of type :class:`attr.Attribute`), the expected type, and the value it
       
    54         got.
       
    55     """
       
    56     return _InstanceOfValidator(type)
       
    57 
       
    58 
       
    59 @attributes(repr=False, slots=True, hash=True)
       
    60 class _ProvidesValidator(object):
       
    61     interface = attr()
       
    62 
       
    63     def __call__(self, inst, attr, value):
       
    64         """
       
    65         We use a callable class to be able to change the ``__repr__``.
       
    66         """
       
    67         if not self.interface.providedBy(value):
       
    68             raise TypeError(
       
    69                 "'{name}' must provide {interface!r} which {value!r} "
       
    70                 "doesn't."
       
    71                 .format(name=attr.name, interface=self.interface, value=value),
       
    72                 attr, self.interface, value,
       
    73             )
       
    74 
       
    75     def __repr__(self):
       
    76         return (
       
    77             "<provides validator for interface {interface!r}>"
       
    78             .format(interface=self.interface)
       
    79         )
       
    80 
       
    81 
       
    82 def provides(interface):
       
    83     """
       
    84     A validator that raises a :exc:`TypeError` if the initializer is called
       
    85     with an object that does not provide the requested *interface* (checks are
       
    86     performed using ``interface.providedBy(value)`` (see `zope.interface
       
    87     <https://zopeinterface.readthedocs.io/en/latest/>`_).
       
    88 
       
    89     :param zope.interface.Interface interface: The interface to check for.
       
    90 
       
    91     :raises TypeError: With a human readable error message, the attribute
       
    92         (of type :class:`attr.Attribute`), the expected interface, and the
       
    93         value it got.
       
    94     """
       
    95     return _ProvidesValidator(interface)
       
    96 
       
    97 
       
    98 @attributes(repr=False, slots=True, hash=True)
       
    99 class _OptionalValidator(object):
       
   100     validator = attr()
       
   101 
       
   102     def __call__(self, inst, attr, value):
       
   103         if value is None:
       
   104             return
       
   105 
       
   106         self.validator(inst, attr, value)
       
   107 
       
   108     def __repr__(self):
       
   109         return (
       
   110             "<optional validator for {what} or None>"
       
   111             .format(what=repr(self.validator))
       
   112         )
       
   113 
       
   114 
       
   115 def optional(validator):
       
   116     """
       
   117     A validator that makes an attribute optional.  An optional attribute is one
       
   118     which can be set to ``None`` in addition to satisfying the requirements of
       
   119     the sub-validator.
       
   120 
       
   121     :param validator: A validator (or a list of validators) that is used for
       
   122         non-``None`` values.
       
   123     :type validator: callable or :class:`list` of callables.
       
   124 
       
   125     .. versionadded:: 15.1.0
       
   126     .. versionchanged:: 17.1.0 *validator* can be a list of validators.
       
   127     """
       
   128     if isinstance(validator, list):
       
   129         return _OptionalValidator(_AndValidator(validator))
       
   130     return _OptionalValidator(validator)
       
   131 
       
   132 
       
   133 @attributes(repr=False, slots=True, hash=True)
       
   134 class _InValidator(object):
       
   135     options = attr()
       
   136 
       
   137     def __call__(self, inst, attr, value):
       
   138         if value not in self.options:
       
   139             raise ValueError(
       
   140                 "'{name}' must be in {options!r} (got {value!r})"
       
   141                 .format(name=attr.name, options=self.options, value=value)
       
   142             )
       
   143 
       
   144     def __repr__(self):
       
   145         return (
       
   146             "<in_ validator with options {options!r}>"
       
   147             .format(options=self.options)
       
   148         )
       
   149 
       
   150 
       
   151 def in_(options):
       
   152     """
       
   153     A validator that raises a :exc:`ValueError` if the initializer is called
       
   154     with a value that does not belong in the options provided.  The check is
       
   155     performed using ``value in options``.
       
   156 
       
   157     :param options: Allowed options.
       
   158     :type options: list, tuple, :class:`enum.Enum`, ...
       
   159 
       
   160     :raises ValueError: With a human readable error message, the attribute (of
       
   161        type :class:`attr.Attribute`), the expected options, and the value it
       
   162        got.
       
   163 
       
   164     .. versionadded:: 17.1.0
       
   165     """
       
   166     return _InValidator(options)