Skip to content

Commit 29ad827

Browse files
authored
⬆️ dep-bump(python): 3.11+ (#75)
* ⬆️ dep-bump(python): 3.11+ * ➕ dep-add: optype * 💥 boom: replace CanCopyReplace with CanReplace Signed-off-by: nstarman <nstarman@users.noreply.github.com>
1 parent c1bbc41 commit 29ad827

9 files changed

Lines changed: 421 additions & 571 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
strategy:
3939
fail-fast: false
4040
matrix:
41-
python-version: ["3.10", "3.11", "3.12", "3.13"]
41+
python-version: ["3.11", "3.12", "3.13"]
4242
runs-on: [ubuntu-latest, macos-latest, windows-latest]
4343

4444
steps:
@@ -61,14 +61,14 @@ jobs:
6161
with:
6262
token: ${{ secrets.CODECOV_TOKEN }}
6363

64-
check_oldest:
64+
test_oldest:
6565
name: Check Oldest Dependencies
6666
runs-on: ${{ matrix.runs-on }}
6767
needs: [format]
6868
strategy:
6969
fail-fast: false
7070
matrix:
71-
python-version: ["3.10"]
71+
python-version: ["3.11"]
7272
runs-on: [ubuntu-latest]
7373

7474
steps:
@@ -92,7 +92,7 @@ jobs:
9292
status:
9393
name: CI Pass
9494
runs-on: ubuntu-latest
95-
needs: [format, tests, check_oldest]
95+
needs: [format, tests, test_oldest]
9696
if: always()
9797
steps:
9898
- name: All required jobs passed

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.10
1+
3.11

pyproject.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@ classifiers = [
1111
"Programming Language :: Python",
1212
"Programming Language :: Python :: 3",
1313
"Programming Language :: Python :: 3 :: Only",
14-
"Programming Language :: Python :: 3.10",
1514
"Programming Language :: Python :: 3.11",
1615
"Programming Language :: Python :: 3.12",
1716
"Programming Language :: Python :: 3.13",
1817
"Topic :: Scientific/Engineering",
1918
"Typing :: Typed",
2019
]
21-
dependencies = ["plum-dispatch>=2.5.1", "typing_extensions>=4.12.2"]
20+
dependencies = [
21+
"optype>=0.16.0",
22+
"plum-dispatch>=2.5.1",
23+
"typing_extensions>=4.12.2",
24+
]
2225
description = "dataclass tools, extended by multiple dispatch"
2326
dynamic = ["version"]
2427
license.file = "LICENSE"
2528
name = "dataclassish"
2629
readme = "README.md"
27-
requires-python = ">=3.10"
30+
requires-python = ">=3.11"
2831

2932
[project.urls]
3033
"Bug Tracker" = "https://github.com/GalacticDynamics/dataclassish/issues"
@@ -84,7 +87,7 @@ disallow_incomplete_defs = false
8487
disallow_untyped_defs = false
8588
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
8689
files = ["src"]
87-
python_version = "3.10"
90+
python_version = "3.11"
8891
strict = true
8992
warn_unreachable = true
9093
warn_unused_configs = true

src/dataclassish/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"field_items",
2020
# Classes
2121
"DataclassInstance",
22-
"CanCopyReplace",
2322
"F",
2423
)
2524

@@ -34,7 +33,7 @@
3433
get_field,
3534
replace,
3635
)
37-
from ._src.types import CanCopyReplace, DataclassInstance, F
36+
from ._src.types import DataclassInstance, F
3837
from ._version import version as __version__
3938

4039
# Register dispatches by importing the submodules

src/dataclassish/_src/converters.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@
2727
Any,
2828
ClassVar,
2929
Generic,
30+
NotRequired,
3031
Protocol,
3132
TypedDict,
3233
TypeVar,
3334
cast,
3435
overload,
3536
)
36-
from typing_extensions import NotRequired, dataclass_transform
37+
from typing_extensions import dataclass_transform
3738

3839
ArgT = TypeVar("ArgT") # Input type
3940
RetT = TypeVar("RetT") # Return type

src/dataclassish/_src/flag_compat.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
from collections.abc import Iterable
66
from dataclasses import Field
7-
from typing import Any, cast
8-
from typing_extensions import Never
7+
from typing import Any, Never, cast
98

109
from plum import dispatch
1110

