Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ jobs:
- name: "3.12"
python-version: "3.12"
extra-install: ""
- name: "3.12-pre-beartype"
python-version: "3.12"
extra-install: "uv pip install --upgrade --pre beartype"
- name: "3.13"
python-version: "3.13"
extra-install: ""
- name: "3.13-pre-beartype"
python-version: "3.13"
extra-install: "uv pip install --upgrade --pre beartype"
extra-install: "pip install --upgrade --pre beartype"
- name: "3.14"
python-version: "3.14"
extra-install: ""
- name: "3.14-pre-beartype"
python-version: "3.14"
extra-install: "pip install --upgrade --pre beartype"
Comment on lines +33 to +39
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The matrix extra-install uses pip install ... even though the job environment is managed via uv sync / uv run. Without activating the venv, pip may install outside the uv environment, so the pre-beartype runs might not actually test against the pre-release beartype. Use uv pip install --upgrade --pre beartype (or uv run python -m pip ...) to ensure the install lands in the environment used by the subsequent uv run pytest.

Suggested change
extra-install: "pip install --upgrade --pre beartype"
- name: "3.14"
python-version: "3.14"
extra-install: ""
- name: "3.14-pre-beartype"
python-version: "3.14"
extra-install: "pip install --upgrade --pre beartype"
extra-install: "uv pip install --upgrade --pre beartype"
- name: "3.14"
python-version: "3.14"
extra-install: ""
- name: "3.14-pre-beartype"
python-version: "3.14"
extra-install: "uv pip install --upgrade --pre beartype"

Copilot uses AI. Check for mistakes.

name: Test ${{ matrix.value.name }}
steps:
Expand Down
3 changes: 0 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ ci:
autoupdate_commit_msg: "chore: update pre-commit hooks"
autofix_commit_msg: "style: pre-commit fixes"

default_language_version:
python: "3.10"

repos:
- repo: meta
hooks:
Expand Down
23 changes: 23 additions & 0 deletions docs/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,27 @@ def f(x: int, y: Number):
return "second"
```

% invisible-code-block: python
%
% import sys

% skip: start if(sys.version_info < (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> try: f(1, 1)
... except Exception as e: print(f"{type(e).__name__}: {e}")
AmbiguousLookupError: `f(1, 1)` is ambiguous.
Candidates:
f(x: int | numbers.Number, y: int)
<function f at ...> @ ...
f(x: int, y: numbers.Number)
<function f at ...> @ ...
```

% skip: end

% skip: start if(sys.version_info >= (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> try: f(1, 1)
... except Exception as e: print(f"{type(e).__name__}: {e}")
Expand All @@ -96,6 +117,8 @@ Candidates:
<function f at ...> @ ...
```

% skip: end

Just to sanity check that things are indeed working correctly:

```python
Expand Down
53 changes: 50 additions & 3 deletions docs/union_aliases.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ by aliasing a union, you change the way it is displayed.
Union aliases must be activated explicitly, because the feature
monkeypatches `Union.__str__` and `Union.__repr__`.
Comment on lines 41 to 42
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph implies union aliases must be activated because they monkeypatch Union.__str__/__repr__, but on Python 3.14+ activate_union_aliases is deprecated and Union repr can’t be monkeypatched. Consider rewording to make the behavior/version split explicit (e.g., activation required only on <=3.13; on 3.14+ aliasing affects Plum’s own formatting only).

Suggested change
Union aliases must be activated explicitly, because the feature
monkeypatches `Union.__str__` and `Union.__repr__`.
On Python 3.13 and earlier, union aliases work by monkeypatching
`typing.Union.__str__` and `typing.Union.__repr__`, and therefore must be
activated explicitly.
On Python 3.14 and later, `typing.Union`'s representation can no longer be
monkeypatched and `activate_union_aliases()` is deprecated; union aliases
instead only affect how Plum formats unions in its own output.

Copilot uses AI. Check for mistakes.

% invisible-code-block: python
%
% import sys

% skip: start if(sys.version_info < (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> from plum import set_union_alias
>>> set_union_alias(Scalar, alias="Scalar")
numpy.bool | numpy.float16 | ...
```

% skip: end

% skip: start if(sys.version_info >= (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> from plum import activate_union_aliases, set_union_alias

Expand All @@ -50,6 +66,8 @@ monkeypatches `Union.__str__` and `Union.__repr__`.
typing.Union[Scalar]
```

% skip: end

After this, `help(add)` now prints the following:

% skip: next "Example"
Expand All @@ -68,6 +86,30 @@ For example, printing just `Scalar` would omit the type parameter(s).

Let's see with a few more examples how this works:

% invisible-code-block: python
%
% import sys

% skip: start if(sys.version_info < (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> Scalar
numpy.bool | numpy.float16 | ...

>>> Union[tuple(scalar_types)]
numpy.bool | numpy.float16 | ...

>>> Union[tuple(scalar_types) + (tuple,)] # Scalar or tuple
numpy.bool | numpy.float16 | ... | tuple

>>> Union[tuple(scalar_types) + (tuple, list)] # Scalar or tuple or list
numpy.bool | numpy.float16 | ... | tuple | list
```

% skip: end

% skip: start if(sys.version_info >= (3, 14), reason="Union repr changed in Python 3.14+")

```python
>>> Scalar
typing.Union[Scalar]
Expand All @@ -76,12 +118,14 @@ typing.Union[Scalar]
typing.Union[Scalar]

>>> Union[tuple(scalar_types) + (tuple,)] # Scalar or tuple
typing.Union[Scalar, tuple]
typing.Union[Scalar, tuple]

>>> Union[tuple(scalar_types) + (tuple, list)] # Scalar or tuple or list
typing.Union[Scalar, tuple, list]
typing.Union[Scalar, tuple, list]
Comment on lines 120 to +124
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two output lines in this code block have leading whitespace before typing.Union[...] (note the extra space). That will likely cause doctest/sybil output matching to fail and also looks unintentional; remove the leading space(s).

Copilot uses AI. Check for mistakes.
```

% skip: end

If we don't include all of `scalar_types`, we won't see `Scalar`, as desired:

% invisible-code-block: python
Expand All @@ -98,9 +142,12 @@ typing.Union[numpy.int8, numpy.int16, numpy.int32, numpy.longlong, numpy.int64,
You can deactivate union aliases with `deactivate_union_aliases`:

```python
>>> import warnings
>>> from plum import deactivate_union_aliases

>>> deactivate_union_aliases()
>>> with warnings.catch_warnings():
... warnings.simplefilter("ignore")
... deactivate_union_aliases()

% skip: next "Result depends on NumPy version."
>>> Scalar
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ dynamic = ["version"]

requires-python = ">=3.10"
dependencies = [
"beartype>=0.16.2",
"beartype>=0.22.2; python_version>='3.14'",
"beartype>=0.16.2; python_version<'3.14'",
"typing-extensions>=4.9.0",
"rich>=10.0"
]
Expand Down
Loading