diff options
author | AlexSm <alex@ydb.tech> | 2024-01-18 11:28:56 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-18 11:28:56 +0100 |
commit | 9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch) | |
tree | 541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/python/attrs/py3 | |
parent | 404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff) | |
download | ydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz |
Library import 8 (#1074)
* Library import 8
* Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/python/attrs/py3')
-rw-r--r-- | contrib/python/attrs/py3/.dist-info/METADATA | 101 | ||||
-rw-r--r-- | contrib/python/attrs/py3/README.md | 38 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/__init__.py | 20 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_cmp.py | 11 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_compat.py | 116 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_config.py | 4 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_funcs.py | 82 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_make.py | 648 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/_next_gen.py | 21 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/converters.py | 16 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/exceptions.py | 6 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attr/validators.py | 121 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attrs/converters.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attrs/exceptions.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attrs/filters.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attrs/setters.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/py3/attrs/validators.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/py3/ya.make | 2 |
18 files changed, 566 insertions, 630 deletions
diff --git a/contrib/python/attrs/py3/.dist-info/METADATA b/contrib/python/attrs/py3/.dist-info/METADATA index 4a986f007f..c20be76c74 100644 --- a/contrib/python/attrs/py3/.dist-info/METADATA +++ b/contrib/python/attrs/py3/.dist-info/METADATA @@ -1,11 +1,10 @@ Metadata-Version: 2.1 Name: attrs -Version: 23.1.0 +Version: 23.2.0 Summary: Classes Without Boilerplate 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: GitHub, 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 Author-email: Hynek Schlawack <hs@ox.cx> @@ -13,13 +12,13 @@ License-Expression: MIT License-File: LICENSE Keywords: attribute,boilerplate,class Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License 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 :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Typing :: Typed @@ -29,7 +28,7 @@ Provides-Extra: cov Requires-Dist: attrs[tests]; extra == 'cov' Requires-Dist: coverage[toml]>=5.3; extra == 'cov' Provides-Extra: dev -Requires-Dist: attrs[docs,tests]; extra == 'dev' +Requires-Dist: attrs[tests]; extra == 'dev' Requires-Dist: pre-commit; extra == 'dev' Provides-Extra: docs Requires-Dist: furo; extra == 'docs' @@ -42,12 +41,14 @@ Requires-Dist: zope-interface; extra == 'docs' Provides-Extra: tests Requires-Dist: attrs[tests-no-zope]; extra == 'tests' Requires-Dist: zope-interface; extra == 'tests' +Provides-Extra: tests-mypy +Requires-Dist: mypy>=1.6; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' +Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' Provides-Extra: tests-no-zope -Requires-Dist: cloudpickle; platform_python_implementation == 'CPython' and extra == 'tests-no-zope' +Requires-Dist: attrs[tests-mypy]; extra == 'tests-no-zope' +Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'tests-no-zope' Requires-Dist: hypothesis; extra == 'tests-no-zope' -Requires-Dist: mypy>=1.1.1; platform_python_implementation == 'CPython' and extra == 'tests-no-zope' Requires-Dist: pympler; extra == 'tests-no-zope' -Requires-Dist: pytest-mypy-plugins; platform_python_implementation == 'CPython' and python_version < '3.11' and extra == 'tests-no-zope' Requires-Dist: pytest-xdist[psutil]; extra == 'tests-no-zope' Requires-Dist: pytest>=4.3.0; extra == 'tests-no-zope' Description-Content-Type: text/markdown @@ -71,21 +72,9 @@ Its main goal is to help you to write **concise** and **correct** software witho Especially those generously supporting us at the *The Organization* tier and higher: <p align="center"> - <a href="https://www.variomedia.de/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Variomedia.svg" width="200" height="60"></img> - </a> - - <a href="https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Tidelift.svg" width="200" height="60"></img> - </a> - - <a href="https://sentry.io/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Sentry.svg" width="200" height="60"></img> - </a> - - <a href="https://filepreviews.io/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/FilePreviews.svg" width="200" height="60"></img> - </a> + <a href="https://www.variomedia.de/"><img src="https://www.attrs.org/en/23.2.0/_static/sponsors/Variomedia.svg" width="200" height="60" /></a> + <a href="https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo"><img src="https://www.attrs.org/en/23.2.0/_static/sponsors/Tidelift.svg" width="200" height="60" /></a> + <a href="https://filepreviews.io/"><img src="https://www.attrs.org/en/23.2.0/_static/sponsors/FilePreviews.svg" width="200" height="60"/></a> </p> <p align="center"> @@ -161,7 +150,7 @@ Please check out [*On The Core API Names*](https://www.attrs.org/en/latest/names On the tin, *attrs* might remind you of `dataclasses` (and indeed, `dataclasses` [are a descendant](https://hynek.me/articles/import-attrs/) of *attrs*). In practice it does a lot more and is more flexible. -For instance it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), or allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization). +For instance it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization), and allows for stepping through the generated methods using a debugger. For more details, please refer to our [comparison page](https://www.attrs.org/en/stable/why.html#data-classes). @@ -174,9 +163,7 @@ For more details, please refer to our [comparison page](https://www.attrs.org/en - [**Source Code**](https://github.com/python-attrs/attrs) - [**Contributing**](https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md) - [**Third-party Extensions**](https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs) -- **License**: [MIT](https://www.attrs.org/en/latest/license.html) - **Get Help**: please use the `python-attrs` tag on [StackOverflow](https://stackoverflow.com/questions/tagged/python-attrs) -- **Supported Python Versions**: 3.7 and later ### *attrs* for Enterprise @@ -189,53 +176,25 @@ Save time, reduce risk, and improve code health, while paying the maintainers of ## Release Information -### Backwards-incompatible Changes - -- Python 3.6 has been dropped and packaging switched to static package data using [Hatch](https://hatch.pypa.io/latest/). - [#993](https://github.com/python-attrs/attrs/issues/993) - - -### Deprecations - -- The support for *zope-interface* via the `attrs.validators.provides` validator is now deprecated and will be removed in, or after, April 2024. - - The presence of a C-based package in our developement dependencies has caused headaches and we're not under the impression it's used a lot. - - Let us know if you're using it and we might publish it as a separate package. - [#1120](https://github.com/python-attrs/attrs/issues/1120) - - ### Changes -- `attrs.filters.exclude()` and `attrs.filters.include()` now support the passing of attribute names as strings. - [#1068](https://github.com/python-attrs/attrs/issues/1068) -- `attrs.has()` and `attrs.fields()` now handle generic classes correctly. - [#1079](https://github.com/python-attrs/attrs/issues/1079) -- Fix frozen exception classes when raised within e.g. `contextlib.contextmanager`, which mutates their `__traceback__` attributes. - [#1081](https://github.com/python-attrs/attrs/issues/1081) -- `@frozen` now works with type checkers that implement [PEP-681](https://peps.python.org/pep-0681/) (ex. [pyright](https://github.com/microsoft/pyright/)). - [#1084](https://github.com/python-attrs/attrs/issues/1084) -- Restored ability to unpickle instances pickled before 22.2.0. - [#1085](https://github.com/python-attrs/attrs/issues/1085) -- `attrs.asdict()`'s and `attrs.astuple()`'s type stubs now accept the `attrs.AttrsInstance` protocol. - [#1090](https://github.com/python-attrs/attrs/issues/1090) -- Fix slots class cellvar updating closure in CPython 3.8+ even when `__code__` introspection is unavailable. - [#1092](https://github.com/python-attrs/attrs/issues/1092) -- `attrs.resolve_types()` can now pass `include_extras` to `typing.get_type_hints()` on Python 3.9+, and does so by default. - [#1099](https://github.com/python-attrs/attrs/issues/1099) -- Added instructions for pull request workflow to `CONTRIBUTING.md`. - [#1105](https://github.com/python-attrs/attrs/issues/1105) -- Added *type* parameter to `attrs.field()` function for use with `attrs.make_class()`. - - Please note that type checkers ignore type metadata passed into `make_class()`, but it can be useful if you're wrapping _attrs_. - [#1107](https://github.com/python-attrs/attrs/issues/1107) -- It is now possible for `attrs.evolve()` (and `attr.evolve()`) to change fields named `inst` if the instance is passed as a positional argument. - - Passing the instance using the `inst` keyword argument is now deprecated and will be removed in, or after, April 2024. - [#1117](https://github.com/python-attrs/attrs/issues/1117) -- `attrs.validators.optional()` now also accepts a tuple of validators (in addition to lists of validators). - [#1122](https://github.com/python-attrs/attrs/issues/1122) - +- The type annotation for `attrs.resolve_types()` is now correct. + [#1141](https://github.com/python-attrs/attrs/issues/1141) +- Type stubs now use `typing.dataclass_transform` to decorate dataclass-like decorators, instead of the non-standard `__dataclass_transform__` special form, which is only supported by Pyright. + [#1158](https://github.com/python-attrs/attrs/issues/1158) +- Fixed serialization of namedtuple fields using `attrs.asdict/astuple()` with `retain_collection_types=True`. + [#1165](https://github.com/python-attrs/attrs/issues/1165) +- `attrs.AttrsInstance` is now a `typing.Protocol` in both type hints and code. + This allows you to subclass it along with another `Protocol`. + [#1172](https://github.com/python-attrs/attrs/issues/1172) +- If *attrs* detects that `__attrs_pre_init__` accepts more than just `self`, it will call it with the same arguments as `__init__` was called. + This allows you to, for example, pass arguments to `super().__init__()`. + [#1187](https://github.com/python-attrs/attrs/issues/1187) +- Slotted classes now transform `functools.cached_property` decorated methods to support equivalent semantics. + [#1200](https://github.com/python-attrs/attrs/issues/1200) +- Added *class_body* argument to `attrs.make_class()` to provide additional attributes for newly created classes. + It is, for example, now possible to attach methods. + [#1203](https://github.com/python-attrs/attrs/issues/1203) --- diff --git a/contrib/python/attrs/py3/README.md b/contrib/python/attrs/py3/README.md index 2f5b223bfd..6ef8c0204e 100644 --- a/contrib/python/attrs/py3/README.md +++ b/contrib/python/attrs/py3/README.md @@ -8,19 +8,11 @@ </p> <p align="center"> - <a href="https://www.attrs.org/en/stable/"> - <img src="https://img.shields.io/badge/Docs-RTD-black" alt="Documentation" /> - </a> - <a href="https://github.com/python-attrs/attrs/blob/main/LICENSE"> - <img src="https://img.shields.io/badge/license-MIT-C06524" alt="License: MIT" /> - </a> + <a href="https://www.attrs.org/en/stable/"><img src="https://img.shields.io/badge/Docs-RTD-black" alt="Documentation" /></a> + <a href="https://github.com/python-attrs/attrs/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-C06524" alt="License: MIT" /></a> <a href="https://bestpractices.coreinfrastructure.org/projects/6482"><img src="https://bestpractices.coreinfrastructure.org/projects/6482/badge"></a> - <a href="https://pypi.org/project/attrs/"> - <img src="https://img.shields.io/pypi/v/attrs" /> - </a> - <a href="https://pepy.tech/project/attrs"> - <img src="https://static.pepy.tech/personalized-badge/attrs?period=month&units=international_system&left_color=grey&right_color=blue&left_text=Downloads%20/%20Month" alt="Downloads per month" /> - </a> + <a href="https://pypi.org/project/attrs/"><img src="https://img.shields.io/pypi/v/attrs" /></a> + <a href="https://pepy.tech/project/attrs"><img src="https://static.pepy.tech/personalized-badge/attrs?period=month&units=international_system&left_color=grey&right_color=blue&left_text=Downloads%20/%20Month" alt="Downloads per month" /></a> <a href="https://zenodo.org/badge/latestdoi/29918975"><img src="https://zenodo.org/badge/29918975.svg" alt="DOI"></a> </p> @@ -38,21 +30,9 @@ Its main goal is to help you to write **concise** and **correct** software witho Especially those generously supporting us at the *The Organization* tier and higher: <p align="center"> - <a href="https://www.variomedia.de/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Variomedia.svg" width="200" height="60"></img> - </a> - - <a href="https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Tidelift.svg" width="200" height="60"></img> - </a> - - <a href="https://sentry.io/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/Sentry.svg" width="200" height="60"></img> - </a> - - <a href="https://filepreviews.io/"> - <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/.github/sponsors/FilePreviews.svg" width="200" height="60"></img> - </a> + <a href="https://www.variomedia.de/"><img src="https://www.attrs.org/en/latest/_static/sponsors/Variomedia.svg" width="200" height="60" /></a> + <a href="https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo"><img src="https://www.attrs.org/en/latest/_static/sponsors/Tidelift.svg" width="200" height="60" /></a> + <a href="https://filepreviews.io/"><img src="https://www.attrs.org/en/latest/_static/sponsors/FilePreviews.svg" width="200" height="60"/></a> </p> <p align="center"> @@ -128,7 +108,7 @@ Please check out [*On The Core API Names*](https://www.attrs.org/en/latest/names On the tin, *attrs* might remind you of `dataclasses` (and indeed, `dataclasses` [are a descendant](https://hynek.me/articles/import-attrs/) of *attrs*). In practice it does a lot more and is more flexible. -For instance it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), or allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization). +For instance it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization), and allows for stepping through the generated methods using a debugger. For more details, please refer to our [comparison page](https://www.attrs.org/en/stable/why.html#data-classes). @@ -141,9 +121,7 @@ For more details, please refer to our [comparison page](https://www.attrs.org/en - [**Source Code**](https://github.com/python-attrs/attrs) - [**Contributing**](https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md) - [**Third-party Extensions**](https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs) -- **License**: [MIT](https://www.attrs.org/en/latest/license.html) - **Get Help**: please use the `python-attrs` tag on [StackOverflow](https://stackoverflow.com/questions/tagged/python-attrs) -- **Supported Python Versions**: 3.7 and later ### *attrs* for Enterprise diff --git a/contrib/python/attrs/py3/attr/__init__.py b/contrib/python/attrs/py3/attr/__init__.py index 7cfa792f74..9226258a2d 100644 --- a/contrib/python/attrs/py3/attr/__init__.py +++ b/contrib/python/attrs/py3/attr/__init__.py @@ -9,6 +9,7 @@ from typing import Callable from . import converters, exceptions, filters, setters, validators from ._cmp import cmp_using +from ._compat import Protocol from ._config import get_run_validators, set_run_validators from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types from ._make import ( @@ -31,7 +32,7 @@ ib = attr = attrib dataclass = partial(attrs, auto_attribs=True) # happy Easter ;) -class AttrsInstance: +class AttrsInstance(Protocol): pass @@ -90,8 +91,9 @@ def _make_getattr(mod_name: str) -> Callable: "__email__": "", "__license__": "license", } - if name not in dunder_to_metadata.keys(): - raise AttributeError(f"module {mod_name} has no attribute {name}") + if name not in dunder_to_metadata: + msg = f"module {mod_name} has no attribute {name}" + raise AttributeError(msg) import sys import warnings @@ -101,7 +103,7 @@ def _make_getattr(mod_name: str) -> Callable: else: from importlib.metadata import metadata - if name != "__version_info__": + if name not in ("__version__", "__version_info__"): warnings.warn( f"Accessing {mod_name}.{name} is deprecated and will be " "removed in a future release. Use importlib.metadata directly " @@ -113,15 +115,15 @@ def _make_getattr(mod_name: str) -> Callable: meta = metadata("attrs") if name == "__license__": return "MIT" - elif name == "__copyright__": + if name == "__copyright__": return "Copyright (c) 2015 Hynek Schlawack" - elif name in ("__uri__", "__url__"): + if name in ("__uri__", "__url__"): return meta["Project-URL"].split(" ", 1)[-1] - elif name == "__version_info__": + if name == "__version_info__": return VersionInfo._from_version_string(meta["version"]) - elif name == "__author__": + if name == "__author__": return meta["Author-email"].rsplit(" ", 1)[0] - elif name == "__email__": + if name == "__email__": return meta["Author-email"].rsplit("<", 1)[1][:-1] return meta[dunder_to_metadata[name]] diff --git a/contrib/python/attrs/py3/attr/_cmp.py b/contrib/python/attrs/py3/attr/_cmp.py index d9cbe22cde..a4a35e08fc 100644 --- a/contrib/python/attrs/py3/attr/_cmp.py +++ b/contrib/python/attrs/py3/attr/_cmp.py @@ -92,10 +92,8 @@ def cmp_using( 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." - ) + msg = "eq must be define is order to complete ordering from lt, le, gt, ge." + raise ValueError(msg) type_ = functools.total_ordering(type_) return type_ @@ -142,10 +140,7 @@ 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 + return all(func(self, other) for func in self._requirements) def _check_same_type(self, other): diff --git a/contrib/python/attrs/py3/attr/_compat.py b/contrib/python/attrs/py3/attr/_compat.py index c3bf5e33ba..46b05ca453 100644 --- a/contrib/python/attrs/py3/attr/_compat.py +++ b/contrib/python/attrs/py3/attr/_compat.py @@ -1,31 +1,28 @@ # SPDX-License-Identifier: MIT - import inspect import platform import sys import threading -import types -import warnings -from collections.abc import Mapping, Sequence # noqa +from collections.abc import Mapping, Sequence # noqa: F401 from typing import _GenericAlias PYPY = platform.python_implementation() == "PyPy" +PY_3_8_PLUS = sys.version_info[:2] >= (3, 8) PY_3_9_PLUS = sys.version_info[:2] >= (3, 9) PY310 = sys.version_info[:2] >= (3, 10) PY_3_12_PLUS = sys.version_info[:2] >= (3, 12) -def just_warn(*args, **kw): - 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, - ) +if sys.version_info < (3, 8): + try: + from typing_extensions import Protocol + except ImportError: # pragma: no cover + Protocol = object +else: + from typing import Protocol # noqa: F401 class _AnnotationExtractor: @@ -68,101 +65,6 @@ class _AnnotationExtractor: return None -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. - - try: - if sys.version_info >= (3, 8): - - def set_closure_cell(cell, value): - cell.cell_contents = value - - else: - # 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 - - # Extract the code object and make sure our assumptions about - # the closure behavior are correct. - 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. - args = [co.co_argcount] - 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 - - 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() - # Thread-local global to track attrs instances which are already being repr'd. # This is needed because there is no other (thread-safe) way to pass info # about the instances that are already being repr'd through the call stack diff --git a/contrib/python/attrs/py3/attr/_config.py b/contrib/python/attrs/py3/attr/_config.py index 96d4200773..9c245b1461 100644 --- a/contrib/python/attrs/py3/attr/_config.py +++ b/contrib/python/attrs/py3/attr/_config.py @@ -1,6 +1,5 @@ # SPDX-License-Identifier: MIT - __all__ = ["set_run_validators", "get_run_validators"] _run_validators = True @@ -15,7 +14,8 @@ def set_run_validators(run): instead. """ if not isinstance(run, bool): - raise TypeError("'run' must be bool.") + msg = "'run' must be bool." + raise TypeError(msg) global _run_validators _run_validators = run diff --git a/contrib/python/attrs/py3/attr/_funcs.py b/contrib/python/attrs/py3/attr/_funcs.py index 7f5d9610f3..a888991d98 100644 --- a/contrib/python/attrs/py3/attr/_funcs.py +++ b/contrib/python/attrs/py3/attr/_funcs.py @@ -72,19 +72,25 @@ def asdict( ) 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, - is_key=False, - filter=filter, - dict_factory=dict_factory, - retain_collection_types=retain_collection_types, - value_serializer=value_serializer, - ) - for i in v - ] - ) + items = [ + _asdict_anything( + i, + is_key=False, + filter=filter, + dict_factory=dict_factory, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ) + for i in v + ] + try: + rv[a.name] = cf(items) + except TypeError: + if not issubclass(cf, tuple): + raise + # Workaround for TypeError: cf.__new__() missing 1 required + # positional argument (which appears, for a namedturle) + rv[a.name] = cf(*items) elif isinstance(v, dict): df = dict_factory rv[a.name] = df( @@ -241,22 +247,26 @@ def astuple( ) 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 - ] + items = [ + astuple( + j, + recurse=True, + filter=filter, + tuple_factory=tuple_factory, + retain_collection_types=retain, ) - ) + if has(j.__class__) + else j + for j in v + ] + try: + rv.append(cf(items)) + except TypeError: + if not issubclass(cf, tuple): + raise + # Workaround for TypeError: cf.__new__() missing 1 required + # positional argument (which appears, for a namedturle) + rv.append(cf(*items)) elif isinstance(v, dict): df = v.__class__ if retain is True else dict rv.append( @@ -344,9 +354,8 @@ def assoc(inst, **changes): for k, v in changes.items(): a = getattr(attrs, k, NOTHING) if a is NOTHING: - raise AttrsAttributeNotFoundError( - f"{k} is not an attrs attribute on {new.__class__}." - ) + msg = f"{k} is not an attrs attribute on {new.__class__}." + raise AttrsAttributeNotFoundError(msg) _obj_setattr(new, k, v) return new @@ -379,17 +388,14 @@ def evolve(*args, **changes): try: (inst,) = args except ValueError: - raise TypeError( - f"evolve() takes 1 positional argument, but {len(args)} " - "were given" - ) from None + msg = f"evolve() takes 1 positional argument, but {len(args)} were given" + raise TypeError(msg) from None else: try: inst = changes.pop("inst") except KeyError: - raise TypeError( - "evolve() missing 1 required positional argument: 'inst'" - ) from None + msg = "evolve() missing 1 required positional argument: 'inst'" + raise TypeError(msg) from None import warnings diff --git a/contrib/python/attrs/py3/attr/_make.py b/contrib/python/attrs/py3/attr/_make.py index d72f738eec..10b4eca779 100644 --- a/contrib/python/attrs/py3/attr/_make.py +++ b/contrib/python/attrs/py3/attr/_make.py @@ -1,7 +1,11 @@ # SPDX-License-Identifier: MIT +import contextlib import copy import enum +import functools +import inspect +import itertools import linecache import sys import types @@ -14,9 +18,9 @@ from operator import itemgetter from . import _compat, _config, setters from ._compat import ( PY310, + PY_3_8_PLUS, _AnnotationExtractor, get_generic_base, - set_closure_cell, ) from .exceptions import ( DefaultAlreadySetError, @@ -87,7 +91,7 @@ class _CacheHashWrapper(int): See GH #613 for more details. """ - def __reduce__(self, _none_constructor=type(None), _args=()): + def __reduce__(self, _none_constructor=type(None), _args=()): # noqa: B008 return _none_constructor, _args @@ -113,8 +117,8 @@ def attrib( .. warning:: - Does *not* do anything unless the class is also decorated with - `attr.s` / `attrs.define` / et cetera! + Does *not* do anything unless the class is also decorated with `attr.s` + / `attrs.define` / and so on! Please consider using `attrs.field` in new code (``attr.ib`` will *never* go away, though). @@ -128,12 +132,12 @@ def attrib( or dicts). If a default is not set (or set manually to `attrs.NOTHING`), a value - *must* be supplied when instantiating; otherwise a `TypeError` - will be raised. + *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 + .. seealso:: `defaults` :param callable factory: Syntactic sugar for ``default=attr.Factory(factory)``. @@ -146,69 +150,80 @@ def attrib( 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. + If a `list` is passed, its items are treated as validators and must all + pass. Validators can be globally disabled and re-enabled using `attrs.validators.get_disabled` / `attrs.validators.set_disabled`. The validator can also be set using decorator notation as shown below. + .. seealso:: :ref:`validators` + :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). + :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. + :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. + + .. seealso:: `comparison` :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. + 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. + + .. seealso:: `comparison` :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*. + + .. seealso:: `comparison` :type cmp: a `bool` or a `callable`. - :param Optional[bool] hash: Include this attribute in the generated + :param bool | None 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*. + + .. seealso:: `hashing` :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`. + + .. seealso:: `init` + :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. + + .. seealso:: :ref:`converters` + :param dict | None metadata: An arbitrary mapping, to be used by + third-party components. See `extending-metadata`. :param type: The type of the attribute. Nowadays, the preferred method to - specify the type is using a variable annotation (see :pep:`526`). - This argument is provided for backward compatibility. - Regardless of the approach used, the type will be stored on - ``Attribute.type``. + specify the type is using a variable annotation (see :pep:`526`). 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 in the generated + itself. You can use it as part of your own code or for `static type + checking <types>`. + :param bool kw_only: Make this attribute keyword-only 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. @@ -216,7 +231,7 @@ def attrib( attribute -- regardless of the setting in `attr.s`. :type on_setattr: `callable`, or a list of callables, or `None`, or `attrs.setters.NO_OP` - :param Optional[str] alias: Override this attribute's parameter name in the + :param str | None alias: Override this attribute's parameter name in the generated ``__init__`` method. If left `None`, default to ``name`` stripped of leading underscores. See `private-attributes`. @@ -248,18 +263,18 @@ def attrib( ) 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." - ) + msg = "Invalid value for hash. Must be True, False, or None." + raise TypeError(msg) if factory is not None: if default is not NOTHING: - raise ValueError( - "The `default` and `factory` arguments are mutually " - "exclusive." + msg = ( + "The `default` and `factory` arguments are mutually exclusive." ) + raise ValueError(msg) if not callable(factory): - raise ValueError("The `factory` argument must be a callable.") + msg = "The `factory` argument must be a callable." + raise ValueError(msg) default = Factory(factory) if metadata is None: @@ -323,9 +338,9 @@ def _make_method(name, script, filename, globs): old_val = linecache.cache.setdefault(filename, linecache_tuple) if old_val == linecache_tuple: break - else: - filename = f"{base_filename[:-1]}-{count}>" - count += 1 + + filename = f"{base_filename[:-1]}-{count}>" + count += 1 _compile_and_eval(script, globs, locs, filename) @@ -430,7 +445,7 @@ def _collect_base_attrs(cls, taken_attr_names): if a.inherited or a.name in taken_attr_names: continue - a = a.evolve(inherited=True) + a = a.evolve(inherited=True) # noqa: PLW2901 base_attrs.append(a) base_attr_map[a.name] = base_cls @@ -468,7 +483,7 @@ def _collect_base_attrs_broken(cls, taken_attr_names): if a.name in taken_attr_names: continue - a = a.evolve(inherited=True) + a = a.evolve(inherited=True) # noqa: PLW2901 taken_attr_names.add(a.name) base_attrs.append(a) base_attr_map[a.name] = base_cls @@ -493,7 +508,7 @@ def _transform_attrs( anns = _get_annotations(cls) if these is not None: - ca_list = [(name, ca) for name, ca in these.items()] + ca_list = list(these.items()) elif auto_attribs is True: ca_names = { name @@ -509,10 +524,7 @@ def _transform_attrs( a = cd.get(attr_name, NOTHING) if not isinstance(a, _CountingAttr): - if a is NOTHING: - a = attrib() - else: - a = attrib(default=a) + a = attrib() if a is NOTHING else attrib(default=a) ca_list.append((attr_name, a)) unannotated = ca_names - annot_names @@ -563,10 +575,8 @@ def _transform_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 " - f"default value or factory. Attribute in question: {a!r}" - ) + msg = f"No mandatory attributes allowed after an attribute with a default value or factory. Attribute in question: {a!r}" + raise ValueError(msg) if had_default is False and a.default is not NOTHING: had_default = True @@ -590,6 +600,62 @@ def _transform_attrs( return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map)) +def _make_cached_property_getattr( + cached_properties, + original_getattr, + cls, +): + lines = [ + # Wrapped to get `__class__` into closure cell for super() + # (It will be replaced with the newly constructed class after construction). + "def wrapper():", + " __class__ = _cls", + " def __getattr__(self, item, cached_properties=cached_properties, original_getattr=original_getattr, _cached_setattr_get=_cached_setattr_get):", + " func = cached_properties.get(item)", + " if func is not None:", + " result = func(self)", + " _setter = _cached_setattr_get(self)", + " _setter(item, result)", + " return result", + ] + if original_getattr is not None: + lines.append( + " return original_getattr(self, item)", + ) + else: + lines.extend( + [ + " if hasattr(super(), '__getattr__'):", + " return super().__getattr__(item)", + " original_error = f\"'{self.__class__.__name__}' object has no attribute '{item}'\"", + " raise AttributeError(original_error)", + ] + ) + + lines.extend( + [ + " return __getattr__", + "__getattr__ = wrapper()", + ] + ) + + unique_filename = _generate_unique_filename(cls, "getattr") + + glob = { + "cached_properties": cached_properties, + "_cached_setattr_get": _obj_setattr.__get__, + "_cls": cls, + "original_getattr": original_getattr, + } + + return _make_method( + "__getattr__", + "\n".join(lines), + unique_filename, + glob, + ) + + def _frozen_setattrs(self, name, value): """ Attached to frozen classes as __setattr__. @@ -628,6 +694,7 @@ class _ClassBuilder: "_delete_attribs", "_frozen", "_has_pre_init", + "_pre_init_has_args", "_has_post_init", "_is_exc", "_on_setattr", @@ -674,6 +741,13 @@ class _ClassBuilder: self._weakref_slot = weakref_slot self._cache_hash = cache_hash self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) + self._pre_init_has_args = False + if self._has_pre_init: + # Check if the pre init method has more arguments than just `self` + # We want to pass arguments if pre init expects arguments + pre_init_func = cls.__attrs_pre_init__ + pre_init_signature = inspect.signature(pre_init_func) + self._pre_init_has_args = len(pre_init_signature.parameters) > 1 self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) self._delete_attribs = not bool(these) self._is_exc = is_exc @@ -768,13 +842,11 @@ class _ClassBuilder: name not in base_names and getattr(cls, name, _sentinel) is not _sentinel ): - try: + # An AttributeError 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. + with contextlib.suppress(AttributeError): 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(): @@ -799,7 +871,7 @@ class _ClassBuilder: cd = { k: v for k, v in self._cls_dict.items() - if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") + if k not in (*tuple(self._attr_names), "__dict__", "__weakref__") } # If our class doesn't have its own implementation of __setattr__ @@ -821,7 +893,7 @@ class _ClassBuilder: # Traverse the MRO to collect existing slots # and check for an existing __weakref__. - existing_slots = dict() + existing_slots = {} weakref_inherited = False for base_cls in self._cls.__mro__[1:-1]: if base_cls.__dict__.get("__weakref__", None) is not None: @@ -844,9 +916,46 @@ class _ClassBuilder: ): names += ("__weakref__",) + if PY_3_8_PLUS: + cached_properties = { + name: cached_property.func + for name, cached_property in cd.items() + if isinstance(cached_property, functools.cached_property) + } + else: + # `functools.cached_property` was introduced in 3.8. + # So can't be used before this. + cached_properties = {} + + # Collect methods with a `__class__` reference that are shadowed in the new class. + # To know to update them. + additional_closure_functions_to_update = [] + if cached_properties: + # Add cached properties to names for slotting. + names += tuple(cached_properties.keys()) + + for name in cached_properties: + # Clear out function from class to avoid clashing. + del cd[name] + + class_annotations = _get_annotations(self._cls) + for name, func in cached_properties.items(): + annotation = inspect.signature(func).return_annotation + if annotation is not inspect.Parameter.empty: + class_annotations[name] = annotation + + original_getattr = cd.get("__getattr__") + if original_getattr is not None: + additional_closure_functions_to_update.append(original_getattr) + + cd["__getattr__"] = _make_cached_property_getattr( + cached_properties, original_getattr, self._cls + ) + # 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 overridden by a child class, @@ -860,6 +969,7 @@ class _ClassBuilder: cd.update(reused_slots) if self._cache_hash: slot_names.append(_hash_cache_field) + cd["__slots__"] = tuple(slot_names) cd["__qualname__"] = self._cls.__qualname__ @@ -873,7 +983,9 @@ class _ClassBuilder: # 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(): + for item in itertools.chain( + cls.__dict__.values(), additional_closure_functions_to_update + ): if isinstance(item, (classmethod, staticmethod)): # Class- and staticmethods hide their functions inside. # These might need to be rewritten as well. @@ -890,12 +1002,12 @@ class _ClassBuilder: for cell in closure_cells: try: match = cell.cell_contents is self._cls - except ValueError: # ValueError: Cell is empty + except ValueError: # noqa: PERF203 + # ValueError: Cell is empty pass else: if match: - set_closure_cell(cell, cls) - + cell.cell_contents = cls return cls def add_repr(self, ns): @@ -907,9 +1019,8 @@ class _ClassBuilder: 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." - ) + msg = "__str__ can only be generated if a __repr__ exists." + raise ValueError(msg) def __str__(self): return self.__repr__() @@ -980,6 +1091,7 @@ class _ClassBuilder: self._cls, self._attrs, self._has_pre_init, + self._pre_init_has_args, self._has_post_init, self._frozen, self._slots, @@ -1006,6 +1118,7 @@ class _ClassBuilder: self._cls, self._attrs, self._has_pre_init, + self._pre_init_has_args, self._has_post_init, self._frozen, self._slots, @@ -1054,9 +1167,8 @@ class _ClassBuilder: 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." - ) + msg = "Can't combine custom __setattr__ with on_setattr hooks." + raise ValueError(msg) # docstring comes from _add_method_dunders def __setattr__(self, name, val): @@ -1079,25 +1191,17 @@ class _ClassBuilder: """ Add __module__ and __qualname__ to a *method* if possible. """ - try: + with contextlib.suppress(AttributeError): method.__module__ = self._cls.__module__ - except AttributeError: - pass - try: - method.__qualname__ = ".".join( - (self._cls.__qualname__, method.__name__) - ) - except AttributeError: - pass + with contextlib.suppress(AttributeError): + method.__qualname__ = f"{self._cls.__qualname__}.{method.__name__}" - try: + with contextlib.suppress(AttributeError): method.__doc__ = ( "Method generated by attrs for class " f"{self._cls.__qualname__}." ) - except AttributeError: - pass return method @@ -1108,7 +1212,8 @@ def _determine_attrs_eq_order(cmp, eq, order, default_eq): 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`.") + msg = "Don't mix `cmp` with `eq' and `order`." + raise ValueError(msg) # cmp takes precedence due to bw-compatibility. if cmp is not None: @@ -1123,7 +1228,8 @@ def _determine_attrs_eq_order(cmp, eq, order, default_eq): order = eq if eq is False and order is True: - raise ValueError("`order` can only be True if `eq` is True too.") + msg = "`order` can only be True if `eq` is True too." + raise ValueError(msg) return eq, order @@ -1134,7 +1240,8 @@ def _determine_attrib_eq_order(cmp, eq, order, default_eq): 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`.") + msg = "Don't mix `cmp` with `eq' and `order`." + raise ValueError(msg) def decide_callable_or_boolean(value): """ @@ -1164,7 +1271,8 @@ def _determine_attrib_eq_order(cmp, eq, order, default_eq): 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.") + msg = "`order` can only be True if `eq` is True too." + raise ValueError(msg) return eq, eq_key, order, order_key @@ -1228,8 +1336,8 @@ def attrs( Please consider using `attrs.define` / `attrs.frozen` in new code (``attr.s`` will *never* go away, though). - :param these: A dictionary of name to `attr.ib` mappings. This is - useful to avoid the definition of your attributes within the class body + :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. @@ -1249,11 +1357,11 @@ def attrs( 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). + 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:: @@ -1263,26 +1371,31 @@ def attrs( 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. + Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*, *cmp*, + or *hash* overrides whatever *auto_detect* would determine. :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__`` + ``__repr__``. This is usually not necessary except for `Exception`\ s. + :param bool | None 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__``, + + .. seealso:: `comparison` + :param bool | None 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] unsafe_hash: If ``None`` (default), the ``__hash__`` + + .. seealso:: `comparison` + :param bool | None cmp: Setting *cmp* is equivalent to setting *eq* and + *order* to the same value. Must not be mixed with *eq* or *order*. + + .. seealso:: `comparison` + :param bool | None unsafe_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. @@ -1292,28 +1405,34 @@ def attrs( ``__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. + 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 Optional[bool] hash: Alias for *unsafe_hash*. *unsafe_hash* takes + .. seealso:: + + - 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 | None hash: Alias for *unsafe_hash*. *unsafe_hash* takes precedence. - :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 + :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__()``. + 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__()``. + + .. seealso:: `init` :param bool slots: Create a :term:`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 @@ -1335,8 +1454,8 @@ def attrs( 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)``. + circumvent that limitation by using ``object.__setattr__(self, + "attribute_name", value)``. 5. Subclasses of a frozen class are frozen too. @@ -1345,11 +1464,11 @@ def attrs( :param bool auto_attribs: If ``True``, collect :pep:`526`-annotated attributes 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. + 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 @@ -1368,20 +1487,18 @@ def attrs( These errors can be quite confusing and probably the most common bug report on our bug tracker. - :param bool kw_only: Make all attributes keyword-only - 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: + :param bool kw_only: Make all attributes keyword-only 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 @@ -1396,22 +1513,22 @@ def attrs( incorrect in certain cases of multiple inheritance. It should be on by default but is kept off for backward-compatibility. - See issue `#428 <https://github.com/python-attrs/attrs/issues/428>`_ for - more details. + .. seealso:: + Issue `#428 <https://github.com/python-attrs/attrs/issues/428>`_ - :param Optional[bool] getstate_setstate: + :param bool | None 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 `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 + 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 @@ -1428,11 +1545,13 @@ def attrs( :type on_setattr: `callable`, or a list of callables, or `None`, or `attrs.setters.NO_OP` - :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. + :param callable | None 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. + + .. seealso:: `transform-fields` :param bool match_args: If `True` (default), set ``__match_args__`` on the class to support @@ -1494,7 +1613,8 @@ def attrs( ) if has_own_setattr and is_frozen: - raise ValueError("Can't freeze a class with a custom __setattr__.") + msg = "Can't freeze a class with a custom __setattr__." + raise ValueError(msg) builder = _ClassBuilder( cls, @@ -1547,18 +1667,15 @@ def attrs( 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: + msg = "Invalid value for hash. Must be True, False, or None." + raise TypeError(msg) + + if 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." - ) + msg = "Invalid value for cache_hash. To use hash caching, hashing must be either explicitly or implicitly enabled." + raise TypeError(msg) elif hash is True or ( hash is None and eq is True and is_frozen is True ): @@ -1567,11 +1684,8 @@ def attrs( 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." - ) + msg = "Invalid value for cache_hash. To use hash caching, hashing must be either explicitly or implicitly enabled." + raise TypeError(msg) builder.make_unhashable() if _determine_whether_to_implement( @@ -1581,10 +1695,8 @@ def attrs( else: builder.add_attrs_init() if cache_hash: - raise TypeError( - "Invalid value for cache_hash. To use hash caching," - " init must be True." - ) + msg = "Invalid value for cache_hash. To use hash caching, init must be True." + raise TypeError(msg) if ( PY310 @@ -1599,8 +1711,8 @@ def attrs( # if it's used as `@attrs` but ``None`` if used as `@attrs()`. if maybe_cls is None: return wrap - else: - return wrap(maybe_cls) + + return wrap(maybe_cls) _attrs = attrs @@ -1648,10 +1760,7 @@ def _make_hash(cls, attrs, frozen, cache_hash): else: hash_def += ", *" - hash_def += ( - ", _cache_wrapper=" - + "__import__('attr._make')._make._CacheHashWrapper):" - ) + hash_def += ", _cache_wrapper=__import__('attr._make')._make._CacheHashWrapper):" hash_func = "_cache_wrapper(" + hash_func closing_braces += ")" @@ -1760,7 +1869,7 @@ def _make_eq(cls, attrs): lines.append(f" self.{a.name},") others.append(f" other.{a.name},") - lines += others + [" )"] + lines += [*others, " )"] else: lines.append(" return True") @@ -1928,7 +2037,8 @@ def fields(cls): generic_base = get_generic_base(cls) if generic_base is None and not isinstance(cls, type): - raise TypeError("Passed object must be a class.") + msg = "Passed object must be a class." + raise TypeError(msg) attrs = getattr(cls, "__attrs_attrs__", None) @@ -1941,7 +2051,8 @@ def fields(cls): # efficient. cls.__attrs_attrs__ = attrs return attrs - raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.") + msg = f"{cls!r} is not an attrs-decorated class." + raise NotAnAttrsClassError(msg) return attrs @@ -1962,10 +2073,12 @@ def fields_dict(cls): .. versionadded:: 18.1.0 """ if not isinstance(cls, type): - raise TypeError("Passed object must be a class.") + msg = "Passed object must be a class." + raise TypeError(msg) attrs = getattr(cls, "__attrs_attrs__", None) if attrs is None: - raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.") + msg = f"{cls!r} is not an attrs-decorated class." + raise NotAnAttrsClassError(msg) return {a.name: a for a in attrs} @@ -2001,6 +2114,7 @@ def _make_init( cls, attrs, pre_init, + pre_init_has_args, post_init, frozen, slots, @@ -2015,7 +2129,8 @@ def _make_init( ) if frozen and has_cls_on_setattr: - raise ValueError("Frozen classes can't use on_setattr.") + msg = "Frozen classes can't use on_setattr." + raise ValueError(msg) needs_cached_setattr = cache_hash or frozen filtered_attrs = [] @@ -2029,7 +2144,8 @@ def _make_init( if a.on_setattr is not None: if frozen is True: - raise ValueError("Frozen classes can't use on_setattr.") + msg = "Frozen classes can't use on_setattr." + raise ValueError(msg) needs_cached_setattr = True elif has_cls_on_setattr and a.on_setattr is not setters.NO_OP: @@ -2042,6 +2158,7 @@ def _make_init( frozen, slots, pre_init, + pre_init_has_args, post_init, cache_hash, base_attr_map, @@ -2122,6 +2239,7 @@ def _attrs_to_init_script( frozen, slots, pre_init, + pre_init_has_args, post_init, cache_hash, base_attr_map, @@ -2208,10 +2326,7 @@ def _attrs_to_init_script( arg_name = a.alias has_factory = isinstance(a.default, Factory) - if has_factory and a.default.takes_self: - maybe_self = "self" - else: - maybe_self = "" + maybe_self = "self" if has_factory and a.default.takes_self else "" if a.init is False: if has_factory: @@ -2235,25 +2350,24 @@ def _attrs_to_init_script( ) ) names_for_globals[init_factory_name] = a.default.factory - else: - if a.converter is not None: - lines.append( - fmt_setter_with_converter( - attr_name, - f"attr_dict['{attr_name}'].default", - has_on_setattr, - ) + elif a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, + f"attr_dict['{attr_name}'].default", + has_on_setattr, ) - conv_name = _init_converter_pat % (a.name,) - names_for_globals[conv_name] = a.converter - else: - lines.append( - fmt_setter( - attr_name, - f"attr_dict['{attr_name}'].default", - has_on_setattr, - ) + ) + conv_name = _init_converter_pat % (a.name,) + names_for_globals[conv_name] = a.converter + else: + lines.append( + fmt_setter( + attr_name, + f"attr_dict['{attr_name}'].default", + has_on_setattr, ) + ) elif a.default is not NOTHING and not has_factory: arg = f"{arg_name}=attr_dict['{attr_name}'].default" if a.kw_only: @@ -2362,7 +2476,7 @@ def _attrs_to_init_script( # hash code would result in silent bugs. if cache_hash: if frozen: - if slots: + if slots: # noqa: SIM108 # if frozen and slots, then _setattr defined above init_hash_cache = "_setattr('%s', %s)" else: @@ -2380,11 +2494,23 @@ def _attrs_to_init_script( lines.append(f"BaseException.__init__(self, {vals})") args = ", ".join(args) + pre_init_args = args if kw_only_args: args += "%s*, %s" % ( ", " if args else "", # leading comma ", ".join(kw_only_args), # kw_only args ) + pre_init_kw_only_args = ", ".join( + ["%s=%s" % (kw_arg, kw_arg) for kw_arg in kw_only_args] + ) + pre_init_args += ( + ", " if pre_init_args else "" + ) # handle only kwargs and no regular args + pre_init_args += pre_init_kw_only_args + + if pre_init and pre_init_has_args: + # If pre init method has arguments, pass same arguments as `__init__` + lines[0] = "self.__attrs_pre_init__(%s)" % pre_init_args return ( "def %s(self, %s):\n %s\n" @@ -2537,9 +2663,8 @@ class Attribute: if type is None: type = ca.type elif ca.type is not None: - raise ValueError( - "Type annotation and type argument cannot both be present" - ) + msg = "Type annotation and type argument cannot both be present" + raise ValueError(msg) inst_dict = { k: getattr(ca, k) for k in Attribute.__slots__ @@ -2663,36 +2788,37 @@ class _CountingAttr: "on_setattr", "alias", ) - __attrs_attrs__ = tuple( - Attribute( - name=name, - alias=_default_init_alias_for(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", - "alias", - ) - ) + ( + __attrs_attrs__ = ( + *tuple( + Attribute( + name=name, + alias=_default_init_alias_for(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", + "alias", + ) + ), Attribute( name="metadata", alias="metadata", @@ -2839,7 +2965,9 @@ _f = [ Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) -def make_class(name, attrs, bases=(object,), **attributes_arguments): +def make_class( + name, attrs, bases=(object,), class_body=None, **attributes_arguments +): r""" A quick way to create a new class called *name* with *attrs*. @@ -2855,6 +2983,8 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): :param tuple bases: Classes that the new class will subclass. + :param dict class_body: An optional dictionary of class attributes for the new class. + :param attributes_arguments: Passed unmodified to `attr.s`. :return: A new class with *attrs*. @@ -2862,19 +2992,23 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): .. versionadded:: 17.1.0 *bases* .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. + .. versionchanged:: 23.2.0 *class_body* """ if isinstance(attrs, dict): cls_dict = attrs elif isinstance(attrs, (list, tuple)): cls_dict = {a: attrib() for a in attrs} else: - raise TypeError("attrs argument must be a dict or a list.") + msg = "attrs argument must be a dict or a list." + raise TypeError(msg) 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 class_body is not None: + body.update(class_body) if pre_init is not None: body["__attrs_pre_init__"] = pre_init if post_init is not None: @@ -2888,12 +3022,10 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): # 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: + with contextlib.suppress(AttributeError, ValueError): 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) diff --git a/contrib/python/attrs/py3/attr/_next_gen.py b/contrib/python/attrs/py3/attr/_next_gen.py index 8f7c0b9a46..1fb9f259b5 100644 --- a/contrib/python/attrs/py3/attr/_next_gen.py +++ b/contrib/python/attrs/py3/attr/_next_gen.py @@ -52,14 +52,14 @@ def define( - Automatically detect whether or not *auto_attribs* should be `True` (c.f. *auto_attribs* parameter). - - If *frozen* is `False`, run converters and validators when setting an - attribute by default. + - Converters and validators run when attributes are set by default -- if + *frozen* is `False`. - *slots=True* .. caution:: Usually this has only upsides and few visible effects in everyday - programming. But it *can* lead to some suprising behaviors, so please + programming. But it *can* lead to some surprising behaviors, so please make sure to read :term:`slotted classes`. - *auto_exc=True* - *auto_detect=True* @@ -131,10 +131,8 @@ def define( 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)." - ) + msg = "Frozen classes can't use on_setattr (frozen-ness was inherited)." + raise ValueError(msg) on_setattr = setters.NO_OP break @@ -151,8 +149,8 @@ def define( # if it's used as `@attrs` but ``None`` if used as `@attrs()`. if maybe_cls is None: return wrap - else: - return wrap(maybe_cls) + + return wrap(maybe_cls) mutable = define @@ -181,9 +179,8 @@ def field( removed. .. versionadded:: 23.1.0 - The *type* parameter has been re-added; mostly for - {func}`attrs.make_class`. Please note that type checkers ignore this - metadata. + The *type* parameter has been re-added; mostly for `attrs.make_class`. + Please note that type checkers ignore this metadata. .. versionadded:: 20.1.0 """ return attrib( diff --git a/contrib/python/attrs/py3/attr/converters.py b/contrib/python/attrs/py3/attr/converters.py index 4cada106b0..2bf4c902a6 100644 --- a/contrib/python/attrs/py3/attr/converters.py +++ b/contrib/python/attrs/py3/attr/converters.py @@ -70,21 +70,20 @@ def default_if_none(default=NOTHING, factory=None): .. versionadded:: 18.2.0 """ if default is NOTHING and factory is None: - raise TypeError("Must pass either `default` or `factory`.") + msg = "Must pass either `default` or `factory`." + raise TypeError(msg) if default is not NOTHING and factory is not None: - raise TypeError( - "Must pass either `default` or `factory` but not both." - ) + msg = "Must pass either `default` or `factory` but not both." + raise TypeError(msg) 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." - ) + msg = "`takes_self` is not supported by default_if_none." + raise ValueError(msg) def default_if_none_converter(val): if val is not None: @@ -141,4 +140,5 @@ def to_bool(val): except TypeError: # Raised when "val" is not hashable (e.g., lists) pass - raise ValueError(f"Cannot convert value to bool: {val}") + msg = f"Cannot convert value to bool: {val}" + raise ValueError(msg) diff --git a/contrib/python/attrs/py3/attr/exceptions.py b/contrib/python/attrs/py3/attr/exceptions.py index 2883493085..3b7abb8154 100644 --- a/contrib/python/attrs/py3/attr/exceptions.py +++ b/contrib/python/attrs/py3/attr/exceptions.py @@ -1,5 +1,9 @@ # SPDX-License-Identifier: MIT +from __future__ import annotations + +from typing import ClassVar + class FrozenError(AttributeError): """ @@ -13,7 +17,7 @@ class FrozenError(AttributeError): """ msg = "can't set attribute" - args = [msg] + args: ClassVar[tuple[str]] = [msg] class FrozenInstanceError(FrozenError): diff --git a/contrib/python/attrs/py3/attr/validators.py b/contrib/python/attrs/py3/attr/validators.py index 1488554f78..34d6b761d3 100644 --- a/contrib/python/attrs/py3/attr/validators.py +++ b/contrib/python/attrs/py3/attr/validators.py @@ -97,23 +97,21 @@ class _InstanceOfValidator: We use a callable class to be able to change the ``__repr__``. """ if not isinstance(value, self.type): + msg = "'{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, + ) 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, - ), + msg, attr, self.type, value, ) def __repr__(self): - return "<instance_of validator for type {type!r}>".format( - type=self.type - ) + return f"<instance_of validator for type {self.type!r}>" def instance_of(type): @@ -142,20 +140,18 @@ class _MatchesReValidator: We use a callable class to be able to change the ``__repr__``. """ if not self.match_func(value): + msg = "'{name}' must match regex {pattern!r} ({value!r} doesn't)".format( + name=attr.name, pattern=self.pattern.pattern, value=value + ) raise ValueError( - "'{name}' must match regex {pattern!r}" - " ({value!r} doesn't)".format( - name=attr.name, pattern=self.pattern.pattern, value=value - ), + msg, attr, self.pattern, value, ) def __repr__(self): - return "<matches_re validator for pattern {pattern!r}>".format( - pattern=self.pattern - ) + return f"<matches_re validator for pattern {self.pattern!r}>" def matches_re(regex, flags=0, func=None): @@ -176,22 +172,17 @@ def matches_re(regex, flags=0, func=None): """ valid_funcs = (re.fullmatch, None, re.search, re.match) if func not in valid_funcs: - raise ValueError( - "'func' must be one of {}.".format( - ", ".join( - sorted( - e and e.__name__ or "None" for e in set(valid_funcs) - ) - ) + msg = "'func' must be one of {}.".format( + ", ".join( + sorted(e and e.__name__ or "None" for e in set(valid_funcs)) ) ) + raise ValueError(msg) if isinstance(regex, Pattern): if flags: - raise TypeError( - "'flags' can only be used with a string pattern; " - "pass flags to re.compile() instead" - ) + msg = "'flags' can only be used with a string pattern; pass flags to re.compile() instead" + raise TypeError(msg) pattern = regex else: pattern = re.compile(regex, flags) @@ -215,20 +206,18 @@ class _ProvidesValidator: We use a callable class to be able to change the ``__repr__``. """ if not self.interface.providedBy(value): + msg = "'{name}' must provide {interface!r} which {value!r} doesn't.".format( + name=attr.name, interface=self.interface, value=value + ) raise TypeError( - "'{name}' must provide {interface!r} which {value!r} " - "doesn't.".format( - name=attr.name, interface=self.interface, value=value - ), + msg, attr, self.interface, value, ) def __repr__(self): - return "<provides validator for interface {interface!r}>".format( - interface=self.interface - ) + return f"<provides validator for interface {self.interface!r}>" def provides(interface): @@ -269,9 +258,7 @@ class _OptionalValidator: self.validator(inst, attr, value) def __repr__(self): - return "<optional validator for {what} or None>".format( - what=repr(self.validator) - ) + return f"<optional validator for {self.validator!r} or None>" def optional(validator): @@ -304,19 +291,16 @@ class _InValidator: in_options = False if not in_options: + msg = f"'{attr.name}' must be in {self.options!r} (got {value!r})" raise ValueError( - "'{name}' must be in {options!r} (got {value!r})".format( - name=attr.name, options=self.options, value=value - ), + msg, attr, self.options, value, ) def __repr__(self): - return "<in_ validator with options {options!r}>".format( - options=self.options - ) + return f"<in_ validator with options {self.options!r}>" def in_(options): @@ -402,11 +386,8 @@ class _DeepIterable: else f" {self.iterable_validator!r}" ) return ( - "<deep_iterable validator for{iterable_identifier}" - " iterables of {member!r}>" - ).format( - iterable_identifier=iterable_identifier, - member=self.member_validator, + f"<deep_iterable validator for{iterable_identifier}" + f" iterables of {self.member_validator!r}>" ) @@ -477,19 +458,11 @@ class _NumberValidator: We use a callable class to be able to change the ``__repr__``. """ if not self.compare_func(value, self.bound): - raise ValueError( - "'{name}' must be {op} {bound}: {value}".format( - name=attr.name, - op=self.compare_op, - bound=self.bound, - value=value, - ) - ) + msg = f"'{attr.name}' must be {self.compare_op} {self.bound}: {value}" + raise ValueError(msg) def __repr__(self): - return "<Validator for x {op} {bound}>".format( - op=self.compare_op, bound=self.bound - ) + return f"<Validator for x {self.compare_op} {self.bound}>" def lt(val): @@ -549,11 +522,8 @@ class _MaxLengthValidator: We use a callable class to be able to change the ``__repr__``. """ if len(value) > self.max_length: - raise ValueError( - "Length of '{name}' must be <= {max}: {len}".format( - name=attr.name, max=self.max_length, len=len(value) - ) - ) + msg = f"Length of '{attr.name}' must be <= {self.max_length}: {len(value)}" + raise ValueError(msg) def __repr__(self): return f"<max_len validator for {self.max_length}>" @@ -580,11 +550,8 @@ class _MinLengthValidator: We use a callable class to be able to change the ``__repr__``. """ if len(value) < self.min_length: - raise ValueError( - "Length of '{name}' must be => {min}: {len}".format( - name=attr.name, min=self.min_length, len=len(value) - ) - ) + msg = f"Length of '{attr.name}' must be >= {self.min_length}: {len(value)}" + raise ValueError(msg) def __repr__(self): return f"<min_len validator for {self.min_length}>" @@ -611,22 +578,16 @@ class _SubclassOfValidator: We use a callable class to be able to change the ``__repr__``. """ if not issubclass(value, self.type): + msg = f"'{attr.name}' must be a subclass of {self.type!r} (got {value!r})." raise TypeError( - "'{name}' must be a subclass of {type!r} " - "(got {value!r}).".format( - name=attr.name, - type=self.type, - value=value, - ), + msg, attr, self.type, value, ) def __repr__(self): - return "<subclass_of validator for type {type!r}>".format( - type=self.type - ) + return f"<subclass_of validator for type {self.type!r}>" def _subclass_of(type): @@ -680,7 +641,7 @@ class _NotValidator: def __repr__(self): return ( - "<not_ validator wrapping {what!r}, " "capturing {exc_types!r}>" + "<not_ validator wrapping {what!r}, capturing {exc_types!r}>" ).format( what=self.validator, exc_types=self.exc_types, diff --git a/contrib/python/attrs/py3/attrs/converters.py b/contrib/python/attrs/py3/attrs/converters.py index edfa8d3c16..7821f6c02c 100644 --- a/contrib/python/attrs/py3/attrs/converters.py +++ b/contrib/python/attrs/py3/attrs/converters.py @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT -from attr.converters import * # noqa +from attr.converters import * # noqa: F403 diff --git a/contrib/python/attrs/py3/attrs/exceptions.py b/contrib/python/attrs/py3/attrs/exceptions.py index bd9efed202..3323f9d211 100644 --- a/contrib/python/attrs/py3/attrs/exceptions.py +++ b/contrib/python/attrs/py3/attrs/exceptions.py @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT -from attr.exceptions import * # noqa +from attr.exceptions import * # noqa: F403 diff --git a/contrib/python/attrs/py3/attrs/filters.py b/contrib/python/attrs/py3/attrs/filters.py index 52959005b0..3080f48398 100644 --- a/contrib/python/attrs/py3/attrs/filters.py +++ b/contrib/python/attrs/py3/attrs/filters.py @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT -from attr.filters import * # noqa +from attr.filters import * # noqa: F403 diff --git a/contrib/python/attrs/py3/attrs/setters.py b/contrib/python/attrs/py3/attrs/setters.py index 9b50770804..f3d73bb793 100644 --- a/contrib/python/attrs/py3/attrs/setters.py +++ b/contrib/python/attrs/py3/attrs/setters.py @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT -from attr.setters import * # noqa +from attr.setters import * # noqa: F403 diff --git a/contrib/python/attrs/py3/attrs/validators.py b/contrib/python/attrs/py3/attrs/validators.py index ab2c9b3024..037e124f29 100644 --- a/contrib/python/attrs/py3/attrs/validators.py +++ b/contrib/python/attrs/py3/attrs/validators.py @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT -from attr.validators import * # noqa +from attr.validators import * # noqa: F403 diff --git a/contrib/python/attrs/py3/ya.make b/contrib/python/attrs/py3/ya.make index 842a03879c..e36f5d0ca3 100644 --- a/contrib/python/attrs/py3/ya.make +++ b/contrib/python/attrs/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(23.1.0) +VERSION(23.2.0) LICENSE(MIT) |