src/dataclassish/_src/register_copyreplace.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Register dispatches for CanCopyReplace objects."""
1+
"""Register dispatches for CanReplace objects."""
22

33
__all__: tuple[str, ...] = ()
44

@@ -7,17 +7,17 @@
77
from collections.abc import Mapping
88
from typing import Any
99

10+
import optype as opt
1011
from plum import dispatch
1112

1213
from .register_base import _recursive_replace_helper
13-
from .types import CanCopyReplace
1414

1515
# ===================================================================
1616
# Get field
1717

1818

1919
@dispatch
20-
def get_field(obj: CanCopyReplace, k: str, /) -> Any:
20+
def get_field(obj: opt.copy.CanReplaceSelf, k: str, /) -> Any:
2121
"""Get a field of a dataclass instance by name.
2222
2323
Examples:
@@ -65,7 +65,7 @@ def get_field(obj: CanCopyReplace, k: str, /) -> Any:
6565

6666

6767
@dispatch
68-
def replace(obj: CanCopyReplace, /, **kwargs: Any) -> CanCopyReplace:
68+
def replace(obj: opt.copy.CanReplaceSelf, /, **kwargs: Any) -> opt.copy.CanReplaceSelf:
6969
"""Replace the fields of an object.
7070
7171
Examples:
@@ -133,7 +133,9 @@ def replace(obj: CanCopyReplace, /, **kwargs: Any) -> CanCopyReplace:
133133

134134

135135
@dispatch # type: ignore[no-redef]
136-
def replace(obj: CanCopyReplace, fs: Mapping[str, Any], /) -> CanCopyReplace:
136+
def replace(
137+
obj: opt.copy.CanReplaceSelf, fs: Mapping[str, Any], /
138+
) -> opt.copy.CanReplaceSelf:
137139
"""Replace the fields of a dataclass instance.
138140
139141
Examples:

src/dataclassish/_src/types.py

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
"""Data types for ``dataclassish``."""
22

3-
__all__ = ("DataclassInstance", "CanCopyReplace", "F")
3+
__all__ = ("DataclassInstance", "F")
44

55
from dataclasses import dataclass
66
from typing import Any, ClassVar, Generic, Protocol, TypeVar, runtime_checkable
7-
from typing_extensions import Self
87

98

109
@runtime_checkable
@@ -72,65 +71,3 @@ class F(Generic[V]):
7271
"""
7372

7473
value: V
75-
76-
77-
# ===================================================================
78-
79-
80-
@runtime_checkable
81-
class CanCopyReplace(Protocol):
82-
"""Protocol for objects that implement the ``__replace__`` method.
83-
84-
This is used by ``copy.replace`` (Python 3.13+) to replace fields of an
85-
object. This is a generalization of the ``dataclasses.replace`` function.
86-
87-
Examples
88-
--------
89-
>>> from dataclassish import CanCopyReplace
90-
91-
>>> class Point:
92-
... def __init__(self, x, y):
93-
... self.x = x
94-
... self.y = y
95-
... def __replace__(self, **changes):
96-
... return Point(**(self.__dict__ | changes))
97-
... def __repr__(self):
98-
... return f"Point(x={self.x}, y={self.y})"
99-
100-
>>> issubclass(Point, CanCopyReplace)
101-
True
102-
103-
>>> point = Point(1.0, 2.0)
104-
>>> isinstance(point, CanCopyReplace)
105-
True
106-
107-
The ``__replace__`` method was introduced in Python 3.13 to bring
108-
``dataclasses.replace``-like functionality to any implementing object. The
109-
method is publicly exposed via the ``copy.replace`` function.
110-
111-
% invisible-code-block: python
112-
%
113-
% import sys
114-
115-
% skip: start if(sys.version_info < (3, 13), reason="py3.13+")
116-
117-
>>> import copy
118-
>>> copy.replace(point, x=3.0)
119-
Point(x=3.0, y=2.0)
120-
121-
% skip: end
122-
123-
"""
124-
125-
def __replace__(self: Self, /, **changes: Any) -> Self:
126-
"""Replace the fields of the object.
127-
128-
This method should return a new object with the fields replaced.
129-
130-
Args:
131-
**changes: Field names and their new values.
132-
133-
Returns:
134-
A new object with the specified fields replaced.
135-
136-
"""

0 commit comments

Comments
 (0)