aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2024-01-18 11:28:56 +0100
committerGitHub <noreply@github.com>2024-01-18 11:28:56 +0100
commit9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch)
tree541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/python
parent404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff)
downloadydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz
Library import 8 (#1074)
* Library import 8 * Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/attrs/py3/.dist-info/METADATA101
-rw-r--r--contrib/python/attrs/py3/README.md38
-rw-r--r--contrib/python/attrs/py3/attr/__init__.py20
-rw-r--r--contrib/python/attrs/py3/attr/_cmp.py11
-rw-r--r--contrib/python/attrs/py3/attr/_compat.py116
-rw-r--r--contrib/python/attrs/py3/attr/_config.py4
-rw-r--r--contrib/python/attrs/py3/attr/_funcs.py82
-rw-r--r--contrib/python/attrs/py3/attr/_make.py648
-rw-r--r--contrib/python/attrs/py3/attr/_next_gen.py21
-rw-r--r--contrib/python/attrs/py3/attr/converters.py16
-rw-r--r--contrib/python/attrs/py3/attr/exceptions.py6
-rw-r--r--contrib/python/attrs/py3/attr/validators.py121
-rw-r--r--contrib/python/attrs/py3/attrs/converters.py2
-rw-r--r--contrib/python/attrs/py3/attrs/exceptions.py2
-rw-r--r--contrib/python/attrs/py3/attrs/filters.py2
-rw-r--r--contrib/python/attrs/py3/attrs/setters.py2
-rw-r--r--contrib/python/attrs/py3/attrs/validators.py2
-rw-r--r--contrib/python/attrs/py3/ya.make2
-rw-r--r--contrib/python/lz4/py3/.dist-info/METADATA10
-rw-r--r--contrib/python/lz4/py3/lz4/version.py16
-rw-r--r--contrib/python/lz4/py3/ya.make2
-rw-r--r--contrib/python/tzdata/.dist-info/METADATA2
-rw-r--r--contrib/python/tzdata/tzdata/__init__.py4
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Ensenadabin1025 -> 1025 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Godthabbin965 -> 965 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Goose_Baybin1580 -> 1580 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Indiana/Winamacbin612 -> 603 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Matamorosbin437 -> 437 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Metlakatlabin595 -> 586 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Monctonbin1493 -> 1493 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Nuukbin965 -> 965 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Ojinagabin709 -> 718 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Santa_Isabelbin1025 -> 1025 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Scoresbysundbin479 -> 984 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/St_Johnsbin1878 -> 1878 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/America/Tijuanabin1025 -> 1025 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Caseybin243 -> 287 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Macquariebin976 -> 976 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Trollbin177 -> 158 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Vostokbin133 -> 170 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Asia/Gazabin2518 -> 2968 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Asia/Hebronbin2536 -> 2986 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Asia/Nicosiabin597 -> 597 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Canada/Newfoundlandbin1878 -> 1878 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Belfastbin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Bucharestbin661 -> 661 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Chisinaubin755 -> 755 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Guernseybin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Isle_of_Manbin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Jerseybin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Kievbin558 -> 558 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Kyivbin558 -> 558 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Londonbin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Nicosiabin597 -> 597 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Rigabin694 -> 694 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Sofiabin592 -> 592 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Tallinnbin675 -> 675 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Tiraspolbin755 -> 755 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Uzhgorodbin558 -> 558 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Vilniusbin676 -> 676 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Europe/Zaporozhyebin558 -> 558 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/GBbin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/GB-Eirebin1599 -> 1599 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Mexico/BajaNortebin1025 -> 1025 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/Pacific/Norfolkbin247 -> 237 bytes
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/iso3166.tab17
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/leapseconds8
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/tzdata.zi23
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/zone.tab24
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/zone1970.tab29
-rw-r--r--contrib/python/tzdata/tzdata/zoneinfo/zonenow.tab301
-rw-r--r--contrib/python/tzdata/tzdata/zones2
-rw-r--r--contrib/python/tzdata/ya.make3
73 files changed, 952 insertions, 685 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)
diff --git a/contrib/python/lz4/py3/.dist-info/METADATA b/contrib/python/lz4/py3/.dist-info/METADATA
index bd01d4f829..c2ff5e7930 100644
--- a/contrib/python/lz4/py3/.dist-info/METADATA
+++ b/contrib/python/lz4/py3/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: lz4
-Version: 4.3.2
+Version: 4.3.3
Summary: LZ4 Bindings for Python
Home-page: https://github.com/python-lz4/python-lz4
Author: Jonathan Underwood
@@ -10,20 +10,20 @@ Classifier: License :: OSI Approved :: BSD License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: C
Classifier: Programming Language :: Python
-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
-Requires-Python: >=3.7
+Classifier: Programming Language :: Python :: 3.12
+Requires-Python: >=3.8
License-File: LICENSE
Provides-Extra: docs
-Requires-Dist: sphinx (>=1.6.0) ; extra == 'docs'
+Requires-Dist: sphinx >=1.6.0 ; extra == 'docs'
Requires-Dist: sphinx-bootstrap-theme ; extra == 'docs'
Provides-Extra: flake8
Requires-Dist: flake8 ; extra == 'flake8'
Provides-Extra: tests
-Requires-Dist: pytest (!=3.3.0) ; extra == 'tests'
+Requires-Dist: pytest !=3.3.0 ; extra == 'tests'
Requires-Dist: psutil ; extra == 'tests'
Requires-Dist: pytest-cov ; extra == 'tests'
diff --git a/contrib/python/lz4/py3/lz4/version.py b/contrib/python/lz4/py3/lz4/version.py
index 1e7ce2f6f5..4dc4c33d63 100644
--- a/contrib/python/lz4/py3/lz4/version.py
+++ b/contrib/python/lz4/py3/lz4/version.py
@@ -1,4 +1,16 @@
# file generated by setuptools_scm
# don't change, don't track in version control
-__version__ = version = '4.3.2'
-__version_tuple__ = version_tuple = (4, 3, 2)
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+ from typing import Tuple, Union
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
+else:
+ VERSION_TUPLE = object
+
+version: str
+__version__: str
+__version_tuple__: VERSION_TUPLE
+version_tuple: VERSION_TUPLE
+
+__version__ = version = '4.3.3'
+__version_tuple__ = version_tuple = (4, 3, 3)
diff --git a/contrib/python/lz4/py3/ya.make b/contrib/python/lz4/py3/ya.make
index c703ac87ce..73f9dcad03 100644
--- a/contrib/python/lz4/py3/ya.make
+++ b/contrib/python/lz4/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(4.3.2)
+VERSION(4.3.3)
LICENSE(BSD-3-Clause)
diff --git a/contrib/python/tzdata/.dist-info/METADATA b/contrib/python/tzdata/.dist-info/METADATA
index f06c73df3a..78be3e11e5 100644
--- a/contrib/python/tzdata/.dist-info/METADATA
+++ b/contrib/python/tzdata/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: tzdata
-Version: 2023.3
+Version: 2023.4
Summary: Provider of IANA time zone data
Home-page: https://github.com/python/tzdata
Author: Python Software Foundation
diff --git a/contrib/python/tzdata/tzdata/__init__.py b/contrib/python/tzdata/tzdata/__init__.py
index a7d6b0b50b..b74233ceb9 100644
--- a/contrib/python/tzdata/tzdata/__init__.py
+++ b/contrib/python/tzdata/tzdata/__init__.py
@@ -1,6 +1,6 @@
# IANA versions like 2020a are not valid PEP 440 identifiers; the recommended
# way to translate the version is to use YYYY.n where `n` is a 0-based index.
-__version__ = "2023.3"
+__version__ = "2023.4"
# This exposes the original IANA version number.
-IANA_VERSION = "2023c"
+IANA_VERSION = "2023d"
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Ensenada b/contrib/python/tzdata/tzdata/zoneinfo/America/Ensenada
index e8be26b139..42087af4cc 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Ensenada
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Godthab b/contrib/python/tzdata/tzdata/zoneinfo/America/Godthab
index 00b57bb13f..310774ea4f 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Godthab
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Godthab
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Goose_Bay b/contrib/python/tzdata/tzdata/zoneinfo/America/Goose_Bay
index 820e0dd2cd..e2cc3eefc2 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Goose_Bay
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Goose_Bay
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Indiana/Winamac b/contrib/python/tzdata/tzdata/zoneinfo/America/Indiana/Winamac
index 8700ed9f06..679d321e3b 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Indiana/Winamac
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Indiana/Winamac
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Matamoros b/contrib/python/tzdata/tzdata/zoneinfo/America/Matamoros
index 88cabcd152..993ac47559 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Matamoros
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Matamoros
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Metlakatla b/contrib/python/tzdata/tzdata/zoneinfo/America/Metlakatla
index 9fefee388e..71b0eab085 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Metlakatla
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Metlakatla
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Moncton b/contrib/python/tzdata/tzdata/zoneinfo/America/Moncton
index ecb69ef2c9..020e33d976 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Moncton
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Moncton
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Nuuk b/contrib/python/tzdata/tzdata/zoneinfo/America/Nuuk
index 00b57bb13f..310774ea4f 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Nuuk
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Nuuk
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Ojinaga b/contrib/python/tzdata/tzdata/zoneinfo/America/Ojinaga
index 2fc74e9473..f7e40c0818 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Ojinaga
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Santa_Isabel b/contrib/python/tzdata/tzdata/zoneinfo/America/Santa_Isabel
index e8be26b139..42087af4cc 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Santa_Isabel
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Scoresbysund b/contrib/python/tzdata/tzdata/zoneinfo/America/Scoresbysund
index 6db49124e2..fc1b11cbe8 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Scoresbysund
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Scoresbysund
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/St_Johns b/contrib/python/tzdata/tzdata/zoneinfo/America/St_Johns
index e5f2aec2bb..94d790baac 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/St_Johns
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/St_Johns
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/America/Tijuana b/contrib/python/tzdata/tzdata/zoneinfo/America/Tijuana
index e8be26b139..42087af4cc 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/America/Tijuana
+++ b/contrib/python/tzdata/tzdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Casey b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Casey
index 30315cc078..84f1c61e5c 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Casey
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Casey
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Macquarie b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Macquarie
index 3fc1f231cb..99a8e60edf 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Macquarie
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Macquarie
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Troll b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Troll
index 4e31affb50..2359c44bd0 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Troll
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Troll
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Vostok b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Vostok
index 69ff7f6fb4..4ce8f74784 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Vostok
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Antarctica/Vostok
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Gaza b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Gaza
index 7e83389819..6241b4e7f5 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Gaza
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Gaza
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Hebron b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Hebron
index fcf923bd28..5267de96ff 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Hebron
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Hebron
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Nicosia b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Nicosia
index c210d0a598..390347f442 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Asia/Nicosia
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Asia/Nicosia
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Canada/Newfoundland b/contrib/python/tzdata/tzdata/zoneinfo/Canada/Newfoundland
index e5f2aec2bb..94d790baac 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Canada/Newfoundland
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Canada/Newfoundland
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Belfast b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Belfast
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Belfast
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Belfast
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Bucharest b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Bucharest
index efa689ba9e..c4a391e73b 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Bucharest
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Bucharest
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Chisinau b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Chisinau
index 6970b14c50..9152e68594 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Chisinau
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Guernsey b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Guernsey
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Guernsey
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Guernsey
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Isle_of_Man b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Isle_of_Man
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Isle_of_Man
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Isle_of_Man
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Jersey b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Jersey
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Jersey
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Jersey
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kiev b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kiev
index 4e026859fd..753a6c86f3 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kiev
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kiev
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kyiv b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kyiv
index 4e026859fd..753a6c86f3 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kyiv
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Kyiv
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/London b/contrib/python/tzdata/tzdata/zoneinfo/Europe/London
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/London
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/London
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Nicosia b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Nicosia
index c210d0a598..390347f442 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Nicosia
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Nicosia
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Riga b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Riga
index 26af4c90b3..d99170b642 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Riga
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Riga
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Sofia b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Sofia
index eabc972a22..89450685cd 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Sofia
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Sofia
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tallinn b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tallinn
index 5321bbd46e..fbebdc6255 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tallinn
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tallinn
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tiraspol b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tiraspol
index 6970b14c50..9152e68594 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tiraspol
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Uzhgorod b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Uzhgorod
index 4e026859fd..753a6c86f3 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Uzhgorod
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Uzhgorod
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Vilnius b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Vilnius
index 75b2eebb57..43c3d7f108 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Vilnius
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Vilnius
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Zaporozhye b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Zaporozhye
index 4e026859fd..753a6c86f3 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Europe/Zaporozhye
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Europe/Zaporozhye
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/GB b/contrib/python/tzdata/tzdata/zoneinfo/GB
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/GB
+++ b/contrib/python/tzdata/tzdata/zoneinfo/GB
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/GB-Eire b/contrib/python/tzdata/tzdata/zoneinfo/GB-Eire
index 323cd3818a..b9e95d9262 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/GB-Eire
+++ b/contrib/python/tzdata/tzdata/zoneinfo/GB-Eire
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Mexico/BajaNorte b/contrib/python/tzdata/tzdata/zoneinfo/Mexico/BajaNorte
index e8be26b139..42087af4cc 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Mexico/BajaNorte
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/Pacific/Norfolk b/contrib/python/tzdata/tzdata/zoneinfo/Pacific/Norfolk
index 79e2a9419a..0c0bdbda2a 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/Pacific/Norfolk
+++ b/contrib/python/tzdata/tzdata/zoneinfo/Pacific/Norfolk
Binary files differ
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/iso3166.tab b/contrib/python/tzdata/tzdata/zoneinfo/iso3166.tab
index be3348d11a..402c015ec6 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/iso3166.tab
+++ b/contrib/python/tzdata/tzdata/zoneinfo/iso3166.tab
@@ -3,17 +3,22 @@
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
#
-# From Paul Eggert (2022-11-18):
+# From Paul Eggert (2023-09-06):
# This file contains a table of two-letter country codes. Columns are
# separated by a single tab. Lines beginning with '#' are comments.
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
-# ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1
-# https://isotc.iso.org/livelink/livelink/Open/16944257
-# 2. The usual English name for the coded region,
-# chosen so that alphabetic sorting of subsets produces helpful lists.
-# This is not the same as the English name in the ISO 3166 tables.
+# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents
+# https://www.iso.org/committee/48750.html?view=documents
+# 2. The usual English name for the coded region. This sometimes
+# departs from ISO-listed names, sometimes so that sorted subsets
+# of names are useful (e.g., "Samoa (American)" and "Samoa
+# (western)" rather than "American Samoa" and "Samoa"),
+# sometimes to avoid confusion among non-experts (e.g.,
+# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"),
+# and sometimes to omit needless detail or churn (e.g., "Netherlands"
+# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)").
#
# The table is sorted by country code.
#
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/leapseconds b/contrib/python/tzdata/tzdata/zoneinfo/leapseconds
index a6a170aa70..8938c763e0 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/leapseconds
+++ b/contrib/python/tzdata/tzdata/zoneinfo/leapseconds
@@ -72,11 +72,11 @@ Leap 2016 Dec 31 23:59:60 + S
# Any additional leap seconds will come after this.
# This Expires line is commented out for now,
# so that pre-2020a zic implementations do not reject this file.
-#Expires 2023 Dec 28 00:00:00
+#Expires 2024 Jun 28 00:00:00
# POSIX timestamps for the data in this file:
#updated 1467936000 (2016-07-08 00:00:00 UTC)
-#expires 1703721600 (2023-12-28 00:00:00 UTC)
+#expires 1719532800 (2024-06-28 00:00:00 UTC)
-# Updated through IERS Bulletin C65
-# File expires on: 28 December 2023
+# Updated through IERS Bulletin C66
+# File expires on: 28 June 2024
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/tzdata.zi b/contrib/python/tzdata/tzdata/zoneinfo/tzdata.zi
index b522e39532..4e01359010 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/tzdata.zi
+++ b/contrib/python/tzdata/tzdata/zoneinfo/tzdata.zi
@@ -1,4 +1,4 @@
-# version 2023c
+# version 2023d
# This zic input file is in the public domain.
R d 1916 o - Jun 14 23s 1 S
R d 1916 1919 - O Su>=1 23s 0 -
@@ -394,7 +394,12 @@ Z Antarctica/Casey 0 - -00 1969
8 - +08 2019 O 4 3
11 - +11 2020 Mar 8 3
8 - +08 2020 O 4 0:1
-11 - +11
+11 - +11 2021 Mar 14
+8 - +08 2021 O 3 0:1
+11 - +11 2022 Mar 13
+8 - +08 2022 O 2 0:1
+11 - +11 2023 Mar 9 3
+8 - +08
Z Antarctica/Davis 0 - -00 1957 Ja 13
7 - +07 1964 N
0 - -00 1969 F
@@ -410,6 +415,11 @@ R Tr 2005 ma - Mar lastSu 1u 2 +02
R Tr 2004 ma - O lastSu 1u 0 +00
Z Antarctica/Troll 0 - -00 2005 F 12
0 Tr %s
+Z Antarctica/Vostok 0 - -00 1957 D 16
+7 - +07 1994 F
+0 - -00 1994 N
+7 - +07 2023 D 18 2
+5 - +05
Z Antarctica/Rothera 0 - -00 1976 D
-3 - -03
Z Asia/Kabul 4:36:48 - LMT 1890
@@ -1050,13 +1060,13 @@ R P 2070 o - O 4 2 0 -
R P 2071 o - S 19 2 0 -
R P 2072 o - S 10 2 0 -
R P 2072 o - O 15 2 1 S
+R P 2072 ma - O Sa<=30 2 0 -
R P 2073 o - S 2 2 0 -
R P 2073 o - O 7 2 1 S
R P 2074 o - Au 18 2 0 -
R P 2074 o - S 29 2 1 S
R P 2075 o - Au 10 2 0 -
R P 2075 o - S 14 2 1 S
-R P 2075 ma - O Sa<=30 2 0 -
R P 2076 o - Jul 25 2 0 -
R P 2076 o - S 5 2 1 S
R P 2077 o - Jul 17 2 0 -
@@ -1831,10 +1841,12 @@ Z America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28
-2 - -02 1980 Ap 6 2
-2 c -02/-01 1981 Mar 29
--1 E -01/+00
+-1 E -01/+00 2024 Mar 31
+-2 E -02/-01
Z America/Nuuk -3:26:56 - LMT 1916 Jul 28
-3 - -03 1980 Ap 6 2
--3 E -03/-02 2023 O 29 1u
+-3 E -03/-02 2023 Mar 26 1u
+-2 - -02 2023 O 29 1u
-2 E -02/-01
Z America/Thule -4:35:8 - LMT 1916 Jul 28
-4 Th A%sT
@@ -4185,7 +4197,6 @@ L America/Puerto_Rico America/Tortola
L Pacific/Port_Moresby Antarctica/DumontDUrville
L Pacific/Auckland Antarctica/McMurdo
L Asia/Riyadh Antarctica/Syowa
-L Asia/Urumqi Antarctica/Vostok
L Europe/Berlin Arctic/Longyearbyen
L Asia/Riyadh Asia/Aden
L Asia/Qatar Asia/Bahrain
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/zone.tab b/contrib/python/tzdata/tzdata/zoneinfo/zone.tab
index dbcb61793e..3fa9306afb 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/zone.tab
+++ b/contrib/python/tzdata/tzdata/zoneinfo/zone.tab
@@ -48,7 +48,7 @@ AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER,
AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
AR -2649-06513 America/Argentina/Tucuman Tucuman (TM)
-AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
@@ -87,7 +87,7 @@ BN +0456+11455 Asia/Brunei
BO -1630-06809 America/La_Paz
BQ +120903-0681636 America/Kralendijk
BR -0351-03225 America/Noronha Atlantic islands
-BR -0127-04829 America/Belem Para (east); Amapa
+BR -0127-04829 America/Belem Para (east), Amapa
BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
BR -0803-03454 America/Recife Pernambuco
BR -0712-04812 America/Araguaina Tocantins
@@ -107,21 +107,21 @@ BT +2728+08939 Asia/Thimphu
BW -2439+02555 Africa/Gaborone
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
-CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast)
-CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
+CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE)
+CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
-CA +4339-07923 America/Toronto Eastern - ON, QC (most areas)
+CA +4339-07923 America/Toronto Eastern - ON & QC (most areas)
CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
-CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H)
-CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
+CA +484531-0913718 America/Atikokan EST - ON (Atikokan), NU (Coral H)
+CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
CA +5024-10439 America/Regina CST - SK (most areas)
CA +5017-10750 America/Swift_Current CST - SK (midwest)
-CA +5333-11328 America/Edmonton Mountain - AB; BC (E); NT (E); SK (W)
+CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
@@ -207,8 +207,8 @@ HT +1832-07220 America/Port-au-Prince
HU +4730+01905 Europe/Budapest
ID -0610+10648 Asia/Jakarta Java, Sumatra
ID -0002+10920 Asia/Pontianak Borneo (west, central)
-ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west)
-ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas
+ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
+ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
IE +5320-00615 Europe/Dublin
IL +314650+0351326 Asia/Jerusalem
IM +5409-00428 Europe/Isle_of_Man
@@ -355,7 +355,7 @@ RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
RU +5934+15048 Asia/Magadan MSK+08 - Magadan
RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
-RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); N Kuril Is
+RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
RW -0157+03004 Africa/Kigali
@@ -418,7 +418,7 @@ US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
-US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
+US +433649-1161209 America/Boise Mountain - ID (south), OR (east)
US +332654-1120424 America/Phoenix MST - AZ (except Navajo)
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/zone1970.tab b/contrib/python/tzdata/tzdata/zoneinfo/zone1970.tab
index 1f1cecb848..abd9489753 100644
--- a/contrib/python/tzdata/tzdata/zoneinfo/zone1970.tab
+++ b/contrib/python/tzdata/tzdata/zoneinfo/zone1970.tab
@@ -37,7 +37,7 @@
#country-
#codes coordinates TZ comments
AD +4230+00131 Europe/Andorra
-AE,OM,RE,SC,TF +2518+05518 Asia/Dubai Crozet, Scattered Is
+AE,OM,RE,SC,TF +2518+05518 Asia/Dubai Crozet
AF +3431+06912 Asia/Kabul
AL +4120+01950 Europe/Tirane
AM +4011+04430 Asia/Yerevan
@@ -47,12 +47,13 @@ AQ -6736+06253 Antarctica/Mawson Mawson
AQ -6448-06406 Antarctica/Palmer Palmer
AQ -6734-06808 Antarctica/Rothera Rothera
AQ -720041+0023206 Antarctica/Troll Troll
+AQ -7824+10654 Antarctica/Vostok Vostok
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
AR -3124-06411 America/Argentina/Cordoba most areas: CB, CC, CN, ER, FM, MN, SE, SF
AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
AR -2649-06513 America/Argentina/Tucuman Tucumán (TM)
-AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
@@ -81,7 +82,7 @@ BG +4241+02319 Europe/Sofia
BM +3217-06446 Atlantic/Bermuda
BO -1630-06809 America/La_Paz
BR -0351-03225 America/Noronha Atlantic islands
-BR -0127-04829 America/Belem Pará (east); Amapá
+BR -0127-04829 America/Belem Pará (east), Amapá
BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
BR -0803-03454 America/Recife Pernambuco
BR -0712-04812 America/Araguaina Tocantins
@@ -99,19 +100,19 @@ BR -0958-06748 America/Rio_Branco Acre
BT +2728+08939 Asia/Thimphu
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
-CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast)
-CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
+CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE)
+CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
-CA,BS +4339-07923 America/Toronto Eastern - ON, QC (most areas)
+CA,BS +4339-07923 America/Toronto Eastern - ON & QC (most areas)
CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
-CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
+CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
CA +5024-10439 America/Regina CST - SK (most areas)
CA +5017-10750 America/Swift_Current CST - SK (midwest)
-CA +5333-11328 America/Edmonton Mountain - AB; BC (E); NT (E); SK (W)
+CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
@@ -126,7 +127,7 @@ CL -3327-07040 America/Santiago most of Chile
CL -5309-07055 America/Punta_Arenas Region of Magallanes
CL -2709-10926 Pacific/Easter Easter Island
CN +3114+12128 Asia/Shanghai Beijing Time
-CN,AQ +4348+08735 Asia/Urumqi Xinjiang Time, Vostok
+CN +4348+08735 Asia/Urumqi Xinjiang Time
CO +0436-07405 America/Bogota
CR +0956-08405 America/Costa_Rica
CU +2308-08222 America/Havana
@@ -171,8 +172,8 @@ HT +1832-07220 America/Port-au-Prince
HU +4730+01905 Europe/Budapest
ID -0610+10648 Asia/Jakarta Java, Sumatra
ID -0002+10920 Asia/Pontianak Borneo (west, central)
-ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west)
-ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas
+ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
+ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
IE +5320-00615 Europe/Dublin
IL +314650+0351326 Asia/Jerusalem
IN +2232+08822 Asia/Kolkata
@@ -251,7 +252,7 @@ PK +2452+06703 Asia/Karachi
PL +5215+02100 Europe/Warsaw
PM +4703-05620 America/Miquelon
PN -2504-13005 Pacific/Pitcairn
-PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST
+PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST - QC (Lower North Shore)
PS +3130+03428 Asia/Gaza Gaza Strip
PS +313200+0350542 Asia/Hebron West Bank
PT +3843-00908 Europe/Lisbon Portugal (mainland)
@@ -287,7 +288,7 @@ RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
RU +5934+15048 Asia/Magadan MSK+08 - Magadan
RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
-RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); N Kuril Is
+RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
SA,AQ,KW,YE +2438+04643 Asia/Riyadh Syowa
@@ -329,7 +330,7 @@ US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
-US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
+US +433649-1161209 America/Boise Mountain - ID (south), OR (east)
US,CA +332654-1120424 America/Phoenix MST - AZ (most areas), Creston BC
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
diff --git a/contrib/python/tzdata/tzdata/zoneinfo/zonenow.tab b/contrib/python/tzdata/tzdata/zoneinfo/zonenow.tab
new file mode 100644
index 0000000000..2dbe8f00d1
--- /dev/null
+++ b/contrib/python/tzdata/tzdata/zoneinfo/zonenow.tab
@@ -0,0 +1,301 @@
+# tzdb timezone descriptions, for users who do not care about old timestamps
+#
+# This file is in the public domain.
+#
+# From Paul Eggert (2023-12-18):
+# This file contains a table where each row stands for a timezone
+# where civil timestamps are predicted to agree from now on.
+# This file is like zone1970.tab (see zone1970.tab's coments),
+# but with the following changes:
+#
+# 1. Each timezone corresponds to a set of clocks that are planned
+# to agree from now on. This is a larger set of clocks than in
+# zone1970.tab, where each timezone's clocks must agree from 1970 on.
+# 2. The first column is irrelevant and ignored.
+# 3. The table is sorted in a different way:
+# first by standard time UTC offset;
+# then, if DST is used, by daylight saving UTC offset;
+# then by time zone abbreviation.
+# 4. Every timezone has a nonempty comments column, with wording
+# distinguishing the timezone only from other timezones with the
+# same UTC offset at some point during the year.
+#
+# The format of this table is experimental, and may change in future versions.
+#
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs. It is not intended to take or
+# endorse any position on legal or territorial claims.
+#
+#XX coordinates TZ comments
+#
+# -11 - SST
+XX -1416-17042 Pacific/Pago_Pago Midway; Samoa ("SST")
+#
+# -11
+XX -1901-16955 Pacific/Niue Niue
+#
+# -10 - HST
+XX +211825-1575130 Pacific/Honolulu Hawaii ("HST")
+#
+# -10
+XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands
+#
+# -10/-09 - HST / HDT (North America DST)
+XX +515248-1763929 America/Adak western Aleutians in Alaska ("HST/HDT")
+#
+# -09:30
+XX -0900-13930 Pacific/Marquesas Marquesas
+#
+# -09
+XX -2308-13457 Pacific/Gambier Gambier
+#
+# -09/-08 - AKST/AKDT (North America DST)
+XX +611305-1495401 America/Anchorage most of Alaska ("AKST/AKDT")
+#
+# -08
+XX -2504-13005 Pacific/Pitcairn Pitcairn
+#
+# -08/-07 - PST/PDT (North America DST)
+XX +340308-1181434 America/Los_Angeles Pacific ("PST/PDT") - US & Canada; Mexico near US border
+#
+# -07 - MST
+XX +332654-1120424 America/Phoenix Mountain Standard ("MST") - Arizona; western Mexico; Yukon
+#
+# -07/-06 - MST/MDT (North America DST)
+XX +394421-1045903 America/Denver Mountain ("MST/MDT") - US & Canada; Mexico near US border
+#
+# -06
+XX -0054-08936 Pacific/Galapagos Galápagos
+#
+# -06 - CST
+XX +1924-09909 America/Mexico_City Central Standard ("CST") - Saskatchewan; central Mexico; Central America
+#
+# -06/-05 (Chile DST)
+XX -2709-10926 Pacific/Easter Easter Island
+#
+# -06/-05 - CST/CDT (North America DST)
+XX +415100-0873900 America/Chicago Central ("CST/CDT") - US & Canada; Mexico near US border
+#
+# -05
+XX -1203-07703 America/Lima eastern South America
+#
+# -05 - EST
+XX +175805-0764736 America/Jamaica Eastern Standard ("EST") - Caymans; Jamaica; eastern Mexico; Panama
+#
+# -05/-04 - CST/CDT (Cuba DST)
+XX +2308-08222 America/Havana Cuba
+#
+# -05/-04 - EST/EDT (North America DST)
+XX +404251-0740023 America/New_York Eastern ("EST/EDT") - US & Canada
+#
+# -04
+XX +1030-06656 America/Caracas western South America
+#
+# -04 - AST
+XX +1828-06954 America/Santo_Domingo Atlantic Standard ("AST") - eastern Caribbean
+#
+# -04/-03 (Chile DST)
+XX -3327-07040 America/Santiago most of Chile
+#
+# -04/-03 (Paraguay DST)
+XX -2516-05740 America/Asuncion Paraguay
+#
+# -04/-03 - AST/ADT (North America DST)
+XX +4439-06336 America/Halifax Atlantic ("AST/ADT") - Canada; Bermuda
+#
+# -03:30/-02:30 - NST/NDT (North America DST)
+XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT")
+#
+# -03
+XX -2332-04637 America/Sao_Paulo eastern South America
+#
+# -03/-02 (North America DST)
+XX +4703-05620 America/Miquelon St Pierre & Miquelon
+#
+# -02
+XX -0351-03225 America/Noronha Fernando de Noronha; South Georgia
+#
+# -02/-01 (EU DST)
+XX +6411-05144 America/Nuuk most of Greenland
+#
+# -01
+XX +1455-02331 Atlantic/Cape_Verde Cape Verde
+#
+# -01/+00 (EU DST)
+XX +3744-02540 Atlantic/Azores Azores
+# -01/+00 (EU DST) until 2024-03-31; then -02/-01 (EU DST)
+XX +7029-02158 America/Scoresbysund Ittoqqortoormiit
+#
+# +00 - GMT
+XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT")
+#
+# +00/+01 - GMT/BST (EU DST)
+XX +513030-0000731 Europe/London United Kingdom ("GMT/BST")
+#
+# +00/+01 - WET/WEST (EU DST)
+XX +3843-00908 Europe/Lisbon western Europe ("WET/WEST")
+#
+# +00/+02 - Troll DST
+XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica
+#
+# +01 - CET
+XX +3647+00303 Africa/Algiers Algeria, Tunisia ("CET")
+#
+# +01 - WAT
+XX +0627+00324 Africa/Lagos western Africa ("WAT")
+#
+# +01/+00 - IST/GMT (EU DST in reverse)
+XX +5320-00615 Europe/Dublin Ireland ("IST/GMT")
+#
+# +01/+00 - (Morocco DST)
+XX +3339-00735 Africa/Casablanca Morocco
+#
+# +01/+02 - CET/CEST (EU DST)
+XX +4852+00220 Europe/Paris central Europe ("CET/CEST")
+#
+# +02 - CAT
+XX -2558+03235 Africa/Maputo central Africa ("CAT")
+#
+# +02 - EET
+XX +3254+01311 Africa/Tripoli Libya; Kaliningrad ("EET")
+#
+# +02 - SAST
+XX -2615+02800 Africa/Johannesburg southern Africa ("SAST")
+#
+# +02/+03 - EET/EEST (EU DST)
+XX +3758+02343 Europe/Athens eastern Europe ("EET/EEST")
+#
+# +02/+03 - EET/EEST (Egypt DST)
+XX +3003+03115 Africa/Cairo Egypt
+#
+# +02/+03 - EET/EEST (Lebanon DST)
+XX +3353+03530 Asia/Beirut Lebanon
+#
+# +02/+03 - EET/EEST (Moldova DST)
+XX +4700+02850 Europe/Chisinau Moldova
+#
+# +02/+03 - EET/EEST (Palestine DST)
+XX +3130+03428 Asia/Gaza Palestine
+#
+# +02/+03 - IST/IDT (Israel DST)
+XX +314650+0351326 Asia/Jerusalem Israel
+#
+# +03
+XX +4101+02858 Europe/Istanbul Near East; Belarus
+#
+# +03 - EAT
+XX -0117+03649 Africa/Nairobi eastern Africa ("EAT")
+#
+# +03 - MSK
+XX +554521+0373704 Europe/Moscow Moscow ("MSK")
+#
+# +03:30
+XX +3540+05126 Asia/Tehran Iran
+#
+# +04
+XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion
+#
+# +04:30
+XX +3431+06912 Asia/Kabul Afghanistan
+#
+# +05
+XX +4120+06918 Asia/Tashkent Russia; Tajikistan; Turkmenistan; Uzbekistan; Maldives
+#
+# +05 - PKT
+XX +2452+06703 Asia/Karachi Pakistan ("PKT")
+#
+# +05:30
+XX +0656+07951 Asia/Colombo Sri Lanka
+#
+# +05:30 - IST
+XX +2232+08822 Asia/Kolkata India ("IST")
+#
+# +05:45
+XX +2743+08519 Asia/Kathmandu Nepal
+#
+# +06
+XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos
+#
+# +06:30
+XX +1647+09610 Asia/Yangon Myanmar; Cocos
+#
+# +07
+XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island
+#
+# +07 - WIB
+XX -0610+10648 Asia/Jakarta Indonesia ("WIB")
+#
+# +08
+XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore
+#
+# +08 - AWST
+XX -3157+11551 Australia/Perth Western Australia ("AWST")
+#
+# +08 - CST
+XX +3114+12128 Asia/Shanghai China ("CST")
+#
+# +08 - HKT
+XX +2217+11409 Asia/Hong_Kong Hong Kong ("HKT")
+#
+# +08 - PHT
+XX +1435+12100 Asia/Manila Philippines ("PHT")
+#
+# +08 - WITA
+XX -0507+11924 Asia/Makassar Indonesia ("WITA")
+#
+# +08:45
+XX -3143+12852 Australia/Eucla Eucla
+#
+# +09
+XX +5203+11328 Asia/Chita Russia; Palau; East Timor
+#
+# +09 - JST
+XX +353916+1394441 Asia/Tokyo Japan ("JST")
+#
+# +09 - KST
+XX +3733+12658 Asia/Seoul Korea ("KST")
+#
+# +09 - WIT
+XX -0232+14042 Asia/Jayapura Indonesia ("WIT")
+#
+# +09:30 - ACST
+XX -1228+13050 Australia/Darwin Northern Territory ("ACST")
+#
+# +09:30/+10:30 - ACST/ACDT (Australia DST)
+XX -3455+13835 Australia/Adelaide South Australia ("ACST/ACDT")
+#
+# +10
+XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d'Urville
+#
+# +10 - AEST
+XX -2728+15302 Australia/Brisbane Queensland ("AEST")
+#
+# +10 - ChST
+XX +1328+14445 Pacific/Guam Mariana Islands ("ChST")
+#
+# +10/+11 - AEST/AEDT (Australia DST)
+XX -3352+15113 Australia/Sydney southeast Australia ("AEST/AEDT")
+#
+# +10:30/+11
+XX -3133+15905 Australia/Lord_Howe Lord Howe Island
+#
+# +11
+XX -0613+15534 Pacific/Bougainville Russia; Kosrae; Bougainville; Solomons
+#
+# +11/+12 (Australia DST)
+XX -2903+16758 Pacific/Norfolk Norfolk Island
+#
+# +12
+XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc.
+#
+# +12/+13 (New Zealand DST)
+XX -3652+17446 Pacific/Auckland New Zealand ("NZST/NZDT")
+#
+# +12:45/+13:45 (Chatham DST)
+XX -4357-17633 Pacific/Chatham Chatham Islands
+#
+# +13
+XX -210800-1751200 Pacific/Tongatapu Kanton; Tokelau; Samoa (western); Tonga
+#
+# +14
+XX +0152-15720 Pacific/Kiritimati Kiritimati
diff --git a/contrib/python/tzdata/tzdata/zones b/contrib/python/tzdata/tzdata/zones
index 9300ebb09a..e1edd9ebc4 100644
--- a/contrib/python/tzdata/tzdata/zones
+++ b/contrib/python/tzdata/tzdata/zones
@@ -22,6 +22,7 @@ Antarctica/Casey
Antarctica/Davis
Antarctica/Mawson
Antarctica/Troll
+Antarctica/Vostok
Antarctica/Rothera
Asia/Kabul
Asia/Yerevan
@@ -497,7 +498,6 @@ America/Tortola
Antarctica/DumontDUrville
Antarctica/McMurdo
Antarctica/Syowa
-Antarctica/Vostok
Arctic/Longyearbyen
Asia/Aden
Asia/Bahrain
diff --git a/contrib/python/tzdata/ya.make b/contrib/python/tzdata/ya.make
index c9f9871738..04cc391451 100644
--- a/contrib/python/tzdata/ya.make
+++ b/contrib/python/tzdata/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(2023.3)
+VERSION(2023.4)
LICENSE(Apache-2.0)
@@ -640,6 +640,7 @@ RESOURCE_FILES(
tzdata/zoneinfo/tzdata.zi
tzdata/zoneinfo/zone.tab
tzdata/zoneinfo/zone1970.tab
+ tzdata/zoneinfo/zonenow.tab
tzdata/zones
)