copium 0.1.dev1__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of copium might be problematic. Click here for more details.

copium/__about__.pyi ADDED
@@ -0,0 +1,23 @@
1
+ """Version information."""
2
+
3
+ from typing import Literal, NamedTuple, TypeVar, Final, Generic
4
+
5
+ NameT = TypeVar("NameT")
6
+ EmailT = TypeVar("EmailT")
7
+
8
+ class Author(NamedTuple, Generic[NameT, EmailT]):
9
+ name: NameT
10
+ email: EmailT
11
+
12
+ class VersionInfo(NamedTuple):
13
+ major: int
14
+ minor: int
15
+ patch: int
16
+ prerelease: str | None
17
+ build: int | None
18
+
19
+ __version__: str
20
+ __version_tuple__: VersionInfo
21
+ __commit_id__: str | None
22
+
23
+ __authors__: Final[tuple[Author[Literal["Arseny Boykov (Bobronium)"], Literal["hi@bobronium.me"]]]]
copium/__init__.pyi ADDED
@@ -0,0 +1,31 @@
1
+ import sys
2
+ from copy import Error
3
+ from typing import Any, TypeVar
4
+
5
+ __all__ = ["copy", "deepcopy", "Error"]
6
+
7
+ T = TypeVar("T")
8
+
9
+ def copy(x: T) -> T:
10
+ """
11
+ Natively compiled copy.
12
+
13
+ :param x: object to copy.
14
+ :return: shallow copy of the `x`.
15
+ """
16
+
17
+ def deepcopy(x: T, memo: dict[int, Any] | None = None) -> T:
18
+ """
19
+ Natively compiled deepcopy.
20
+
21
+ :param x: object to deepcopy
22
+ :param memo: treat as opaque.
23
+ :return: deep copy of the `x`.
24
+ """
25
+
26
+ if sys.version_info >= (3, 13):
27
+ def replace(obj: T, /, **changes: Any) -> T:
28
+ """
29
+ Creates a new object of the same type as obj, replacing fields with values from changes.
30
+ """
31
+ __all__.append("replace")
copium/extra.pyi ADDED
@@ -0,0 +1,20 @@
1
+ from typing import Callable
2
+ from typing import TypeVar
3
+
4
+ __all__ = ["repeatcall", "replicate"]
5
+
6
+ T = TypeVar("T")
7
+
8
+ def repeatcall(function: Callable[[], T], size: int, /) -> list[T]:
9
+ """
10
+ Call function repeatedly size times and return the list of results.
11
+
12
+ Equivalent of [function() for _ in range(size)], but faster.
13
+ """
14
+
15
+ def replicate(obj: T, /, n: int) -> list[T]:
16
+ """
17
+ Returns n copies of the object in a list.
18
+
19
+ Equivalent of [deepcopy(obj) for _ in range(n)], but faster.
20
+ """
copium/patch.pyi ADDED
@@ -0,0 +1,16 @@
1
+ __all__ = ["enable", "disable", "enabled"]
2
+
3
+ def enable() -> bool:
4
+ """
5
+ :return: True if copium was enabled, False if it was already enabled.
6
+ """
7
+
8
+ def disable() -> bool:
9
+ """
10
+ :return: True if copium was disabled, False if it was already disabled.
11
+ """
12
+
13
+ def enabled() -> bool:
14
+ """
15
+ :return: Whether copium is currently enabled.
16
+ """
copium/py.typed ADDED
File without changes
@@ -0,0 +1,242 @@
1
+ Metadata-Version: 2.4
2
+ Name: copium
3
+ Version: 0.1.dev1
4
+ Summary: Fastest deepcopy implementation for CPython
5
+ Author-email: "Arseny Boykov (Bobronium)" <hi@bobronium.me>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Bobronium/copium
8
+ Project-URL: Source, https://github.com/Bobronium/copium
9
+ Project-URL: Issues, https://github.com/Bobronium/copium/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Development Status :: 3 - Alpha
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: dev
24
+ Requires-Dist: copium[lint]; extra == "dev"
25
+ Requires-Dist: copium[typecheck]; extra == "dev"
26
+ Requires-Dist: copium[test]; extra == "dev"
27
+ Requires-Dist: copium[docs]; extra == "dev"
28
+ Provides-Extra: lint
29
+ Requires-Dist: ruff>=0.5; extra == "lint"
30
+ Provides-Extra: typecheck
31
+ Requires-Dist: mypy>=1.10; extra == "typecheck"
32
+ Requires-Dist: pyright>=1.1.400; extra == "typecheck"
33
+ Requires-Dist: zuban>=0.2.0; extra == "typecheck"
34
+ Requires-Dist: pytest; extra == "typecheck"
35
+ Provides-Extra: test
36
+ Requires-Dist: pytest>=8; extra == "test"
37
+ Requires-Dist: pytest-assert-type>=0.1.5; extra == "test"
38
+ Requires-Dist: indifference>=0.1.0; extra == "test"
39
+ Requires-Dist: typing-extensions; python_version < "3.12" and extra == "test"
40
+ Requires-Dist: datamodelzoo; extra == "test"
41
+ Provides-Extra: docs
42
+ Requires-Dist: mkdocs-material; extra == "docs"
43
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
44
+ Requires-Dist: mkdocs-autorefs; extra == "docs"
45
+ Requires-Dist: mkdocs-section-index; extra == "docs"
46
+ Provides-Extra: benchmark
47
+ Requires-Dist: tyro>=0.9.33; extra == "benchmark"
48
+ Requires-Dist: pyperf>=2.9.0; extra == "benchmark"
49
+ Requires-Dist: ipython>=8.37.0; extra == "benchmark"
50
+ Requires-Dist: datamodelzoo; extra == "benchmark"
51
+ Provides-Extra: build
52
+ Requires-Dist: build>=1.3.0; extra == "build"
53
+ Requires-Dist: cibuildwheel>=2.23.3; extra == "build"
54
+ Requires-Dist: pip>=25.3; extra == "build"
55
+ Requires-Dist: setuptools>=80.9.0; extra == "build"
56
+ Requires-Dist: setuptools-scm>=9.2.2; extra == "build"
57
+ Requires-Dist: wheel>=0.45.1; extra == "build"
58
+ Dynamic: license-file
59
+
60
+ # copium
61
+
62
+ [![image](https://img.shields.io/pypi/v/copium.svg)](https://pypi.python.org/pypi/copium)
63
+ [![image](https://img.shields.io/pypi/l/copium.svg)](https://pypi.python.org/pypi/copium)
64
+ [![image](https://img.shields.io/pypi/pyversions/copium.svg)](https://pypi.python.org/pypi/copium)
65
+ [![Actions status](https://github.com/Bobronium/copium/actions/workflows/build.yml/badge.svg)](https://github.com/Bobronium/copium/actions)
66
+
67
+ An extremely fast Python copy/deepcopy implementation, written in C.
68
+
69
+ <div align="center">
70
+ <picture>
71
+ <source srcset="https://raw.githubusercontent.com/Bobronium/copium/main/assets/chart_dark.svg" media="(prefers-color-scheme: dark)">
72
+ <source srcset="https://raw.githubusercontent.com/Bobronium/copium/main/assets/chart_light.svg" media="(prefers-color-scheme: light)">
73
+ <img src="https://raw.githubusercontent.com/Bobronium/copium/main/assets/chart_light.svg" alt="Benchmark results bar chart">
74
+ </picture>
75
+ </div>
76
+
77
+ <div align="center">
78
+ <i>Getting a deep copy of <a href="https://github.com/python-jsonschema/jsonschema/blob/0798cd7a59caea669e2de2ecac9c6e2dfcb57f6d/jsonschema/validators.py#L812">jsonschema.Draft202012Validator.META_SCHEMA</a>.</i>
79
+ </div>
80
+
81
+ ## Highlights
82
+
83
+ - ~3x faster on mixed data
84
+ - ~6x faster on typical data
85
+ - [~30 faster in some cases](#benchmarks)
86
+ - [Requires **zero** code changes to adopt](#1-you-set-copium_patch_deepcopy1-before-launch)
87
+ - Passes all tests from `CPython/Lib/test/test_copy.py`
88
+
89
+ ## Installation
90
+
91
+ ```bash
92
+ pip install copium
93
+ ```
94
+
95
+ ## Usage
96
+
97
+ `copium` is designed to be drop-in replacement for `copy` module.
98
+
99
+ After installation deepcopy will be fast in either of 3 cases:
100
+
101
+ ##### 1) You set `COPIUM_PATCH_DEEPCOPY=1` before launch
102
+
103
+ ##### 2) You call `copium.patch.enable()` manually at launch
104
+
105
+ ##### 3) You use `copium.deepcopy()` directly
106
+
107
+ Generally any code that uses stdlib `copy` can be replaced with `copium` simply by:
108
+
109
+ ```diff
110
+ - from copy import deepcopy
111
+ + from copium import deepcopy
112
+ ```
113
+
114
+ Alternatively, you can import `copium.patch` once and enable it:
115
+
116
+ ```python
117
+ import copium.patch
118
+
119
+
120
+ copium.patch.enable()
121
+ ```
122
+
123
+ Or just `export COPIUM_PATCH_DEEPCOPY=1` before running your Python process.
124
+
125
+ This will automatically call `copium.patch.enable()` on start, and all calls to `copy.deepcopy()` will be forwarded to
126
+ `copium.deepcopy()`. On Python 3.12+ there's no performance overhead compared to direct
127
+ usage.
128
+
129
+ There are two main benefits of using `copium.patch`,
130
+
131
+ - It requires zero code changes
132
+ - It automatically makes any third party code that uses deepcopy faster, for
133
+ instance, it will speed up instantiations of pydantic
134
+ models with mutable defaults
135
+ \(see [pydantic_core](https://github.com/pydantic/pydantic-core/blob/f1239f81d944bcda84bffec64527d46f041ccc9e/src/validators/with_default.rs#L23)).
136
+
137
+ ## Caveats
138
+
139
+ - `copium.deepcopy()` ignores `sys.getrecursionlimit()`. It still may raise `RecursionError` at some point, but at much
140
+ larger depths than default interpreter recursion limit (see `tests.test_copium.test_recursion_error`)
141
+ - unless `memo` argument supplied as `dict` when calling `copium.deepcopy()`, special lightweight memo storage will be
142
+ used to reduce memoization overhead. It implements `MutableMapping` methods, so any custom `__deepcopy__` methods
143
+ should work as expected
144
+ - `copium.deepcopy()` will raise `TypeError` if `type(memo) is not dict` — if you're unsure what it means, don't worry —
145
+ you don't need to supply memo to deepcopy in the first place.
146
+ - `copium` uses unstable CPython API. This means that it might break on new major Python release
147
+
148
+ ## Benchmarks
149
+
150
+ A full benchmark suite is in progress and will be published soon.
151
+ In the meanwhile, you can reproduce the results shown in the chart above with this minimal script
152
+
153
+ <details>
154
+ <summary>Pyperf case</summary>
155
+
156
+ ```shell
157
+ cat > benchmark.py << 'PY'
158
+ # /// script
159
+ # requires-python = ">=3.10"
160
+ # dependencies = [
161
+ # "pyperf",
162
+ # "copium",
163
+ # ]
164
+ # ///
165
+ import pyperf
166
+
167
+ runner = pyperf.Runner()
168
+
169
+ setup = """
170
+ import copy
171
+ from decimal import Decimal
172
+
173
+ payload = {
174
+ "a": 1,
175
+ "b": (b := [(1, 2, 3), (4, 5, 6)]),
176
+ "c": [Decimal("3.14"), complex(), [], (), frozenset(), b],
177
+ }
178
+ """
179
+
180
+ runner.timeit(name="deepcopy", stmt=f"b=copy.deepcopy(payload)", setup=setup)
181
+ PY
182
+ ```
183
+
184
+ ```shell
185
+ uv run --python 3.14t benchmark.py -q -o copy3.14t.json && \
186
+ COPIUM_PATCH_DEEPCOPY=1 PYTHON_GIL=0 \
187
+ uv run --python 3.14t benchmark.py -q -o copium3.14t.json --copy-env && \
188
+ uvx pyperf compare_to copy3.14t.json copium3.14t.json --table
189
+ ```
190
+
191
+ Output:
192
+
193
+ ```shell
194
+ deepcopy: Mean +- std dev: 20.8 us +- 1.6 us
195
+ deepcopy: Mean +- std dev: 928 ns +- 11 ns
196
+ +--------------+---------+--------------------+
197
+ | Benchmark | copy | copium |
198
+ +===========+=========+=======================+
199
+ | deepcopy | 20.8 us | 928 ns: 22.40x faster |
200
+ +-----------+---------+-----------------------+
201
+ ```
202
+
203
+ ```shell
204
+ ❯ uv run --python 3.13 benchmark.py -q -o copy3.13.json && \
205
+ COPIUM_PATCH_DEEPCOPY=1 \
206
+ uv run --python 3.13 benchmark.py -q -o copium3.13.json --copy-env && \
207
+ uvx pyperf compare_to copy3.13.json copium3.13.json --table
208
+ ```
209
+
210
+ ```shell
211
+ deepcopy: Mean +- std dev: 10.8 us +- 0.9 us
212
+ deepcopy: Mean +- std dev: 880 ns +- 23 ns
213
+ +-----------+-----------+-----------------------+
214
+ | Benchmark | copy3.13t | copium3.13t |
215
+ +===========+===========+=======================+
216
+ | deepcopy | 10.8 us | 880 ns: 12.26x faster |
217
+ +-----------+-----------+-----------------------+
218
+ ```
219
+
220
+ ```shell
221
+ ❯ uv run --python 3.13t benchmark.py -q -o copy3.13t.json && \
222
+ COPIUM_PATCH_DEEPCOPY=1 PYTHON_GIL=0 \
223
+ uv run --python 3.13t benchmark.py -q -o copium3.13t.json --copy-env && \
224
+ uvx pyperf compare_to copy3.13t.json copium3.13t.json --table
225
+ ```
226
+
227
+ ```shell
228
+ deepcopy: Mean +- std dev: 29.0 us +- 6.7 us
229
+ deepcopy: Mean +- std dev: 942 ns +- 29 ns
230
+ +-----------+-----------+-----------------------+
231
+ | Benchmark | copy3.13t | copium3.13t |
232
+ +===========+===========+=======================+
233
+ | deepcopy | 29.0 us | 942 ns: 30.84x faster |
234
+ +-----------+-----------+-----------------------+
235
+ ```
236
+
237
+ </details>
238
+
239
+ ## Development
240
+
241
+ - Install Task: https://taskfile.dev
242
+ - All checks: `task` / `task MATRIX=1`
@@ -0,0 +1,12 @@
1
+ copium.cpython-310-x86_64-linux-gnu.so,sha256=0Aacpg4aSVX3e4SWpkqoLsC_RzFAzmoHJQ9JFJNA8dU,503824
2
+ copium_autopatch.pth,sha256=UcSx17eEUd8h7uYOesLl2XDMl1mR8YVEJUdkCZg-SHA,109
3
+ copium/__about__.pyi,sha256=264RED3QSme4aQgAMWMjysYqqxUNF5k56bFEY2NlUrA,532
4
+ copium/__init__.pyi,sha256=mZaGBbGEozD_sbTBpvFPvXGnC70mebTn2Rl2_zCRmVE,706
5
+ copium/extra.pyi,sha256=W8KY9J8DhEtNHSjRpt2SAlSrTkgKfb_Tnw226olbMBc,509
6
+ copium/patch.pyi,sha256=GMau568ksXVzookydYzrhC9Yo_gJdkDWI08QqCEFVLA,362
7
+ copium/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ copium-0.1.dev1.dist-info/METADATA,sha256=bq8aYsWi_6RBIGLlbAchY_wYbonCajYPpSYSLY_P1CU,8702
9
+ copium-0.1.dev1.dist-info/WHEEL,sha256=DZl4yYurviXJJQsilHH1qAzCRDsdz--oNtDZ-hUrZUk,190
10
+ copium-0.1.dev1.dist-info/top_level.txt,sha256=GZDlOGAVPhG7xdRAtxyamzeXrv8DCjarx47lcsT-XFI,7
11
+ copium-0.1.dev1.dist-info/RECORD,,
12
+ copium-0.1.dev1.dist-info/licenses/LICENSE,sha256=sFeF-fGOZxa6tjQksRRUUTuZQ6IiWVtwQRAJIC_FkrU,1078
@@ -0,0 +1,7 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-cp310-manylinux_2_17_x86_64
5
+ Tag: cp310-cp310-manylinux2014_x86_64
6
+ Tag: cp310-cp310-manylinux_2_28_x86_64
7
+
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) <year> <copyright holders>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ copium
Binary file
copium_autopatch.pth ADDED
@@ -0,0 +1 @@
1
+ import os, sys; os.environ.get('COPIUM_PATCH_DEEPCOPY') == '1' and __import__('copium.patch').patch.enable()