Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/attr/validators.py
7763 views
# SPDX-License-Identifier: MIT12"""3Commonly useful validators.4"""56from __future__ import absolute_import, division, print_function78import operator9import re1011from contextlib import contextmanager1213from ._config import get_run_validators, set_run_validators14from ._make import _AndValidator, and_, attrib, attrs15from .exceptions import NotCallableError161718try:19Pattern = re.Pattern20except AttributeError: # Python <3.7 lacks a Pattern type.21Pattern = type(re.compile(""))222324__all__ = [25"and_",26"deep_iterable",27"deep_mapping",28"disabled",29"ge",30"get_disabled",31"gt",32"in_",33"instance_of",34"is_callable",35"le",36"lt",37"matches_re",38"max_len",39"optional",40"provides",41"set_disabled",42]434445def set_disabled(disabled):46"""47Globally disable or enable running validators.4849By default, they are run.5051:param disabled: If ``True``, disable running all validators.52:type disabled: bool5354.. warning::5556This function is not thread-safe!5758.. versionadded:: 21.3.059"""60set_run_validators(not disabled)616263def get_disabled():64"""65Return a bool indicating whether validators are currently disabled or not.6667:return: ``True`` if validators are currently disabled.68:rtype: bool6970.. versionadded:: 21.3.071"""72return not get_run_validators()737475@contextmanager76def disabled():77"""78Context manager that disables running validators within its context.7980.. warning::8182This context manager is not thread-safe!8384.. versionadded:: 21.3.085"""86set_run_validators(False)87try:88yield89finally:90set_run_validators(True)919293@attrs(repr=False, slots=True, hash=True)94class _InstanceOfValidator(object):95type = attrib()9697def __call__(self, inst, attr, value):98"""99We use a callable class to be able to change the ``__repr__``.100"""101if not isinstance(value, self.type):102raise TypeError(103"'{name}' must be {type!r} (got {value!r} that is a "104"{actual!r}).".format(105name=attr.name,106type=self.type,107actual=value.__class__,108value=value,109),110attr,111self.type,112value,113)114115def __repr__(self):116return "<instance_of validator for type {type!r}>".format(117type=self.type118)119120121def instance_of(type):122"""123A validator that raises a `TypeError` if the initializer is called124with a wrong type for this particular attribute (checks are performed using125`isinstance` therefore it's also valid to pass a tuple of types).126127:param type: The type to check for.128:type type: type or tuple of types129130:raises TypeError: With a human readable error message, the attribute131(of type `attrs.Attribute`), the expected type, and the value it132got.133"""134return _InstanceOfValidator(type)135136137@attrs(repr=False, frozen=True, slots=True)138class _MatchesReValidator(object):139pattern = attrib()140match_func = attrib()141142def __call__(self, inst, attr, value):143"""144We use a callable class to be able to change the ``__repr__``.145"""146if not self.match_func(value):147raise ValueError(148"'{name}' must match regex {pattern!r}"149" ({value!r} doesn't)".format(150name=attr.name, pattern=self.pattern.pattern, value=value151),152attr,153self.pattern,154value,155)156157def __repr__(self):158return "<matches_re validator for pattern {pattern!r}>".format(159pattern=self.pattern160)161162163def matches_re(regex, flags=0, func=None):164r"""165A validator that raises `ValueError` if the initializer is called166with a string that doesn't match *regex*.167168:param regex: a regex string or precompiled pattern to match against169:param int flags: flags that will be passed to the underlying re function170(default 0)171:param callable func: which underlying `re` function to call (options172are `re.fullmatch`, `re.search`, `re.match`, default173is ``None`` which means either `re.fullmatch` or an emulation of174it on Python 2). For performance reasons, they won't be used directly175but on a pre-`re.compile`\ ed pattern.176177.. versionadded:: 19.2.0178.. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern.179"""180fullmatch = getattr(re, "fullmatch", None)181valid_funcs = (fullmatch, None, re.search, re.match)182if func not in valid_funcs:183raise ValueError(184"'func' must be one of {}.".format(185", ".join(186sorted(187e and e.__name__ or "None" for e in set(valid_funcs)188)189)190)191)192193if isinstance(regex, Pattern):194if flags:195raise TypeError(196"'flags' can only be used with a string pattern; "197"pass flags to re.compile() instead"198)199pattern = regex200else:201pattern = re.compile(regex, flags)202203if func is re.match:204match_func = pattern.match205elif func is re.search:206match_func = pattern.search207elif fullmatch:208match_func = pattern.fullmatch209else: # Python 2 fullmatch emulation (https://bugs.python.org/issue16203)210pattern = re.compile(211r"(?:{})\Z".format(pattern.pattern), pattern.flags212)213match_func = pattern.match214215return _MatchesReValidator(pattern, match_func)216217218@attrs(repr=False, slots=True, hash=True)219class _ProvidesValidator(object):220interface = attrib()221222def __call__(self, inst, attr, value):223"""224We use a callable class to be able to change the ``__repr__``.225"""226if not self.interface.providedBy(value):227raise TypeError(228"'{name}' must provide {interface!r} which {value!r} "229"doesn't.".format(230name=attr.name, interface=self.interface, value=value231),232attr,233self.interface,234value,235)236237def __repr__(self):238return "<provides validator for interface {interface!r}>".format(239interface=self.interface240)241242243def provides(interface):244"""245A validator that raises a `TypeError` if the initializer is called246with an object that does not provide the requested *interface* (checks are247performed using ``interface.providedBy(value)`` (see `zope.interface248<https://zopeinterface.readthedocs.io/en/latest/>`_).249250:param interface: The interface to check for.251:type interface: ``zope.interface.Interface``252253:raises TypeError: With a human readable error message, the attribute254(of type `attrs.Attribute`), the expected interface, and the255value it got.256"""257return _ProvidesValidator(interface)258259260@attrs(repr=False, slots=True, hash=True)261class _OptionalValidator(object):262validator = attrib()263264def __call__(self, inst, attr, value):265if value is None:266return267268self.validator(inst, attr, value)269270def __repr__(self):271return "<optional validator for {what} or None>".format(272what=repr(self.validator)273)274275276def optional(validator):277"""278A validator that makes an attribute optional. An optional attribute is one279which can be set to ``None`` in addition to satisfying the requirements of280the sub-validator.281282:param validator: A validator (or a list of validators) that is used for283non-``None`` values.284:type validator: callable or `list` of callables.285286.. versionadded:: 15.1.0287.. versionchanged:: 17.1.0 *validator* can be a list of validators.288"""289if isinstance(validator, list):290return _OptionalValidator(_AndValidator(validator))291return _OptionalValidator(validator)292293294@attrs(repr=False, slots=True, hash=True)295class _InValidator(object):296options = attrib()297298def __call__(self, inst, attr, value):299try:300in_options = value in self.options301except TypeError: # e.g. `1 in "abc"`302in_options = False303304if not in_options:305raise ValueError(306"'{name}' must be in {options!r} (got {value!r})".format(307name=attr.name, options=self.options, value=value308)309)310311def __repr__(self):312return "<in_ validator with options {options!r}>".format(313options=self.options314)315316317def in_(options):318"""319A validator that raises a `ValueError` if the initializer is called320with a value that does not belong in the options provided. The check is321performed using ``value in options``.322323:param options: Allowed options.324:type options: list, tuple, `enum.Enum`, ...325326:raises ValueError: With a human readable error message, the attribute (of327type `attrs.Attribute`), the expected options, and the value it328got.329330.. versionadded:: 17.1.0331"""332return _InValidator(options)333334335@attrs(repr=False, slots=False, hash=True)336class _IsCallableValidator(object):337def __call__(self, inst, attr, value):338"""339We use a callable class to be able to change the ``__repr__``.340"""341if not callable(value):342message = (343"'{name}' must be callable "344"(got {value!r} that is a {actual!r})."345)346raise NotCallableError(347msg=message.format(348name=attr.name, value=value, actual=value.__class__349),350value=value,351)352353def __repr__(self):354return "<is_callable validator>"355356357def is_callable():358"""359A validator that raises a `attr.exceptions.NotCallableError` if the360initializer is called with a value for this particular attribute361that is not callable.362363.. versionadded:: 19.1.0364365:raises `attr.exceptions.NotCallableError`: With a human readable error366message containing the attribute (`attrs.Attribute`) name,367and the value it got.368"""369return _IsCallableValidator()370371372@attrs(repr=False, slots=True, hash=True)373class _DeepIterable(object):374member_validator = attrib(validator=is_callable())375iterable_validator = attrib(376default=None, validator=optional(is_callable())377)378379def __call__(self, inst, attr, value):380"""381We use a callable class to be able to change the ``__repr__``.382"""383if self.iterable_validator is not None:384self.iterable_validator(inst, attr, value)385386for member in value:387self.member_validator(inst, attr, member)388389def __repr__(self):390iterable_identifier = (391""392if self.iterable_validator is None393else " {iterable!r}".format(iterable=self.iterable_validator)394)395return (396"<deep_iterable validator for{iterable_identifier}"397" iterables of {member!r}>"398).format(399iterable_identifier=iterable_identifier,400member=self.member_validator,401)402403404def deep_iterable(member_validator, iterable_validator=None):405"""406A validator that performs deep validation of an iterable.407408:param member_validator: Validator to apply to iterable members409:param iterable_validator: Validator to apply to iterable itself410(optional)411412.. versionadded:: 19.1.0413414:raises TypeError: if any sub-validators fail415"""416return _DeepIterable(member_validator, iterable_validator)417418419@attrs(repr=False, slots=True, hash=True)420class _DeepMapping(object):421key_validator = attrib(validator=is_callable())422value_validator = attrib(validator=is_callable())423mapping_validator = attrib(default=None, validator=optional(is_callable()))424425def __call__(self, inst, attr, value):426"""427We use a callable class to be able to change the ``__repr__``.428"""429if self.mapping_validator is not None:430self.mapping_validator(inst, attr, value)431432for key in value:433self.key_validator(inst, attr, key)434self.value_validator(inst, attr, value[key])435436def __repr__(self):437return (438"<deep_mapping validator for objects mapping {key!r} to {value!r}>"439).format(key=self.key_validator, value=self.value_validator)440441442def deep_mapping(key_validator, value_validator, mapping_validator=None):443"""444A validator that performs deep validation of a dictionary.445446:param key_validator: Validator to apply to dictionary keys447:param value_validator: Validator to apply to dictionary values448:param mapping_validator: Validator to apply to top-level mapping449attribute (optional)450451.. versionadded:: 19.1.0452453:raises TypeError: if any sub-validators fail454"""455return _DeepMapping(key_validator, value_validator, mapping_validator)456457458@attrs(repr=False, frozen=True, slots=True)459class _NumberValidator(object):460bound = attrib()461compare_op = attrib()462compare_func = attrib()463464def __call__(self, inst, attr, value):465"""466We use a callable class to be able to change the ``__repr__``.467"""468if not self.compare_func(value, self.bound):469raise ValueError(470"'{name}' must be {op} {bound}: {value}".format(471name=attr.name,472op=self.compare_op,473bound=self.bound,474value=value,475)476)477478def __repr__(self):479return "<Validator for x {op} {bound}>".format(480op=self.compare_op, bound=self.bound481)482483484def lt(val):485"""486A validator that raises `ValueError` if the initializer is called487with a number larger or equal to *val*.488489:param val: Exclusive upper bound for values490491.. versionadded:: 21.3.0492"""493return _NumberValidator(val, "<", operator.lt)494495496def le(val):497"""498A validator that raises `ValueError` if the initializer is called499with a number greater than *val*.500501:param val: Inclusive upper bound for values502503.. versionadded:: 21.3.0504"""505return _NumberValidator(val, "<=", operator.le)506507508def ge(val):509"""510A validator that raises `ValueError` if the initializer is called511with a number smaller than *val*.512513:param val: Inclusive lower bound for values514515.. versionadded:: 21.3.0516"""517return _NumberValidator(val, ">=", operator.ge)518519520def gt(val):521"""522A validator that raises `ValueError` if the initializer is called523with a number smaller or equal to *val*.524525:param val: Exclusive lower bound for values526527.. versionadded:: 21.3.0528"""529return _NumberValidator(val, ">", operator.gt)530531532@attrs(repr=False, frozen=True, slots=True)533class _MaxLengthValidator(object):534max_length = attrib()535536def __call__(self, inst, attr, value):537"""538We use a callable class to be able to change the ``__repr__``.539"""540if len(value) > self.max_length:541raise ValueError(542"Length of '{name}' must be <= {max}: {len}".format(543name=attr.name, max=self.max_length, len=len(value)544)545)546547def __repr__(self):548return "<max_len validator for {max}>".format(max=self.max_length)549550551def max_len(length):552"""553A validator that raises `ValueError` if the initializer is called554with a string or iterable that is longer than *length*.555556:param int length: Maximum length of the string or iterable557558.. versionadded:: 21.3.0559"""560return _MaxLengthValidator(length)561562563