summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/markdown-it-py/.dist-info/METADATA2
-rw-r--r--contrib/python/markdown-it-py/markdown_it/__init__.py2
-rw-r--r--contrib/python/markdown-it-py/markdown_it/rules_block/__init__.py3
-rw-r--r--contrib/python/markdown-it-py/markdown_it/rules_block/fence.py177
-rw-r--r--contrib/python/markdown-it-py/ya.make2
-rw-r--r--contrib/python/matplotlib-inline/.dist-info/METADATA4
-rw-r--r--contrib/python/matplotlib-inline/matplotlib_inline/__init__.py2
-rw-r--r--contrib/python/matplotlib-inline/ya.make2
-rw-r--r--contrib/python/traitlets/py3/.dist-info/METADATA7
-rw-r--r--contrib/python/traitlets/py3/patches/e3d5c5a66de52c623da02b4cafd9c34f5b0ff3bb.patch24
-rw-r--r--contrib/python/traitlets/py3/tests/test_traitlets.py4
-rw-r--r--contrib/python/traitlets/py3/tests/test_typing.py18
-rw-r--r--contrib/python/traitlets/py3/tests/utils/test_bunch.py5
-rw-r--r--contrib/python/traitlets/py3/traitlets/__init__.py12
-rw-r--r--contrib/python/traitlets/py3/traitlets/_version.py5
-rw-r--r--contrib/python/traitlets/py3/traitlets/config/application.py8
-rw-r--r--contrib/python/traitlets/py3/traitlets/config/configurable.py2
-rw-r--r--contrib/python/traitlets/py3/traitlets/tests/utils.py3
-rw-r--r--contrib/python/traitlets/py3/traitlets/traitlets.py153
-rw-r--r--contrib/python/traitlets/py3/traitlets/utils/__init__.py2
-rw-r--r--contrib/python/traitlets/py3/traitlets/utils/bunch.py4
-rw-r--r--contrib/python/traitlets/py3/traitlets/utils/decorators.py4
-rw-r--r--contrib/python/traitlets/py3/traitlets/utils/nested_update.py4
-rw-r--r--contrib/python/traitlets/py3/traitlets/utils/text.py25
-rw-r--r--contrib/python/traitlets/py3/ya.make2
25 files changed, 273 insertions, 203 deletions
diff --git a/contrib/python/markdown-it-py/.dist-info/METADATA b/contrib/python/markdown-it-py/.dist-info/METADATA
index 488e089b08e..c44604a6677 100644
--- a/contrib/python/markdown-it-py/.dist-info/METADATA
+++ b/contrib/python/markdown-it-py/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: markdown-it-py
-Version: 4.1.0
+Version: 4.2.0
Summary: Python port of markdown-it. Markdown parsing, done right!
Keywords: markdown,lexer,parser,commonmark,markdown-it
Author-email: Chris Sewell <[email protected]>
diff --git a/contrib/python/markdown-it-py/markdown_it/__init__.py b/contrib/python/markdown-it-py/markdown_it/__init__.py
index 523d92ef4ba..58dfa3bcc46 100644
--- a/contrib/python/markdown-it-py/markdown_it/__init__.py
+++ b/contrib/python/markdown-it-py/markdown_it/__init__.py
@@ -1,6 +1,6 @@
"""A Python port of Markdown-It"""
__all__ = ("MarkdownIt",)
-__version__ = "4.1.0"
+__version__ = "4.2.0"
from .main import MarkdownIt
diff --git a/contrib/python/markdown-it-py/markdown_it/rules_block/__init__.py b/contrib/python/markdown-it-py/markdown_it/rules_block/__init__.py
index 517da2312aa..2c5efa85ccf 100644
--- a/contrib/python/markdown-it-py/markdown_it/rules_block/__init__.py
+++ b/contrib/python/markdown-it-py/markdown_it/rules_block/__init__.py
@@ -8,6 +8,7 @@ __all__ = (
"html_block",
"lheading",
"list_block",
+ "make_fence_rule",
"paragraph",
"reference",
"table",
@@ -15,7 +16,7 @@ __all__ = (
from .blockquote import blockquote
from .code import code
-from .fence import fence
+from .fence import fence, make_fence_rule
from .heading import heading
from .hr import hr
from .html_block import html_block
diff --git a/contrib/python/markdown-it-py/markdown_it/rules_block/fence.py b/contrib/python/markdown-it-py/markdown_it/rules_block/fence.py
index 263f1b8de8d..0d7e651eb06 100644
--- a/contrib/python/markdown-it-py/markdown_it/rules_block/fence.py
+++ b/contrib/python/markdown-it-py/markdown_it/rules_block/fence.py
@@ -1,4 +1,7 @@
# fences (``` lang, ~~~ lang)
+from __future__ import annotations
+
+from collections.abc import Callable
import logging
from .state_block import StateBlock
@@ -6,96 +9,138 @@ from .state_block import StateBlock
LOGGER = logging.getLogger(__name__)
-def fence(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool:
- LOGGER.debug("entering fence: %s, %s, %s, %s", state, startLine, endLine, silent)
+def make_fence_rule(
+ *,
+ markers: tuple[str, ...] = ("~", "`"),
+ token_type: str = "fence",
+ exact_match: bool = False,
+ disallow_marker_in_info: tuple[str, ...] = ("`",),
+ min_markers: int = 3,
+) -> Callable[[StateBlock, int, int, bool], bool]:
+ """Create a fence parsing rule with configurable options.
- haveEndMarker = False
- pos = state.bMarks[startLine] + state.tShift[startLine]
- maximum = state.eMarks[startLine]
+ :param markers: Tuple of single characters that can be used as fence markers.
+ :param token_type: The token type name to emit (e.g. "fence", "colon_fence").
+ :param exact_match: If True, the closing fence must have exactly the same
+ number of marker characters as the opening fence (not "at least as many").
+ This enables nesting of fences with different marker counts.
+ :param disallow_marker_in_info: Tuple of marker characters that are not allowed
+ to appear in the info string. The check only applies when the actual opening
+ marker is in this tuple (e.g. a tilde fence is unaffected by ``"`"`` being
+ listed). Per CommonMark, backtick fences cannot have backticks in the info
+ string. Use ``()`` to disable this restriction.
+ :param min_markers: Minimum number of marker characters to form a fence.
+ :return: A block rule function with signature
+ ``(state, startLine, endLine, silent) -> bool``.
+ """
- if state.is_code_block(startLine):
- return False
+ closing_matcher: Callable[[int, int], bool]
+ if exact_match:
+ # closing code fence must have exactly the same number of markers as the opening one
+ closing_matcher = lambda opening_len, closing_len: closing_len == opening_len # noqa: E731
+ else:
+ # closing code fence must be at least as long as the opening one
+ closing_matcher = lambda opening_len, closing_len: closing_len >= opening_len # noqa: E731
- if pos + 3 > maximum:
- return False
+ def _fence_rule(
+ state: StateBlock, startLine: int, endLine: int, silent: bool
+ ) -> bool:
+ LOGGER.debug(
+ "entering fence: %s, %s, %s, %s", state, startLine, endLine, silent
+ )
- marker = state.src[pos]
+ haveEndMarker = False
+ pos = state.bMarks[startLine] + state.tShift[startLine]
+ maximum = state.eMarks[startLine]
- if marker not in ("~", "`"):
- return False
+ if state.is_code_block(startLine):
+ return False
- # scan marker length
- mem = pos
- pos = state.skipCharsStr(pos, marker)
+ if pos + min_markers > maximum:
+ return False
- length = pos - mem
+ marker = state.src[pos]
- if length < 3:
- return False
+ if marker not in markers:
+ return False
- markup = state.src[mem:pos]
- params = state.src[pos:maximum]
+ # scan marker length
+ mem = pos
+ pos = state.skipCharsStr(pos, marker)
- if marker == "`" and marker in params:
- return False
+ length = pos - mem
- # Since start is found, we can report success here in validation mode
- if silent:
- return True
+ if length < min_markers:
+ return False
- # search end of block
- nextLine = startLine
+ markup = state.src[mem:pos]
+ params = state.src[pos:maximum]
- while True:
- nextLine += 1
- if nextLine >= endLine:
- # unclosed block should be autoclosed by end of document.
- # also block seems to be autoclosed by end of parent
- break
+ if marker in disallow_marker_in_info and marker in params:
+ return False
- pos = mem = state.bMarks[nextLine] + state.tShift[nextLine]
- maximum = state.eMarks[nextLine]
+ # Since start is found, we can report success here in validation mode
+ if silent:
+ return True
- if pos < maximum and state.sCount[nextLine] < state.blkIndent:
- # non-empty line with negative indent should stop the list:
- # - ```
- # test
- break
+ # search end of block
+ nextLine = startLine
+
+ while True:
+ nextLine += 1
+ if nextLine >= endLine:
+ # unclosed block should be autoclosed by end of document.
+ # also block seems to be autoclosed by end of parent
+ break
+
+ pos = mem = state.bMarks[nextLine] + state.tShift[nextLine]
+ maximum = state.eMarks[nextLine]
+
+ if pos < maximum and state.sCount[nextLine] < state.blkIndent:
+ # non-empty line with negative indent should stop the list:
+ # - ```
+ # test
+ break
+
+ try:
+ if state.src[pos] != marker:
+ continue
+ except IndexError:
+ break
- try:
- if state.src[pos] != marker:
+ if state.is_code_block(nextLine):
continue
- except IndexError:
- break
- if state.is_code_block(nextLine):
- continue
+ pos = state.skipCharsStr(pos, marker)
- pos = state.skipCharsStr(pos, marker)
+ if not closing_matcher(length, pos - mem):
+ continue
- # closing code fence must be at least as long as the opening one
- if pos - mem < length:
- continue
+ # make sure tail has spaces only
+ pos = state.skipSpaces(pos)
- # make sure tail has spaces only
- pos = state.skipSpaces(pos)
+ if pos < maximum:
+ continue
- if pos < maximum:
- continue
+ haveEndMarker = True
+ # found!
+ break
+
+ # If a fence has heading spaces, they should be removed from its inner block
+ length = state.sCount[startLine]
- haveEndMarker = True
- # found!
- break
+ state.line = nextLine + (1 if haveEndMarker else 0)
- # If a fence has heading spaces, they should be removed from its inner block
- length = state.sCount[startLine]
+ token = state.push(token_type, "code", 0)
+ token.info = params
+ token.content = state.getLines(startLine + 1, nextLine, length, True)
+ token.markup = markup
+ token.map = [startLine, state.line]
+
+ return True
- state.line = nextLine + (1 if haveEndMarker else 0)
+ return _fence_rule
- token = state.push("fence", "code", 0)
- token.info = params
- token.content = state.getLines(startLine + 1, nextLine, length, True)
- token.markup = markup
- token.map = [startLine, state.line]
- return True
+#: The default fence rule (backtick and tilde markers, CommonMark compliant).
+fence = make_fence_rule()
diff --git a/contrib/python/markdown-it-py/ya.make b/contrib/python/markdown-it-py/ya.make
index dd380e6d343..bdbb0a782c7 100644
--- a/contrib/python/markdown-it-py/ya.make
+++ b/contrib/python/markdown-it-py/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(4.1.0)
+VERSION(4.2.0)
LICENSE(MIT)
diff --git a/contrib/python/matplotlib-inline/.dist-info/METADATA b/contrib/python/matplotlib-inline/.dist-info/METADATA
index c0aef502d2e..fe86ee74a23 100644
--- a/contrib/python/matplotlib-inline/.dist-info/METADATA
+++ b/contrib/python/matplotlib-inline/.dist-info/METADATA
@@ -1,11 +1,12 @@
Metadata-Version: 2.4
Name: matplotlib-inline
-Version: 0.2.1
+Version: 0.2.2
Summary: Inline Matplotlib backend for Jupyter
Keywords: ipython,jupyter,matplotlib,python
Author-email: IPython Development Team <[email protected]>
Requires-Python: >=3.9
Description-Content-Type: text/markdown
+License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: IPython
Classifier: Framework :: Jupyter :: JupyterLab :: 3
@@ -30,6 +31,7 @@ Requires-Dist: nbdime ; extra == "test"
Requires-Dist: nbval ; extra == "test"
Requires-Dist: notebook ; extra == "test"
Requires-Dist: pytest ; extra == "test"
+Requires-Dist: matplotlib ; extra == "test"
Project-URL: Homepage, https://github.com/ipython/matplotlib-inline
Provides-Extra: test
diff --git a/contrib/python/matplotlib-inline/matplotlib_inline/__init__.py b/contrib/python/matplotlib-inline/matplotlib_inline/__init__.py
index d275175ecd9..2c03285e778 100644
--- a/contrib/python/matplotlib-inline/matplotlib_inline/__init__.py
+++ b/contrib/python/matplotlib-inline/matplotlib_inline/__init__.py
@@ -1,6 +1,6 @@
from . import backend_inline, config # noqa
-__version__ = "0.2.1"
+__version__ = "0.2.2"
# we can't ''.join(...) otherwise finding the version number at build time requires
# import which introduces IPython and matplotlib at build time, and thus circular
diff --git a/contrib/python/matplotlib-inline/ya.make b/contrib/python/matplotlib-inline/ya.make
index 718e1ebacab..979b055fb22 100644
--- a/contrib/python/matplotlib-inline/ya.make
+++ b/contrib/python/matplotlib-inline/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(0.2.1)
+VERSION(0.2.2)
LICENSE(BSD-3-Clause)
diff --git a/contrib/python/traitlets/py3/.dist-info/METADATA b/contrib/python/traitlets/py3/.dist-info/METADATA
index 777822558d1..379f2d9c97b 100644
--- a/contrib/python/traitlets/py3/.dist-info/METADATA
+++ b/contrib/python/traitlets/py3/.dist-info/METADATA
@@ -1,6 +1,6 @@
-Metadata-Version: 2.3
+Metadata-Version: 2.4
Name: traitlets
-Version: 5.14.3
+Version: 5.15.0
Summary: Traitlets Python configuration system
Project-URL: Homepage, https://github.com/ipython/traitlets
Project-URL: Documentation, https://traitlets.readthedocs.io
@@ -49,13 +49,14 @@ Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
-Requires-Python: >=3.8
+Requires-Python: >=3.9
Provides-Extra: docs
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: pydata-sphinx-theme; extra == 'docs'
Requires-Dist: sphinx; extra == 'docs'
Provides-Extra: test
Requires-Dist: argcomplete>=3.0.3; extra == 'test'
+Requires-Dist: mypy<1.19,>=1.7.0; (platform_python_implementation == 'PyPy') and extra == 'test'
Requires-Dist: mypy>=1.7.0; extra == 'test'
Requires-Dist: pre-commit; extra == 'test'
Requires-Dist: pytest-mock; extra == 'test'
diff --git a/contrib/python/traitlets/py3/patches/e3d5c5a66de52c623da02b4cafd9c34f5b0ff3bb.patch b/contrib/python/traitlets/py3/patches/e3d5c5a66de52c623da02b4cafd9c34f5b0ff3bb.patch
deleted file mode 100644
index d610cde18d7..00000000000
--- a/contrib/python/traitlets/py3/patches/e3d5c5a66de52c623da02b4cafd9c34f5b0ff3bb.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From e3d5c5a66de52c623da02b4cafd9c34f5b0ff3bb Mon Sep 17 00:00:00 2001
-From: M Bussonnier <[email protected]>
-Date: Tue, 14 Oct 2025 08:55:52 +0200
-Subject: [PATCH] start testing on 3.14 and 3.14t (#929)
-
----
- .github/workflows/tests.yml | 2 +-
- traitlets/config/application.py | 3 ++-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/traitlets/config/application.py b/traitlets/config/application.py
-index 672fa1c9..b07ca818 100644
---- a/traitlets/config/application.py
-+++ b/traitlets/config/application.py
-@@ -215,7 +215,8 @@ def _classes_inc_parents(
- _log_formatter_cls = LevelFormatter
-
- log_datefmt = Unicode(
-- "%Y-%m-%d %H:%M:%S", help="The date format used by logging formatters for %(asctime)s"
-+ "%Y-%m-%d %H:%M:%S",
-+ help="The date format used by logging formatters for `asctime`",
- ).tag(config=True)
-
- log_format = Unicode(
diff --git a/contrib/python/traitlets/py3/tests/test_traitlets.py b/contrib/python/traitlets/py3/tests/test_traitlets.py
index f9f623b4ae6..665422cd9d2 100644
--- a/contrib/python/traitlets/py3/tests/test_traitlets.py
+++ b/contrib/python/traitlets/py3/tests/test_traitlets.py
@@ -7,6 +7,7 @@
# also under the terms of the Modified BSD License.
from __future__ import annotations
+import decimal
import pickle
import re
import typing as t
@@ -1391,7 +1392,7 @@ class TestLong(TraitTestBase):
obj = LongTrait()
_default_value = 99
- _good_values = [10, -10]
+ _good_values = [10, -10, 10.0, decimal.Decimal("10.0")]
_bad_values = [
"ten",
[10],
@@ -1401,6 +1402,7 @@ class TestLong(TraitTestBase):
1j,
10.1,
-10.1,
+ decimal.Decimal("10.1"),
"10",
"-10",
"10L",
diff --git a/contrib/python/traitlets/py3/tests/test_typing.py b/contrib/python/traitlets/py3/tests/test_typing.py
index 8329feb8375..940447478dc 100644
--- a/contrib/python/traitlets/py3/tests/test_typing.py
+++ b/contrib/python/traitlets/py3/tests/test_typing.py
@@ -407,27 +407,27 @@ def mypy_tcp_typing() -> None:
otcp = TCPAddress(None, allow_none=True)
t = T()
- reveal_type(t.tcp) # R: Tuple[builtins.str, builtins.int]
+ reveal_type(t.tcp) # R: tuple[builtins.str, builtins.int]
reveal_type(
- T.tcp # R: traitlets.traitlets.TCPAddress[Tuple[builtins.str, builtins.int], Tuple[builtins.str, builtins.int]]
+ T.tcp # R: traitlets.traitlets.TCPAddress[tuple[builtins.str, builtins.int], tuple[builtins.str, builtins.int]]
)
reveal_type(
- T.tcp.tag( # R:traitlets.traitlets.TCPAddress[Tuple[builtins.str, builtins.int], Tuple[builtins.str, builtins.int]]
+ T.tcp.tag( # R:traitlets.traitlets.TCPAddress[tuple[builtins.str, builtins.int], tuple[builtins.str, builtins.int]]
sync=True
)
)
- reveal_type(t.otcp) # R: Union[Tuple[builtins.str, builtins.int], None]
+ reveal_type(t.otcp) # R: Union[tuple[builtins.str, builtins.int], None]
reveal_type(
- T.otcp # R: traitlets.traitlets.TCPAddress[Union[Tuple[builtins.str, builtins.int], None], Union[Tuple[builtins.str, builtins.int], None]]
+ T.otcp # R: traitlets.traitlets.TCPAddress[Union[tuple[builtins.str, builtins.int], None], Union[tuple[builtins.str, builtins.int], None]]
)
reveal_type(
- T.otcp.tag( # R: traitlets.traitlets.TCPAddress[Union[Tuple[builtins.str, builtins.int], None], Union[Tuple[builtins.str, builtins.int], None]]
+ T.otcp.tag( # R: traitlets.traitlets.TCPAddress[Union[tuple[builtins.str, builtins.int], None], Union[tuple[builtins.str, builtins.int], None]]
sync=True
)
)
- t.tcp = "foo" # E: Incompatible types in assignment (expression has type "str", variable has type "Tuple[str, int]") [assignment]
- t.otcp = "foo" # E: Incompatible types in assignment (expression has type "str", variable has type "Optional[Tuple[str, int]]") [assignment]
- t.tcp = None # E: Incompatible types in assignment (expression has type "None", variable has type "Tuple[str, int]") [assignment]
+ t.tcp = "foo" # E: Incompatible types in assignment (expression has type "str", variable has type "tuple[str, int]") [assignment]
+ t.otcp = "foo" # E: Incompatible types in assignment (expression has type "str", variable has type "Optional[tuple[str, int]]") [assignment]
+ t.tcp = None # E: Incompatible types in assignment (expression has type "None", variable has type "tuple[str, int]") [assignment]
@pytest.mark.mypy_testing
diff --git a/contrib/python/traitlets/py3/tests/utils/test_bunch.py b/contrib/python/traitlets/py3/tests/utils/test_bunch.py
index 90efe982739..98bf262016a 100644
--- a/contrib/python/traitlets/py3/tests/utils/test_bunch.py
+++ b/contrib/python/traitlets/py3/tests/utils/test_bunch.py
@@ -14,5 +14,8 @@ def test_bunch():
def test_bunch_dir():
b = Bunch(x=5, y=10)
- assert "x" in dir(b)
assert "keys" in dir(b)
+ assert "x" in dir(b)
+ assert "z" not in dir(b)
+ b.z = 15
+ assert "z" in dir(b)
diff --git a/contrib/python/traitlets/py3/traitlets/__init__.py b/contrib/python/traitlets/py3/traitlets/__init__.py
index e27ecf1a451..da56f5c663d 100644
--- a/contrib/python/traitlets/py3/traitlets/__init__.py
+++ b/contrib/python/traitlets/py3/traitlets/__init__.py
@@ -1,4 +1,5 @@
"""Traitlets Python configuration system"""
+
from __future__ import annotations
import typing as _t
@@ -12,14 +13,15 @@ from .utils.importstring import import_item
from .utils.warnings import warn
__all__ = [
- "traitlets",
- "__version__",
- "version_info",
"Bunch",
- "signature_has_traits",
- "import_item",
"Sentinel",
+ "__version__",
+ "import_item",
+ "signature_has_traits",
+ "traitlets",
+ "version_info",
]
+__all__ += traitlets.__all__
class Sentinel(traitlets.Sentinel): # type:ignore[name-defined, misc]
diff --git a/contrib/python/traitlets/py3/traitlets/_version.py b/contrib/python/traitlets/py3/traitlets/_version.py
index fea66b5e0ad..fb2dbc36d16 100644
--- a/contrib/python/traitlets/py3/traitlets/_version.py
+++ b/contrib/python/traitlets/py3/traitlets/_version.py
@@ -4,16 +4,15 @@ handle the current version info of traitlets.
from __future__ import annotations
import re
-from typing import List
# Version string must appear intact for hatch versioning
-__version__ = "5.14.3"
+__version__ = "5.15.0"
# Build up version_info tuple for backwards compatibility
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
match = re.match(pattern, __version__)
assert match is not None
-parts: List[object] = [int(match[part]) for part in ["major", "minor", "patch"]]
+parts: list[object] = [int(match[part]) for part in ["major", "minor", "patch"]]
if match["rest"]:
parts.append(match["rest"])
version_info = tuple(parts)
diff --git a/contrib/python/traitlets/py3/traitlets/config/application.py b/contrib/python/traitlets/py3/traitlets/config/application.py
index 2860de722b8..b07ca818fc8 100644
--- a/contrib/python/traitlets/py3/traitlets/config/application.py
+++ b/contrib/python/traitlets/py3/traitlets/config/application.py
@@ -900,6 +900,8 @@ class Application(SingletonConfigurable):
yield each config object in turn.
"""
+ if os.path.isabs(basefilename):
+ path = [None]
if isinstance(path, str) or path is None:
path = [path]
for current in reversed(path):
@@ -1063,7 +1065,11 @@ class Application(SingletonConfigurable):
sys.exit(exit_status)
def __del__(self) -> None:
- self.close_handlers()
+ # __del__ may be called during process teardown,
+ # at which point any fraction of attributes and modules may have been cleared,
+ # e.g. even _accessing_ self.log may fail.
+ with suppress(Exception):
+ self.close_handlers()
@classmethod
def launch_instance(cls, argv: ArgvType = None, **kwargs: t.Any) -> None:
diff --git a/contrib/python/traitlets/py3/traitlets/config/configurable.py b/contrib/python/traitlets/py3/traitlets/config/configurable.py
index 44b4793ebd5..9740311513b 100644
--- a/contrib/python/traitlets/py3/traitlets/config/configurable.py
+++ b/contrib/python/traitlets/py3/traitlets/config/configurable.py
@@ -300,7 +300,7 @@ class Configurable(HasTraits):
if helptext is None:
helptext = trait.help
if helptext != "":
- helptext = "\n".join(wrap_paragraphs(helptext, 76))
+ helptext = "\n\n".join(wrap_paragraphs(helptext, 76))
lines.append(indent(helptext))
if "Enum" in trait.__class__.__name__:
diff --git a/contrib/python/traitlets/py3/traitlets/tests/utils.py b/contrib/python/traitlets/py3/traitlets/tests/utils.py
index 254d46a758a..fb587a24d17 100644
--- a/contrib/python/traitlets/py3/traitlets/tests/utils.py
+++ b/contrib/python/traitlets/py3/traitlets/tests/utils.py
@@ -1,8 +1,9 @@
from __future__ import annotations
import sys
+from collections.abc import Sequence
from subprocess import PIPE, Popen
-from typing import Any, Sequence
+from typing import Any
def get_output_error_code(cmd: str | Sequence[str]) -> tuple[str, str, Any]:
diff --git a/contrib/python/traitlets/py3/traitlets/traitlets.py b/contrib/python/traitlets/py3/traitlets/traitlets.py
index ecd0d7cc399..4aa08cf3d02 100644
--- a/contrib/python/traitlets/py3/traitlets/traitlets.py
+++ b/contrib/python/traitlets/py3/traitlets/traitlets.py
@@ -44,6 +44,7 @@ from __future__ import annotations
import contextlib
import enum
import inspect
+import numbers
import os
import re
import sys
@@ -169,8 +170,13 @@ class TraitError(Exception):
# -----------------------------------------------------------------------------
-def isidentifier(s: t.Any) -> bool:
- return t.cast(bool, s.isidentifier())
+def isidentifier(s: str) -> bool:
+ warn(
+ "traitlets.traitlets.isidentifier(s) is deprecated since traitlets 5.14.4 Use `s.isidentifier()`.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return s.isidentifier()
def _safe_literal_eval(s: str) -> t.Any:
@@ -293,13 +299,21 @@ class link:
updating = False
- def __init__(self, source: t.Any, target: t.Any, transform: t.Any = None) -> None:
+ def __init__(
+ self, source: t.Any, target: t.Any, transform: t.Iterable[FuncT] | None = None
+ ) -> None:
_validate_link(source, target)
self.source, self.target = source, target
- self._transform, self._transform_inv = transform if transform else (lambda x: x,) * 2
-
+ if transform:
+ self._transform, self._transform_inv = transform # type:ignore[method-assign]
self.link()
+ def _transform(self, x: T) -> T:
+ """default transform: no-op"""
+ return x
+
+ _transform_inv = _transform
+
def link(self) -> None:
try:
setattr(
@@ -491,6 +505,11 @@ if t.TYPE_CHECKING:
K = TypeVar("K", default=str)
V = TypeVar("V", default=t.Any)
+else:
+ # This is required to avoid warnings about unresolved references when generating
+ # the documentation of downstream projects.
+ K = TypeVar("K")
+ V = TypeVar("V")
# We use a type for the getter (G) and setter (G) because we allow
@@ -597,12 +616,12 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
in the same way that dynamic defaults defined by ``@default`` are.
"""
if self.default_value is not Undefined:
- return t.cast(G, self.default_value)
+ return self.default_value # type:ignore[no-any-return]
elif hasattr(self, "make_dynamic_default"):
- return t.cast(G, self.make_dynamic_default())
+ return self.make_dynamic_default() # type:ignore[no-any-return]
else:
# Undefined will raise in TraitType.get
- return t.cast(G, self.default_value)
+ return self.default_value # type:ignore[no-any-return]
def get_default_value(self) -> G | None:
"""DEPRECATED: Retrieve the static default value for this trait.
@@ -613,7 +632,7 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
DeprecationWarning,
stacklevel=2,
)
- return t.cast(G, self.default_value)
+ return self.default_value # type:ignore[no-any-return]
def init_default_value(self, obj: t.Any) -> G | None:
"""DEPRECATED: Set the static default value for the trait type."""
@@ -658,12 +677,12 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
type="default",
)
)
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
except Exception as e:
# This should never be reached.
raise TraitError("Unexpected error in TraitType: default value not set properly") from e
else:
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
@t.overload
def __get__(self, obj: None, cls: type[t.Any]) -> Self:
@@ -684,7 +703,7 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
if obj is None:
return self
else:
- return t.cast(G, self.get(obj, cls)) # the G should encode the Optional
+ return self.get(obj, cls) # type:ignore[return-value]
def set(self, obj: HasTraits, value: S) -> None:
new_value = self._validate(obj, value)
@@ -722,7 +741,7 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
value = self.validate(obj, value)
if obj._cross_validation_lock is False:
value = self._cross_validate(obj, value)
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
def _cross_validate(self, obj: t.Any, value: t.Any) -> G | None:
if self.name in obj._trait_validators:
@@ -738,7 +757,7 @@ class TraitType(BaseDescriptor, t.Generic[G, S]):
"use @validate decorator instead.",
)
value = cross_validate(value, self)
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
def __or__(self, other: TraitType[t.Any, t.Any]) -> Union:
if isinstance(other, Union):
@@ -1142,7 +1161,7 @@ def observe_compat(func: FuncT) -> FuncT:
)
return func(self, change)
- return t.cast(FuncT, compatible_observer)
+ return compatible_observer # type:ignore[return-value]
def validate(*names: Sentinel | str) -> ValidateHandler:
@@ -1277,11 +1296,7 @@ class DefaultHandler(EventHandler):
class HasDescriptors(metaclass=MetaHasDescriptors):
"""The base class for all classes that have descriptors."""
- def __new__(*args: t.Any, **kwargs: t.Any) -> t.Any:
- # Pass cls as args[0] to allow "cls" as keyword argument
- cls = args[0]
- args = args[1:]
-
+ def __new__(cls, /, *args: t.Any, **kwargs: t.Any) -> Self:
# This is needed because object.__new__ only accepts
# the cls argument.
new_meth = super(HasDescriptors, cls).__new__
@@ -1292,13 +1307,10 @@ class HasDescriptors(metaclass=MetaHasDescriptors):
inst.setup_instance(*args, **kwargs)
return inst
- def setup_instance(*args: t.Any, **kwargs: t.Any) -> None:
+ def setup_instance(self, /, *args: t.Any, **kwargs: t.Any) -> None:
"""
This is called **before** self.__init__ is called.
"""
- # Pass self as args[0] to allow "self" as keyword argument
- self = args[0]
- args = args[1:]
self._cross_validation_lock = False
cls = self.__class__
@@ -1320,11 +1332,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits):
_traits: dict[str, t.Any]
_all_trait_default_generators: dict[str, t.Any]
- def setup_instance(*args: t.Any, **kwargs: t.Any) -> None:
- # Pass self as args[0] to allow "self" as keyword argument
- self = args[0]
- args = args[1:]
-
+ def setup_instance(self, /, *args: t.Any, **kwargs: t.Any) -> None:
# although we'd prefer to set only the initial values not present
# in kwargs, we will overwrite them in `__init__`, and simply making
# a copy of a dict is faster than checking for each key.
@@ -1894,7 +1902,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits):
raise TraitError(f"'{n}' is not a trait of '{type(self).__name__}' instances")
if len(names) == 1 and len(metadata) == 0:
- return t.cast(Sentinel, self._get_trait_default_generator(names[0])(self))
+ return self._get_trait_default_generator(names[0])(self) # type:ignore[no-any-return]
trait_names = self.trait_names(**metadata)
trait_names.extend(names)
@@ -2144,7 +2152,7 @@ class Type(ClassBasedTraitType[G, S]):
) from e
try:
if issubclass(value, self.klass): # type:ignore[arg-type]
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
except Exception:
pass
@@ -2306,7 +2314,7 @@ class Instance(ClassBasedTraitType[T, T]):
if self.allow_none and value is None:
return value
if isinstance(value, self.klass): # type:ignore[arg-type]
- return t.cast(T, value)
+ return value # type:ignore[no-any-return]
else:
self.error(obj, value)
@@ -2338,7 +2346,7 @@ class Instance(ClassBasedTraitType[T, T]):
return repr(self.make_dynamic_default())
def from_string(self, s: str) -> T | None:
- return t.cast(T, _safe_literal_eval(s))
+ return _safe_literal_eval(s) # type:ignore[no-any-return]
class ForwardDeclaredMixin:
@@ -2633,14 +2641,23 @@ class Int(TraitType[G, S]):
)
def validate(self, obj: t.Any, value: t.Any) -> G:
+ if not isinstance(value, int) and isinstance(value, numbers.Number):
+ # allow casting integer-valued numbers to int
+ # allows for more concise assignment like `4e9` which is a float
+ try:
+ int_value = int(value)
+ if int_value == value:
+ value = int_value
+ except Exception:
+ pass
if not isinstance(value, int):
self.error(obj, value)
- return t.cast(G, _validate_bounds(self, obj, value))
+ return _validate_bounds(self, obj, value) # type:ignore[no-any-return]
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
- return t.cast(G, None)
- return t.cast(G, int(s))
+ return None # type:ignore[return-value]
+ return int(s) # type:ignore[return-value]
def subclass_init(self, cls: type[t.Any]) -> None:
pass # fully opt out of instance_init
@@ -2691,7 +2708,7 @@ class CInt(Int[G, S]):
value = int(value)
except Exception:
self.error(obj, value)
- return t.cast(G, _validate_bounds(self, obj, value))
+ return _validate_bounds(self, obj, value) # type:ignore[no-any-return]
Long, CLong = Int, CInt
@@ -2753,12 +2770,12 @@ class Float(TraitType[G, S]):
value = float(value)
if not isinstance(value, float):
self.error(obj, value)
- return t.cast(G, _validate_bounds(self, obj, value))
+ return _validate_bounds(self, obj, value) # type:ignore[no-any-return]
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
- return t.cast(G, None)
- return t.cast(G, float(s))
+ return None # type:ignore[return-value]
+ return float(s) # type:ignore[return-value]
def subclass_init(self, cls: type[t.Any]) -> None:
pass # fully opt out of instance_init
@@ -2809,7 +2826,7 @@ class CFloat(Float[G, S]):
value = float(value)
except Exception:
self.error(obj, value)
- return t.cast(G, _validate_bounds(self, obj, value))
+ return _validate_bounds(self, obj, value) # type:ignore[no-any-return]
class Complex(TraitType[complex, t.Union[complex, float, int]]):
@@ -2935,10 +2952,10 @@ class Unicode(TraitType[G, S]):
def validate(self, obj: t.Any, value: t.Any) -> G:
if isinstance(value, str):
- return t.cast(G, value)
+ return value # type:ignore[return-value]
if isinstance(value, bytes):
try:
- return t.cast(G, value.decode("ascii", "strict"))
+ return value.decode("ascii", "strict") # type:ignore[return-value]
except UnicodeDecodeError as e:
msg = "Could not decode {!r} for unicode trait '{}' of {} instance."
raise TraitError(msg.format(value, self.name, class_of(obj))) from e
@@ -2946,7 +2963,7 @@ class Unicode(TraitType[G, S]):
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
- return t.cast(G, None)
+ return None # type:ignore[return-value]
s = os.path.expanduser(s)
if len(s) >= 2:
# handle deprecated "1"
@@ -2960,7 +2977,7 @@ class Unicode(TraitType[G, S]):
DeprecationWarning,
stacklevel=2,
)
- return t.cast(G, s)
+ return s # type:ignore[return-value]
def subclass_init(self, cls: type[t.Any]) -> None:
pass # fully opt out of instance_init
@@ -3008,7 +3025,7 @@ class CUnicode(Unicode[G, S], TraitType[str, t.Any]):
def validate(self, obj: t.Any, value: t.Any) -> G:
try:
- return t.cast(G, str(value))
+ return str(value) # type:ignore[return-value]
except Exception:
self.error(obj, value)
@@ -3025,7 +3042,7 @@ class ObjectName(TraitType[str, str]):
def validate(self, obj: t.Any, value: t.Any) -> str:
value = self.coerce_str(obj, value)
- if isinstance(value, str) and isidentifier(value):
+ if isinstance(value, str) and value.isidentifier():
return value
self.error(obj, value)
@@ -3041,7 +3058,7 @@ class DottedObjectName(ObjectName):
def validate(self, obj: t.Any, value: t.Any) -> str:
value = self.coerce_str(obj, value)
- if isinstance(value, str) and all(isidentifier(a) for a in value.split(".")):
+ if isinstance(value, str) and all(a.isidentifier() for a in value.split(".")):
return value
self.error(obj, value)
@@ -3091,22 +3108,22 @@ class Bool(TraitType[G, S]):
def validate(self, obj: t.Any, value: t.Any) -> G:
if isinstance(value, bool):
- return t.cast(G, value)
+ return value # type:ignore[return-value]
elif isinstance(value, int):
if value == 1:
- return t.cast(G, True)
+ return True # type:ignore[return-value]
elif value == 0:
- return t.cast(G, False)
+ return False # type:ignore[return-value]
self.error(obj, value)
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
- return t.cast(G, None)
+ return None # type:ignore[return-value]
s = s.lower()
if s in {"true", "1"}:
- return t.cast(G, True)
+ return True # type:ignore[return-value]
elif s in {"false", "0"}:
- return t.cast(G, False)
+ return False # type:ignore[return-value]
else:
raise ValueError("%r is not 1, 0, true, or false")
@@ -3163,7 +3180,7 @@ class CBool(Bool[G, S]):
def validate(self, obj: t.Any, value: t.Any) -> G:
try:
- return t.cast(G, bool(value))
+ return bool(value) # type:ignore[return-value]
except Exception:
self.error(obj, value)
@@ -3220,7 +3237,7 @@ class Enum(TraitType[G, G]):
def validate(self, obj: t.Any, value: t.Any) -> G:
if self.values and value in self.values:
- return t.cast(G, value)
+ return value # type:ignore[no-any-return]
self.error(obj, value)
def _choices_str(self, as_rst: bool = False) -> str:
@@ -3247,7 +3264,7 @@ class Enum(TraitType[G, G]):
try:
return self.validate(None, s)
except TraitError:
- return t.cast(G, _safe_literal_eval(s))
+ return _safe_literal_eval(s) # type:ignore[no-any-return]
def subclass_init(self, cls: type[t.Any]) -> None:
pass # fully opt out of instance_init
@@ -3275,7 +3292,7 @@ class CaselessStrEnum(Enum[G]):
for v in self.values or []:
assert isinstance(v, str)
if v.lower() == value.lower():
- return t.cast(G, v)
+ return v # type:ignore[return-value]
self.error(obj, value)
def _info(self, as_rst: bool = False) -> str:
@@ -3479,14 +3496,12 @@ class Container(Instance[T]):
if value is None:
return value
- value = self.validate_elements(obj, value)
-
- return t.cast(T, value)
+ return self.validate_elements(obj, value)
def validate_elements(self, obj: t.Any, value: t.Any) -> T | None:
validated = []
if self._trait is None or isinstance(self._trait, Any):
- return t.cast(T, value)
+ return value # type:ignore[no-any-return]
for v in value:
try:
v = self._trait._validate(obj, v)
@@ -3553,7 +3568,7 @@ class Container(Instance[T]):
else:
# backward-compat: allow item_from_string to ignore index arg
def item_from_string(s: str, index: int | None = None) -> T | str:
- return t.cast(T, self.item_from_string(s))
+ return self.item_from_string(s)
return self.klass( # type:ignore[call-arg]
[item_from_string(s, index=idx) for idx, s in enumerate(s_list)]
@@ -3565,7 +3580,7 @@ class Container(Instance[T]):
Evaluated when parsing CLI configuration from a string
"""
if self._trait:
- return t.cast(T, self._trait.from_string(s))
+ return self._trait.from_string(s) # type:ignore[no-any-return]
else:
return s
@@ -4051,7 +4066,7 @@ class Dict(Instance["dict[K, V]"]):
if not isinstance(s, str):
raise TypeError(f"from_string expects a string, got {s!r} of type {type(s)}")
try:
- return t.cast("dict[K, V]", self.from_string_list([s]))
+ return self.from_string_list([s]) # type:ignore[no-any-return]
except Exception:
test = _safe_literal_eval(s)
if isinstance(test, dict):
@@ -4109,7 +4124,7 @@ class Dict(Instance["dict[K, V]"]):
value_trait = (self._per_key_traits or {}).get(key, self._value_trait)
if value_trait:
value = value_trait.from_string(value)
- return t.cast("dict[K, V]", {key: value})
+ return {key: value} # type:ignore[dict-item]
class TCPAddress(TraitType[G, S]):
@@ -4165,17 +4180,17 @@ class TCPAddress(TraitType[G, S]):
if isinstance(value[0], str) and isinstance(value[1], int):
port = value[1]
if port >= 0 and port <= 65535:
- return t.cast(G, value)
+ return value # type:ignore[return-value]
self.error(obj, value)
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
- return t.cast(G, None)
+ return None # type:ignore[return-value]
if ":" not in s:
raise ValueError("Require `ip:port`, got %r" % s)
ip, port_str = s.split(":", 1)
port = int(port_str)
- return t.cast(G, (ip, port))
+ return (ip, port) # type:ignore[return-value]
class CRegExp(TraitType["re.Pattern[t.Any]", t.Union["re.Pattern[t.Any]", str]]):
diff --git a/contrib/python/traitlets/py3/traitlets/utils/__init__.py b/contrib/python/traitlets/py3/traitlets/utils/__init__.py
index 2695dc73357..10d6a80fa54 100644
--- a/contrib/python/traitlets/py3/traitlets/utils/__init__.py
+++ b/contrib/python/traitlets/py3/traitlets/utils/__init__.py
@@ -2,7 +2,7 @@ from __future__ import annotations
import os
import pathlib
-from typing import Sequence
+from collections.abc import Sequence
# vestigal things from IPython_genutils.
diff --git a/contrib/python/traitlets/py3/traitlets/utils/bunch.py b/contrib/python/traitlets/py3/traitlets/utils/bunch.py
index 498563e0b5b..b1eb6c28de9 100644
--- a/contrib/python/traitlets/py3/traitlets/utils/bunch.py
+++ b/contrib/python/traitlets/py3/traitlets/utils/bunch.py
@@ -23,7 +23,7 @@ class Bunch(dict): # type:ignore[type-arg]
self.__setitem__(key, value)
def __dir__(self) -> list[str]:
- # py2-compat: can't use super because dict doesn't have __dir__
- names = dir({})
+ names: list[str] = []
+ names.extend(super().__dir__())
names.extend(self.keys())
return names
diff --git a/contrib/python/traitlets/py3/traitlets/utils/decorators.py b/contrib/python/traitlets/py3/traitlets/utils/decorators.py
index 5b77d701dee..923959a7e9e 100644
--- a/contrib/python/traitlets/py3/traitlets/utils/decorators.py
+++ b/contrib/python/traitlets/py3/traitlets/utils/decorators.py
@@ -3,7 +3,7 @@ from __future__ import annotations
import copy
from inspect import Parameter, Signature, signature
-from typing import Any, Type, TypeVar
+from typing import Any, TypeVar
from ..traitlets import HasTraits, Undefined
@@ -16,7 +16,7 @@ def _get_default(value: Any) -> Any:
T = TypeVar("T", bound=HasTraits)
-def signature_has_traits(cls: Type[T]) -> Type[T]:
+def signature_has_traits(cls: type[T]) -> type[T]:
"""Return a decorated class with a constructor signature that contain Trait names as kwargs."""
traits = [
(name, _get_default(value.default_value))
diff --git a/contrib/python/traitlets/py3/traitlets/utils/nested_update.py b/contrib/python/traitlets/py3/traitlets/utils/nested_update.py
index 33a5ab8a77b..976beff6025 100644
--- a/contrib/python/traitlets/py3/traitlets/utils/nested_update.py
+++ b/contrib/python/traitlets/py3/traitlets/utils/nested_update.py
@@ -2,10 +2,10 @@
# Distributed under the terms of the Modified BSD License.
from __future__ import annotations
-from typing import Any, Dict
+from typing import Any
-def nested_update(this: Dict[Any, Any], that: Dict[Any, Any]) -> Dict[Any, Any]:
+def nested_update(this: dict[Any, Any], that: dict[Any, Any]) -> dict[Any, Any]:
"""Merge two nested dictionaries.
Effectively a recursive ``dict.update``.
diff --git a/contrib/python/traitlets/py3/traitlets/utils/text.py b/contrib/python/traitlets/py3/traitlets/utils/text.py
index 1c1ac208150..a177c2ca3e7 100644
--- a/contrib/python/traitlets/py3/traitlets/utils/text.py
+++ b/contrib/python/traitlets/py3/traitlets/utils/text.py
@@ -5,16 +5,33 @@ from __future__ import annotations
import re
import textwrap
-from textwrap import dedent
from textwrap import indent as _indent
-from typing import List
def indent(val: str) -> str:
return _indent(val, " ")
-def wrap_paragraphs(text: str, ncols: int = 80) -> List[str]:
+def _dedent(text: str) -> str:
+ """Equivalent of textwrap.dedent that ignores unindented first line."""
+
+ if text.startswith("\n"):
+ # text starts with blank line, don't ignore the first line
+ return textwrap.dedent(text)
+
+ # split first line
+ splits = text.split("\n", 1)
+ if len(splits) == 1:
+ # only one line
+ return textwrap.dedent(text)
+
+ first, rest = splits
+ # dedent everything but the first line
+ rest = textwrap.dedent(rest)
+ return "\n".join([first, rest])
+
+
+def wrap_paragraphs(text: str, ncols: int = 80) -> list[str]:
"""Wrap multiple paragraphs to fit a specified width.
This is equivalent to textwrap.wrap, but with support for multiple
@@ -26,7 +43,7 @@ def wrap_paragraphs(text: str, ncols: int = 80) -> List[str]:
list of complete paragraphs, wrapped to fill `ncols` columns.
"""
paragraph_re = re.compile(r"\n(\s*\n)+", re.MULTILINE)
- text = dedent(text).strip()
+ text = _dedent(text).strip()
paragraphs = paragraph_re.split(text)[::2] # every other entry is space
out_ps = []
indent_re = re.compile(r"\n\s+", re.MULTILINE)
diff --git a/contrib/python/traitlets/py3/ya.make b/contrib/python/traitlets/py3/ya.make
index ed5c06a2c06..545b7dcfca3 100644
--- a/contrib/python/traitlets/py3/ya.make
+++ b/contrib/python/traitlets/py3/ya.make
@@ -4,7 +4,7 @@ PY3_LIBRARY()
PROVIDES(python_traitlets)
-VERSION(5.14.3)
+VERSION(5.15.0)
LICENSE(BSD-3-Clause)