Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-eval-type-backport for
openSUSE:Factory checked in at 2026-06-15 19:43:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-eval-type-backport (Old)
and /work/SRC/openSUSE:Factory/.python-eval-type-backport.new.1981 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-eval-type-backport"
Mon Jun 15 19:43:12 2026 rev:2 rq:1359267 version:0.4.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-eval-type-backport/python-eval-type-backport.changes
2026-01-15 16:48:54.382855385 +0100
+++
/work/SRC/openSUSE:Factory/.python-eval-type-backport.new.1981/python-eval-type-backport.changes
2026-06-15 19:46:16.322525220 +0200
@@ -1,0 +2,6 @@
+Sun Jun 14 15:43:08 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.4.0:
+ * Add install_patch() function for easy usage, updated docs
+
+-------------------------------------------------------------------
Old:
----
eval_type_backport-0.3.1.tar.gz
New:
----
eval_type_backport-0.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-eval-type-backport.spec ++++++
--- /var/tmp/diff_new_pack.wVIyO3/_old 2026-06-15 19:46:17.970594286 +0200
+++ /var/tmp/diff_new_pack.wVIyO3/_new 2026-06-15 19:46:17.978594621 +0200
@@ -1,7 +1,7 @@
#
-# spec file for package python-eval_type_backport
+# spec file for package python-eval-type-backport
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: python-eval-type-backport
-Version: 0.3.1
+Version: 0.4.0
Release: 0
Summary: `typing._eval_type` for older Python versions
License: MIT
++++++ eval_type_backport-0.3.1.tar.gz -> eval_type_backport-0.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/eval_type_backport-0.3.1/.github/workflows/test.yml
new/eval_type_backport-0.4.0/.github/workflows/test.yml
--- old/eval_type_backport-0.3.1/.github/workflows/test.yml 2025-12-02
12:50:19.000000000 +0100
+++ new/eval_type_backport-0.4.0/.github/workflows/test.yml 2026-06-02
15:20:20.000000000 +0200
@@ -8,6 +8,27 @@
workflow_dispatch:
jobs:
+ pre-commit:
+ name: pre-commit
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.13'
+ - name: Install dependencies
+ run: |
+ python -m venv venv
+ . venv/bin/activate
+ python --version
+ pip install --upgrade pip pre-commit uv .[tests]
+ - name: Run pre-commit
+ run: |
+ . venv/bin/activate
+ pre-commit run --all-files
+
test:
name: test ${{ matrix.os }} / ${{ matrix.python-version }}
strategy:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/eval_type_backport-0.3.1/.pre-commit-config.yaml
new/eval_type_backport-0.4.0/.pre-commit-config.yaml
--- old/eval_type_backport-0.3.1/.pre-commit-config.yaml 2024-07-07
23:49:24.000000000 +0200
+++ new/eval_type_backport-0.4.0/.pre-commit-config.yaml 2026-06-02
15:20:20.000000000 +0200
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v6.0.0
hooks:
- id: check-yaml
- id: check-toml
@@ -8,12 +8,21 @@
- id: trailing-whitespace
- id: check-merge-conflict
- id: debug-statements
-- repo: https://github.com/RobertCraigie/pyright-python
- rev: v1.1.335
+- repo: local
hooks:
- id: pyright
-- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.1.5
- hooks:
- - id: ruff
- - id: ruff-format
+ name: pyright
+ entry: uvx pyright@latest
+ language: system
+ pass_filenames: false
+ types_or: [python, pyi]
+ - id: ruff
+ name: ruff
+ entry: uvx ruff@latest check --force-exclude
+ language: system
+ types_or: [python, pyi]
+ - id: ruff-format
+ name: ruff format
+ entry: uvx ruff@latest format --force-exclude
+ language: system
+ types_or: [python, pyi]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/eval_type_backport-0.3.1/PKG-INFO
new/eval_type_backport-0.4.0/PKG-INFO
--- old/eval_type_backport-0.3.1/PKG-INFO 2025-12-02 12:51:37.228015700
+0100
+++ new/eval_type_backport-0.4.0/PKG-INFO 2026-06-02 15:22:01.362258200
+0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.4
+Metadata-Version: 2.1
Name: eval_type_backport
-Version: 0.3.1
+Version: 0.4.0
Summary: Like `typing._eval_type`, but lets older Python versions use newer
typing features.
Home-page: https://github.com/alexmojaki/eval_type_backport
Author: Alex Hall
@@ -22,20 +22,40 @@
License-File: LICENSE.txt
Provides-Extra: tests
Requires-Dist: pytest; extra == "tests"
-Dynamic: license-file
# eval_type_backport
[](https://github.com/alexmojaki/eval_type_backport/actions)
[](https://coveralls.io/github/alexmojaki/eval_type_backport)
[](https://pypi.python.org/pypi/eval_type_backport)
[](https://anaconda.org/conda-forge/eval-type-backport)
-This is a tiny package providing a replacement for `typing._eval_type` to
support newer typing features in older Python versions.
-
-Yes, that's very specific, and yes, `typing._eval_type` is a protected
function that you shouldn't normally be using. Really this package is
specifically made for https://github.com/pydantic/pydantic/issues/7873.
-
+This package makes runtime typing inspection with the `typing` module possible
with newer syntax in older Python versions.
Specifically, this transforms `X | Y` into `typing.Union[X, Y]`
and `list[X]` into `typing.List[X]` etc. (for all the types made generic in
PEP 585)
if the original syntax is not supported in the current Python version.
+For users of Pydantic, merely having this package installed should make
Pydantic models with newer syntax work in older Python versions.
+
+Here's an example of how to use it directly:
+
+```python
+import typing
+
+from eval_type_backport import install_patch
+
+install_patch()
+
+
+class Foo:
+ a: 'int | str'
+
+
+print(typing.get_type_hints(Foo))
+```
+
+In Python 3.9, without the `install_patch`, the above code will raise
`TypeError: unsupported operand type(s) for |: 'type' and 'type'`.
+With it, it prints `{'a': typing.Union[int, str]}` as expected.
+
+`install_patch` monkey-patches the `typing` module so that things should 'just
work' from wherever. To specifically use the backport where you need it instead
of patching globally, you can use the `eval_type_backport.eval_type_backport`
function directly instead of `typing._eval_type`. Yes, `typing._eval_type` is a
protected function that you shouldn't normally be using. This package was
written to support Pydantic, which uses it internally.
+
## Install
From PyPI:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/eval_type_backport-0.3.1/README.md
new/eval_type_backport-0.4.0/README.md
--- old/eval_type_backport-0.3.1/README.md 2025-12-02 12:50:19.000000000
+0100
+++ new/eval_type_backport-0.4.0/README.md 2026-05-28 14:05:12.000000000
+0200
@@ -2,14 +2,35 @@
[](https://github.com/alexmojaki/eval_type_backport/actions)
[](https://coveralls.io/github/alexmojaki/eval_type_backport)
[](https://pypi.python.org/pypi/eval_type_backport)
[](https://anaconda.org/conda-forge/eval-type-backport)
-This is a tiny package providing a replacement for `typing._eval_type` to
support newer typing features in older Python versions.
-
-Yes, that's very specific, and yes, `typing._eval_type` is a protected
function that you shouldn't normally be using. Really this package is
specifically made for https://github.com/pydantic/pydantic/issues/7873.
-
+This package makes runtime typing inspection with the `typing` module possible
with newer syntax in older Python versions.
Specifically, this transforms `X | Y` into `typing.Union[X, Y]`
and `list[X]` into `typing.List[X]` etc. (for all the types made generic in
PEP 585)
if the original syntax is not supported in the current Python version.
+For users of Pydantic, merely having this package installed should make
Pydantic models with newer syntax work in older Python versions.
+
+Here's an example of how to use it directly:
+
+```python
+import typing
+
+from eval_type_backport import install_patch
+
+install_patch()
+
+
+class Foo:
+ a: 'int | str'
+
+
+print(typing.get_type_hints(Foo))
+```
+
+In Python 3.9, without the `install_patch`, the above code will raise
`TypeError: unsupported operand type(s) for |: 'type' and 'type'`.
+With it, it prints `{'a': typing.Union[int, str]}` as expected.
+
+`install_patch` monkey-patches the `typing` module so that things should 'just
work' from wherever. To specifically use the backport where you need it instead
of patching globally, you can use the `eval_type_backport.eval_type_backport`
function directly instead of `typing._eval_type`. Yes, `typing._eval_type` is a
protected function that you shouldn't normally be using. This package was
written to support Pydantic, which uses it internally.
+
## Install
From PyPI:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/eval_type_backport-0.3.1/eval_type_backport/__init__.py
new/eval_type_backport-0.4.0/eval_type_backport/__init__.py
--- old/eval_type_backport-0.3.1/eval_type_backport/__init__.py 2024-07-07
23:49:24.000000000 +0200
+++ new/eval_type_backport-0.4.0/eval_type_backport/__init__.py 2026-05-28
14:05:12.000000000 +0200
@@ -1,4 +1,4 @@
-from .eval_type_backport import ForwardRef, eval_type_backport
+from .eval_type_backport import ForwardRef, eval_type_backport, install_patch
try:
from .version import __version__
@@ -6,4 +6,4 @@
# version.py is auto-generated with the git tag when building
__version__ = '???'
-__all__ = ['ForwardRef', 'eval_type_backport', '__version__']
+__all__ = ['install_patch', 'ForwardRef', 'eval_type_backport', '__version__']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/eval_type_backport-0.3.1/eval_type_backport/eval_type_backport.py
new/eval_type_backport-0.4.0/eval_type_backport/eval_type_backport.py
--- old/eval_type_backport-0.3.1/eval_type_backport/eval_type_backport.py
2025-11-13 21:53:00.000000000 +0100
+++ new/eval_type_backport-0.4.0/eval_type_backport/eval_type_backport.py
2026-06-02 15:20:20.000000000 +0200
@@ -28,52 +28,74 @@
# From https://peps.python.org/pep-0585/#implementation
+_generic_type_origins: tuple[Any, ...] = (
+ collections.OrderedDict,
+ collections.Counter,
+ collections.ChainMap,
+ collections.abc.Awaitable,
+ collections.abc.Coroutine,
+ collections.abc.AsyncIterable,
+ collections.abc.AsyncIterator,
+ collections.abc.AsyncGenerator,
+ collections.abc.Iterable,
+ collections.abc.Iterator,
+ collections.abc.Generator,
+ collections.abc.Reversible,
+ collections.abc.Container,
+ collections.abc.Collection,
+ collections.abc.Callable,
+ collections.abc.MutableSet,
+ collections.abc.Mapping,
+ collections.abc.MutableMapping,
+ collections.abc.Sequence,
+ collections.abc.MutableSequence,
+ collections.abc.MappingView,
+ collections.abc.KeysView,
+ collections.abc.ItemsView,
+ collections.abc.ValuesView,
+ re.Pattern,
+ re.Match,
+)
+
+
new_generic_types = {
- tuple: 'Tuple',
- list: 'List',
- dict: 'Dict',
- set: 'Set',
- frozenset: 'FrozenSet',
- type: 'Type',
- collections.deque: 'Deque',
- collections.defaultdict: 'DefaultDict',
- collections.abc.Set: 'AbstractSet',
- contextlib.AbstractContextManager: 'ContextManager',
- contextlib.AbstractAsyncContextManager: 'AsyncContextManager',
- **{
- k: k.__name__
- for k in (
- collections.OrderedDict,
- collections.Counter,
- collections.ChainMap,
- collections.abc.Awaitable,
- collections.abc.Coroutine,
- collections.abc.AsyncIterable,
- collections.abc.AsyncIterator,
- collections.abc.AsyncGenerator,
- collections.abc.Iterable,
- collections.abc.Iterator,
- collections.abc.Generator,
- collections.abc.Reversible,
- collections.abc.Container,
- collections.abc.Collection,
- collections.abc.Callable,
- collections.abc.MutableSet,
- collections.abc.Mapping,
- collections.abc.MutableMapping,
- collections.abc.Sequence,
- collections.abc.MutableSequence,
- collections.abc.MappingView,
- collections.abc.KeysView,
- collections.abc.ItemsView,
- collections.abc.ValuesView,
- re.Pattern,
- re.Match,
- )
- },
+ tuple: typing.Tuple,
+ list: typing.List,
+ dict: typing.Dict,
+ set: typing.Set,
+ frozenset: typing.FrozenSet,
+ type: typing.Type,
+ collections.deque: typing.Deque,
+ collections.defaultdict: typing.DefaultDict,
+ collections.abc.Set: typing.AbstractSet,
+ contextlib.AbstractContextManager: typing.ContextManager,
+ contextlib.AbstractAsyncContextManager: typing.AsyncContextManager,
+ **{k: getattr(typing, k.__name__) for k in _generic_type_origins},
}
+def safe_or(a: Any, b: Any) -> Any:
+ try:
+ return a | b
+ except TypeError as e:
+ if not is_unsupported_types_for_union_error(e):
+ raise
+ union = typing.Union
+ return union[a, b]
+
+
+def safe_subscript(value: Any, index: Any) -> Any:
+ try:
+ return value[index]
+ except TypeError as e:
+ if not is_not_subscriptable_error(e):
+ raise
+ if value not in new_generic_types:
+ raise
+ new_value = new_generic_types[value]
+ return new_value[index]
+
+
class BackportTransformer(ast.NodeTransformer):
"""
Transforms `X | Y` into `typing.Union[X, Y]`
@@ -94,81 +116,57 @@
elif localns is None:
localns = globalns
- self.typing_name = f'typing_{uuid.uuid4().hex}'
+ self.safe_or_name = f'safe_or_{uuid.uuid4().hex}'
+ self.safe_subscript_name = f'safe_subscript_{uuid.uuid4().hex}'
self.globalns = globalns
- self.localns = {**localns, self.typing_name: typing}
+ self.localns = {
+ **localns,
+ self.safe_or_name: safe_or,
+ self.safe_subscript_name: safe_subscript,
+ }
def eval_type(
self,
- node: ast.Expression | ast.expr,
- *,
- original_ref: typing.ForwardRef | None = None,
+ node: ast.Expression,
+ original_ref: typing.ForwardRef,
) -> Any:
- if not isinstance(node, ast.Expression):
- node = ast.copy_location(ast.Expression(node), node)
ref = typing.ForwardRef(ast.dump(node))
- if original_ref:
- for attr in 'is_argument is_class module'.split():
- attr = f'__forward_{attr}__'
- if hasattr(original_ref, attr):
- setattr(ref, attr, getattr(original_ref, attr))
+ for attr in 'is_argument is_class module'.split():
+ attr = f'__forward_{attr}__'
+ if hasattr(original_ref, attr):
+ setattr(ref, attr, getattr(original_ref, attr))
ref.__forward_code__ = compile(node, '<node>', 'eval')
return typing._eval_type( # type: ignore
ref, self.globalns, self.localns
)
- def visit_BinOp(self, node) -> ast.BinOp | ast.Subscript:
+ def _call(self, func_name: str, args: list[ast.expr]) -> ast.Call:
+ return ast.fix_missing_locations(
+ ast.Call(
+ func=ast.Name(id=func_name, ctx=ast.Load()),
+ args=args,
+ keywords=[],
+ )
+ )
+
+ def visit_BinOp(self, node) -> ast.BinOp | ast.Call:
node = self.generic_visit(node)
assert isinstance(node, ast.BinOp)
- if isinstance(node.op, ast.BitOr):
- left_val = self.eval_type(node.left)
- right_val = self.eval_type(node.right)
- try:
- _ = left_val | right_val
- except TypeError as e:
- if not is_unsupported_types_for_union_error(e):
- raise
- # Replace `left | right` with `typing.Union[left, right]`
- replacement = ast.Subscript(
- value=ast.Attribute(
- value=ast.Name(id=self.typing_name, ctx=ast.Load()),
- attr='Union',
- ctx=ast.Load(),
- ),
- slice=ast.Index(
- value=ast.Tuple(elts=[node.left, node.right],
ctx=ast.Load())
- ),
- ctx=ast.Load(),
- )
- return ast.fix_missing_locations(replacement)
+ if not isinstance(node.op, ast.BitOr):
+ return node
- return node
+ return self._call(self.safe_or_name, [node.left, node.right])
if sys.version_info[:2] < (3, 9):
- def visit_Subscript(self, node) -> ast.Subscript:
+ def visit_Subscript(self, node) -> ast.Subscript | ast.Call:
node = self.generic_visit(node)
assert isinstance(node, ast.Subscript)
- try:
- value_val = self.eval_type(node.value)
- except TypeError:
- # Likely typing._type_check complaining that the result isn't
a type,
- # e.g. that it's a plain `Literal`.
- # Either way, this probably isn't one of the new generic types
- # that needs replacing.
- return node
- if value_val not in new_generic_types:
+ if not isinstance(node.slice, ast.Index):
return node
- replacement = ast.Subscript(
- value=ast.Attribute(
- value=ast.Name(id=self.typing_name, ctx=ast.Load()),
- attr=new_generic_types[value_val],
- ctx=ast.Load(),
- ),
- slice=node.slice,
- ctx=ast.Load(),
- )
- return ast.fix_missing_locations(replacement)
+
+ slice_value = node.slice.value # type: ignore
+ return self._call(self.safe_subscript_name, [node.value,
slice_value])
original_evaluate = typing.ForwardRef._evaluate
@@ -188,7 +186,7 @@
"""
@functools.wraps(original_evaluate)
- def _evaluate(
+ def _evaluate( # pyright: ignore[reportIncompatibleMethodOverride]
self,
globalns: dict[str, Any] | None,
localns: dict[str, Any] | None,
@@ -215,7 +213,8 @@
if sys.version_info[:2] >= (3, 10):
- def eval_type_backport(
+
+ def eval_type_backport( # type: ignore # allow duplicate declaration
value: Any,
globalns: dict[str, Any] | None = None,
localns: Mapping[str, Any] | None = None,
@@ -252,3 +251,12 @@
):
raise
return _eval_direct(value, globalns, localns)
+
+
+def install_patch() -> None:
+ """Monkey-patch `typing.ForwardRef._evaluate` to support newer syntax on
older Python versions.
+
+ This indirectly makes functions like `typing.get_type_hints` and
`typing._eval_type` work as well.
+ """
+ if sys.version_info[:2] < (3, 10):
+ typing.ForwardRef._evaluate = ForwardRef._evaluate # type: ignore
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/eval_type_backport-0.3.1/eval_type_backport/version.py
new/eval_type_backport-0.4.0/eval_type_backport/version.py
--- old/eval_type_backport-0.3.1/eval_type_backport/version.py 2025-12-02
12:51:37.000000000 +0100
+++ new/eval_type_backport-0.4.0/eval_type_backport/version.py 2026-06-02
15:22:01.000000000 +0200
@@ -1 +1 @@
-__version__ = '0.3.1'
\ No newline at end of file
+__version__ = '0.4.0'
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/eval_type_backport-0.3.1/eval_type_backport.egg-info/PKG-INFO
new/eval_type_backport-0.4.0/eval_type_backport.egg-info/PKG-INFO
--- old/eval_type_backport-0.3.1/eval_type_backport.egg-info/PKG-INFO
2025-12-02 12:51:37.000000000 +0100
+++ new/eval_type_backport-0.4.0/eval_type_backport.egg-info/PKG-INFO
2026-06-02 15:22:01.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.4
+Metadata-Version: 2.1
Name: eval_type_backport
-Version: 0.3.1
+Version: 0.4.0
Summary: Like `typing._eval_type`, but lets older Python versions use newer
typing features.
Home-page: https://github.com/alexmojaki/eval_type_backport
Author: Alex Hall
@@ -22,20 +22,40 @@
License-File: LICENSE.txt
Provides-Extra: tests
Requires-Dist: pytest; extra == "tests"
-Dynamic: license-file
# eval_type_backport
[](https://github.com/alexmojaki/eval_type_backport/actions)
[](https://coveralls.io/github/alexmojaki/eval_type_backport)
[](https://pypi.python.org/pypi/eval_type_backport)
[](https://anaconda.org/conda-forge/eval-type-backport)
-This is a tiny package providing a replacement for `typing._eval_type` to
support newer typing features in older Python versions.
-
-Yes, that's very specific, and yes, `typing._eval_type` is a protected
function that you shouldn't normally be using. Really this package is
specifically made for https://github.com/pydantic/pydantic/issues/7873.
-
+This package makes runtime typing inspection with the `typing` module possible
with newer syntax in older Python versions.
Specifically, this transforms `X | Y` into `typing.Union[X, Y]`
and `list[X]` into `typing.List[X]` etc. (for all the types made generic in
PEP 585)
if the original syntax is not supported in the current Python version.
+For users of Pydantic, merely having this package installed should make
Pydantic models with newer syntax work in older Python versions.
+
+Here's an example of how to use it directly:
+
+```python
+import typing
+
+from eval_type_backport import install_patch
+
+install_patch()
+
+
+class Foo:
+ a: 'int | str'
+
+
+print(typing.get_type_hints(Foo))
+```
+
+In Python 3.9, without the `install_patch`, the above code will raise
`TypeError: unsupported operand type(s) for |: 'type' and 'type'`.
+With it, it prints `{'a': typing.Union[int, str]}` as expected.
+
+`install_patch` monkey-patches the `typing` module so that things should 'just
work' from wherever. To specifically use the backport where you need it instead
of patching globally, you can use the `eval_type_backport.eval_type_backport`
function directly instead of `typing._eval_type`. Yes, `typing._eval_type` is a
protected function that you shouldn't normally be using. This package was
written to support Pydantic, which uses it internally.
+
## Install
From PyPI:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/eval_type_backport-0.3.1/pyproject.toml
new/eval_type_backport-0.4.0/pyproject.toml
--- old/eval_type_backport-0.3.1/pyproject.toml 2024-07-07 23:49:24.000000000
+0200
+++ new/eval_type_backport-0.4.0/pyproject.toml 2026-06-02 15:20:20.000000000
+0200
@@ -7,13 +7,14 @@
write_to_template = "__version__ = '{version}'"
[tool.pyright]
+include = ["eval_type_backport", "tests"]
venvPath = "."
venv = "venv"
[tool.ruff]
line-length = 89
-flake8-quotes = {inline-quotes = 'single', multiline-quotes = 'double'}
-mccabe = { max-complexity = 14 }
+lint.flake8-quotes = {inline-quotes = 'single', multiline-quotes = 'double'}
+lint.mccabe = { max-complexity = 14 }
target-version = "py38"
[tool.ruff.format]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/eval_type_backport-0.3.1/tests/test_eval_type_backport.py
new/eval_type_backport-0.4.0/tests/test_eval_type_backport.py
--- old/eval_type_backport-0.3.1/tests/test_eval_type_backport.py
2024-12-21 21:10:54.000000000 +0100
+++ new/eval_type_backport-0.4.0/tests/test_eval_type_backport.py
2026-05-28 20:49:00.000000000 +0200
@@ -8,8 +8,9 @@
import pytest
-from eval_type_backport import ForwardRef, eval_type_backport
-from eval_type_backport.eval_type_backport import new_generic_types
+import eval_type_backport as eval_type_backport_module
+from eval_type_backport import ForwardRef, eval_type_backport, install_patch
+from eval_type_backport.eval_type_backport import new_generic_types,
safe_subscript
str((collections, contextlib, re)) # mark these as used (by eval calls)
@@ -136,6 +137,11 @@
pass
+class OtherSubscriptError:
+ def __class_getitem__(cls, item):
+ raise TypeError('other')
+
+
def test_other_or_type_error():
for code in [
'Foo | (int | str)',
@@ -182,7 +188,7 @@
assert args == t.get_args(expected_new)
assert origin == t.get_origin(expected_new)
assert origin[args] == expected_new != expected_old
- assert t.get_origin(getattr(t, new_generic_types[origin])) ==
origin
+ assert t.get_origin(new_generic_types[origin]) == origin
else:
assert eval_type_backport(ref, **kwargs) == expected_old
@@ -354,6 +360,42 @@
t.Match[str],
)
+ assert eval_type_backport(ForwardRef('tuple[(int, str)[:]]')) ==
eval_type_backport(
+ ForwardRef('tuple[int, str]')
+ )
+
+
+def test_unsupported_subscript_type_error():
+ with pytest.raises(TypeError, match='subscriptable'):
+ eval_type_backport(
+ ForwardRef('Foo[int]'),
+ globalns=globals(),
+ localns=locals(),
+ )
+
+
+def test_subscript_other_error():
+ with pytest.raises(TypeError, match='other'):
+ eval_type_backport(
+ ForwardRef('OtherSubscriptError[int]'),
+ globalns=globals(),
+ localns=locals(),
+ try_default=False,
+ )
+
+
+def test_safe_subscript():
+ if sys.version_info[:2] < (3, 9):
+ assert safe_subscript(list, int) == t.List[int]
+ else:
+ assert safe_subscript(list, int) == list[int]
+
+ with pytest.raises(TypeError, match='subscriptable'):
+ safe_subscript(Foo(), int)
+
+ with pytest.raises(TypeError, match='other'):
+ safe_subscript(OtherSubscriptError, int)
+
def test_copy_forward_ref_attrs():
ref = t.ForwardRef(
@@ -362,3 +404,22 @@
**({} if sys.version_info < (3, 9, 8) else {'is_class': True}),
)
eval_type_backport(ref, globalns=globals(), localns=locals())
+
+
+def test_install_patch_supports_get_type_hints():
+ assert 'install_patch' in eval_type_backport_module.__all__
+ assert eval_type_backport_module.install_patch is install_patch
+
+ class Foo:
+ value: int | str
+
+ original_evaluate = t.ForwardRef._evaluate
+ try:
+ install_patch()
+ assert t.get_type_hints(Foo) == {'value': t.Union[int, str]}
+ if sys.version_info[:2] < (3, 10):
+ assert t.ForwardRef._evaluate is ForwardRef._evaluate
+ else:
+ assert t.ForwardRef._evaluate is original_evaluate
+ finally:
+ t.ForwardRef._evaluate = original_evaluate