aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/attrs
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/attrs
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/python/attrs')
-rw-r--r--contrib/python/attrs/.dist-info/METADATA211
-rw-r--r--contrib/python/attrs/.dist-info/top_level.txt1
-rw-r--r--contrib/python/attrs/.yandex_meta/yamaker.yaml2
-rw-r--r--contrib/python/attrs/AUTHORS.rst11
-rw-r--r--contrib/python/attrs/LICENSE21
-rw-r--r--contrib/python/attrs/README.rst122
-rw-r--r--contrib/python/attrs/attr/__init__.py78
-rw-r--r--contrib/python/attrs/attr/__init__.pyi475
-rw-r--r--contrib/python/attrs/attr/_cmp.py152
-rw-r--r--contrib/python/attrs/attr/_cmp.pyi14
-rw-r--r--contrib/python/attrs/attr/_compat.py242
-rw-r--r--contrib/python/attrs/attr/_config.py23
-rw-r--r--contrib/python/attrs/attr/_funcs.py395
-rw-r--r--contrib/python/attrs/attr/_make.py3052
-rw-r--r--contrib/python/attrs/attr/_next_gen.py158
-rw-r--r--contrib/python/attrs/attr/_version_info.py85
-rw-r--r--contrib/python/attrs/attr/_version_info.pyi9
-rw-r--r--contrib/python/attrs/attr/converters.py111
-rw-r--r--contrib/python/attrs/attr/converters.pyi13
-rw-r--r--contrib/python/attrs/attr/exceptions.py92
-rw-r--r--contrib/python/attrs/attr/exceptions.pyi18
-rw-r--r--contrib/python/attrs/attr/filters.py52
-rw-r--r--contrib/python/attrs/attr/filters.pyi7
-rw-r--r--contrib/python/attrs/attr/py.typed0
-rw-r--r--contrib/python/attrs/attr/setters.py77
-rw-r--r--contrib/python/attrs/attr/setters.pyi20
-rw-r--r--contrib/python/attrs/attr/validators.py379
-rw-r--r--contrib/python/attrs/attr/validators.pyi68
28 files changed, 0 insertions, 5888 deletions
diff --git a/contrib/python/attrs/.dist-info/METADATA b/contrib/python/attrs/.dist-info/METADATA
deleted file mode 100644
index ceca5b9adfe..00000000000
--- a/contrib/python/attrs/.dist-info/METADATA
+++ /dev/null
@@ -1,211 +0,0 @@
-Metadata-Version: 2.1
-Name: attrs
-Version: 21.2.0
-Summary: Classes Without Boilerplate
-Home-page: https://www.attrs.org/
-Author: Hynek Schlawack
-Author-email: hs@ox.cx
-Maintainer: Hynek Schlawack
-Maintainer-email: hs@ox.cx
-License: MIT
-Project-URL: Documentation, https://www.attrs.org/
-Project-URL: Changelog, https://www.attrs.org/en/stable/changelog.html
-Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues
-Project-URL: Source Code, https://github.com/python-attrs/attrs
-Project-URL: Funding, https://github.com/sponsors/hynek
-Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi
-Project-URL: Ko-fi, https://ko-fi.com/the_hynek
-Keywords: class,attribute,boilerplate
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Natural Language :: English
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
-Description-Content-Type: text/x-rst
-Provides-Extra: dev
-Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'dev'
-Requires-Dist: hypothesis ; extra == 'dev'
-Requires-Dist: pympler ; extra == 'dev'
-Requires-Dist: pytest (>=4.3.0) ; extra == 'dev'
-Requires-Dist: six ; extra == 'dev'
-Requires-Dist: mypy ; extra == 'dev'
-Requires-Dist: pytest-mypy-plugins ; extra == 'dev'
-Requires-Dist: zope.interface ; extra == 'dev'
-Requires-Dist: furo ; extra == 'dev'
-Requires-Dist: sphinx ; extra == 'dev'
-Requires-Dist: sphinx-notfound-page ; extra == 'dev'
-Requires-Dist: pre-commit ; extra == 'dev'
-Provides-Extra: docs
-Requires-Dist: furo ; extra == 'docs'
-Requires-Dist: sphinx ; extra == 'docs'
-Requires-Dist: zope.interface ; extra == 'docs'
-Requires-Dist: sphinx-notfound-page ; extra == 'docs'
-Provides-Extra: tests
-Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests'
-Requires-Dist: hypothesis ; extra == 'tests'
-Requires-Dist: pympler ; extra == 'tests'
-Requires-Dist: pytest (>=4.3.0) ; extra == 'tests'
-Requires-Dist: six ; extra == 'tests'
-Requires-Dist: mypy ; extra == 'tests'
-Requires-Dist: pytest-mypy-plugins ; extra == 'tests'
-Requires-Dist: zope.interface ; extra == 'tests'
-Provides-Extra: tests_no_zope
-Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope'
-Requires-Dist: hypothesis ; extra == 'tests_no_zope'
-Requires-Dist: pympler ; extra == 'tests_no_zope'
-Requires-Dist: pytest (>=4.3.0) ; extra == 'tests_no_zope'
-Requires-Dist: six ; extra == 'tests_no_zope'
-Requires-Dist: mypy ; extra == 'tests_no_zope'
-Requires-Dist: pytest-mypy-plugins ; extra == 'tests_no_zope'
-
-======================================
-``attrs``: Classes Without Boilerplate
-======================================
-
-
-``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder <https://nedbatchelder.com/blog/200605/dunder.html>`_ methods).
-`Trusted by NASA <https://docs.github.com/en/github/setting-up-and-managing-your-github-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-badge>`_ for Mars missions since 2020!
-
-Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
-
-.. teaser-end
-
-For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
-
-.. -code-begin-
-
-.. code-block:: pycon
-
- >>> import attr
-
- >>> @attr.s
- ... class SomeClass(object):
- ... a_number = attr.ib(default=42)
- ... list_of_numbers = attr.ib(factory=list)
- ...
- ... def hard_math(self, another_number):
- ... return self.a_number + sum(self.list_of_numbers) * another_number
-
-
- >>> sc = SomeClass(1, [1, 2, 3])
- >>> sc
- SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
-
- >>> sc.hard_math(3)
- 19
- >>> sc == SomeClass(1, [1, 2, 3])
- True
- >>> sc != SomeClass(2, [3, 2, 1])
- True
-
- >>> attr.asdict(sc)
- {'a_number': 1, 'list_of_numbers': [1, 2, 3]}
-
- >>> SomeClass()
- SomeClass(a_number=42, list_of_numbers=[])
-
- >>> C = attr.make_class("C", ["a", "b"])
- >>> C("foo", "bar")
- C(a='foo', b='bar')
-
-
-After *declaring* your attributes ``attrs`` gives you:
-
-- a concise and explicit overview of the class's attributes,
-- a nice human-readable ``__repr__``,
-- a complete set of comparison methods (equality and ordering),
-- an initializer,
-- and much more,
-
-*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
-
-On Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations <https://www.attrs.org/en/latest/types.html>`_.
-
-This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving <https://www.attrs.org/en/stable/why.html#namedtuples>`_ ``namedtuple``\ s.
-Which in turn encourages you to write *small classes* that do `one thing well <https://www.destroyallsoftware.com/talks/boundaries>`_.
-Never again violate the `single responsibility principle <https://en.wikipedia.org/wiki/Single_responsibility_principle>`_ just because implementing ``__init__`` et al is a painful drag.
-
-
-.. -getting-help-
-
-Getting Help
-============
-
-Please use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ to get help.
-
-Answering questions of your fellow developers is also a great way to help the project!
-
-
-.. -project-information-
-
-Project Information
-===================
-
-``attrs`` is released under the `MIT <https://choosealicense.com/licenses/mit/>`_ license,
-its documentation lives at `Read the Docs <https://www.attrs.org/>`_,
-the code on `GitHub <https://github.com/python-attrs/attrs>`_,
-and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
-It’s rigorously tested on Python 2.7, 3.5+, and PyPy.
-
-We collect information on **third-party extensions** in our `wiki <https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs>`_.
-Feel free to browse and add your own!
-
-If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide <https://www.attrs.org/en/latest/contributing.html>`_ to get you started!
-
-
-``attrs`` for Enterprise
-------------------------
-
-Available as part of the Tidelift Subscription.
-
-The maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.
-Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
-`Learn more. <https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
-
-
-Release Information
-===================
-
-21.2.0 (2021-05-07)
--------------------
-
-Backward-incompatible Changes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-- We had to revert the recursive feature for ``attr.evolve()`` because it broke some use-cases -- sorry!
- `#806 <https://github.com/python-attrs/attrs/issues/806>`_
-- Python 3.4 is now blocked using packaging metadata because ``attrs`` can't be imported on it anymore.
- To ensure that 3.4 users can keep installing ``attrs`` easily, we will `yank <https://pypi.org/help/#yanked>`_ 21.1.0 from PyPI.
- This has **no** consequences if you pin ``attrs`` to 21.1.0.
- `#807 <https://github.com/python-attrs/attrs/issues/807>`_
-
-`Full changelog <https://www.attrs.org/en/stable/changelog.html>`_.
-
-Credits
-=======
-
-``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_.
-
-The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_.
-
-A full list of contributors can be found in `GitHub's overview <https://github.com/python-attrs/attrs/graphs/contributors>`_.
-
-It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.io/>`_ and aspires to fix some of it clunkiness and unfortunate decisions.
-Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `subclassing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay?
-
-
diff --git a/contrib/python/attrs/.dist-info/top_level.txt b/contrib/python/attrs/.dist-info/top_level.txt
deleted file mode 100644
index 66a062d889d..00000000000
--- a/contrib/python/attrs/.dist-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-attr
diff --git a/contrib/python/attrs/.yandex_meta/yamaker.yaml b/contrib/python/attrs/.yandex_meta/yamaker.yaml
deleted file mode 100644
index c14879ed876..00000000000
--- a/contrib/python/attrs/.yandex_meta/yamaker.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-mark_as_py3_sources:
-- attr/_next_gen.py
diff --git a/contrib/python/attrs/AUTHORS.rst b/contrib/python/attrs/AUTHORS.rst
deleted file mode 100644
index f14ef6c6074..00000000000
--- a/contrib/python/attrs/AUTHORS.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-Credits
-=======
-
-``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_.
-
-The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_.
-
-A full list of contributors can be found in `GitHub's overview <https://github.com/python-attrs/attrs/graphs/contributors>`_.
-
-It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.io/>`_ and aspires to fix some of it clunkiness and unfortunate decisions.
-Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `subclassing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay?
diff --git a/contrib/python/attrs/LICENSE b/contrib/python/attrs/LICENSE
deleted file mode 100644
index 7ae3df93097..00000000000
--- a/contrib/python/attrs/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Hynek Schlawack
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/contrib/python/attrs/README.rst b/contrib/python/attrs/README.rst
deleted file mode 100644
index d080f1de81a..00000000000
--- a/contrib/python/attrs/README.rst
+++ /dev/null
@@ -1,122 +0,0 @@
-.. raw:: html
-
- <p align="center">
- <a href="https://www.attrs.org/">
- <img src="./docs/_static/attrs_logo.svg" width="35%" alt="attrs" />
- </a>
- </p>
- <p align="center">
- <a href="https://www.attrs.org/en/stable/?badge=stable">
- <img src="https://readthedocs.org/projects/attrs/badge/?version=stable" alt="Documentation Status" />
- </a>
- <a href="https://github.com/python-attrs/attrs/actions?workflow=CI">
- <img src="https://github.com/python-attrs/attrs/workflows/CI/badge.svg?branch=main" alt="CI Status" />
- </a>
- <a href="https://codecov.io/github/python-attrs/attrs">
- <img src="https://codecov.io/github/python-attrs/attrs/branch/main/graph/badge.svg" alt="Test Coverage" />
- </a>
- <a href="https://github.com/psf/black">
- <img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code style: black" />
- </a>
- </p>
-
-.. teaser-begin
-
-``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder <https://nedbatchelder.com/blog/200605/dunder.html>`_ methods).
-`Trusted by NASA <https://docs.github.com/en/github/setting-up-and-managing-your-github-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-badge>`_ for Mars missions since 2020!
-
-Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
-
-.. teaser-end
-
-For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
-
-.. -code-begin-
-
-.. code-block:: pycon
-
- >>> import attr
-
- >>> @attr.s
- ... class SomeClass(object):
- ... a_number = attr.ib(default=42)
- ... list_of_numbers = attr.ib(factory=list)
- ...
- ... def hard_math(self, another_number):
- ... return self.a_number + sum(self.list_of_numbers) * another_number
-
-
- >>> sc = SomeClass(1, [1, 2, 3])
- >>> sc
- SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
-
- >>> sc.hard_math(3)
- 19
- >>> sc == SomeClass(1, [1, 2, 3])
- True
- >>> sc != SomeClass(2, [3, 2, 1])
- True
-
- >>> attr.asdict(sc)
- {'a_number': 1, 'list_of_numbers': [1, 2, 3]}
-
- >>> SomeClass()
- SomeClass(a_number=42, list_of_numbers=[])
-
- >>> C = attr.make_class("C", ["a", "b"])
- >>> C("foo", "bar")
- C(a='foo', b='bar')
-
-
-After *declaring* your attributes ``attrs`` gives you:
-
-- a concise and explicit overview of the class's attributes,
-- a nice human-readable ``__repr__``,
-- a complete set of comparison methods (equality and ordering),
-- an initializer,
-- and much more,
-
-*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
-
-On Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations <https://www.attrs.org/en/latest/types.html>`_.
-
-This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving <https://www.attrs.org/en/stable/why.html#namedtuples>`_ ``namedtuple``\ s.
-Which in turn encourages you to write *small classes* that do `one thing well <https://www.destroyallsoftware.com/talks/boundaries>`_.
-Never again violate the `single responsibility principle <https://en.wikipedia.org/wiki/Single_responsibility_principle>`_ just because implementing ``__init__`` et al is a painful drag.
-
-
-.. -getting-help-
-
-Getting Help
-============
-
-Please use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ to get help.
-
-Answering questions of your fellow developers is also a great way to help the project!
-
-
-.. -project-information-
-
-Project Information
-===================
-
-``attrs`` is released under the `MIT <https://choosealicense.com/licenses/mit/>`_ license,
-its documentation lives at `Read the Docs <https://www.attrs.org/>`_,
-the code on `GitHub <https://github.com/python-attrs/attrs>`_,
-and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
-It’s rigorously tested on Python 2.7, 3.5+, and PyPy.
-
-We collect information on **third-party extensions** in our `wiki <https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs>`_.
-Feel free to browse and add your own!
-
-If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide <https://www.attrs.org/en/latest/contributing.html>`_ to get you started!
-
-
-``attrs`` for Enterprise
-------------------------
-
-Available as part of the Tidelift Subscription.
-
-The maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.
-Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
-`Learn more. <https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
diff --git a/contrib/python/attrs/attr/__init__.py b/contrib/python/attrs/attr/__init__.py
deleted file mode 100644
index b1ce7fe248b..00000000000
--- a/contrib/python/attrs/attr/__init__.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-import sys
-
-from functools import partial
-
-from . import converters, exceptions, filters, setters, validators
-from ._cmp import cmp_using
-from ._config import get_run_validators, set_run_validators
-from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types
-from ._make import (
- NOTHING,
- Attribute,
- Factory,
- attrib,
- attrs,
- fields,
- fields_dict,
- make_class,
- validate,
-)
-from ._version_info import VersionInfo
-
-
-__version__ = "21.2.0"
-__version_info__ = VersionInfo._from_version_string(__version__)
-
-__title__ = "attrs"
-__description__ = "Classes Without Boilerplate"
-__url__ = "https://www.attrs.org/"
-__uri__ = __url__
-__doc__ = __description__ + " <" + __uri__ + ">"
-
-__author__ = "Hynek Schlawack"
-__email__ = "hs@ox.cx"
-
-__license__ = "MIT"
-__copyright__ = "Copyright (c) 2015 Hynek Schlawack"
-
-
-s = attributes = attrs
-ib = attr = attrib
-dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
-
-__all__ = [
- "Attribute",
- "Factory",
- "NOTHING",
- "asdict",
- "assoc",
- "astuple",
- "attr",
- "attrib",
- "attributes",
- "attrs",
- "cmp_using",
- "converters",
- "evolve",
- "exceptions",
- "fields",
- "fields_dict",
- "filters",
- "get_run_validators",
- "has",
- "ib",
- "make_class",
- "resolve_types",
- "s",
- "set_run_validators",
- "setters",
- "validate",
- "validators",
-]
-
-if sys.version_info[:2] >= (3, 6):
- from ._next_gen import define, field, frozen, mutable
-
- __all__.extend((define, field, frozen, mutable))
diff --git a/contrib/python/attrs/attr/__init__.pyi b/contrib/python/attrs/attr/__init__.pyi
deleted file mode 100644
index 3503b073b4d..00000000000
--- a/contrib/python/attrs/attr/__init__.pyi
+++ /dev/null
@@ -1,475 +0,0 @@
-import sys
-
-from typing import (
- Any,
- Callable,
- Dict,
- Generic,
- List,
- Mapping,
- Optional,
- Sequence,
- Tuple,
- Type,
- TypeVar,
- Union,
- overload,
-)
-
-# `import X as X` is required to make these public
-from . import converters as converters
-from . import exceptions as exceptions
-from . import filters as filters
-from . import setters as setters
-from . import validators as validators
-from ._version_info import VersionInfo
-
-
-__version__: str
-__version_info__: VersionInfo
-__title__: str
-__description__: str
-__url__: str
-__uri__: str
-__author__: str
-__email__: str
-__license__: str
-__copyright__: str
-
-_T = TypeVar("_T")
-_C = TypeVar("_C", bound=type)
-
-_EqOrderType = Union[bool, Callable[[Any], Any]]
-_ValidatorType = Callable[[Any, Attribute[_T], _T], Any]
-_ConverterType = Callable[[Any], Any]
-_FilterType = Callable[[Attribute[_T], _T], bool]
-_ReprType = Callable[[Any], str]
-_ReprArgType = Union[bool, _ReprType]
-_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any]
-_OnSetAttrArgType = Union[
- _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType
-]
-_FieldTransformer = Callable[[type, List[Attribute[Any]]], List[Attribute[Any]]]
-# FIXME: in reality, if multiple validators are passed they must be in a list
-# or tuple, but those are invariant and so would prevent subtypes of
-# _ValidatorType from working when passed in a list or tuple.
-_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
-
-# _make --
-
-NOTHING: object
-
-# NOTE: Factory lies about its return type to make this possible:
-# `x: List[int] # = Factory(list)`
-# Work around mypy issue #4554 in the common case by using an overload.
-if sys.version_info >= (3, 8):
- from typing import Literal
-
- @overload
- def Factory(factory: Callable[[], _T]) -> _T: ...
- @overload
- def Factory(
- factory: Callable[[Any], _T],
- takes_self: Literal[True],
- ) -> _T: ...
- @overload
- def Factory(
- factory: Callable[[], _T],
- takes_self: Literal[False],
- ) -> _T: ...
-else:
- @overload
- def Factory(factory: Callable[[], _T]) -> _T: ...
- @overload
- def Factory(
- factory: Union[Callable[[Any], _T], Callable[[], _T]],
- takes_self: bool = ...,
- ) -> _T: ...
-
-# Static type inference support via __dataclass_transform__ implemented as per:
-# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md
-# This annotation must be applied to all overloads of "define" and "attrs"
-#
-# NOTE: This is a typing construct and does not exist at runtime. Extensions
-# wrapping attrs decorators should declare a separate __dataclass_transform__
-# signature in the extension module using the specification linked above to
-# provide pyright support.
-def __dataclass_transform__(
- *,
- eq_default: bool = True,
- order_default: bool = False,
- kw_only_default: bool = False,
- field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
-) -> Callable[[_T], _T]: ...
-
-class Attribute(Generic[_T]):
- name: str
- default: Optional[_T]
- validator: Optional[_ValidatorType[_T]]
- repr: _ReprArgType
- cmp: _EqOrderType
- eq: _EqOrderType
- order: _EqOrderType
- hash: Optional[bool]
- init: bool
- converter: Optional[_ConverterType]
- metadata: Dict[Any, Any]
- type: Optional[Type[_T]]
- kw_only: bool
- on_setattr: _OnSetAttrType
-
- def evolve(self, **changes: Any) -> "Attribute[Any]": ...
-
-# NOTE: We had several choices for the annotation to use for type arg:
-# 1) Type[_T]
-# - Pros: Handles simple cases correctly
-# - Cons: Might produce less informative errors in the case of conflicting
-# TypeVars e.g. `attr.ib(default='bad', type=int)`
-# 2) Callable[..., _T]
-# - Pros: Better error messages than #1 for conflicting TypeVars
-# - Cons: Terrible error messages for validator checks.
-# e.g. attr.ib(type=int, validator=validate_str)
-# -> error: Cannot infer function type argument
-# 3) type (and do all of the work in the mypy plugin)
-# - Pros: Simple here, and we could customize the plugin with our own errors.
-# - Cons: Would need to write mypy plugin code to handle all the cases.
-# We chose option #1.
-
-# `attr` lies about its return type to make the following possible:
-# attr() -> Any
-# attr(8) -> int
-# attr(validator=<some callable>) -> Whatever the callable expects.
-# This makes this type of assignments possible:
-# x: int = attr(8)
-#
-# This form catches explicit None or no default but with no other arguments
-# returns Any.
-@overload
-def attrib(
- default: None = ...,
- validator: None = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: None = ...,
- converter: None = ...,
- factory: None = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> Any: ...
-
-# This form catches an explicit None or no default and infers the type from the
-# other arguments.
-@overload
-def attrib(
- default: None = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: Optional[Type[_T]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> _T: ...
-
-# This form catches an explicit default argument.
-@overload
-def attrib(
- default: _T,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: Optional[Type[_T]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> _T: ...
-
-# This form covers type=non-Type: e.g. forward references (str), Any
-@overload
-def attrib(
- default: Optional[_T] = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: object = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> Any: ...
-@overload
-def field(
- *,
- default: None = ...,
- validator: None = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: None = ...,
- factory: None = ...,
- kw_only: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> Any: ...
-
-# This form catches an explicit None or no default and infers the type from the
-# other arguments.
-@overload
-def field(
- *,
- default: None = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> _T: ...
-
-# This form catches an explicit default argument.
-@overload
-def field(
- *,
- default: _T,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> _T: ...
-
-# This form covers type=non-Type: e.g. forward references (str), Any
-@overload
-def field(
- *,
- default: Optional[_T] = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
-) -> Any: ...
-@overload
-@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
-def attrs(
- maybe_cls: _C,
- these: Optional[Dict[str, Any]] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- auto_detect: bool = ...,
- collect_by_mro: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> _C: ...
-@overload
-@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
-def attrs(
- maybe_cls: None = ...,
- these: Optional[Dict[str, Any]] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- auto_detect: bool = ...,
- collect_by_mro: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> Callable[[_C], _C]: ...
-@overload
-@__dataclass_transform__(field_descriptors=(attrib, field))
-def define(
- maybe_cls: _C,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> _C: ...
-@overload
-@__dataclass_transform__(field_descriptors=(attrib, field))
-def define(
- maybe_cls: None = ...,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> Callable[[_C], _C]: ...
-
-mutable = define
-frozen = define # they differ only in their defaults
-
-# TODO: add support for returning NamedTuple from the mypy plugin
-class _Fields(Tuple[Attribute[Any], ...]):
- def __getattr__(self, name: str) -> Attribute[Any]: ...
-
-def fields(cls: type) -> _Fields: ...
-def fields_dict(cls: type) -> Dict[str, Attribute[Any]]: ...
-def validate(inst: Any) -> None: ...
-def resolve_types(
- cls: _C,
- globalns: Optional[Dict[str, Any]] = ...,
- localns: Optional[Dict[str, Any]] = ...,
- attribs: Optional[List[Attribute[Any]]] = ...,
-) -> _C: ...
-
-# TODO: add support for returning a proper attrs class from the mypy plugin
-# we use Any instead of _CountingAttr so that e.g. `make_class('Foo',
-# [attr.ib()])` is valid
-def make_class(
- name: str,
- attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
- bases: Tuple[type, ...] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- collect_by_mro: bool = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> type: ...
-
-# _funcs --
-
-# TODO: add support for returning TypedDict from the mypy plugin
-# FIXME: asdict/astuple do not honor their factory args. Waiting on one of
-# these:
-# https://github.com/python/mypy/issues/4236
-# https://github.com/python/typing/issues/253
-def asdict(
- inst: Any,
- recurse: bool = ...,
- filter: Optional[_FilterType[Any]] = ...,
- dict_factory: Type[Mapping[Any, Any]] = ...,
- retain_collection_types: bool = ...,
- value_serializer: Optional[Callable[[type, Attribute[Any], Any], Any]] = ...,
-) -> Dict[str, Any]: ...
-
-# TODO: add support for returning NamedTuple from the mypy plugin
-def astuple(
- inst: Any,
- recurse: bool = ...,
- filter: Optional[_FilterType[Any]] = ...,
- tuple_factory: Type[Sequence[Any]] = ...,
- retain_collection_types: bool = ...,
-) -> Tuple[Any, ...]: ...
-def has(cls: type) -> bool: ...
-def assoc(inst: _T, **changes: Any) -> _T: ...
-def evolve(inst: _T, **changes: Any) -> _T: ...
-
-# _config --
-
-def set_run_validators(run: bool) -> None: ...
-def get_run_validators() -> bool: ...
-
-# aliases --
-
-s = attributes = attrs
-ib = attr = attrib
-dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;)
diff --git a/contrib/python/attrs/attr/_cmp.py b/contrib/python/attrs/attr/_cmp.py
deleted file mode 100644
index b747b603f17..00000000000
--- a/contrib/python/attrs/attr/_cmp.py
+++ /dev/null
@@ -1,152 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-import functools
-
-from ._compat import new_class
-from ._make import _make_ne
-
-
-_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="}
-
-
-def cmp_using(
- eq=None,
- lt=None,
- le=None,
- gt=None,
- ge=None,
- require_same_type=True,
- class_name="Comparable",
-):
- """
- Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and
- ``cmp`` arguments to customize field comparison.
-
- The resulting class will have a full set of ordering methods if
- at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided.
-
- :param Optional[callable] eq: `callable` used to evaluate equality
- of two objects.
- :param Optional[callable] lt: `callable` used to evaluate whether
- one object is less than another object.
- :param Optional[callable] le: `callable` used to evaluate whether
- one object is less than or equal to another object.
- :param Optional[callable] gt: `callable` used to evaluate whether
- one object is greater than another object.
- :param Optional[callable] ge: `callable` used to evaluate whether
- one object is greater than or equal to another object.
-
- :param bool require_same_type: When `True`, equality and ordering methods
- will return `NotImplemented` if objects are not of the same type.
-
- :param Optional[str] class_name: Name of class. Defaults to 'Comparable'.
-
- See `comparison` for more details.
-
- .. versionadded:: 21.1.0
- """
-
- body = {
- "__slots__": ["value"],
- "__init__": _make_init(),
- "_requirements": [],
- "_is_comparable_to": _is_comparable_to,
- }
-
- # Add operations.
- num_order_functions = 0
- has_eq_function = False
-
- if eq is not None:
- has_eq_function = True
- body["__eq__"] = _make_operator("eq", eq)
- body["__ne__"] = _make_ne()
-
- if lt is not None:
- num_order_functions += 1
- body["__lt__"] = _make_operator("lt", lt)
-
- if le is not None:
- num_order_functions += 1
- body["__le__"] = _make_operator("le", le)
-
- if gt is not None:
- num_order_functions += 1
- body["__gt__"] = _make_operator("gt", gt)
-
- if ge is not None:
- num_order_functions += 1
- body["__ge__"] = _make_operator("ge", ge)
-
- type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body))
-
- # Add same type requirement.
- if require_same_type:
- type_._requirements.append(_check_same_type)
-
- # Add total ordering if at least one operation was defined.
- if 0 < num_order_functions < 4:
- if not has_eq_function:
- # functools.total_ordering requires __eq__ to be defined,
- # so raise early error here to keep a nice stack.
- raise ValueError(
- "eq must be define is order to complete ordering from "
- "lt, le, gt, ge."
- )
- type_ = functools.total_ordering(type_)
-
- return type_
-
-
-def _make_init():
- """
- Create __init__ method.
- """
-
- def __init__(self, value):
- """
- Initialize object with *value*.
- """
- self.value = value
-
- return __init__
-
-
-def _make_operator(name, func):
- """
- Create operator method.
- """
-
- def method(self, other):
- if not self._is_comparable_to(other):
- return NotImplemented
-
- result = func(self.value, other.value)
- if result is NotImplemented:
- return NotImplemented
-
- return result
-
- method.__name__ = "__%s__" % (name,)
- method.__doc__ = "Return a %s b. Computed by attrs." % (
- _operation_names[name],
- )
-
- return method
-
-
-def _is_comparable_to(self, other):
- """
- Check whether `other` is comparable to `self`.
- """
- for func in self._requirements:
- if not func(self, other):
- return False
- return True
-
-
-def _check_same_type(self, other):
- """
- Return True if *self* and *other* are of the same type, False otherwise.
- """
- return other.value.__class__ is self.value.__class__
diff --git a/contrib/python/attrs/attr/_cmp.pyi b/contrib/python/attrs/attr/_cmp.pyi
deleted file mode 100644
index 7093550f0f8..00000000000
--- a/contrib/python/attrs/attr/_cmp.pyi
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import Type
-
-from . import _CompareWithType
-
-
-def cmp_using(
- eq: Optional[_CompareWithType],
- lt: Optional[_CompareWithType],
- le: Optional[_CompareWithType],
- gt: Optional[_CompareWithType],
- ge: Optional[_CompareWithType],
- require_same_type: bool,
- class_name: str,
-) -> Type: ...
diff --git a/contrib/python/attrs/attr/_compat.py b/contrib/python/attrs/attr/_compat.py
deleted file mode 100644
index 6939f338dad..00000000000
--- a/contrib/python/attrs/attr/_compat.py
+++ /dev/null
@@ -1,242 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-import platform
-import sys
-import types
-import warnings
-
-
-PY2 = sys.version_info[0] == 2
-PYPY = platform.python_implementation() == "PyPy"
-
-
-if PYPY or sys.version_info[:2] >= (3, 6):
- ordered_dict = dict
-else:
- from collections import OrderedDict
-
- ordered_dict = OrderedDict
-
-
-if PY2:
- from collections import Mapping, Sequence
-
- from UserDict import IterableUserDict
-
- # We 'bundle' isclass instead of using inspect as importing inspect is
- # fairly expensive (order of 10-15 ms for a modern machine in 2016)
- def isclass(klass):
- return isinstance(klass, (type, types.ClassType))
-
- def new_class(name, bases, kwds, exec_body):
- """
- A minimal stub of types.new_class that we need for make_class.
- """
- ns = {}
- exec_body(ns)
-
- return type(name, bases, ns)
-
- # TYPE is used in exceptions, repr(int) is different on Python 2 and 3.
- TYPE = "type"
-
- def iteritems(d):
- return d.iteritems()
-
- # Python 2 is bereft of a read-only dict proxy, so we make one!
- class ReadOnlyDict(IterableUserDict):
- """
- Best-effort read-only dict wrapper.
- """
-
- def __setitem__(self, key, val):
- # We gently pretend we're a Python 3 mappingproxy.
- raise TypeError(
- "'mappingproxy' object does not support item assignment"
- )
-
- def update(self, _):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError(
- "'mappingproxy' object has no attribute 'update'"
- )
-
- def __delitem__(self, _):
- # We gently pretend we're a Python 3 mappingproxy.
- raise TypeError(
- "'mappingproxy' object does not support item deletion"
- )
-
- def clear(self):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError(
- "'mappingproxy' object has no attribute 'clear'"
- )
-
- def pop(self, key, default=None):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError(
- "'mappingproxy' object has no attribute 'pop'"
- )
-
- def popitem(self):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError(
- "'mappingproxy' object has no attribute 'popitem'"
- )
-
- def setdefault(self, key, default=None):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError(
- "'mappingproxy' object has no attribute 'setdefault'"
- )
-
- def __repr__(self):
- # Override to be identical to the Python 3 version.
- return "mappingproxy(" + repr(self.data) + ")"
-
- def metadata_proxy(d):
- res = ReadOnlyDict()
- res.data.update(d) # We blocked update, so we have to do it like this.
- return res
-
- def just_warn(*args, **kw): # pragma: no cover
- """
- We only warn on Python 3 because we are not aware of any concrete
- consequences of not setting the cell on Python 2.
- """
-
-
-else: # Python 3 and later.
- from collections.abc import Mapping, Sequence # noqa
-
- def just_warn(*args, **kw):
- """
- We only warn on Python 3 because we are not aware of any concrete
- consequences of not setting the cell on Python 2.
- """
- warnings.warn(
- "Running interpreter doesn't sufficiently support code object "
- "introspection. Some features like bare super() or accessing "
- "__class__ will not work with slotted classes.",
- RuntimeWarning,
- stacklevel=2,
- )
-
- def isclass(klass):
- return isinstance(klass, type)
-
- TYPE = "class"
-
- def iteritems(d):
- return d.items()
-
- new_class = types.new_class
-
- def metadata_proxy(d):
- return types.MappingProxyType(dict(d))
-
-
-def make_set_closure_cell():
- """Return a function of two arguments (cell, value) which sets
- the value stored in the closure cell `cell` to `value`.
- """
- # pypy makes this easy. (It also supports the logic below, but
- # why not do the easy/fast thing?)
- if PYPY:
-
- def set_closure_cell(cell, value):
- cell.__setstate__((value,))
-
- return set_closure_cell
-
- # Otherwise gotta do it the hard way.
-
- # Create a function that will set its first cellvar to `value`.
- def set_first_cellvar_to(value):
- x = value
- return
-
- # This function will be eliminated as dead code, but
- # not before its reference to `x` forces `x` to be
- # represented as a closure cell rather than a local.
- def force_x_to_be_a_cell(): # pragma: no cover
- return x
-
- try:
- # Extract the code object and make sure our assumptions about
- # the closure behavior are correct.
- if PY2:
- co = set_first_cellvar_to.func_code
- else:
- co = set_first_cellvar_to.__code__
- if co.co_cellvars != ("x",) or co.co_freevars != ():
- raise AssertionError # pragma: no cover
-
- # Convert this code object to a code object that sets the
- # function's first _freevar_ (not cellvar) to the argument.
- if sys.version_info >= (3, 8):
- # CPython 3.8+ has an incompatible CodeType signature
- # (added a posonlyargcount argument) but also added
- # CodeType.replace() to do this without counting parameters.
- set_first_freevar_code = co.replace(
- co_cellvars=co.co_freevars, co_freevars=co.co_cellvars
- )
- else:
- args = [co.co_argcount]
- if not PY2:
- args.append(co.co_kwonlyargcount)
- args.extend(
- [
- co.co_nlocals,
- co.co_stacksize,
- co.co_flags,
- co.co_code,
- co.co_consts,
- co.co_names,
- co.co_varnames,
- co.co_filename,
- co.co_name,
- co.co_firstlineno,
- co.co_lnotab,
- # These two arguments are reversed:
- co.co_cellvars,
- co.co_freevars,
- ]
- )
- set_first_freevar_code = types.CodeType(*args)
-
- def set_closure_cell(cell, value):
- # Create a function using the set_first_freevar_code,
- # whose first closure cell is `cell`. Calling it will
- # change the value of that cell.
- setter = types.FunctionType(
- set_first_freevar_code, {}, "setter", (), (cell,)
- )
- # And call it to set the cell.
- setter(value)
-
- # Make sure it works on this interpreter:
- def make_func_with_cell():
- x = None
-
- def func():
- return x # pragma: no cover
-
- return func
-
- if PY2:
- cell = make_func_with_cell().func_closure[0]
- else:
- cell = make_func_with_cell().__closure__[0]
- set_closure_cell(cell, 100)
- if cell.cell_contents != 100:
- raise AssertionError # pragma: no cover
-
- except Exception:
- return just_warn
- else:
- return set_closure_cell
-
-
-set_closure_cell = make_set_closure_cell()
diff --git a/contrib/python/attrs/attr/_config.py b/contrib/python/attrs/attr/_config.py
deleted file mode 100644
index 8ec920962d1..00000000000
--- a/contrib/python/attrs/attr/_config.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-
-__all__ = ["set_run_validators", "get_run_validators"]
-
-_run_validators = True
-
-
-def set_run_validators(run):
- """
- Set whether or not validators are run. By default, they are run.
- """
- if not isinstance(run, bool):
- raise TypeError("'run' must be bool.")
- global _run_validators
- _run_validators = run
-
-
-def get_run_validators():
- """
- Return whether or not validators are run.
- """
- return _run_validators
diff --git a/contrib/python/attrs/attr/_funcs.py b/contrib/python/attrs/attr/_funcs.py
deleted file mode 100644
index fda508c5c4b..00000000000
--- a/contrib/python/attrs/attr/_funcs.py
+++ /dev/null
@@ -1,395 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-import copy
-
-from ._compat import iteritems
-from ._make import NOTHING, _obj_setattr, fields
-from .exceptions import AttrsAttributeNotFoundError
-
-
-def asdict(
- inst,
- recurse=True,
- filter=None,
- dict_factory=dict,
- retain_collection_types=False,
- value_serializer=None,
-):
- """
- Return the ``attrs`` attribute values of *inst* as a dict.
-
- Optionally recurse into other ``attrs``-decorated classes.
-
- :param inst: Instance of an ``attrs``-decorated class.
- :param bool recurse: Recurse into classes that are also
- ``attrs``-decorated.
- :param callable filter: A callable whose return code determines whether an
- attribute or element is included (``True``) or dropped (``False``). Is
- called with the `attr.Attribute` as the first argument and the
- value as the second argument.
- :param callable dict_factory: A callable to produce dictionaries from. For
- example, to produce ordered dictionaries instead of normal Python
- dictionaries, pass in ``collections.OrderedDict``.
- :param bool retain_collection_types: Do not convert to ``list`` when
- encountering an attribute whose type is ``tuple`` or ``set``. Only
- meaningful if ``recurse`` is ``True``.
- :param Optional[callable] value_serializer: A hook that is called for every
- attribute or dict key/value. It receives the current instance, field
- and value and must return the (updated) value. The hook is run *after*
- the optional *filter* has been applied.
-
- :rtype: return type of *dict_factory*
-
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- .. versionadded:: 16.0.0 *dict_factory*
- .. versionadded:: 16.1.0 *retain_collection_types*
- .. versionadded:: 20.3.0 *value_serializer*
- """
- attrs = fields(inst.__class__)
- rv = dict_factory()
- for a in attrs:
- v = getattr(inst, a.name)
- if filter is not None and not filter(a, v):
- continue
-
- if value_serializer is not None:
- v = value_serializer(inst, a, v)
-
- if recurse is True:
- if has(v.__class__):
- rv[a.name] = asdict(
- v,
- True,
- filter,
- dict_factory,
- retain_collection_types,
- value_serializer,
- )
- elif isinstance(v, (tuple, list, set, frozenset)):
- cf = v.__class__ if retain_collection_types is True else list
- rv[a.name] = cf(
- [
- _asdict_anything(
- i,
- filter,
- dict_factory,
- retain_collection_types,
- value_serializer,
- )
- for i in v
- ]
- )
- elif isinstance(v, dict):
- df = dict_factory
- rv[a.name] = df(
- (
- _asdict_anything(
- kk,
- filter,
- df,
- retain_collection_types,
- value_serializer,
- ),
- _asdict_anything(
- vv,
- filter,
- df,
- retain_collection_types,
- value_serializer,
- ),
- )
- for kk, vv in iteritems(v)
- )
- else:
- rv[a.name] = v
- else:
- rv[a.name] = v
- return rv
-
-
-def _asdict_anything(
- val,
- filter,
- dict_factory,
- retain_collection_types,
- value_serializer,
-):
- """
- ``asdict`` only works on attrs instances, this works on anything.
- """
- if getattr(val.__class__, "__attrs_attrs__", None) is not None:
- # Attrs class.
- rv = asdict(
- val,
- True,
- filter,
- dict_factory,
- retain_collection_types,
- value_serializer,
- )
- elif isinstance(val, (tuple, list, set, frozenset)):
- cf = val.__class__ if retain_collection_types is True else list
- rv = cf(
- [
- _asdict_anything(
- i,
- filter,
- dict_factory,
- retain_collection_types,
- value_serializer,
- )
- for i in val
- ]
- )
- elif isinstance(val, dict):
- df = dict_factory
- rv = df(
- (
- _asdict_anything(
- kk, filter, df, retain_collection_types, value_serializer
- ),
- _asdict_anything(
- vv, filter, df, retain_collection_types, value_serializer
- ),
- )
- for kk, vv in iteritems(val)
- )
- else:
- rv = val
- if value_serializer is not None:
- rv = value_serializer(None, None, rv)
-
- return rv
-
-
-def astuple(
- inst,
- recurse=True,
- filter=None,
- tuple_factory=tuple,
- retain_collection_types=False,
-):
- """
- Return the ``attrs`` attribute values of *inst* as a tuple.
-
- Optionally recurse into other ``attrs``-decorated classes.
-
- :param inst: Instance of an ``attrs``-decorated class.
- :param bool recurse: Recurse into classes that are also
- ``attrs``-decorated.
- :param callable filter: A callable whose return code determines whether an
- attribute or element is included (``True``) or dropped (``False``). Is
- called with the `attr.Attribute` as the first argument and the
- value as the second argument.
- :param callable tuple_factory: A callable to produce tuples from. For
- example, to produce lists instead of tuples.
- :param bool retain_collection_types: Do not convert to ``list``
- or ``dict`` when encountering an attribute which type is
- ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is
- ``True``.
-
- :rtype: return type of *tuple_factory*
-
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- .. versionadded:: 16.2.0
- """
- attrs = fields(inst.__class__)
- rv = []
- retain = retain_collection_types # Very long. :/
- for a in attrs:
- v = getattr(inst, a.name)
- if filter is not None and not filter(a, v):
- continue
- if recurse is True:
- if has(v.__class__):
- rv.append(
- astuple(
- v,
- recurse=True,
- filter=filter,
- tuple_factory=tuple_factory,
- retain_collection_types=retain,
- )
- )
- elif isinstance(v, (tuple, list, set, frozenset)):
- cf = v.__class__ if retain is True else list
- rv.append(
- cf(
- [
- astuple(
- j,
- recurse=True,
- filter=filter,
- tuple_factory=tuple_factory,
- retain_collection_types=retain,
- )
- if has(j.__class__)
- else j
- for j in v
- ]
- )
- )
- elif isinstance(v, dict):
- df = v.__class__ if retain is True else dict
- rv.append(
- df(
- (
- astuple(
- kk,
- tuple_factory=tuple_factory,
- retain_collection_types=retain,
- )
- if has(kk.__class__)
- else kk,
- astuple(
- vv,
- tuple_factory=tuple_factory,
- retain_collection_types=retain,
- )
- if has(vv.__class__)
- else vv,
- )
- for kk, vv in iteritems(v)
- )
- )
- else:
- rv.append(v)
- else:
- rv.append(v)
-
- return rv if tuple_factory is list else tuple_factory(rv)
-
-
-def has(cls):
- """
- Check whether *cls* is a class with ``attrs`` attributes.
-
- :param type cls: Class to introspect.
- :raise TypeError: If *cls* is not a class.
-
- :rtype: bool
- """
- return getattr(cls, "__attrs_attrs__", None) is not None
-
-
-def assoc(inst, **changes):
- """
- Copy *inst* and apply *changes*.
-
- :param inst: Instance of a class with ``attrs`` attributes.
- :param changes: Keyword changes in the new copy.
-
- :return: A copy of inst with *changes* incorporated.
-
- :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't
- be found on *cls*.
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- .. deprecated:: 17.1.0
- Use `evolve` instead.
- """
- import warnings
-
- warnings.warn(
- "assoc is deprecated and will be removed after 2018/01.",
- DeprecationWarning,
- stacklevel=2,
- )
- new = copy.copy(inst)
- attrs = fields(inst.__class__)
- for k, v in iteritems(changes):
- a = getattr(attrs, k, NOTHING)
- if a is NOTHING:
- raise AttrsAttributeNotFoundError(
- "{k} is not an attrs attribute on {cl}.".format(
- k=k, cl=new.__class__
- )
- )
- _obj_setattr(new, k, v)
- return new
-
-
-def evolve(inst, **changes):
- """
- Create a new instance, based on *inst* with *changes* applied.
-
- :param inst: Instance of a class with ``attrs`` attributes.
- :param changes: Keyword changes in the new copy.
-
- :return: A copy of inst with *changes* incorporated.
-
- :raise TypeError: If *attr_name* couldn't be found in the class
- ``__init__``.
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- .. versionadded:: 17.1.0
- """
- cls = inst.__class__
- attrs = fields(cls)
- for a in attrs:
- if not a.init:
- continue
- attr_name = a.name # To deal with private attributes.
- init_name = attr_name if attr_name[0] != "_" else attr_name[1:]
- if init_name not in changes:
- changes[init_name] = getattr(inst, attr_name)
-
- return cls(**changes)
-
-
-def resolve_types(cls, globalns=None, localns=None, attribs=None):
- """
- Resolve any strings and forward annotations in type annotations.
-
- This is only required if you need concrete types in `Attribute`'s *type*
- field. In other words, you don't need to resolve your types if you only
- use them for static type checking.
-
- With no arguments, names will be looked up in the module in which the class
- was created. If this is not what you want, e.g. if the name only exists
- inside a method, you may pass *globalns* or *localns* to specify other
- dictionaries in which to look up these names. See the docs of
- `typing.get_type_hints` for more details.
-
- :param type cls: Class to resolve.
- :param Optional[dict] globalns: Dictionary containing global variables.
- :param Optional[dict] localns: Dictionary containing local variables.
- :param Optional[list] attribs: List of attribs for the given class.
- This is necessary when calling from inside a ``field_transformer``
- since *cls* is not an ``attrs`` class yet.
-
- :raise TypeError: If *cls* is not a class.
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class and you didn't pass any attribs.
- :raise NameError: If types cannot be resolved because of missing variables.
-
- :returns: *cls* so you can use this function also as a class decorator.
- Please note that you have to apply it **after** `attr.s`. That means
- the decorator has to come in the line **before** `attr.s`.
-
- .. versionadded:: 20.1.0
- .. versionadded:: 21.1.0 *attribs*
-
- """
- try:
- # Since calling get_type_hints is expensive we cache whether we've
- # done it already.
- cls.__attrs_types_resolved__
- except AttributeError:
- import typing
-
- hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)
- for field in fields(cls) if attribs is None else attribs:
- if field.name in hints:
- # Since fields have been frozen we must work around it.
- _obj_setattr(field, "type", hints[field.name])
- cls.__attrs_types_resolved__ = True
-
- # Return the class so you can use it as a decorator too.
- return cls
diff --git a/contrib/python/attrs/attr/_make.py b/contrib/python/attrs/attr/_make.py
deleted file mode 100644
index a1912b1233f..00000000000
--- a/contrib/python/attrs/attr/_make.py
+++ /dev/null
@@ -1,3052 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-import copy
-import inspect
-import linecache
-import sys
-import threading
-import uuid
-import warnings
-
-from operator import itemgetter
-
-from . import _config, setters
-from ._compat import (
- PY2,
- PYPY,
- isclass,
- iteritems,
- metadata_proxy,
- new_class,
- ordered_dict,
- set_closure_cell,
-)
-from .exceptions import (
- DefaultAlreadySetError,
- FrozenInstanceError,
- NotAnAttrsClassError,
- PythonTooOldError,
- UnannotatedAttributeError,
-)
-
-
-if not PY2:
- import typing
-
-
-# This is used at least twice, so cache it here.
-_obj_setattr = object.__setattr__
-_init_converter_pat = "__attr_converter_%s"
-_init_factory_pat = "__attr_factory_{}"
-_tuple_property_pat = (
- " {attr_name} = _attrs_property(_attrs_itemgetter({index}))"
-)
-_classvar_prefixes = (
- "typing.ClassVar",
- "t.ClassVar",
- "ClassVar",
- "typing_extensions.ClassVar",
-)
-# we don't use a double-underscore prefix because that triggers
-# name mangling when trying to create a slot for the field
-# (when slots=True)
-_hash_cache_field = "_attrs_cached_hash"
-
-_empty_metadata_singleton = metadata_proxy({})
-
-# Unique object for unequivocal getattr() defaults.
-_sentinel = object()
-
-
-class _Nothing(object):
- """
- Sentinel class to indicate the lack of a value when ``None`` is ambiguous.
-
- ``_Nothing`` is a singleton. There is only ever one of it.
-
- .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False.
- """
-
- _singleton = None
-
- def __new__(cls):
- if _Nothing._singleton is None:
- _Nothing._singleton = super(_Nothing, cls).__new__(cls)
- return _Nothing._singleton
-
- def __repr__(self):
- return "NOTHING"
-
- def __bool__(self):
- return False
-
- def __len__(self):
- return 0 # __bool__ for Python 2
-
-
-NOTHING = _Nothing()
-"""
-Sentinel to indicate the lack of a value when ``None`` is ambiguous.
-"""
-
-
-class _CacheHashWrapper(int):
- """
- An integer subclass that pickles / copies as None
-
- This is used for non-slots classes with ``cache_hash=True``, to avoid
- serializing a potentially (even likely) invalid hash value. Since ``None``
- is the default value for uncalculated hashes, whenever this is copied,
- the copy's value for the hash should automatically reset.
-
- See GH #613 for more details.
- """
-
- if PY2:
- # For some reason `type(None)` isn't callable in Python 2, but we don't
- # actually need a constructor for None objects, we just need any
- # available function that returns None.
- def __reduce__(self, _none_constructor=getattr, _args=(0, "", None)):
- return _none_constructor, _args
-
- else:
-
- def __reduce__(self, _none_constructor=type(None), _args=()):
- return _none_constructor, _args
-
-
-def attrib(
- default=NOTHING,
- validator=None,
- repr=True,
- cmp=None,
- hash=None,
- init=True,
- metadata=None,
- type=None,
- converter=None,
- factory=None,
- kw_only=False,
- eq=None,
- order=None,
- on_setattr=None,
-):
- """
- Create a new attribute on a class.
-
- .. warning::
-
- Does *not* do anything unless the class is also decorated with
- `attr.s`!
-
- :param default: A value that is used if an ``attrs``-generated ``__init__``
- is used and no value is passed while instantiating or the attribute is
- excluded using ``init=False``.
-
- If the value is an instance of `Factory`, its callable will be
- used to construct a new value (useful for mutable data types like lists
- or dicts).
-
- If a default is not set (or set manually to `attr.NOTHING`), a value
- *must* be supplied when instantiating; otherwise a `TypeError`
- will be raised.
-
- The default can also be set using decorator notation as shown below.
-
- :type default: Any value
-
- :param callable factory: Syntactic sugar for
- ``default=attr.Factory(factory)``.
-
- :param validator: `callable` that is called by ``attrs``-generated
- ``__init__`` methods after the instance has been initialized. They
- receive the initialized instance, the `Attribute`, and the
- passed value.
-
- The return value is *not* inspected so the validator has to throw an
- exception itself.
-
- If a `list` is passed, its items are treated as validators and must
- all pass.
-
- Validators can be globally disabled and re-enabled using
- `get_run_validators`.
-
- The validator can also be set using decorator notation as shown below.
-
- :type validator: `callable` or a `list` of `callable`\\ s.
-
- :param repr: Include this attribute in the generated ``__repr__``
- method. If ``True``, include the attribute; if ``False``, omit it. By
- default, the built-in ``repr()`` function is used. To override how the
- attribute value is formatted, pass a ``callable`` that takes a single
- value and returns a string. Note that the resulting string is used
- as-is, i.e. it will be used directly *instead* of calling ``repr()``
- (the default).
- :type repr: a `bool` or a `callable` to use a custom function.
-
- :param eq: If ``True`` (default), include this attribute in the
- generated ``__eq__`` and ``__ne__`` methods that check two instances
- for equality. To override how the attribute value is compared,
- pass a ``callable`` that takes a single value and returns the value
- to be compared.
- :type eq: a `bool` or a `callable`.
-
- :param order: If ``True`` (default), include this attributes in the
- generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods.
- To override how the attribute value is ordered,
- pass a ``callable`` that takes a single value and returns the value
- to be ordered.
- :type order: a `bool` or a `callable`.
-
- :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the
- same value. Must not be mixed with *eq* or *order*.
- :type cmp: a `bool` or a `callable`.
-
- :param Optional[bool] hash: Include this attribute in the generated
- ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This
- is the correct behavior according the Python spec. Setting this value
- to anything else than ``None`` is *discouraged*.
- :param bool init: Include this attribute in the generated ``__init__``
- method. It is possible to set this to ``False`` and set a default
- value. In that case this attributed is unconditionally initialized
- with the specified default value or factory.
- :param callable converter: `callable` that is called by
- ``attrs``-generated ``__init__`` methods to convert attribute's value
- to the desired format. It is given the passed-in value, and the
- returned value will be used as the new value of the attribute. The
- value is converted before being passed to the validator, if any.
- :param metadata: An arbitrary mapping, to be used by third-party
- components. See `extending_metadata`.
- :param type: The type of the attribute. In Python 3.6 or greater, the
- preferred method to specify the type is using a variable annotation
- (see `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_).
- This argument is provided for backward compatibility.
- Regardless of the approach used, the type will be stored on
- ``Attribute.type``.
-
- Please note that ``attrs`` doesn't do anything with this metadata by
- itself. You can use it as part of your own code or for
- `static type checking <types>`.
- :param kw_only: Make this attribute keyword-only (Python 3+)
- in the generated ``__init__`` (if ``init`` is ``False``, this
- parameter is ignored).
- :param on_setattr: Allows to overwrite the *on_setattr* setting from
- `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used.
- Set to `attr.setters.NO_OP` to run **no** `setattr` hooks for this
- attribute -- regardless of the setting in `attr.s`.
- :type on_setattr: `callable`, or a list of callables, or `None`, or
- `attr.setters.NO_OP`
-
- .. versionadded:: 15.2.0 *convert*
- .. versionadded:: 16.3.0 *metadata*
- .. versionchanged:: 17.1.0 *validator* can be a ``list`` now.
- .. versionchanged:: 17.1.0
- *hash* is ``None`` and therefore mirrors *eq* by default.
- .. versionadded:: 17.3.0 *type*
- .. deprecated:: 17.4.0 *convert*
- .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated
- *convert* to achieve consistency with other noun-based arguments.
- .. versionadded:: 18.1.0
- ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``.
- .. versionadded:: 18.2.0 *kw_only*
- .. versionchanged:: 19.2.0 *convert* keyword argument removed.
- .. versionchanged:: 19.2.0 *repr* also accepts a custom callable.
- .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01.
- .. versionadded:: 19.2.0 *eq* and *order*
- .. versionadded:: 20.1.0 *on_setattr*
- .. versionchanged:: 20.3.0 *kw_only* backported to Python 2
- .. versionchanged:: 21.1.0
- *eq*, *order*, and *cmp* also accept a custom callable
- .. versionchanged:: 21.1.0 *cmp* undeprecated
- """
- eq, eq_key, order, order_key = _determine_attrib_eq_order(
- cmp, eq, order, True
- )
-
- if hash is not None and hash is not True and hash is not False:
- raise TypeError(
- "Invalid value for hash. Must be True, False, or None."
- )
-
- if factory is not None:
- if default is not NOTHING:
- raise ValueError(
- "The `default` and `factory` arguments are mutually "
- "exclusive."
- )
- if not callable(factory):
- raise ValueError("The `factory` argument must be a callable.")
- default = Factory(factory)
-
- if metadata is None:
- metadata = {}
-
- # Apply syntactic sugar by auto-wrapping.
- if isinstance(on_setattr, (list, tuple)):
- on_setattr = setters.pipe(*on_setattr)
-
- if validator and isinstance(validator, (list, tuple)):
- validator = and_(*validator)
-
- if converter and isinstance(converter, (list, tuple)):
- converter = pipe(*converter)
-
- return _CountingAttr(
- default=default,
- validator=validator,
- repr=repr,
- cmp=None,
- hash=hash,
- init=init,
- converter=converter,
- metadata=metadata,
- type=type,
- kw_only=kw_only,
- eq=eq,
- eq_key=eq_key,
- order=order,
- order_key=order_key,
- on_setattr=on_setattr,
- )
-
-
-def _compile_and_eval(script, globs, locs=None, filename=""):
- """
- "Exec" the script with the given global (globs) and local (locs) variables.
- """
- bytecode = compile(script, filename, "exec")
- eval(bytecode, globs, locs)
-
-
-def _make_method(name, script, filename, globs=None):
- """
- Create the method with the script given and return the method object.
- """
- locs = {}
- if globs is None:
- globs = {}
-
- _compile_and_eval(script, globs, locs, filename)
-
- # In order of debuggers like PDB being able to step through the code,
- # we add a fake linecache entry.
- linecache.cache[filename] = (
- len(script),
- None,
- script.splitlines(True),
- filename,
- )
-
- return locs[name]
-
-
-def _make_attr_tuple_class(cls_name, attr_names):
- """
- Create a tuple subclass to hold `Attribute`s for an `attrs` class.
-
- The subclass is a bare tuple with properties for names.
-
- class MyClassAttributes(tuple):
- __slots__ = ()
- x = property(itemgetter(0))
- """
- attr_class_name = "{}Attributes".format(cls_name)
- attr_class_template = [
- "class {}(tuple):".format(attr_class_name),
- " __slots__ = ()",
- ]
- if attr_names:
- for i, attr_name in enumerate(attr_names):
- attr_class_template.append(
- _tuple_property_pat.format(index=i, attr_name=attr_name)
- )
- else:
- attr_class_template.append(" pass")
- globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property}
- _compile_and_eval("\n".join(attr_class_template), globs)
- return globs[attr_class_name]
-
-
-# Tuple class for extracted attributes from a class definition.
-# `base_attrs` is a subset of `attrs`.
-_Attributes = _make_attr_tuple_class(
- "_Attributes",
- [
- # all attributes to build dunder methods for
- "attrs",
- # attributes that have been inherited
- "base_attrs",
- # map inherited attributes to their originating classes
- "base_attrs_map",
- ],
-)
-
-
-def _is_class_var(annot):
- """
- Check whether *annot* is a typing.ClassVar.
-
- The string comparison hack is used to avoid evaluating all string
- annotations which would put attrs-based classes at a performance
- disadvantage compared to plain old classes.
- """
- annot = str(annot)
-
- # Annotation can be quoted.
- if annot.startswith(("'", '"')) and annot.endswith(("'", '"')):
- annot = annot[1:-1]
-
- return annot.startswith(_classvar_prefixes)
-
-
-def _has_own_attribute(cls, attrib_name):
- """
- Check whether *cls* defines *attrib_name* (and doesn't just inherit it).
-
- Requires Python 3.
- """
- attr = getattr(cls, attrib_name, _sentinel)
- if attr is _sentinel:
- return False
-
- for base_cls in cls.__mro__[1:]:
- a = getattr(base_cls, attrib_name, None)
- if attr is a:
- return False
-
- return True
-
-
-def _get_annotations(cls):
- """
- Get annotations for *cls*.
- """
- if _has_own_attribute(cls, "__annotations__"):
- return cls.__annotations__
-
- return {}
-
-
-def _counter_getter(e):
- """
- Key function for sorting to avoid re-creating a lambda for every class.
- """
- return e[1].counter
-
-
-def _collect_base_attrs(cls, taken_attr_names):
- """
- Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
- """
- base_attrs = []
- base_attr_map = {} # A dictionary of base attrs to their classes.
-
- # Traverse the MRO and collect attributes.
- for base_cls in reversed(cls.__mro__[1:-1]):
- for a in getattr(base_cls, "__attrs_attrs__", []):
- if a.inherited or a.name in taken_attr_names:
- continue
-
- a = a.evolve(inherited=True)
- base_attrs.append(a)
- base_attr_map[a.name] = base_cls
-
- # For each name, only keep the freshest definition i.e. the furthest at the
- # back. base_attr_map is fine because it gets overwritten with every new
- # instance.
- filtered = []
- seen = set()
- for a in reversed(base_attrs):
- if a.name in seen:
- continue
- filtered.insert(0, a)
- seen.add(a.name)
-
- return filtered, base_attr_map
-
-
-def _collect_base_attrs_broken(cls, taken_attr_names):
- """
- Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
-
- N.B. *taken_attr_names* will be mutated.
-
- Adhere to the old incorrect behavior.
-
- Notably it collects from the front and considers inherited attributes which
- leads to the buggy behavior reported in #428.
- """
- base_attrs = []
- base_attr_map = {} # A dictionary of base attrs to their classes.
-
- # Traverse the MRO and collect attributes.
- for base_cls in cls.__mro__[1:-1]:
- for a in getattr(base_cls, "__attrs_attrs__", []):
- if a.name in taken_attr_names:
- continue
-
- a = a.evolve(inherited=True)
- taken_attr_names.add(a.name)
- base_attrs.append(a)
- base_attr_map[a.name] = base_cls
-
- return base_attrs, base_attr_map
-
-
-def _transform_attrs(
- cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer
-):
- """
- Transform all `_CountingAttr`s on a class into `Attribute`s.
-
- If *these* is passed, use that and don't look for them on the class.
-
- *collect_by_mro* is True, collect them in the correct MRO order, otherwise
- use the old -- incorrect -- order. See #428.
-
- Return an `_Attributes`.
- """
- cd = cls.__dict__
- anns = _get_annotations(cls)
-
- if these is not None:
- ca_list = [(name, ca) for name, ca in iteritems(these)]
-
- if not isinstance(these, ordered_dict):
- ca_list.sort(key=_counter_getter)
- elif auto_attribs is True:
- ca_names = {
- name
- for name, attr in cd.items()
- if isinstance(attr, _CountingAttr)
- }
- ca_list = []
- annot_names = set()
- for attr_name, type in anns.items():
- if _is_class_var(type):
- continue
- annot_names.add(attr_name)
- a = cd.get(attr_name, NOTHING)
-
- if not isinstance(a, _CountingAttr):
- if a is NOTHING:
- a = attrib()
- else:
- a = attrib(default=a)
- ca_list.append((attr_name, a))
-
- unannotated = ca_names - annot_names
- if len(unannotated) > 0:
- raise UnannotatedAttributeError(
- "The following `attr.ib`s lack a type annotation: "
- + ", ".join(
- sorted(unannotated, key=lambda n: cd.get(n).counter)
- )
- + "."
- )
- else:
- ca_list = sorted(
- (
- (name, attr)
- for name, attr in cd.items()
- if isinstance(attr, _CountingAttr)
- ),
- key=lambda e: e[1].counter,
- )
-
- own_attrs = [
- Attribute.from_counting_attr(
- name=attr_name, ca=ca, type=anns.get(attr_name)
- )
- for attr_name, ca in ca_list
- ]
-
- if collect_by_mro:
- base_attrs, base_attr_map = _collect_base_attrs(
- cls, {a.name for a in own_attrs}
- )
- else:
- base_attrs, base_attr_map = _collect_base_attrs_broken(
- cls, {a.name for a in own_attrs}
- )
-
- attr_names = [a.name for a in base_attrs + own_attrs]
-
- AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
-
- if kw_only:
- own_attrs = [a.evolve(kw_only=True) for a in own_attrs]
- base_attrs = [a.evolve(kw_only=True) for a in base_attrs]
-
- attrs = AttrsClass(base_attrs + own_attrs)
-
- # Mandatory vs non-mandatory attr order only matters when they are part of
- # the __init__ signature and when they aren't kw_only (which are moved to
- # the end and can be mandatory or non-mandatory in any order, as they will
- # be specified as keyword args anyway). Check the order of those attrs:
- had_default = False
- for a in (a for a in attrs if a.init is not False and a.kw_only is False):
- if had_default is True and a.default is NOTHING:
- raise ValueError(
- "No mandatory attributes allowed after an attribute with a "
- "default value or factory. Attribute in question: %r" % (a,)
- )
-
- if had_default is False and a.default is not NOTHING:
- had_default = True
-
- if field_transformer is not None:
- attrs = field_transformer(cls, attrs)
- return _Attributes((attrs, base_attrs, base_attr_map))
-
-
-if PYPY:
-
- def _frozen_setattrs(self, name, value):
- """
- Attached to frozen classes as __setattr__.
- """
- if isinstance(self, BaseException) and name in (
- "__cause__",
- "__context__",
- ):
- BaseException.__setattr__(self, name, value)
- return
-
- raise FrozenInstanceError()
-
-
-else:
-
- def _frozen_setattrs(self, name, value):
- """
- Attached to frozen classes as __setattr__.
- """
- raise FrozenInstanceError()
-
-
-def _frozen_delattrs(self, name):
- """
- Attached to frozen classes as __delattr__.
- """
- raise FrozenInstanceError()
-
-
-class _ClassBuilder(object):
- """
- Iteratively build *one* class.
- """
-
- __slots__ = (
- "_attr_names",
- "_attrs",
- "_base_attr_map",
- "_base_names",
- "_cache_hash",
- "_cls",
- "_cls_dict",
- "_delete_attribs",
- "_frozen",
- "_has_pre_init",
- "_has_post_init",
- "_is_exc",
- "_on_setattr",
- "_slots",
- "_weakref_slot",
- "_has_own_setattr",
- "_has_custom_setattr",
- )
-
- def __init__(
- self,
- cls,
- these,
- slots,
- frozen,
- weakref_slot,
- getstate_setstate,
- auto_attribs,
- kw_only,
- cache_hash,
- is_exc,
- collect_by_mro,
- on_setattr,
- has_custom_setattr,
- field_transformer,
- ):
- attrs, base_attrs, base_map = _transform_attrs(
- cls,
- these,
- auto_attribs,
- kw_only,
- collect_by_mro,
- field_transformer,
- )
-
- self._cls = cls
- self._cls_dict = dict(cls.__dict__) if slots else {}
- self._attrs = attrs
- self._base_names = set(a.name for a in base_attrs)
- self._base_attr_map = base_map
- self._attr_names = tuple(a.name for a in attrs)
- self._slots = slots
- self._frozen = frozen
- self._weakref_slot = weakref_slot
- self._cache_hash = cache_hash
- self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False))
- self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False))
- self._delete_attribs = not bool(these)
- self._is_exc = is_exc
- self._on_setattr = on_setattr
-
- self._has_custom_setattr = has_custom_setattr
- self._has_own_setattr = False
-
- self._cls_dict["__attrs_attrs__"] = self._attrs
-
- if frozen:
- self._cls_dict["__setattr__"] = _frozen_setattrs
- self._cls_dict["__delattr__"] = _frozen_delattrs
-
- self._has_own_setattr = True
-
- if getstate_setstate:
- (
- self._cls_dict["__getstate__"],
- self._cls_dict["__setstate__"],
- ) = self._make_getstate_setstate()
-
- def __repr__(self):
- return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__)
-
- def build_class(self):
- """
- Finalize class based on the accumulated configuration.
-
- Builder cannot be used after calling this method.
- """
- if self._slots is True:
- return self._create_slots_class()
- else:
- return self._patch_original_class()
-
- def _patch_original_class(self):
- """
- Apply accumulated methods and return the class.
- """
- cls = self._cls
- base_names = self._base_names
-
- # Clean class of attribute definitions (`attr.ib()`s).
- if self._delete_attribs:
- for name in self._attr_names:
- if (
- name not in base_names
- and getattr(cls, name, _sentinel) is not _sentinel
- ):
- try:
- delattr(cls, name)
- except AttributeError:
- # This can happen if a base class defines a class
- # variable and we want to set an attribute with the
- # same name by using only a type annotation.
- pass
-
- # Attach our dunder methods.
- for name, value in self._cls_dict.items():
- setattr(cls, name, value)
-
- # If we've inherited an attrs __setattr__ and don't write our own,
- # reset it to object's.
- if not self._has_own_setattr and getattr(
- cls, "__attrs_own_setattr__", False
- ):
- cls.__attrs_own_setattr__ = False
-
- if not self._has_custom_setattr:
- cls.__setattr__ = object.__setattr__
-
- return cls
-
- def _create_slots_class(self):
- """
- Build and return a new class with a `__slots__` attribute.
- """
- cd = {
- k: v
- for k, v in iteritems(self._cls_dict)
- if k not in tuple(self._attr_names) + ("__dict__", "__weakref__")
- }
-
- # If our class doesn't have its own implementation of __setattr__
- # (either from the user or by us), check the bases, if one of them has
- # an attrs-made __setattr__, that needs to be reset. We don't walk the
- # MRO because we only care about our immediate base classes.
- # XXX: This can be confused by subclassing a slotted attrs class with
- # XXX: a non-attrs class and subclass the resulting class with an attrs
- # XXX: class. See `test_slotted_confused` for details. For now that's
- # XXX: OK with us.
- if not self._has_own_setattr:
- cd["__attrs_own_setattr__"] = False
-
- if not self._has_custom_setattr:
- for base_cls in self._cls.__bases__:
- if base_cls.__dict__.get("__attrs_own_setattr__", False):
- cd["__setattr__"] = object.__setattr__
- break
-
- # Traverse the MRO to collect existing slots
- # and check for an existing __weakref__.
- existing_slots = dict()
- weakref_inherited = False
- for base_cls in self._cls.__mro__[1:-1]:
- if base_cls.__dict__.get("__weakref__", None) is not None:
- weakref_inherited = True
- existing_slots.update(
- {
- name: getattr(base_cls, name)
- for name in getattr(base_cls, "__slots__", [])
- }
- )
-
- base_names = set(self._base_names)
-
- names = self._attr_names
- if (
- self._weakref_slot
- and "__weakref__" not in getattr(self._cls, "__slots__", ())
- and "__weakref__" not in names
- and not weakref_inherited
- ):
- names += ("__weakref__",)
-
- # We only add the names of attributes that aren't inherited.
- # Setting __slots__ to inherited attributes wastes memory.
- slot_names = [name for name in names if name not in base_names]
- # There are slots for attributes from current class
- # that are defined in parent classes.
- # As their descriptors may be overriden by a child class,
- # we collect them here and update the class dict
- reused_slots = {
- slot: slot_descriptor
- for slot, slot_descriptor in iteritems(existing_slots)
- if slot in slot_names
- }
- slot_names = [name for name in slot_names if name not in reused_slots]
- cd.update(reused_slots)
- if self._cache_hash:
- slot_names.append(_hash_cache_field)
- cd["__slots__"] = tuple(slot_names)
-
- qualname = getattr(self._cls, "__qualname__", None)
- if qualname is not None:
- cd["__qualname__"] = qualname
-
- # Create new class based on old class and our methods.
- cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd)
-
- # The following is a fix for
- # https://github.com/python-attrs/attrs/issues/102. On Python 3,
- # if a method mentions `__class__` or uses the no-arg super(), the
- # compiler will bake a reference to the class in the method itself
- # as `method.__closure__`. Since we replace the class with a
- # clone, we rewrite these references so it keeps working.
- for item in cls.__dict__.values():
- if isinstance(item, (classmethod, staticmethod)):
- # Class- and staticmethods hide their functions inside.
- # These might need to be rewritten as well.
- closure_cells = getattr(item.__func__, "__closure__", None)
- elif isinstance(item, property):
- # Workaround for property `super()` shortcut (PY3-only).
- # There is no universal way for other descriptors.
- closure_cells = getattr(item.fget, "__closure__", None)
- else:
- closure_cells = getattr(item, "__closure__", None)
-
- if not closure_cells: # Catch None or the empty list.
- continue
- for cell in closure_cells:
- try:
- match = cell.cell_contents is self._cls
- except ValueError: # ValueError: Cell is empty
- pass
- else:
- if match:
- set_closure_cell(cell, cls)
-
- return cls
-
- def add_repr(self, ns):
- self._cls_dict["__repr__"] = self._add_method_dunders(
- _make_repr(self._attrs, ns=ns)
- )
- return self
-
- def add_str(self):
- repr = self._cls_dict.get("__repr__")
- if repr is None:
- raise ValueError(
- "__str__ can only be generated if a __repr__ exists."
- )
-
- def __str__(self):
- return self.__repr__()
-
- self._cls_dict["__str__"] = self._add_method_dunders(__str__)
- return self
-
- def _make_getstate_setstate(self):
- """
- Create custom __setstate__ and __getstate__ methods.
- """
- # __weakref__ is not writable.
- state_attr_names = tuple(
- an for an in self._attr_names if an != "__weakref__"
- )
-
- def slots_getstate(self):
- """
- Automatically created by attrs.
- """
- return tuple(getattr(self, name) for name in state_attr_names)
-
- hash_caching_enabled = self._cache_hash
-
- def slots_setstate(self, state):
- """
- Automatically created by attrs.
- """
- __bound_setattr = _obj_setattr.__get__(self, Attribute)
- for name, value in zip(state_attr_names, state):
- __bound_setattr(name, value)
-
- # The hash code cache is not included when the object is
- # serialized, but it still needs to be initialized to None to
- # indicate that the first call to __hash__ should be a cache
- # miss.
- if hash_caching_enabled:
- __bound_setattr(_hash_cache_field, None)
-
- return slots_getstate, slots_setstate
-
- def make_unhashable(self):
- self._cls_dict["__hash__"] = None
- return self
-
- def add_hash(self):
- self._cls_dict["__hash__"] = self._add_method_dunders(
- _make_hash(
- self._cls,
- self._attrs,
- frozen=self._frozen,
- cache_hash=self._cache_hash,
- )
- )
-
- return self
-
- def add_init(self):
- self._cls_dict["__init__"] = self._add_method_dunders(
- _make_init(
- self._cls,
- self._attrs,
- self._has_pre_init,
- self._has_post_init,
- self._frozen,
- self._slots,
- self._cache_hash,
- self._base_attr_map,
- self._is_exc,
- self._on_setattr is not None
- and self._on_setattr is not setters.NO_OP,
- attrs_init=False,
- )
- )
-
- return self
-
- def add_attrs_init(self):
- self._cls_dict["__attrs_init__"] = self._add_method_dunders(
- _make_init(
- self._cls,
- self._attrs,
- self._has_pre_init,
- self._has_post_init,
- self._frozen,
- self._slots,
- self._cache_hash,
- self._base_attr_map,
- self._is_exc,
- self._on_setattr is not None
- and self._on_setattr is not setters.NO_OP,
- attrs_init=True,
- )
- )
-
- return self
-
- def add_eq(self):
- cd = self._cls_dict
-
- cd["__eq__"] = self._add_method_dunders(
- _make_eq(self._cls, self._attrs)
- )
- cd["__ne__"] = self._add_method_dunders(_make_ne())
-
- return self
-
- def add_order(self):
- cd = self._cls_dict
-
- cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = (
- self._add_method_dunders(meth)
- for meth in _make_order(self._cls, self._attrs)
- )
-
- return self
-
- def add_setattr(self):
- if self._frozen:
- return self
-
- sa_attrs = {}
- for a in self._attrs:
- on_setattr = a.on_setattr or self._on_setattr
- if on_setattr and on_setattr is not setters.NO_OP:
- sa_attrs[a.name] = a, on_setattr
-
- if not sa_attrs:
- return self
-
- if self._has_custom_setattr:
- # We need to write a __setattr__ but there already is one!
- raise ValueError(
- "Can't combine custom __setattr__ with on_setattr hooks."
- )
-
- # docstring comes from _add_method_dunders
- def __setattr__(self, name, val):
- try:
- a, hook = sa_attrs[name]
- except KeyError:
- nval = val
- else:
- nval = hook(self, a, val)
-
- _obj_setattr(self, name, nval)
-
- self._cls_dict["__attrs_own_setattr__"] = True
- self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__)
- self._has_own_setattr = True
-
- return self
-
- def _add_method_dunders(self, method):
- """
- Add __module__ and __qualname__ to a *method* if possible.
- """
- try:
- method.__module__ = self._cls.__module__
- except AttributeError:
- pass
-
- try:
- method.__qualname__ = ".".join(
- (self._cls.__qualname__, method.__name__)
- )
- except AttributeError:
- pass
-
- try:
- method.__doc__ = "Method generated by attrs for class %s." % (
- self._cls.__qualname__,
- )
- except AttributeError:
- pass
-
- return method
-
-
-_CMP_DEPRECATION = (
- "The usage of `cmp` is deprecated and will be removed on or after "
- "2021-06-01. Please use `eq` and `order` instead."
-)
-
-
-def _determine_attrs_eq_order(cmp, eq, order, default_eq):
- """
- Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
- values of eq and order. If *eq* is None, set it to *default_eq*.
- """
- if cmp is not None and any((eq is not None, order is not None)):
- raise ValueError("Don't mix `cmp` with `eq' and `order`.")
-
- # cmp takes precedence due to bw-compatibility.
- if cmp is not None:
- return cmp, cmp
-
- # If left None, equality is set to the specified default and ordering
- # mirrors equality.
- if eq is None:
- eq = default_eq
-
- if order is None:
- order = eq
-
- if eq is False and order is True:
- raise ValueError("`order` can only be True if `eq` is True too.")
-
- return eq, order
-
-
-def _determine_attrib_eq_order(cmp, eq, order, default_eq):
- """
- Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
- values of eq and order. If *eq* is None, set it to *default_eq*.
- """
- if cmp is not None and any((eq is not None, order is not None)):
- raise ValueError("Don't mix `cmp` with `eq' and `order`.")
-
- def decide_callable_or_boolean(value):
- """
- Decide whether a key function is used.
- """
- if callable(value):
- value, key = True, value
- else:
- key = None
- return value, key
-
- # cmp takes precedence due to bw-compatibility.
- if cmp is not None:
- cmp, cmp_key = decide_callable_or_boolean(cmp)
- return cmp, cmp_key, cmp, cmp_key
-
- # If left None, equality is set to the specified default and ordering
- # mirrors equality.
- if eq is None:
- eq, eq_key = default_eq, None
- else:
- eq, eq_key = decide_callable_or_boolean(eq)
-
- if order is None:
- order, order_key = eq, eq_key
- else:
- order, order_key = decide_callable_or_boolean(order)
-
- if eq is False and order is True:
- raise ValueError("`order` can only be True if `eq` is True too.")
-
- return eq, eq_key, order, order_key
-
-
-def _determine_whether_to_implement(
- cls, flag, auto_detect, dunders, default=True
-):
- """
- Check whether we should implement a set of methods for *cls*.
-
- *flag* is the argument passed into @attr.s like 'init', *auto_detect* the
- same as passed into @attr.s and *dunders* is a tuple of attribute names
- whose presence signal that the user has implemented it themselves.
-
- Return *default* if no reason for either for or against is found.
-
- auto_detect must be False on Python 2.
- """
- if flag is True or flag is False:
- return flag
-
- if flag is None and auto_detect is False:
- return default
-
- # Logically, flag is None and auto_detect is True here.
- for dunder in dunders:
- if _has_own_attribute(cls, dunder):
- return False
-
- return default
-
-
-def attrs(
- maybe_cls=None,
- these=None,
- repr_ns=None,
- repr=None,
- cmp=None,
- hash=None,
- init=None,
- slots=False,
- frozen=False,
- weakref_slot=True,
- str=False,
- auto_attribs=False,
- kw_only=False,
- cache_hash=False,
- auto_exc=False,
- eq=None,
- order=None,
- auto_detect=False,
- collect_by_mro=False,
- getstate_setstate=None,
- on_setattr=None,
- field_transformer=None,
-):
- r"""
- A class decorator that adds `dunder
- <https://wiki.python.org/moin/DunderAlias>`_\ -methods according to the
- specified attributes using `attr.ib` or the *these* argument.
-
- :param these: A dictionary of name to `attr.ib` mappings. This is
- useful to avoid the definition of your attributes within the class body
- because you can't (e.g. if you want to add ``__repr__`` methods to
- Django models) or don't want to.
-
- If *these* is not ``None``, ``attrs`` will *not* search the class body
- for attributes and will *not* remove any attributes from it.
-
- If *these* is an ordered dict (`dict` on Python 3.6+,
- `collections.OrderedDict` otherwise), the order is deduced from
- the order of the attributes inside *these*. Otherwise the order
- of the definition of the attributes is used.
-
- :type these: `dict` of `str` to `attr.ib`
-
- :param str repr_ns: When using nested classes, there's no way in Python 2
- to automatically detect that. Therefore it's possible to set the
- namespace explicitly for a more meaningful ``repr`` output.
- :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*,
- *order*, and *hash* arguments explicitly, assume they are set to
- ``True`` **unless any** of the involved methods for one of the
- arguments is implemented in the *current* class (i.e. it is *not*
- inherited from some base class).
-
- So for example by implementing ``__eq__`` on a class yourself,
- ``attrs`` will deduce ``eq=False`` and will create *neither*
- ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible
- ``__ne__`` by default, so it *should* be enough to only implement
- ``__eq__`` in most cases).
-
- .. warning::
-
- If you prevent ``attrs`` from creating the ordering methods for you
- (``order=False``, e.g. by implementing ``__le__``), it becomes
- *your* responsibility to make sure its ordering is sound. The best
- way is to use the `functools.total_ordering` decorator.
-
-
- Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*,
- *cmp*, or *hash* overrides whatever *auto_detect* would determine.
-
- *auto_detect* requires Python 3. Setting it ``True`` on Python 2 raises
- a `PythonTooOldError`.
-
- :param bool repr: Create a ``__repr__`` method with a human readable
- representation of ``attrs`` attributes..
- :param bool str: Create a ``__str__`` method that is identical to
- ``__repr__``. This is usually not necessary except for
- `Exception`\ s.
- :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__``
- and ``__ne__`` methods that check two instances for equality.
-
- They compare the instances as if they were tuples of their ``attrs``
- attributes if and only if the types of both classes are *identical*!
- :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``,
- ``__gt__``, and ``__ge__`` methods that behave like *eq* above and
- allow instances to be ordered. If ``None`` (default) mirror value of
- *eq*.
- :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq*
- and *order* to the same value. Must not be mixed with *eq* or *order*.
- :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method
- is generated according how *eq* and *frozen* are set.
-
- 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
- 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to
- None, marking it unhashable (which it is).
- 3. If *eq* is False, ``__hash__`` will be left untouched meaning the
- ``__hash__`` method of the base class will be used (if base class is
- ``object``, this means it will fall back to id-based hashing.).
-
- Although not recommended, you can decide for yourself and force
- ``attrs`` to create one (e.g. if the class is immutable even though you
- didn't freeze it programmatically) by passing ``True`` or not. Both of
- these cases are rather special and should be used carefully.
-
- See our documentation on `hashing`, Python's documentation on
- `object.__hash__`, and the `GitHub issue that led to the default \
- behavior <https://github.com/python-attrs/attrs/issues/136>`_ for more
- details.
- :param bool init: Create a ``__init__`` method that initializes the
- ``attrs`` attributes. Leading underscores are stripped for the argument
- name. If a ``__attrs_pre_init__`` method exists on the class, it will
- be called before the class is initialized. If a ``__attrs_post_init__``
- method exists on the class, it will be called after the class is fully
- initialized.
-
- If ``init`` is ``False``, an ``__attrs_init__`` method will be
- injected instead. This allows you to define a custom ``__init__``
- method that can do pre-init work such as ``super().__init__()``,
- and then call ``__attrs_init__()`` and ``__attrs_post_init__()``.
- :param bool slots: Create a `slotted class <slotted classes>` that's more
- memory-efficient. Slotted classes are generally superior to the default
- dict classes, but have some gotchas you should know about, so we
- encourage you to read the `glossary entry <slotted classes>`.
- :param bool frozen: Make instances immutable after initialization. If
- someone attempts to modify a frozen instance,
- `attr.exceptions.FrozenInstanceError` is raised.
-
- .. note::
-
- 1. This is achieved by installing a custom ``__setattr__`` method
- on your class, so you can't implement your own.
-
- 2. True immutability is impossible in Python.
-
- 3. This *does* have a minor a runtime performance `impact
- <how-frozen>` when initializing new instances. In other words:
- ``__init__`` is slightly slower with ``frozen=True``.
-
- 4. If a class is frozen, you cannot modify ``self`` in
- ``__attrs_post_init__`` or a self-written ``__init__``. You can
- circumvent that limitation by using
- ``object.__setattr__(self, "attribute_name", value)``.
-
- 5. Subclasses of a frozen class are frozen too.
-
- :param bool weakref_slot: Make instances weak-referenceable. This has no
- effect unless ``slots`` is also enabled.
- :param bool auto_attribs: If ``True``, collect `PEP 526`_-annotated
- attributes (Python 3.6 and later only) from the class body.
-
- In this case, you **must** annotate every field. If ``attrs``
- encounters a field that is set to an `attr.ib` but lacks a type
- annotation, an `attr.exceptions.UnannotatedAttributeError` is
- raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't
- want to set a type.
-
- If you assign a value to those attributes (e.g. ``x: int = 42``), that
- value becomes the default value like if it were passed using
- ``attr.ib(default=42)``. Passing an instance of `Factory` also
- works as expected in most cases (see warning below).
-
- Attributes annotated as `typing.ClassVar`, and attributes that are
- neither annotated nor set to an `attr.ib` are **ignored**.
-
- .. warning::
- For features that use the attribute name to create decorators (e.g.
- `validators <validators>`), you still *must* assign `attr.ib` to
- them. Otherwise Python will either not find the name or try to use
- the default value to call e.g. ``validator`` on it.
-
- These errors can be quite confusing and probably the most common bug
- report on our bug tracker.
-
- .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/
- :param bool kw_only: Make all attributes keyword-only (Python 3+)
- in the generated ``__init__`` (if ``init`` is ``False``, this
- parameter is ignored).
- :param bool cache_hash: Ensure that the object's hash code is computed
- only once and stored on the object. If this is set to ``True``,
- hashing must be either explicitly or implicitly enabled for this
- class. If the hash code is cached, avoid any reassignments of
- fields involved in hash code computation or mutations of the objects
- those fields point to after object creation. If such changes occur,
- the behavior of the object's hash code is undefined.
- :param bool auto_exc: If the class subclasses `BaseException`
- (which implicitly includes any subclass of any exception), the
- following happens to behave like a well-behaved Python exceptions
- class:
-
- - the values for *eq*, *order*, and *hash* are ignored and the
- instances compare and hash by the instance's ids (N.B. ``attrs`` will
- *not* remove existing implementations of ``__hash__`` or the equality
- methods. It just won't add own ones.),
- - all attributes that are either passed into ``__init__`` or have a
- default value are additionally available as a tuple in the ``args``
- attribute,
- - the value of *str* is ignored leaving ``__str__`` to base classes.
- :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs``
- collects attributes from base classes. The default behavior is
- incorrect in certain cases of multiple inheritance. It should be on by
- default but is kept off for backward-compatability.
-
- See issue `#428 <https://github.com/python-attrs/attrs/issues/428>`_ for
- more details.
-
- :param Optional[bool] getstate_setstate:
- .. note::
- This is usually only interesting for slotted classes and you should
- probably just set *auto_detect* to `True`.
-
- If `True`, ``__getstate__`` and
- ``__setstate__`` are generated and attached to the class. This is
- necessary for slotted classes to be pickleable. If left `None`, it's
- `True` by default for slotted classes and ``False`` for dict classes.
-
- If *auto_detect* is `True`, and *getstate_setstate* is left `None`,
- and **either** ``__getstate__`` or ``__setstate__`` is detected directly
- on the class (i.e. not inherited), it is set to `False` (this is usually
- what you want).
-
- :param on_setattr: A callable that is run whenever the user attempts to set
- an attribute (either by assignment like ``i.x = 42`` or by using
- `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments
- as validators: the instance, the attribute that is being modified, and
- the new value.
-
- If no exception is raised, the attribute is set to the return value of
- the callable.
-
- If a list of callables is passed, they're automatically wrapped in an
- `attr.setters.pipe`.
-
- :param Optional[callable] field_transformer:
- A function that is called with the original class object and all
- fields right before ``attrs`` finalizes the class. You can use
- this, e.g., to automatically add converters or validators to
- fields based on their types. See `transform-fields` for more details.
-
- .. versionadded:: 16.0.0 *slots*
- .. versionadded:: 16.1.0 *frozen*
- .. versionadded:: 16.3.0 *str*
- .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``.
- .. versionchanged:: 17.1.0
- *hash* supports ``None`` as value which is also the default now.
- .. versionadded:: 17.3.0 *auto_attribs*
- .. versionchanged:: 18.1.0
- If *these* is passed, no attributes are deleted from the class body.
- .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained.
- .. versionadded:: 18.2.0 *weakref_slot*
- .. deprecated:: 18.2.0
- ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a
- `DeprecationWarning` if the classes compared are subclasses of
- each other. ``__eq`` and ``__ne__`` never tried to compared subclasses
- to each other.
- .. versionchanged:: 19.2.0
- ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider
- subclasses comparable anymore.
- .. versionadded:: 18.2.0 *kw_only*
- .. versionadded:: 18.2.0 *cache_hash*
- .. versionadded:: 19.1.0 *auto_exc*
- .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01.
- .. versionadded:: 19.2.0 *eq* and *order*
- .. versionadded:: 20.1.0 *auto_detect*
- .. versionadded:: 20.1.0 *collect_by_mro*
- .. versionadded:: 20.1.0 *getstate_setstate*
- .. versionadded:: 20.1.0 *on_setattr*
- .. versionadded:: 20.3.0 *field_transformer*
- .. versionchanged:: 21.1.0
- ``init=False`` injects ``__attrs_init__``
- .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__``
- .. versionchanged:: 21.1.0 *cmp* undeprecated
- """
- if auto_detect and PY2:
- raise PythonTooOldError(
- "auto_detect only works on Python 3 and later."
- )
-
- eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None)
- hash_ = hash # work around the lack of nonlocal
-
- if isinstance(on_setattr, (list, tuple)):
- on_setattr = setters.pipe(*on_setattr)
-
- def wrap(cls):
-
- if getattr(cls, "__class__", None) is None:
- raise TypeError("attrs only works with new-style classes.")
-
- is_frozen = frozen or _has_frozen_base_class(cls)
- is_exc = auto_exc is True and issubclass(cls, BaseException)
- has_own_setattr = auto_detect and _has_own_attribute(
- cls, "__setattr__"
- )
-
- if has_own_setattr and is_frozen:
- raise ValueError("Can't freeze a class with a custom __setattr__.")
-
- builder = _ClassBuilder(
- cls,
- these,
- slots,
- is_frozen,
- weakref_slot,
- _determine_whether_to_implement(
- cls,
- getstate_setstate,
- auto_detect,
- ("__getstate__", "__setstate__"),
- default=slots,
- ),
- auto_attribs,
- kw_only,
- cache_hash,
- is_exc,
- collect_by_mro,
- on_setattr,
- has_own_setattr,
- field_transformer,
- )
- if _determine_whether_to_implement(
- cls, repr, auto_detect, ("__repr__",)
- ):
- builder.add_repr(repr_ns)
- if str is True:
- builder.add_str()
-
- eq = _determine_whether_to_implement(
- cls, eq_, auto_detect, ("__eq__", "__ne__")
- )
- if not is_exc and eq is True:
- builder.add_eq()
- if not is_exc and _determine_whether_to_implement(
- cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__")
- ):
- builder.add_order()
-
- builder.add_setattr()
-
- if (
- hash_ is None
- and auto_detect is True
- and _has_own_attribute(cls, "__hash__")
- ):
- hash = False
- else:
- hash = hash_
- if hash is not True and hash is not False and hash is not None:
- # Can't use `hash in` because 1 == True for example.
- raise TypeError(
- "Invalid value for hash. Must be True, False, or None."
- )
- elif hash is False or (hash is None and eq is False) or is_exc:
- # Don't do anything. Should fall back to __object__'s __hash__
- # which is by id.
- if cache_hash:
- raise TypeError(
- "Invalid value for cache_hash. To use hash caching,"
- " hashing must be either explicitly or implicitly "
- "enabled."
- )
- elif hash is True or (
- hash is None and eq is True and is_frozen is True
- ):
- # Build a __hash__ if told so, or if it's safe.
- builder.add_hash()
- else:
- # Raise TypeError on attempts to hash.
- if cache_hash:
- raise TypeError(
- "Invalid value for cache_hash. To use hash caching,"
- " hashing must be either explicitly or implicitly "
- "enabled."
- )
- builder.make_unhashable()
-
- if _determine_whether_to_implement(
- cls, init, auto_detect, ("__init__",)
- ):
- builder.add_init()
- else:
- builder.add_attrs_init()
- if cache_hash:
- raise TypeError(
- "Invalid value for cache_hash. To use hash caching,"
- " init must be True."
- )
-
- return builder.build_class()
-
- # maybe_cls's type depends on the usage of the decorator. It's a class
- # if it's used as `@attrs` but ``None`` if used as `@attrs()`.
- if maybe_cls is None:
- return wrap
- else:
- return wrap(maybe_cls)
-
-
-_attrs = attrs
-"""
-Internal alias so we can use it in functions that take an argument called
-*attrs*.
-"""
-
-
-if PY2:
-
- def _has_frozen_base_class(cls):
- """
- Check whether *cls* has a frozen ancestor by looking at its
- __setattr__.
- """
- return (
- getattr(cls.__setattr__, "__module__", None)
- == _frozen_setattrs.__module__
- and cls.__setattr__.__name__ == _frozen_setattrs.__name__
- )
-
-
-else:
-
- def _has_frozen_base_class(cls):
- """
- Check whether *cls* has a frozen ancestor by looking at its
- __setattr__.
- """
- return cls.__setattr__ == _frozen_setattrs
-
-
-def _generate_unique_filename(cls, func_name):
- """
- Create a "filename" suitable for a function being generated.
- """
- unique_id = uuid.uuid4()
- extra = ""
- count = 1
-
- while True:
- unique_filename = "<attrs generated {0} {1}.{2}{3}>".format(
- func_name,
- cls.__module__,
- getattr(cls, "__qualname__", cls.__name__),
- extra,
- )
- # To handle concurrency we essentially "reserve" our spot in
- # the linecache with a dummy line. The caller can then
- # set this value correctly.
- cache_line = (1, None, (str(unique_id),), unique_filename)
- if (
- linecache.cache.setdefault(unique_filename, cache_line)
- == cache_line
- ):
- return unique_filename
-
- # Looks like this spot is taken. Try again.
- count += 1
- extra = "-{0}".format(count)
-
-
-def _make_hash(cls, attrs, frozen, cache_hash):
- attrs = tuple(
- a for a in attrs if a.hash is True or (a.hash is None and a.eq is True)
- )
-
- tab = " "
-
- unique_filename = _generate_unique_filename(cls, "hash")
- type_hash = hash(unique_filename)
-
- hash_def = "def __hash__(self"
- hash_func = "hash(("
- closing_braces = "))"
- if not cache_hash:
- hash_def += "):"
- else:
- if not PY2:
- hash_def += ", *"
-
- hash_def += (
- ", _cache_wrapper="
- + "__import__('attr._make')._make._CacheHashWrapper):"
- )
- hash_func = "_cache_wrapper(" + hash_func
- closing_braces += ")"
-
- method_lines = [hash_def]
-
- def append_hash_computation_lines(prefix, indent):
- """
- Generate the code for actually computing the hash code.
- Below this will either be returned directly or used to compute
- a value which is then cached, depending on the value of cache_hash
- """
-
- method_lines.extend(
- [
- indent + prefix + hash_func,
- indent + " %d," % (type_hash,),
- ]
- )
-
- for a in attrs:
- method_lines.append(indent + " self.%s," % a.name)
-
- method_lines.append(indent + " " + closing_braces)
-
- if cache_hash:
- method_lines.append(tab + "if self.%s is None:" % _hash_cache_field)
- if frozen:
- append_hash_computation_lines(
- "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2
- )
- method_lines.append(tab * 2 + ")") # close __setattr__
- else:
- append_hash_computation_lines(
- "self.%s = " % _hash_cache_field, tab * 2
- )
- method_lines.append(tab + "return self.%s" % _hash_cache_field)
- else:
- append_hash_computation_lines("return ", tab)
-
- script = "\n".join(method_lines)
- return _make_method("__hash__", script, unique_filename)
-
-
-def _add_hash(cls, attrs):
- """
- Add a hash method to *cls*.
- """
- cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False)
- return cls
-
-
-def _make_ne():
- """
- Create __ne__ method.
- """
-
- def __ne__(self, other):
- """
- Check equality and either forward a NotImplemented or
- return the result negated.
- """
- result = self.__eq__(other)
- if result is NotImplemented:
- return NotImplemented
-
- return not result
-
- return __ne__
-
-
-def _make_eq(cls, attrs):
- """
- Create __eq__ method for *cls* with *attrs*.
- """
- attrs = [a for a in attrs if a.eq]
-
- unique_filename = _generate_unique_filename(cls, "eq")
- lines = [
- "def __eq__(self, other):",
- " if other.__class__ is not self.__class__:",
- " return NotImplemented",
- ]
-
- # We can't just do a big self.x = other.x and... clause due to
- # irregularities like nan == nan is false but (nan,) == (nan,) is true.
- globs = {}
- if attrs:
- lines.append(" return (")
- others = [" ) == ("]
- for a in attrs:
- if a.eq_key:
- cmp_name = "_%s_key" % (a.name,)
- # Add the key function to the global namespace
- # of the evaluated function.
- globs[cmp_name] = a.eq_key
- lines.append(
- " %s(self.%s),"
- % (
- cmp_name,
- a.name,
- )
- )
- others.append(
- " %s(other.%s),"
- % (
- cmp_name,
- a.name,
- )
- )
- else:
- lines.append(" self.%s," % (a.name,))
- others.append(" other.%s," % (a.name,))
-
- lines += others + [" )"]
- else:
- lines.append(" return True")
-
- script = "\n".join(lines)
-
- return _make_method("__eq__", script, unique_filename, globs)
-
-
-def _make_order(cls, attrs):
- """
- Create ordering methods for *cls* with *attrs*.
- """
- attrs = [a for a in attrs if a.order]
-
- def attrs_to_tuple(obj):
- """
- Save us some typing.
- """
- return tuple(
- key(value) if key else value
- for value, key in (
- (getattr(obj, a.name), a.order_key) for a in attrs
- )
- )
-
- def __lt__(self, other):
- """
- Automatically created by attrs.
- """
- if other.__class__ is self.__class__:
- return attrs_to_tuple(self) < attrs_to_tuple(other)
-
- return NotImplemented
-
- def __le__(self, other):
- """
- Automatically created by attrs.
- """
- if other.__class__ is self.__class__:
- return attrs_to_tuple(self) <= attrs_to_tuple(other)
-
- return NotImplemented
-
- def __gt__(self, other):
- """
- Automatically created by attrs.
- """
- if other.__class__ is self.__class__:
- return attrs_to_tuple(self) > attrs_to_tuple(other)
-
- return NotImplemented
-
- def __ge__(self, other):
- """
- Automatically created by attrs.
- """
- if other.__class__ is self.__class__:
- return attrs_to_tuple(self) >= attrs_to_tuple(other)
-
- return NotImplemented
-
- return __lt__, __le__, __gt__, __ge__
-
-
-def _add_eq(cls, attrs=None):
- """
- Add equality methods to *cls* with *attrs*.
- """
- if attrs is None:
- attrs = cls.__attrs_attrs__
-
- cls.__eq__ = _make_eq(cls, attrs)
- cls.__ne__ = _make_ne()
-
- return cls
-
-
-_already_repring = threading.local()
-
-
-def _make_repr(attrs, ns):
- """
- Make a repr method that includes relevant *attrs*, adding *ns* to the full
- name.
- """
-
- # Figure out which attributes to include, and which function to use to
- # format them. The a.repr value can be either bool or a custom callable.
- attr_names_with_reprs = tuple(
- (a.name, repr if a.repr is True else a.repr)
- for a in attrs
- if a.repr is not False
- )
-
- def __repr__(self):
- """
- Automatically created by attrs.
- """
- try:
- working_set = _already_repring.working_set
- except AttributeError:
- working_set = set()
- _already_repring.working_set = working_set
-
- if id(self) in working_set:
- return "..."
- real_cls = self.__class__
- if ns is None:
- qualname = getattr(real_cls, "__qualname__", None)
- if qualname is not None:
- class_name = qualname.rsplit(">.", 1)[-1]
- else:
- class_name = real_cls.__name__
- else:
- class_name = ns + "." + real_cls.__name__
-
- # Since 'self' remains on the stack (i.e.: strongly referenced) for the
- # duration of this call, it's safe to depend on id(...) stability, and
- # not need to track the instance and therefore worry about properties
- # like weakref- or hash-ability.
- working_set.add(id(self))
- try:
- result = [class_name, "("]
- first = True
- for name, attr_repr in attr_names_with_reprs:
- if first:
- first = False
- else:
- result.append(", ")
- result.extend(
- (name, "=", attr_repr(getattr(self, name, NOTHING)))
- )
- return "".join(result) + ")"
- finally:
- working_set.remove(id(self))
-
- return __repr__
-
-
-def _add_repr(cls, ns=None, attrs=None):
- """
- Add a repr method to *cls*.
- """
- if attrs is None:
- attrs = cls.__attrs_attrs__
-
- cls.__repr__ = _make_repr(attrs, ns)
- return cls
-
-
-def fields(cls):
- """
- Return the tuple of ``attrs`` attributes for a class.
-
- The tuple also allows accessing the fields by their names (see below for
- examples).
-
- :param type cls: Class to introspect.
-
- :raise TypeError: If *cls* is not a class.
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- :rtype: tuple (with name accessors) of `attr.Attribute`
-
- .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields
- by name.
- """
- if not isclass(cls):
- raise TypeError("Passed object must be a class.")
- attrs = getattr(cls, "__attrs_attrs__", None)
- if attrs is None:
- raise NotAnAttrsClassError(
- "{cls!r} is not an attrs-decorated class.".format(cls=cls)
- )
- return attrs
-
-
-def fields_dict(cls):
- """
- Return an ordered dictionary of ``attrs`` attributes for a class, whose
- keys are the attribute names.
-
- :param type cls: Class to introspect.
-
- :raise TypeError: If *cls* is not a class.
- :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
- class.
-
- :rtype: an ordered dict where keys are attribute names and values are
- `attr.Attribute`\\ s. This will be a `dict` if it's
- naturally ordered like on Python 3.6+ or an
- :class:`~collections.OrderedDict` otherwise.
-
- .. versionadded:: 18.1.0
- """
- if not isclass(cls):
- raise TypeError("Passed object must be a class.")
- attrs = getattr(cls, "__attrs_attrs__", None)
- if attrs is None:
- raise NotAnAttrsClassError(
- "{cls!r} is not an attrs-decorated class.".format(cls=cls)
- )
- return ordered_dict(((a.name, a) for a in attrs))
-
-
-def validate(inst):
- """
- Validate all attributes on *inst* that have a validator.
-
- Leaves all exceptions through.
-
- :param inst: Instance of a class with ``attrs`` attributes.
- """
- if _config._run_validators is False:
- return
-
- for a in fields(inst.__class__):
- v = a.validator
- if v is not None:
- v(inst, a, getattr(inst, a.name))
-
-
-def _is_slot_cls(cls):
- return "__slots__" in cls.__dict__
-
-
-def _is_slot_attr(a_name, base_attr_map):
- """
- Check if the attribute name comes from a slot class.
- """
- return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name])
-
-
-def _make_init(
- cls,
- attrs,
- pre_init,
- post_init,
- frozen,
- slots,
- cache_hash,
- base_attr_map,
- is_exc,
- has_global_on_setattr,
- attrs_init,
-):
- if frozen and has_global_on_setattr:
- raise ValueError("Frozen classes can't use on_setattr.")
-
- needs_cached_setattr = cache_hash or frozen
- filtered_attrs = []
- attr_dict = {}
- for a in attrs:
- if not a.init and a.default is NOTHING:
- continue
-
- filtered_attrs.append(a)
- attr_dict[a.name] = a
-
- if a.on_setattr is not None:
- if frozen is True:
- raise ValueError("Frozen classes can't use on_setattr.")
-
- needs_cached_setattr = True
- elif (
- has_global_on_setattr and a.on_setattr is not setters.NO_OP
- ) or _is_slot_attr(a.name, base_attr_map):
- needs_cached_setattr = True
-
- unique_filename = _generate_unique_filename(cls, "init")
-
- script, globs, annotations = _attrs_to_init_script(
- filtered_attrs,
- frozen,
- slots,
- pre_init,
- post_init,
- cache_hash,
- base_attr_map,
- is_exc,
- needs_cached_setattr,
- has_global_on_setattr,
- attrs_init,
- )
- if cls.__module__ in sys.modules:
- # This makes typing.get_type_hints(CLS.__init__) resolve string types.
- globs.update(sys.modules[cls.__module__].__dict__)
-
- globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict})
-
- if needs_cached_setattr:
- # Save the lookup overhead in __init__ if we need to circumvent
- # setattr hooks.
- globs["_cached_setattr"] = _obj_setattr
-
- init = _make_method(
- "__attrs_init__" if attrs_init else "__init__",
- script,
- unique_filename,
- globs,
- )
- init.__annotations__ = annotations
-
- return init
-
-
-def _setattr(attr_name, value_var, has_on_setattr):
- """
- Use the cached object.setattr to set *attr_name* to *value_var*.
- """
- return "_setattr('%s', %s)" % (attr_name, value_var)
-
-
-def _setattr_with_converter(attr_name, value_var, has_on_setattr):
- """
- Use the cached object.setattr to set *attr_name* to *value_var*, but run
- its converter first.
- """
- return "_setattr('%s', %s(%s))" % (
- attr_name,
- _init_converter_pat % (attr_name,),
- value_var,
- )
-
-
-def _assign(attr_name, value, has_on_setattr):
- """
- Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise
- relegate to _setattr.
- """
- if has_on_setattr:
- return _setattr(attr_name, value, True)
-
- return "self.%s = %s" % (attr_name, value)
-
-
-def _assign_with_converter(attr_name, value_var, has_on_setattr):
- """
- Unless *attr_name* has an on_setattr hook, use normal assignment after
- conversion. Otherwise relegate to _setattr_with_converter.
- """
- if has_on_setattr:
- return _setattr_with_converter(attr_name, value_var, True)
-
- return "self.%s = %s(%s)" % (
- attr_name,
- _init_converter_pat % (attr_name,),
- value_var,
- )
-
-
-if PY2:
-
- def _unpack_kw_only_py2(attr_name, default=None):
- """
- Unpack *attr_name* from _kw_only dict.
- """
- if default is not None:
- arg_default = ", %s" % default
- else:
- arg_default = ""
- return "%s = _kw_only.pop('%s'%s)" % (
- attr_name,
- attr_name,
- arg_default,
- )
-
- def _unpack_kw_only_lines_py2(kw_only_args):
- """
- Unpack all *kw_only_args* from _kw_only dict and handle errors.
-
- Given a list of strings "{attr_name}" and "{attr_name}={default}"
- generates list of lines of code that pop attrs from _kw_only dict and
- raise TypeError similar to builtin if required attr is missing or
- extra key is passed.
-
- >>> print("\n".join(_unpack_kw_only_lines_py2(["a", "b=42"])))
- try:
- a = _kw_only.pop('a')
- b = _kw_only.pop('b', 42)
- except KeyError as _key_error:
- raise TypeError(
- ...
- if _kw_only:
- raise TypeError(
- ...
- """
- lines = ["try:"]
- lines.extend(
- " " + _unpack_kw_only_py2(*arg.split("="))
- for arg in kw_only_args
- )
- lines += """\
-except KeyError as _key_error:
- raise TypeError(
- '__init__() missing required keyword-only argument: %s' % _key_error
- )
-if _kw_only:
- raise TypeError(
- '__init__() got an unexpected keyword argument %r'
- % next(iter(_kw_only))
- )
-""".split(
- "\n"
- )
- return lines
-
-
-def _attrs_to_init_script(
- attrs,
- frozen,
- slots,
- pre_init,
- post_init,
- cache_hash,
- base_attr_map,
- is_exc,
- needs_cached_setattr,
- has_global_on_setattr,
- attrs_init,
-):
- """
- Return a script of an initializer for *attrs* and a dict of globals.
-
- The globals are expected by the generated script.
-
- If *frozen* is True, we cannot set the attributes directly so we use
- a cached ``object.__setattr__``.
- """
- lines = []
- if pre_init:
- lines.append("self.__attrs_pre_init__()")
-
- if needs_cached_setattr:
- lines.append(
- # Circumvent the __setattr__ descriptor to save one lookup per
- # assignment.
- # Note _setattr will be used again below if cache_hash is True
- "_setattr = _cached_setattr.__get__(self, self.__class__)"
- )
-
- if frozen is True:
- if slots is True:
- fmt_setter = _setattr
- fmt_setter_with_converter = _setattr_with_converter
- else:
- # Dict frozen classes assign directly to __dict__.
- # But only if the attribute doesn't come from an ancestor slot
- # class.
- # Note _inst_dict will be used again below if cache_hash is True
- lines.append("_inst_dict = self.__dict__")
-
- def fmt_setter(attr_name, value_var, has_on_setattr):
- if _is_slot_attr(attr_name, base_attr_map):
- return _setattr(attr_name, value_var, has_on_setattr)
-
- return "_inst_dict['%s'] = %s" % (attr_name, value_var)
-
- def fmt_setter_with_converter(
- attr_name, value_var, has_on_setattr
- ):
- if has_on_setattr or _is_slot_attr(attr_name, base_attr_map):
- return _setattr_with_converter(
- attr_name, value_var, has_on_setattr
- )
-
- return "_inst_dict['%s'] = %s(%s)" % (
- attr_name,
- _init_converter_pat % (attr_name,),
- value_var,
- )
-
- else:
- # Not frozen.
- fmt_setter = _assign
- fmt_setter_with_converter = _assign_with_converter
-
- args = []
- kw_only_args = []
- attrs_to_validate = []
-
- # This is a dictionary of names to validator and converter callables.
- # Injecting this into __init__ globals lets us avoid lookups.
- names_for_globals = {}
- annotations = {"return": None}
-
- for a in attrs:
- if a.validator:
- attrs_to_validate.append(a)
-
- attr_name = a.name
- has_on_setattr = a.on_setattr is not None or (
- a.on_setattr is not setters.NO_OP and has_global_on_setattr
- )
- arg_name = a.name.lstrip("_")
-
- has_factory = isinstance(a.default, Factory)
- if has_factory and a.default.takes_self:
- maybe_self = "self"
- else:
- maybe_self = ""
-
- if a.init is False:
- if has_factory:
- init_factory_name = _init_factory_pat.format(a.name)
- if a.converter is not None:
- lines.append(
- fmt_setter_with_converter(
- attr_name,
- init_factory_name + "(%s)" % (maybe_self,),
- has_on_setattr,
- )
- )
- conv_name = _init_converter_pat % (a.name,)
- names_for_globals[conv_name] = a.converter
- else:
- lines.append(
- fmt_setter(
- attr_name,
- init_factory_name + "(%s)" % (maybe_self,),
- has_on_setattr,
- )
- )
- names_for_globals[init_factory_name] = a.default.factory
- else:
- if a.converter is not None:
- lines.append(
- fmt_setter_with_converter(
- attr_name,
- "attr_dict['%s'].default" % (attr_name,),
- has_on_setattr,
- )
- )
- conv_name = _init_converter_pat % (a.name,)
- names_for_globals[conv_name] = a.converter
- else:
- lines.append(
- fmt_setter(
- attr_name,
- "attr_dict['%s'].default" % (attr_name,),
- has_on_setattr,
- )
- )
- elif a.default is not NOTHING and not has_factory:
- arg = "%s=attr_dict['%s'].default" % (arg_name, attr_name)
- if a.kw_only:
- kw_only_args.append(arg)
- else:
- args.append(arg)
-
- if a.converter is not None:
- lines.append(
- fmt_setter_with_converter(
- attr_name, arg_name, has_on_setattr
- )
- )
- names_for_globals[
- _init_converter_pat % (a.name,)
- ] = a.converter
- else:
- lines.append(fmt_setter(attr_name, arg_name, has_on_setattr))
-
- elif has_factory:
- arg = "%s=NOTHING" % (arg_name,)
- if a.kw_only:
- kw_only_args.append(arg)
- else:
- args.append(arg)
- lines.append("if %s is not NOTHING:" % (arg_name,))
-
- init_factory_name = _init_factory_pat.format(a.name)
- if a.converter is not None:
- lines.append(
- " "
- + fmt_setter_with_converter(
- attr_name, arg_name, has_on_setattr
- )
- )
- lines.append("else:")
- lines.append(
- " "
- + fmt_setter_with_converter(
- attr_name,
- init_factory_name + "(" + maybe_self + ")",
- has_on_setattr,
- )
- )
- names_for_globals[
- _init_converter_pat % (a.name,)
- ] = a.converter
- else:
- lines.append(
- " " + fmt_setter(attr_name, arg_name, has_on_setattr)
- )
- lines.append("else:")
- lines.append(
- " "
- + fmt_setter(
- attr_name,
- init_factory_name + "(" + maybe_self + ")",
- has_on_setattr,
- )
- )
- names_for_globals[init_factory_name] = a.default.factory
- else:
- if a.kw_only:
- kw_only_args.append(arg_name)
- else:
- args.append(arg_name)
-
- if a.converter is not None:
- lines.append(
- fmt_setter_with_converter(
- attr_name, arg_name, has_on_setattr
- )
- )
- names_for_globals[
- _init_converter_pat % (a.name,)
- ] = a.converter
- else:
- lines.append(fmt_setter(attr_name, arg_name, has_on_setattr))
-
- if a.init is True:
- if a.type is not None and a.converter is None:
- annotations[arg_name] = a.type
- elif a.converter is not None and not PY2:
- # Try to get the type from the converter.
- sig = None
- try:
- sig = inspect.signature(a.converter)
- except (ValueError, TypeError): # inspect failed
- pass
- if sig:
- sig_params = list(sig.parameters.values())
- if (
- sig_params
- and sig_params[0].annotation
- is not inspect.Parameter.empty
- ):
- annotations[arg_name] = sig_params[0].annotation
-
- if attrs_to_validate: # we can skip this if there are no validators.
- names_for_globals["_config"] = _config
- lines.append("if _config._run_validators is True:")
- for a in attrs_to_validate:
- val_name = "__attr_validator_" + a.name
- attr_name = "__attr_" + a.name
- lines.append(
- " %s(self, %s, self.%s)" % (val_name, attr_name, a.name)
- )
- names_for_globals[val_name] = a.validator
- names_for_globals[attr_name] = a
-
- if post_init:
- lines.append("self.__attrs_post_init__()")
-
- # because this is set only after __attrs_post_init is called, a crash
- # will result if post-init tries to access the hash code. This seemed
- # preferable to setting this beforehand, in which case alteration to
- # field values during post-init combined with post-init accessing the
- # hash code would result in silent bugs.
- if cache_hash:
- if frozen:
- if slots:
- # if frozen and slots, then _setattr defined above
- init_hash_cache = "_setattr('%s', %s)"
- else:
- # if frozen and not slots, then _inst_dict defined above
- init_hash_cache = "_inst_dict['%s'] = %s"
- else:
- init_hash_cache = "self.%s = %s"
- lines.append(init_hash_cache % (_hash_cache_field, "None"))
-
- # For exceptions we rely on BaseException.__init__ for proper
- # initialization.
- if is_exc:
- vals = ",".join("self." + a.name for a in attrs if a.init)
-
- lines.append("BaseException.__init__(self, %s)" % (vals,))
-
- args = ", ".join(args)
- if kw_only_args:
- if PY2:
- lines = _unpack_kw_only_lines_py2(kw_only_args) + lines
-
- args += "%s**_kw_only" % (", " if args else "",) # leading comma
- else:
- args += "%s*, %s" % (
- ", " if args else "", # leading comma
- ", ".join(kw_only_args), # kw_only args
- )
- return (
- """\
-def {init_name}(self, {args}):
- {lines}
-""".format(
- init_name=("__attrs_init__" if attrs_init else "__init__"),
- args=args,
- lines="\n ".join(lines) if lines else "pass",
- ),
- names_for_globals,
- annotations,
- )
-
-
-class Attribute(object):
- """
- *Read-only* representation of an attribute.
-
- Instances of this class are frequently used for introspection purposes
- like:
-
- - `fields` returns a tuple of them.
- - Validators get them passed as the first argument.
- - The *field transformer* hook receives a list of them.
-
- :attribute name: The name of the attribute.
- :attribute inherited: Whether or not that attribute has been inherited from
- a base class.
-
- Plus *all* arguments of `attr.ib` (except for ``factory``
- which is only syntactic sugar for ``default=Factory(...)``.
-
- .. versionadded:: 20.1.0 *inherited*
- .. versionadded:: 20.1.0 *on_setattr*
- .. versionchanged:: 20.2.0 *inherited* is not taken into account for
- equality checks and hashing anymore.
- .. versionadded:: 21.1.0 *eq_key* and *order_key*
-
- For the full version history of the fields, see `attr.ib`.
- """
-
- __slots__ = (
- "name",
- "default",
- "validator",
- "repr",
- "eq",
- "eq_key",
- "order",
- "order_key",
- "hash",
- "init",
- "metadata",
- "type",
- "converter",
- "kw_only",
- "inherited",
- "on_setattr",
- )
-
- def __init__(
- self,
- name,
- default,
- validator,
- repr,
- cmp, # XXX: unused, remove along with other cmp code.
- hash,
- init,
- inherited,
- metadata=None,
- type=None,
- converter=None,
- kw_only=False,
- eq=None,
- eq_key=None,
- order=None,
- order_key=None,
- on_setattr=None,
- ):
- eq, eq_key, order, order_key = _determine_attrib_eq_order(
- cmp, eq_key or eq, order_key or order, True
- )
-
- # Cache this descriptor here to speed things up later.
- bound_setattr = _obj_setattr.__get__(self, Attribute)
-
- # Despite the big red warning, people *do* instantiate `Attribute`
- # themselves.
- bound_setattr("name", name)
- bound_setattr("default", default)
- bound_setattr("validator", validator)
- bound_setattr("repr", repr)
- bound_setattr("eq", eq)
- bound_setattr("eq_key", eq_key)
- bound_setattr("order", order)
- bound_setattr("order_key", order_key)
- bound_setattr("hash", hash)
- bound_setattr("init", init)
- bound_setattr("converter", converter)
- bound_setattr(
- "metadata",
- (
- metadata_proxy(metadata)
- if metadata
- else _empty_metadata_singleton
- ),
- )
- bound_setattr("type", type)
- bound_setattr("kw_only", kw_only)
- bound_setattr("inherited", inherited)
- bound_setattr("on_setattr", on_setattr)
-
- def __setattr__(self, name, value):
- raise FrozenInstanceError()
-
- @classmethod
- def from_counting_attr(cls, name, ca, type=None):
- # type holds the annotated value. deal with conflicts:
- if type is None:
- type = ca.type
- elif ca.type is not None:
- raise ValueError(
- "Type annotation and type argument cannot both be present"
- )
- inst_dict = {
- k: getattr(ca, k)
- for k in Attribute.__slots__
- if k
- not in (
- "name",
- "validator",
- "default",
- "type",
- "inherited",
- ) # exclude methods and deprecated alias
- }
- return cls(
- name=name,
- validator=ca._validator,
- default=ca._default,
- type=type,
- cmp=None,
- inherited=False,
- **inst_dict
- )
-
- @property
- def cmp(self):
- """
- Simulate the presence of a cmp attribute and warn.
- """
- warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=2)
-
- return self.eq and self.order
-
- # Don't use attr.evolve since fields(Attribute) doesn't work
- def evolve(self, **changes):
- """
- Copy *self* and apply *changes*.
-
- This works similarly to `attr.evolve` but that function does not work
- with ``Attribute``.
-
- It is mainly meant to be used for `transform-fields`.
-
- .. versionadded:: 20.3.0
- """
- new = copy.copy(self)
-
- new._setattrs(changes.items())
-
- return new
-
- # Don't use _add_pickle since fields(Attribute) doesn't work
- def __getstate__(self):
- """
- Play nice with pickle.
- """
- return tuple(
- getattr(self, name) if name != "metadata" else dict(self.metadata)
- for name in self.__slots__
- )
-
- def __setstate__(self, state):
- """
- Play nice with pickle.
- """
- self._setattrs(zip(self.__slots__, state))
-
- def _setattrs(self, name_values_pairs):
- bound_setattr = _obj_setattr.__get__(self, Attribute)
- for name, value in name_values_pairs:
- if name != "metadata":
- bound_setattr(name, value)
- else:
- bound_setattr(
- name,
- metadata_proxy(value)
- if value
- else _empty_metadata_singleton,
- )
-
-
-_a = [
- Attribute(
- name=name,
- default=NOTHING,
- validator=None,
- repr=True,
- cmp=None,
- eq=True,
- order=False,
- hash=(name != "metadata"),
- init=True,
- inherited=False,
- )
- for name in Attribute.__slots__
-]
-
-Attribute = _add_hash(
- _add_eq(
- _add_repr(Attribute, attrs=_a),
- attrs=[a for a in _a if a.name != "inherited"],
- ),
- attrs=[a for a in _a if a.hash and a.name != "inherited"],
-)
-
-
-class _CountingAttr(object):
- """
- Intermediate representation of attributes that uses a counter to preserve
- the order in which the attributes have been defined.
-
- *Internal* data structure of the attrs library. Running into is most
- likely the result of a bug like a forgotten `@attr.s` decorator.
- """
-
- __slots__ = (
- "counter",
- "_default",
- "repr",
- "eq",
- "eq_key",
- "order",
- "order_key",
- "hash",
- "init",
- "metadata",
- "_validator",
- "converter",
- "type",
- "kw_only",
- "on_setattr",
- )
- __attrs_attrs__ = tuple(
- Attribute(
- name=name,
- default=NOTHING,
- validator=None,
- repr=True,
- cmp=None,
- hash=True,
- init=True,
- kw_only=False,
- eq=True,
- eq_key=None,
- order=False,
- order_key=None,
- inherited=False,
- on_setattr=None,
- )
- for name in (
- "counter",
- "_default",
- "repr",
- "eq",
- "order",
- "hash",
- "init",
- "on_setattr",
- )
- ) + (
- Attribute(
- name="metadata",
- default=None,
- validator=None,
- repr=True,
- cmp=None,
- hash=False,
- init=True,
- kw_only=False,
- eq=True,
- eq_key=None,
- order=False,
- order_key=None,
- inherited=False,
- on_setattr=None,
- ),
- )
- cls_counter = 0
-
- def __init__(
- self,
- default,
- validator,
- repr,
- cmp,
- hash,
- init,
- converter,
- metadata,
- type,
- kw_only,
- eq,
- eq_key,
- order,
- order_key,
- on_setattr,
- ):
- _CountingAttr.cls_counter += 1
- self.counter = _CountingAttr.cls_counter
- self._default = default
- self._validator = validator
- self.converter = converter
- self.repr = repr
- self.eq = eq
- self.eq_key = eq_key
- self.order = order
- self.order_key = order_key
- self.hash = hash
- self.init = init
- self.metadata = metadata
- self.type = type
- self.kw_only = kw_only
- self.on_setattr = on_setattr
-
- def validator(self, meth):
- """
- Decorator that adds *meth* to the list of validators.
-
- Returns *meth* unchanged.
-
- .. versionadded:: 17.1.0
- """
- if self._validator is None:
- self._validator = meth
- else:
- self._validator = and_(self._validator, meth)
- return meth
-
- def default(self, meth):
- """
- Decorator that allows to set the default for an attribute.
-
- Returns *meth* unchanged.
-
- :raises DefaultAlreadySetError: If default has been set before.
-
- .. versionadded:: 17.1.0
- """
- if self._default is not NOTHING:
- raise DefaultAlreadySetError()
-
- self._default = Factory(meth, takes_self=True)
-
- return meth
-
-
-_CountingAttr = _add_eq(_add_repr(_CountingAttr))
-
-
-class Factory(object):
- """
- Stores a factory callable.
-
- If passed as the default value to `attr.ib`, the factory is used to
- generate a new value.
-
- :param callable factory: A callable that takes either none or exactly one
- mandatory positional argument depending on *takes_self*.
- :param bool takes_self: Pass the partially initialized instance that is
- being initialized as a positional argument.
-
- .. versionadded:: 17.1.0 *takes_self*
- """
-
- __slots__ = ("factory", "takes_self")
-
- def __init__(self, factory, takes_self=False):
- """
- `Factory` is part of the default machinery so if we want a default
- value here, we have to implement it ourselves.
- """
- self.factory = factory
- self.takes_self = takes_self
-
- def __getstate__(self):
- """
- Play nice with pickle.
- """
- return tuple(getattr(self, name) for name in self.__slots__)
-
- def __setstate__(self, state):
- """
- Play nice with pickle.
- """
- for name, value in zip(self.__slots__, state):
- setattr(self, name, value)
-
-
-_f = [
- Attribute(
- name=name,
- default=NOTHING,
- validator=None,
- repr=True,
- cmp=None,
- eq=True,
- order=False,
- hash=True,
- init=True,
- inherited=False,
- )
- for name in Factory.__slots__
-]
-
-Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f)
-
-
-def make_class(name, attrs, bases=(object,), **attributes_arguments):
- """
- A quick way to create a new class called *name* with *attrs*.
-
- :param str name: The name for the new class.
-
- :param attrs: A list of names or a dictionary of mappings of names to
- attributes.
-
- If *attrs* is a list or an ordered dict (`dict` on Python 3.6+,
- `collections.OrderedDict` otherwise), the order is deduced from
- the order of the names or attributes inside *attrs*. Otherwise the
- order of the definition of the attributes is used.
- :type attrs: `list` or `dict`
-
- :param tuple bases: Classes that the new class will subclass.
-
- :param attributes_arguments: Passed unmodified to `attr.s`.
-
- :return: A new class with *attrs*.
- :rtype: type
-
- .. versionadded:: 17.1.0 *bases*
- .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained.
- """
- if isinstance(attrs, dict):
- cls_dict = attrs
- elif isinstance(attrs, (list, tuple)):
- cls_dict = dict((a, attrib()) for a in attrs)
- else:
- raise TypeError("attrs argument must be a dict or a list.")
-
- pre_init = cls_dict.pop("__attrs_pre_init__", None)
- post_init = cls_dict.pop("__attrs_post_init__", None)
- user_init = cls_dict.pop("__init__", None)
-
- body = {}
- if pre_init is not None:
- body["__attrs_pre_init__"] = pre_init
- if post_init is not None:
- body["__attrs_post_init__"] = post_init
- if user_init is not None:
- body["__init__"] = user_init
-
- type_ = new_class(name, bases, {}, lambda ns: ns.update(body))
-
- # For pickling to work, the __module__ variable needs to be set to the
- # frame where the class is created. Bypass this step in environments where
- # sys._getframe is not defined (Jython for example) or sys._getframe is not
- # defined for arguments greater than 0 (IronPython).
- try:
- type_.__module__ = sys._getframe(1).f_globals.get(
- "__name__", "__main__"
- )
- except (AttributeError, ValueError):
- pass
-
- # We do it here for proper warnings with meaningful stacklevel.
- cmp = attributes_arguments.pop("cmp", None)
- (
- attributes_arguments["eq"],
- attributes_arguments["order"],
- ) = _determine_attrs_eq_order(
- cmp,
- attributes_arguments.get("eq"),
- attributes_arguments.get("order"),
- True,
- )
-
- return _attrs(these=cls_dict, **attributes_arguments)(type_)
-
-
-# These are required by within this module so we define them here and merely
-# import into .validators / .converters.
-
-
-@attrs(slots=True, hash=True)
-class _AndValidator(object):
- """
- Compose many validators to a single one.
- """
-
- _validators = attrib()
-
- def __call__(self, inst, attr, value):
- for v in self._validators:
- v(inst, attr, value)
-
-
-def and_(*validators):
- """
- A validator that composes multiple validators into one.
-
- When called on a value, it runs all wrapped validators.
-
- :param callables validators: Arbitrary number of validators.
-
- .. versionadded:: 17.1.0
- """
- vals = []
- for validator in validators:
- vals.extend(
- validator._validators
- if isinstance(validator, _AndValidator)
- else [validator]
- )
-
- return _AndValidator(tuple(vals))
-
-
-def pipe(*converters):
- """
- A converter that composes multiple converters into one.
-
- When called on a value, it runs all wrapped converters, returning the
- *last* value.
-
- Type annotations will be inferred from the wrapped converters', if
- they have any.
-
- :param callables converters: Arbitrary number of converters.
-
- .. versionadded:: 20.1.0
- """
-
- def pipe_converter(val):
- for converter in converters:
- val = converter(val)
-
- return val
-
- if not PY2:
- if not converters:
- # If the converter list is empty, pipe_converter is the identity.
- A = typing.TypeVar("A")
- pipe_converter.__annotations__ = {"val": A, "return": A}
- else:
- # Get parameter type.
- sig = None
- try:
- sig = inspect.signature(converters[0])
- except (ValueError, TypeError): # inspect failed
- pass
- if sig:
- params = list(sig.parameters.values())
- if (
- params
- and params[0].annotation is not inspect.Parameter.empty
- ):
- pipe_converter.__annotations__["val"] = params[
- 0
- ].annotation
- # Get return type.
- sig = None
- try:
- sig = inspect.signature(converters[-1])
- except (ValueError, TypeError): # inspect failed
- pass
- if sig and sig.return_annotation is not inspect.Signature().empty:
- pipe_converter.__annotations__[
- "return"
- ] = sig.return_annotation
-
- return pipe_converter
diff --git a/contrib/python/attrs/attr/_next_gen.py b/contrib/python/attrs/attr/_next_gen.py
deleted file mode 100644
index fab0af966a5..00000000000
--- a/contrib/python/attrs/attr/_next_gen.py
+++ /dev/null
@@ -1,158 +0,0 @@
-"""
-These are Python 3.6+-only and keyword-only APIs that call `attr.s` and
-`attr.ib` with different default values.
-"""
-
-from functools import partial
-
-from attr.exceptions import UnannotatedAttributeError
-
-from . import setters
-from ._make import NOTHING, _frozen_setattrs, attrib, attrs
-
-
-def define(
- maybe_cls=None,
- *,
- these=None,
- repr=None,
- hash=None,
- init=None,
- slots=True,
- frozen=False,
- weakref_slot=True,
- str=False,
- auto_attribs=None,
- kw_only=False,
- cache_hash=False,
- auto_exc=True,
- eq=None,
- order=False,
- auto_detect=True,
- getstate_setstate=None,
- on_setattr=None,
- field_transformer=None,
-):
- r"""
- The only behavioral differences are the handling of the *auto_attribs*
- option:
-
- :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
- exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
-
- 1. If any attributes are annotated and no unannotated `attr.ib`\ s
- are found, it assumes *auto_attribs=True*.
- 2. Otherwise it assumes *auto_attribs=False* and tries to collect
- `attr.ib`\ s.
-
- and that mutable classes (``frozen=False``) validate on ``__setattr__``.
-
- .. versionadded:: 20.1.0
- """
-
- def do_it(cls, auto_attribs):
- return attrs(
- maybe_cls=cls,
- these=these,
- repr=repr,
- hash=hash,
- init=init,
- slots=slots,
- frozen=frozen,
- weakref_slot=weakref_slot,
- str=str,
- auto_attribs=auto_attribs,
- kw_only=kw_only,
- cache_hash=cache_hash,
- auto_exc=auto_exc,
- eq=eq,
- order=order,
- auto_detect=auto_detect,
- collect_by_mro=True,
- getstate_setstate=getstate_setstate,
- on_setattr=on_setattr,
- field_transformer=field_transformer,
- )
-
- def wrap(cls):
- """
- Making this a wrapper ensures this code runs during class creation.
-
- We also ensure that frozen-ness of classes is inherited.
- """
- nonlocal frozen, on_setattr
-
- had_on_setattr = on_setattr not in (None, setters.NO_OP)
-
- # By default, mutable classes validate on setattr.
- if frozen is False and on_setattr is None:
- on_setattr = setters.validate
-
- # However, if we subclass a frozen class, we inherit the immutability
- # and disable on_setattr.
- for base_cls in cls.__bases__:
- if base_cls.__setattr__ is _frozen_setattrs:
- if had_on_setattr:
- raise ValueError(
- "Frozen classes can't use on_setattr "
- "(frozen-ness was inherited)."
- )
-
- on_setattr = setters.NO_OP
- break
-
- if auto_attribs is not None:
- return do_it(cls, auto_attribs)
-
- try:
- return do_it(cls, True)
- except UnannotatedAttributeError:
- return do_it(cls, False)
-
- # maybe_cls's type depends on the usage of the decorator. It's a class
- # if it's used as `@attrs` but ``None`` if used as `@attrs()`.
- if maybe_cls is None:
- return wrap
- else:
- return wrap(maybe_cls)
-
-
-mutable = define
-frozen = partial(define, frozen=True, on_setattr=None)
-
-
-def field(
- *,
- default=NOTHING,
- validator=None,
- repr=True,
- hash=None,
- init=True,
- metadata=None,
- converter=None,
- factory=None,
- kw_only=False,
- eq=None,
- order=None,
- on_setattr=None,
-):
- """
- Identical to `attr.ib`, except keyword-only and with some arguments
- removed.
-
- .. versionadded:: 20.1.0
- """
- return attrib(
- default=default,
- validator=validator,
- repr=repr,
- hash=hash,
- init=init,
- metadata=metadata,
- converter=converter,
- factory=factory,
- kw_only=kw_only,
- eq=eq,
- order=order,
- on_setattr=on_setattr,
- )
diff --git a/contrib/python/attrs/attr/_version_info.py b/contrib/python/attrs/attr/_version_info.py
deleted file mode 100644
index 014e78a1b43..00000000000
--- a/contrib/python/attrs/attr/_version_info.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-from functools import total_ordering
-
-from ._funcs import astuple
-from ._make import attrib, attrs
-
-
-@total_ordering
-@attrs(eq=False, order=False, slots=True, frozen=True)
-class VersionInfo(object):
- """
- A version object that can be compared to tuple of length 1--4:
-
- >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2)
- True
- >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1)
- True
- >>> vi = attr.VersionInfo(19, 2, 0, "final")
- >>> vi < (19, 1, 1)
- False
- >>> vi < (19,)
- False
- >>> vi == (19, 2,)
- True
- >>> vi == (19, 2, 1)
- False
-
- .. versionadded:: 19.2
- """
-
- year = attrib(type=int)
- minor = attrib(type=int)
- micro = attrib(type=int)
- releaselevel = attrib(type=str)
-
- @classmethod
- def _from_version_string(cls, s):
- """
- Parse *s* and return a _VersionInfo.
- """
- v = s.split(".")
- if len(v) == 3:
- v.append("final")
-
- return cls(
- year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3]
- )
-
- def _ensure_tuple(self, other):
- """
- Ensure *other* is a tuple of a valid length.
-
- Returns a possibly transformed *other* and ourselves as a tuple of
- the same length as *other*.
- """
-
- if self.__class__ is other.__class__:
- other = astuple(other)
-
- if not isinstance(other, tuple):
- raise NotImplementedError
-
- if not (1 <= len(other) <= 4):
- raise NotImplementedError
-
- return astuple(self)[: len(other)], other
-
- def __eq__(self, other):
- try:
- us, them = self._ensure_tuple(other)
- except NotImplementedError:
- return NotImplemented
-
- return us == them
-
- def __lt__(self, other):
- try:
- us, them = self._ensure_tuple(other)
- except NotImplementedError:
- return NotImplemented
-
- # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't
- # have to do anything special with releaselevel for now.
- return us < them
diff --git a/contrib/python/attrs/attr/_version_info.pyi b/contrib/python/attrs/attr/_version_info.pyi
deleted file mode 100644
index 45ced086337..00000000000
--- a/contrib/python/attrs/attr/_version_info.pyi
+++ /dev/null
@@ -1,9 +0,0 @@
-class VersionInfo:
- @property
- def year(self) -> int: ...
- @property
- def minor(self) -> int: ...
- @property
- def micro(self) -> int: ...
- @property
- def releaselevel(self) -> str: ...
diff --git a/contrib/python/attrs/attr/converters.py b/contrib/python/attrs/attr/converters.py
deleted file mode 100644
index 2777db6d0af..00000000000
--- a/contrib/python/attrs/attr/converters.py
+++ /dev/null
@@ -1,111 +0,0 @@
-"""
-Commonly useful converters.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-from ._compat import PY2
-from ._make import NOTHING, Factory, pipe
-
-
-if not PY2:
- import inspect
- import typing
-
-
-__all__ = [
- "pipe",
- "optional",
- "default_if_none",
-]
-
-
-def optional(converter):
- """
- A converter that allows an attribute to be optional. An optional attribute
- is one which can be set to ``None``.
-
- Type annotations will be inferred from the wrapped converter's, if it
- has any.
-
- :param callable converter: the converter that is used for non-``None``
- values.
-
- .. versionadded:: 17.1.0
- """
-
- def optional_converter(val):
- if val is None:
- return None
- return converter(val)
-
- if not PY2:
- sig = None
- try:
- sig = inspect.signature(converter)
- except (ValueError, TypeError): # inspect failed
- pass
- if sig:
- params = list(sig.parameters.values())
- if params and params[0].annotation is not inspect.Parameter.empty:
- optional_converter.__annotations__["val"] = typing.Optional[
- params[0].annotation
- ]
- if sig.return_annotation is not inspect.Signature.empty:
- optional_converter.__annotations__["return"] = typing.Optional[
- sig.return_annotation
- ]
-
- return optional_converter
-
-
-def default_if_none(default=NOTHING, factory=None):
- """
- A converter that allows to replace ``None`` values by *default* or the
- result of *factory*.
-
- :param default: Value to be used if ``None`` is passed. Passing an instance
- of `attr.Factory` is supported, however the ``takes_self`` option
- is *not*.
- :param callable factory: A callable that takes no parameters whose result
- is used if ``None`` is passed.
-
- :raises TypeError: If **neither** *default* or *factory* is passed.
- :raises TypeError: If **both** *default* and *factory* are passed.
- :raises ValueError: If an instance of `attr.Factory` is passed with
- ``takes_self=True``.
-
- .. versionadded:: 18.2.0
- """
- if default is NOTHING and factory is None:
- raise TypeError("Must pass either `default` or `factory`.")
-
- if default is not NOTHING and factory is not None:
- raise TypeError(
- "Must pass either `default` or `factory` but not both."
- )
-
- if factory is not None:
- default = Factory(factory)
-
- if isinstance(default, Factory):
- if default.takes_self:
- raise ValueError(
- "`takes_self` is not supported by default_if_none."
- )
-
- def default_if_none_converter(val):
- if val is not None:
- return val
-
- return default.factory()
-
- else:
-
- def default_if_none_converter(val):
- if val is not None:
- return val
-
- return default
-
- return default_if_none_converter
diff --git a/contrib/python/attrs/attr/converters.pyi b/contrib/python/attrs/attr/converters.pyi
deleted file mode 100644
index 84a57590b0f..00000000000
--- a/contrib/python/attrs/attr/converters.pyi
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import Callable, Optional, TypeVar, overload
-
-from . import _ConverterType
-
-
-_T = TypeVar("_T")
-
-def pipe(*validators: _ConverterType) -> _ConverterType: ...
-def optional(converter: _ConverterType) -> _ConverterType: ...
-@overload
-def default_if_none(default: _T) -> _ConverterType: ...
-@overload
-def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ...
diff --git a/contrib/python/attrs/attr/exceptions.py b/contrib/python/attrs/attr/exceptions.py
deleted file mode 100644
index f6f9861bea9..00000000000
--- a/contrib/python/attrs/attr/exceptions.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from __future__ import absolute_import, division, print_function
-
-
-class FrozenError(AttributeError):
- """
- A frozen/immutable instance or attribute have been attempted to be
- modified.
-
- It mirrors the behavior of ``namedtuples`` by using the same error message
- and subclassing `AttributeError`.
-
- .. versionadded:: 20.1.0
- """
-
- msg = "can't set attribute"
- args = [msg]
-
-
-class FrozenInstanceError(FrozenError):
- """
- A frozen instance has been attempted to be modified.
-
- .. versionadded:: 16.1.0
- """
-
-
-class FrozenAttributeError(FrozenError):
- """
- A frozen attribute has been attempted to be modified.
-
- .. versionadded:: 20.1.0
- """
-
-
-class AttrsAttributeNotFoundError(ValueError):
- """
- An ``attrs`` function couldn't find an attribute that the user asked for.
-
- .. versionadded:: 16.2.0
- """
-
-
-class NotAnAttrsClassError(ValueError):
- """
- A non-``attrs`` class has been passed into an ``attrs`` function.
-
- .. versionadded:: 16.2.0
- """
-
-
-class DefaultAlreadySetError(RuntimeError):
- """
- A default has been set using ``attr.ib()`` and is attempted to be reset
- using the decorator.
-
- .. versionadded:: 17.1.0
- """
-
-
-class UnannotatedAttributeError(RuntimeError):
- """
- A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type
- annotation.
-
- .. versionadded:: 17.3.0
- """
-
-
-class PythonTooOldError(RuntimeError):
- """
- It was attempted to use an ``attrs`` feature that requires a newer Python
- version.
-
- .. versionadded:: 18.2.0
- """
-
-
-class NotCallableError(TypeError):
- """
- A ``attr.ib()`` requiring a callable has been set with a value
- that is not callable.
-
- .. versionadded:: 19.2.0
- """
-
- def __init__(self, msg, value):
- super(TypeError, self).__init__(msg, value)
- self.msg = msg
- self.value = value
-
- def __str__(self):
- return str(self.msg)
diff --git a/contrib/python/attrs/attr/exceptions.pyi b/contrib/python/attrs/attr/exceptions.pyi
deleted file mode 100644
index a800fb26bba..00000000000
--- a/contrib/python/attrs/attr/exceptions.pyi
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Any
-
-
-class FrozenError(AttributeError):
- msg: str = ...
-
-class FrozenInstanceError(FrozenError): ...
-class FrozenAttributeError(FrozenError): ...
-class AttrsAttributeNotFoundError(ValueError): ...
-class NotAnAttrsClassError(ValueError): ...
-class DefaultAlreadySetError(RuntimeError): ...
-class UnannotatedAttributeError(RuntimeError): ...
-class PythonTooOldError(RuntimeError): ...
-
-class NotCallableError(TypeError):
- msg: str = ...
- value: Any = ...
- def __init__(self, msg: str, value: Any) -> None: ...
diff --git a/contrib/python/attrs/attr/filters.py b/contrib/python/attrs/attr/filters.py
deleted file mode 100644
index dc47e8fa38c..00000000000
--- a/contrib/python/attrs/attr/filters.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-Commonly useful filters for `attr.asdict`.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-from ._compat import isclass
-from ._make import Attribute
-
-
-def _split_what(what):
- """
- Returns a tuple of `frozenset`s of classes and attributes.
- """
- return (
- frozenset(cls for cls in what if isclass(cls)),
- frozenset(cls for cls in what if isinstance(cls, Attribute)),
- )
-
-
-def include(*what):
- """
- Whitelist *what*.
-
- :param what: What to whitelist.
- :type what: `list` of `type` or `attr.Attribute`\\ s
-
- :rtype: `callable`
- """
- cls, attrs = _split_what(what)
-
- def include_(attribute, value):
- return value.__class__ in cls or attribute in attrs
-
- return include_
-
-
-def exclude(*what):
- """
- Blacklist *what*.
-
- :param what: What to blacklist.
- :type what: `list` of classes or `attr.Attribute`\\ s.
-
- :rtype: `callable`
- """
- cls, attrs = _split_what(what)
-
- def exclude_(attribute, value):
- return value.__class__ not in cls and attribute not in attrs
-
- return exclude_
diff --git a/contrib/python/attrs/attr/filters.pyi b/contrib/python/attrs/attr/filters.pyi
deleted file mode 100644
index f7b63f1bb45..00000000000
--- a/contrib/python/attrs/attr/filters.pyi
+++ /dev/null
@@ -1,7 +0,0 @@
-from typing import Any, Union
-
-from . import Attribute, _FilterType
-
-
-def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ...
-def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ...
diff --git a/contrib/python/attrs/attr/py.typed b/contrib/python/attrs/attr/py.typed
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/contrib/python/attrs/attr/py.typed
+++ /dev/null
diff --git a/contrib/python/attrs/attr/setters.py b/contrib/python/attrs/attr/setters.py
deleted file mode 100644
index 240014b3c1e..00000000000
--- a/contrib/python/attrs/attr/setters.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-Commonly used hooks for on_setattr.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-from . import _config
-from .exceptions import FrozenAttributeError
-
-
-def pipe(*setters):
- """
- Run all *setters* and return the return value of the last one.
-
- .. versionadded:: 20.1.0
- """
-
- def wrapped_pipe(instance, attrib, new_value):
- rv = new_value
-
- for setter in setters:
- rv = setter(instance, attrib, rv)
-
- return rv
-
- return wrapped_pipe
-
-
-def frozen(_, __, ___):
- """
- Prevent an attribute to be modified.
-
- .. versionadded:: 20.1.0
- """
- raise FrozenAttributeError()
-
-
-def validate(instance, attrib, new_value):
- """
- Run *attrib*'s validator on *new_value* if it has one.
-
- .. versionadded:: 20.1.0
- """
- if _config._run_validators is False:
- return new_value
-
- v = attrib.validator
- if not v:
- return new_value
-
- v(instance, attrib, new_value)
-
- return new_value
-
-
-def convert(instance, attrib, new_value):
- """
- Run *attrib*'s converter -- if it has one -- on *new_value* and return the
- result.
-
- .. versionadded:: 20.1.0
- """
- c = attrib.converter
- if c:
- return c(new_value)
-
- return new_value
-
-
-NO_OP = object()
-"""
-Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
-
-Does not work in `pipe` or within lists.
-
-.. versionadded:: 20.1.0
-"""
diff --git a/contrib/python/attrs/attr/setters.pyi b/contrib/python/attrs/attr/setters.pyi
deleted file mode 100644
index a921e07deb6..00000000000
--- a/contrib/python/attrs/attr/setters.pyi
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Any, NewType, NoReturn, TypeVar, cast
-
-from . import Attribute, _OnSetAttrType
-
-
-_T = TypeVar("_T")
-
-def frozen(
- instance: Any, attribute: Attribute[Any], new_value: Any
-) -> NoReturn: ...
-def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ...
-def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ...
-
-# convert is allowed to return Any, because they can be chained using pipe.
-def convert(
- instance: Any, attribute: Attribute[Any], new_value: Any
-) -> Any: ...
-
-_NoOpType = NewType("_NoOpType", object)
-NO_OP: _NoOpType
diff --git a/contrib/python/attrs/attr/validators.py b/contrib/python/attrs/attr/validators.py
deleted file mode 100644
index b9a73054e9c..00000000000
--- a/contrib/python/attrs/attr/validators.py
+++ /dev/null
@@ -1,379 +0,0 @@
-"""
-Commonly useful validators.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-import re
-
-from ._make import _AndValidator, and_, attrib, attrs
-from .exceptions import NotCallableError
-
-
-__all__ = [
- "and_",
- "deep_iterable",
- "deep_mapping",
- "in_",
- "instance_of",
- "is_callable",
- "matches_re",
- "optional",
- "provides",
-]
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _InstanceOfValidator(object):
- type = attrib()
-
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if not isinstance(value, self.type):
- raise TypeError(
- "'{name}' must be {type!r} (got {value!r} that is a "
- "{actual!r}).".format(
- name=attr.name,
- type=self.type,
- actual=value.__class__,
- value=value,
- ),
- attr,
- self.type,
- value,
- )
-
- def __repr__(self):
- return "<instance_of validator for type {type!r}>".format(
- type=self.type
- )
-
-
-def instance_of(type):
- """
- A validator that raises a `TypeError` if the initializer is called
- with a wrong type for this particular attribute (checks are performed using
- `isinstance` therefore it's also valid to pass a tuple of types).
-
- :param type: The type to check for.
- :type type: type or tuple of types
-
- :raises TypeError: With a human readable error message, the attribute
- (of type `attr.Attribute`), the expected type, and the value it
- got.
- """
- return _InstanceOfValidator(type)
-
-
-@attrs(repr=False, frozen=True, slots=True)
-class _MatchesReValidator(object):
- regex = attrib()
- flags = attrib()
- match_func = attrib()
-
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if not self.match_func(value):
- raise ValueError(
- "'{name}' must match regex {regex!r}"
- " ({value!r} doesn't)".format(
- name=attr.name, regex=self.regex.pattern, value=value
- ),
- attr,
- self.regex,
- value,
- )
-
- def __repr__(self):
- return "<matches_re validator for pattern {regex!r}>".format(
- regex=self.regex
- )
-
-
-def matches_re(regex, flags=0, func=None):
- r"""
- A validator that raises `ValueError` if the initializer is called
- with a string that doesn't match *regex*.
-
- :param str regex: a regex string to match against
- :param int flags: flags that will be passed to the underlying re function
- (default 0)
- :param callable func: which underlying `re` function to call (options
- are `re.fullmatch`, `re.search`, `re.match`, default
- is ``None`` which means either `re.fullmatch` or an emulation of
- it on Python 2). For performance reasons, they won't be used directly
- but on a pre-`re.compile`\ ed pattern.
-
- .. versionadded:: 19.2.0
- """
- fullmatch = getattr(re, "fullmatch", None)
- valid_funcs = (fullmatch, None, re.search, re.match)
- if func not in valid_funcs:
- raise ValueError(
- "'func' must be one of %s."
- % (
- ", ".join(
- sorted(
- e and e.__name__ or "None" for e in set(valid_funcs)
- )
- ),
- )
- )
-
- pattern = re.compile(regex, flags)
- if func is re.match:
- match_func = pattern.match
- elif func is re.search:
- match_func = pattern.search
- else:
- if fullmatch:
- match_func = pattern.fullmatch
- else:
- pattern = re.compile(r"(?:{})\Z".format(regex), flags)
- match_func = pattern.match
-
- return _MatchesReValidator(pattern, flags, match_func)
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _ProvidesValidator(object):
- interface = attrib()
-
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if not self.interface.providedBy(value):
- raise TypeError(
- "'{name}' must provide {interface!r} which {value!r} "
- "doesn't.".format(
- name=attr.name, interface=self.interface, value=value
- ),
- attr,
- self.interface,
- value,
- )
-
- def __repr__(self):
- return "<provides validator for interface {interface!r}>".format(
- interface=self.interface
- )
-
-
-def provides(interface):
- """
- A validator that raises a `TypeError` if the initializer is called
- with an object that does not provide the requested *interface* (checks are
- performed using ``interface.providedBy(value)`` (see `zope.interface
- <https://zopeinterface.readthedocs.io/en/latest/>`_).
-
- :param interface: The interface to check for.
- :type interface: ``zope.interface.Interface``
-
- :raises TypeError: With a human readable error message, the attribute
- (of type `attr.Attribute`), the expected interface, and the
- value it got.
- """
- return _ProvidesValidator(interface)
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _OptionalValidator(object):
- validator = attrib()
-
- def __call__(self, inst, attr, value):
- if value is None:
- return
-
- self.validator(inst, attr, value)
-
- def __repr__(self):
- return "<optional validator for {what} or None>".format(
- what=repr(self.validator)
- )
-
-
-def optional(validator):
- """
- A validator that makes an attribute optional. An optional attribute is one
- which can be set to ``None`` in addition to satisfying the requirements of
- the sub-validator.
-
- :param validator: A validator (or a list of validators) that is used for
- non-``None`` values.
- :type validator: callable or `list` of callables.
-
- .. versionadded:: 15.1.0
- .. versionchanged:: 17.1.0 *validator* can be a list of validators.
- """
- if isinstance(validator, list):
- return _OptionalValidator(_AndValidator(validator))
- return _OptionalValidator(validator)
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _InValidator(object):
- options = attrib()
-
- def __call__(self, inst, attr, value):
- try:
- in_options = value in self.options
- except TypeError: # e.g. `1 in "abc"`
- in_options = False
-
- if not in_options:
- raise ValueError(
- "'{name}' must be in {options!r} (got {value!r})".format(
- name=attr.name, options=self.options, value=value
- )
- )
-
- def __repr__(self):
- return "<in_ validator with options {options!r}>".format(
- options=self.options
- )
-
-
-def in_(options):
- """
- A validator that raises a `ValueError` if the initializer is called
- with a value that does not belong in the options provided. The check is
- performed using ``value in options``.
-
- :param options: Allowed options.
- :type options: list, tuple, `enum.Enum`, ...
-
- :raises ValueError: With a human readable error message, the attribute (of
- type `attr.Attribute`), the expected options, and the value it
- got.
-
- .. versionadded:: 17.1.0
- """
- return _InValidator(options)
-
-
-@attrs(repr=False, slots=False, hash=True)
-class _IsCallableValidator(object):
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if not callable(value):
- message = (
- "'{name}' must be callable "
- "(got {value!r} that is a {actual!r})."
- )
- raise NotCallableError(
- msg=message.format(
- name=attr.name, value=value, actual=value.__class__
- ),
- value=value,
- )
-
- def __repr__(self):
- return "<is_callable validator>"
-
-
-def is_callable():
- """
- A validator that raises a `attr.exceptions.NotCallableError` if the
- initializer is called with a value for this particular attribute
- that is not callable.
-
- .. versionadded:: 19.1.0
-
- :raises `attr.exceptions.NotCallableError`: With a human readable error
- message containing the attribute (`attr.Attribute`) name,
- and the value it got.
- """
- return _IsCallableValidator()
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _DeepIterable(object):
- member_validator = attrib(validator=is_callable())
- iterable_validator = attrib(
- default=None, validator=optional(is_callable())
- )
-
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if self.iterable_validator is not None:
- self.iterable_validator(inst, attr, value)
-
- for member in value:
- self.member_validator(inst, attr, member)
-
- def __repr__(self):
- iterable_identifier = (
- ""
- if self.iterable_validator is None
- else " {iterable!r}".format(iterable=self.iterable_validator)
- )
- return (
- "<deep_iterable validator for{iterable_identifier}"
- " iterables of {member!r}>"
- ).format(
- iterable_identifier=iterable_identifier,
- member=self.member_validator,
- )
-
-
-def deep_iterable(member_validator, iterable_validator=None):
- """
- A validator that performs deep validation of an iterable.
-
- :param member_validator: Validator to apply to iterable members
- :param iterable_validator: Validator to apply to iterable itself
- (optional)
-
- .. versionadded:: 19.1.0
-
- :raises TypeError: if any sub-validators fail
- """
- return _DeepIterable(member_validator, iterable_validator)
-
-
-@attrs(repr=False, slots=True, hash=True)
-class _DeepMapping(object):
- key_validator = attrib(validator=is_callable())
- value_validator = attrib(validator=is_callable())
- mapping_validator = attrib(default=None, validator=optional(is_callable()))
-
- def __call__(self, inst, attr, value):
- """
- We use a callable class to be able to change the ``__repr__``.
- """
- if self.mapping_validator is not None:
- self.mapping_validator(inst, attr, value)
-
- for key in value:
- self.key_validator(inst, attr, key)
- self.value_validator(inst, attr, value[key])
-
- def __repr__(self):
- return (
- "<deep_mapping validator for objects mapping {key!r} to {value!r}>"
- ).format(key=self.key_validator, value=self.value_validator)
-
-
-def deep_mapping(key_validator, value_validator, mapping_validator=None):
- """
- A validator that performs deep validation of a dictionary.
-
- :param key_validator: Validator to apply to dictionary keys
- :param value_validator: Validator to apply to dictionary values
- :param mapping_validator: Validator to apply to top-level mapping
- attribute (optional)
-
- .. versionadded:: 19.1.0
-
- :raises TypeError: if any sub-validators fail
- """
- return _DeepMapping(key_validator, value_validator, mapping_validator)
diff --git a/contrib/python/attrs/attr/validators.pyi b/contrib/python/attrs/attr/validators.pyi
deleted file mode 100644
index fe92aac421b..00000000000
--- a/contrib/python/attrs/attr/validators.pyi
+++ /dev/null
@@ -1,68 +0,0 @@
-from typing import (
- Any,
- AnyStr,
- Callable,
- Container,
- Iterable,
- List,
- Mapping,
- Match,
- Optional,
- Tuple,
- Type,
- TypeVar,
- Union,
- overload,
-)
-
-from . import _ValidatorType
-
-
-_T = TypeVar("_T")
-_T1 = TypeVar("_T1")
-_T2 = TypeVar("_T2")
-_T3 = TypeVar("_T3")
-_I = TypeVar("_I", bound=Iterable)
-_K = TypeVar("_K")
-_V = TypeVar("_V")
-_M = TypeVar("_M", bound=Mapping)
-
-# To be more precise on instance_of use some overloads.
-# If there are more than 3 items in the tuple then we fall back to Any
-@overload
-def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ...
-@overload
-def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
-@overload
-def instance_of(
- type: Tuple[Type[_T1], Type[_T2]]
-) -> _ValidatorType[Union[_T1, _T2]]: ...
-@overload
-def instance_of(
- type: Tuple[Type[_T1], Type[_T2], Type[_T3]]
-) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
-@overload
-def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
-def provides(interface: Any) -> _ValidatorType[Any]: ...
-def optional(
- validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]]
-) -> _ValidatorType[Optional[_T]]: ...
-def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
-def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
-def matches_re(
- regex: AnyStr,
- flags: int = ...,
- func: Optional[
- Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]
- ] = ...,
-) -> _ValidatorType[AnyStr]: ...
-def deep_iterable(
- member_validator: _ValidatorType[_T],
- iterable_validator: Optional[_ValidatorType[_I]] = ...,
-) -> _ValidatorType[_I]: ...
-def deep_mapping(
- key_validator: _ValidatorType[_K],
- value_validator: _ValidatorType[_V],
- mapping_validator: Optional[_ValidatorType[_M]] = ...,
-) -> _ValidatorType[_M]: ...
-def is_callable() -> _ValidatorType[_T]: ...