circuitpython-functools 2.0.3__tar.gz → 3.0.0__tar.gz

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.
Files changed (46) hide show
  1. circuitpython_functools-3.0.0/.github/workflows/codecov.yml +43 -0
  2. {circuitpython_functools-2.0.3/circuitpython_functools.egg-info → circuitpython_functools-3.0.0}/PKG-INFO +1 -1
  3. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0/circuitpython_functools.egg-info}/PKG-INFO +1 -1
  4. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/SOURCES.txt +7 -1
  5. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.py +68 -2
  6. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/pyproject.toml +1 -1
  7. circuitpython_functools-3.0.0/tests/test_cache.py +34 -0
  8. circuitpython_functools-3.0.0/tests/test_lru_cache.py +165 -0
  9. circuitpython_functools-3.0.0/tests/test_partial.py +26 -0
  10. circuitpython_functools-3.0.0/tests/test_total_ordering.py +124 -0
  11. circuitpython_functools-3.0.0/tests/test_wraps.py +28 -0
  12. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +0 -0
  13. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/dependabot.yml +0 -0
  14. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/build.yml +0 -0
  15. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/failure-help-text.yml +0 -0
  16. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_gh.yml +0 -0
  17. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_pypi.yml +0 -0
  18. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.gitignore +0 -0
  19. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.pre-commit-config.yaml +0 -0
  20. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.readthedocs.yaml +0 -0
  21. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/CODE_OF_CONDUCT.md +0 -0
  22. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSE-MIT +0 -0
  23. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSE-PSF +0 -0
  24. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/CC-BY-4.0.txt +0 -0
  25. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/MIT.txt +0 -0
  26. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/PSF-2.0.txt +0 -0
  27. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/Unlicense.txt +0 -0
  28. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/README.rst +0 -0
  29. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/README.rst.license +0 -0
  30. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/dependency_links.txt +0 -0
  31. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/requires.txt +0 -0
  32. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/top_level.txt +0 -0
  33. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/_static/favicon.ico +0 -0
  34. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/_static/favicon.ico.license +0 -0
  35. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/api.rst +0 -0
  36. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/api.rst.license +0 -0
  37. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/conf.py +0 -0
  38. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/examples.rst +0 -0
  39. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/examples.rst.license +0 -0
  40. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/index.rst +0 -0
  41. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/index.rst.license +0 -0
  42. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/requirements.txt +0 -0
  43. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/examples/functools_simpletest.py +0 -0
  44. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/optional_requirements.txt +0 -0
  45. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/requirements.txt +0 -0
  46. {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/setup.cfg +0 -0
@@ -0,0 +1,43 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ name: Run code tests
5
+
6
+ on:
7
+ push:
8
+ branches:
9
+ - 'main'
10
+ pull_request:
11
+ paths:
12
+ - '.github/workflows/codecov.yml'
13
+ - 'pyproject.toml'
14
+ - 'circuitpython_functools'
15
+ - 'tests/**'
16
+
17
+ permissions: read-all
18
+
19
+ jobs:
20
+ codecov:
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - name: Setup Python 3.x
25
+ uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.py-version }}
28
+ - name: Checkout the repository
29
+ uses: actions/checkout@v6
30
+ - name: Install base requirements
31
+ run: |
32
+ pip install ".[optional]"
33
+ - name: Install test requirements
34
+ run: |
35
+ pip install pytest pytest-cov
36
+ - name: Run tests
37
+ run: |
38
+ pytest --cov --cov-branch --cov-report=xml
39
+ - name: Upload coverage reports to Codecov
40
+ uses: codecov/codecov-action@v5
41
+ with:
42
+ token: ${{ secrets.CODECOV_TOKEN }}
43
+ fail_ci_if_error: true
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: circuitpython-functools
3
- Version: 2.0.3
3
+ Version: 3.0.0
4
4
  Summary: A CircuitPython implementation of CPython's functools library
5
5
  Author-email: Alec Delaney <tekktrik@gmail.com>
6
6
  License-Expression: MIT AND PSF-2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: circuitpython-functools
3
- Version: 2.0.3
3
+ Version: 3.0.0
4
4
  Summary: A CircuitPython implementation of CPython's functools library
5
5
  Author-email: Alec Delaney <tekktrik@gmail.com>
6
6
  License-Expression: MIT AND PSF-2.0
@@ -13,6 +13,7 @@ requirements.txt
13
13
  .github/dependabot.yml
14
14
  .github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md
15
15
  .github/workflows/build.yml
16
+ .github/workflows/codecov.yml
16
17
  .github/workflows/failure-help-text.yml
17
18
  .github/workflows/release_gh.yml
18
19
  .github/workflows/release_pypi.yml
@@ -35,4 +36,9 @@ docs/index.rst.license
35
36
  docs/requirements.txt
36
37
  docs/_static/favicon.ico
37
38
  docs/_static/favicon.ico.license
38
- examples/functools_simpletest.py
39
+ examples/functools_simpletest.py
40
+ tests/test_cache.py
41
+ tests/test_lru_cache.py
42
+ tests/test_partial.py
43
+ tests/test_total_ordering.py
44
+ tests/test_wraps.py
@@ -23,7 +23,7 @@ Implementation Notes
23
23
  import gc
24
24
  from collections import OrderedDict
25
25
 
26
- __version__ = "2.0.3"
26
+ __version__ = "3.0.0"
27
27
  __repo__ = "https://github.com/tekktrik/CircuitPython_functools.git"
28
28
 
29
29
  _cache_records = {}
@@ -146,4 +146,70 @@ def partial(func, *args, **kwargs):
146
146
  # their simplified implementation of the wraps function!
147
147
  def wraps(wrapped, assigned=None, updated=None):
148
148
  """Define a wrapper function when writing function decorators."""
149
- return wrapped
149
+
150
+ def decorator(wrapper):
151
+ return wrapper
152
+
153
+ return decorator
154
+
155
+
156
+ def total_ordering(cls): # noqa: PLR0912
157
+ """Automatically create the comparison functions."""
158
+ has_lt = "__lt__" in cls.__dict__
159
+ has_gt = "__gt__" in cls.__dict__
160
+ has_le = "__le__" in cls.__dict__
161
+ has_ge = "__ge__" in cls.__dict__
162
+
163
+ if not (has_lt or has_gt or has_le or has_ge):
164
+ raise ValueError("must define at least one ordering operation: < > <= >=")
165
+
166
+ def instance_guard(x, cls):
167
+ if not isinstance(x, cls):
168
+ raise TypeError("unsupport comparison")
169
+ return True
170
+
171
+ if not has_lt:
172
+ if has_le:
173
+ lt_func = lambda self, other: self <= other and self != other
174
+ elif has_gt:
175
+ lt_func = lambda self, other: not (self > other) and self != other
176
+ else: # has_ge
177
+ lt_func = lambda self, other: not (self >= other)
178
+ cls.__lt__ = lambda self, other: instance_guard(other, cls) and lt_func(
179
+ self, other
180
+ )
181
+
182
+ if not has_le:
183
+ if has_lt:
184
+ le_func = lambda self, other: self < other or self == other
185
+ elif has_gt:
186
+ le_func = lambda self, other: not (self > other)
187
+ else: # has_ge
188
+ le_func = lambda self, other: self == other or not (self >= other)
189
+ cls.__le__ = lambda self, other: instance_guard(other, cls) and le_func(
190
+ self, other
191
+ )
192
+
193
+ if not has_gt:
194
+ if has_lt:
195
+ gt_func = lambda self, other: self != other and not (self < other)
196
+ elif has_ge:
197
+ gt_func = lambda self, other: self >= other and self != other
198
+ else: # has_le
199
+ gt_func = lambda self, other: not (self <= other)
200
+ cls.__gt__ = lambda self, other: instance_guard(other, cls) and gt_func(
201
+ self, other
202
+ )
203
+
204
+ if not has_ge:
205
+ if has_lt:
206
+ ge_func = lambda self, other: not (self < other)
207
+ elif has_gt:
208
+ ge_func = lambda self, other: self > other or self == other
209
+ else: # has_le
210
+ ge_func = lambda self, other: self == other or not (self <= other)
211
+ cls.__ge__ = lambda self, other: instance_guard(other, cls) and ge_func(
212
+ self, other
213
+ )
214
+
215
+ return cls
@@ -12,7 +12,7 @@ requires = [
12
12
  [project]
13
13
  name = "circuitpython-functools"
14
14
  description = "A CircuitPython implementation of CPython's functools library"
15
- version = "2.0.3"
15
+ version = "3.0.0"
16
16
  readme = "README.rst"
17
17
  authors = [
18
18
  {name = "Alec Delaney", email = "tekktrik@gmail.com"}
@@ -0,0 +1,34 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ # SPDX-FileCopyrightText: Python Software Foundation
3
+
4
+ # SPDX-License-Identifier: MIT
5
+ # SPDX-License-Identifier: PSF-2.0
6
+
7
+ """Tests for cache."""
8
+
9
+ from circuitpython_functools import cache
10
+
11
+ # Example adapted from CPython documentation
12
+
13
+ TOTAL_CALLS = 0
14
+
15
+
16
+ def test_cache():
17
+ """Tests that cache decorator works as expected."""
18
+
19
+ @cache
20
+ def factorial(n):
21
+ global TOTAL_CALLS # noqa: PLW0603
22
+ TOTAL_CALLS += 1
23
+ return n * factorial(n - 1) if n else 1
24
+
25
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
26
+
27
+ _ = factorial(10)
28
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
29
+
30
+ _ = factorial(5)
31
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
32
+
33
+ _ = factorial(12)
34
+ assert TOTAL_CALLS == 13 # noqa: PLR2004
@@ -0,0 +1,165 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ # SPDX-FileCopyrightText: Python Software Foundation
3
+ #
4
+ # SPDX-License-Identifier: MIT
5
+ # SPDX-License-Identifier: PSF-2.0
6
+
7
+ """Tests for lru_cache."""
8
+
9
+ import pytest
10
+
11
+ from circuitpython_functools import _lru_cache_records, lru_cache
12
+
13
+ # Factorial example adapted from CPython documentation
14
+
15
+ TOTAL_CALLS = 0
16
+
17
+
18
+ def test_lru_cache_default():
19
+ """Tests the lru_cache works with default settings (no arguments provided)."""
20
+ global TOTAL_CALLS # noqa: PLW0603
21
+
22
+ @lru_cache
23
+ def factorial(n):
24
+ global TOTAL_CALLS # noqa: PLW0603
25
+ TOTAL_CALLS += 1
26
+ return n * factorial(n - 1) if n else 1
27
+
28
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
29
+
30
+ _ = factorial(10)
31
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
32
+
33
+ _ = factorial(5)
34
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
35
+
36
+ _ = factorial(12)
37
+ assert TOTAL_CALLS == 13 # noqa: PLR2004
38
+
39
+ TOTAL_CALLS = 0
40
+
41
+
42
+ def test_lru_cache_maxsize_arg():
43
+ """Tests the lru_cache maxsize function when given as arg."""
44
+ global TOTAL_CALLS # noqa: PLW0603
45
+
46
+ @lru_cache(5)
47
+ def factorial(n):
48
+ global TOTAL_CALLS # noqa: PLW0603
49
+ TOTAL_CALLS += 1
50
+ return n * factorial(n - 1) if n else 1
51
+
52
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
53
+
54
+ _ = factorial(10)
55
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
56
+ print("---")
57
+
58
+ _ = factorial(5)
59
+ assert TOTAL_CALLS == 17 # noqa: PLR2004
60
+ print("---")
61
+
62
+ _ = factorial(12)
63
+ assert TOTAL_CALLS == 24 # noqa: PLR2004
64
+
65
+ TOTAL_CALLS = 0
66
+
67
+
68
+ def test_lru_cache_maxsize_kwarg():
69
+ """Tests the lru_cache maxsize function when given as kwarg."""
70
+ global TOTAL_CALLS # noqa: PLW0603
71
+
72
+ @lru_cache(maxsize=5)
73
+ def factorial(n):
74
+ global TOTAL_CALLS # noqa: PLW0603
75
+ TOTAL_CALLS += 1
76
+ return n * factorial(n - 1) if n else 1
77
+
78
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
79
+
80
+ _ = factorial(10)
81
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
82
+ print("---")
83
+
84
+ _ = factorial(5)
85
+ assert TOTAL_CALLS == 17 # noqa: PLR2004
86
+ print("---")
87
+
88
+ _ = factorial(12)
89
+ assert TOTAL_CALLS == 24 # noqa: PLR2004
90
+
91
+ TOTAL_CALLS = 0
92
+
93
+
94
+ def test_lru_cache_func_kwarg():
95
+ """Tests the lru_cache when function has kwargs."""
96
+ global TOTAL_CALLS # noqa: PLW0603
97
+
98
+ @lru_cache
99
+ def factorial(*, n):
100
+ global TOTAL_CALLS # noqa: PLW0603
101
+ TOTAL_CALLS += 1
102
+ return n * factorial(n=n - 1) if n else 1
103
+
104
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
105
+
106
+ _ = factorial(n=10)
107
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
108
+
109
+ _ = factorial(n=5)
110
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
111
+
112
+ _ = factorial(n=12)
113
+ assert TOTAL_CALLS == 13 # noqa: PLR2004
114
+
115
+ TOTAL_CALLS = 0
116
+
117
+
118
+ def test_lru_cache_cache_clear():
119
+ """Tests the automatically attached cache_clear method works."""
120
+ global TOTAL_CALLS # noqa: PLW0603
121
+
122
+ @lru_cache
123
+ def factorial(n):
124
+ global TOTAL_CALLS # noqa: PLW0603
125
+ TOTAL_CALLS += 1
126
+ return n * factorial(n=n - 1) if n else 1
127
+
128
+ assert TOTAL_CALLS == 0 # noqa: PLR2004
129
+
130
+ _ = factorial(n=10)
131
+ assert TOTAL_CALLS == 11 # noqa: PLR2004
132
+
133
+ factorial.cache_clear()
134
+
135
+ _ = factorial(n=10)
136
+ assert TOTAL_CALLS == 22 # noqa: PLR2004
137
+
138
+ TOTAL_CALLS = 0
139
+
140
+
141
+ def test_lru_cache_typed_error_args():
142
+ """Tests that lru_cache raises an error if "typed" given as arg."""
143
+ with pytest.raises(NotImplementedError):
144
+
145
+ @lru_cache(100, True)
146
+ def factorial(n):
147
+ return n * factorial(n=n - 1) if n else 1
148
+
149
+
150
+ def test_lru_cache_typed_error_kwargs():
151
+ """Tests that lru_cache raises an error if "typed" given as kwarg."""
152
+ with pytest.raises(NotImplementedError):
153
+
154
+ @lru_cache(typed=True)
155
+ def factorial(n):
156
+ return n * factorial(n=n - 1) if n else 1
157
+
158
+
159
+ def test_lru_cache_syntax_error():
160
+ """Tests that lru_cache raises an error if arguments are incorrect."""
161
+ with pytest.raises(SyntaxError):
162
+
163
+ @lru_cache(100, True, "a")
164
+ def factorial(n):
165
+ return n * factorial(n=n - 1) if n else 1
@@ -0,0 +1,26 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Tests for partial."""
6
+
7
+ from circuitpython_functools import partial
8
+
9
+
10
+ def test_partial():
11
+ """Tests functionality of partial."""
12
+
13
+ def towerize(x, y, z):
14
+ return (x * 100) + (y * 10) + z
15
+
16
+ towerize100 = partial(towerize, 1)
17
+ assert towerize100(5, 3) == 153 # noqa: PLR2004
18
+ assert towerize100(z=2, y=7) == 172 # noqa: PLR2004
19
+
20
+ towerize150 = partial(towerize, 1, 5)
21
+ assert towerize150(6) == 156 # noqa: PLR2004
22
+ assert towerize150(z=8) == 158 # noqa: PLR2004
23
+
24
+ towerize20 = partial(towerize, y=2)
25
+ assert towerize20(9, z=0) == 920 # noqa: PLR2004
26
+ assert towerize20(z=1, x=5) == 521 # noqa: PLR2004
@@ -0,0 +1,124 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ """Tests for total_ordering."""
5
+
6
+ import pytest
7
+
8
+ from circuitpython_functools import total_ordering
9
+
10
+
11
+ class BaseClass:
12
+ """Basic test base class."""
13
+
14
+ def __init__(self, attr):
15
+ """Initialize the instance."""
16
+ self.attr = attr
17
+
18
+ def __eq__(self, other):
19
+ """Perform basic equal to operation."""
20
+ if not isinstance(other, BaseClass):
21
+ return False
22
+ return self.attr == other.attr
23
+
24
+
25
+ class OtherClass:
26
+ """A different class."""
27
+
28
+
29
+ parameters = []
30
+
31
+
32
+ @total_ordering
33
+ class UsesLT(BaseClass):
34
+ """Basic class that implements less than."""
35
+
36
+ def __lt__(self, other):
37
+ """Perform basic less than operation."""
38
+ if not isinstance(other, BaseClass):
39
+ raise TypeError
40
+ return self.attr < other.attr
41
+
42
+
43
+ parameters.append((UsesLT(1), UsesLT(1), UsesLT(2)))
44
+
45
+
46
+ @total_ordering
47
+ class UsesGT(BaseClass):
48
+ """Basic class that implements greater than."""
49
+
50
+ def __gt__(self, other):
51
+ """Perform basic greater than operation."""
52
+ if not isinstance(other, BaseClass):
53
+ raise TypeError
54
+ return self.attr > other.attr
55
+
56
+
57
+ parameters.append((UsesGT(1), UsesGT(1), UsesGT(2)))
58
+
59
+
60
+ @total_ordering
61
+ class UsesLE(BaseClass):
62
+ """Basic class that implements less than or equal to."""
63
+
64
+ def __le__(self, other):
65
+ """Perform basic less than or equal to operation."""
66
+ if not isinstance(other, BaseClass):
67
+ raise TypeError
68
+ return self.attr <= other.attr
69
+
70
+
71
+ parameters.append((UsesLE(1), UsesLE(1), UsesLE(2)))
72
+
73
+
74
+ @total_ordering
75
+ class UsesGE(BaseClass):
76
+ """Basic class that implements greater than or equal to."""
77
+
78
+ def __ge__(self, other):
79
+ """Perform basic greater than or equal to operation."""
80
+ if not isinstance(other, BaseClass):
81
+ raise TypeError
82
+ return self.attr >= other.attr
83
+
84
+
85
+ parameters.append((UsesGE(1), UsesGE(1), UsesGE(2)))
86
+
87
+
88
+ @pytest.mark.parametrize("x,y,z", parameters)
89
+ def test_comparisons(x, y, z):
90
+ """Tests that comparisons are correct."""
91
+ w = OtherClass()
92
+
93
+ # lt
94
+ assert not x < y
95
+ assert x < z
96
+ with pytest.raises(TypeError):
97
+ x < w
98
+
99
+ # gt
100
+ assert not x > y
101
+ assert z > x
102
+ with pytest.raises(TypeError):
103
+ x > w
104
+
105
+ # le
106
+ assert x <= y
107
+ assert x <= z
108
+ with pytest.raises(TypeError):
109
+ x <= w
110
+
111
+ # ge
112
+ assert x >= y
113
+ assert not x >= z
114
+ with pytest.raises(TypeError):
115
+ x >= w
116
+
117
+
118
+ def test_none_implemented():
119
+ """Tests the not implementig compraison function results in an error."""
120
+ with pytest.raises(ValueError):
121
+
122
+ @total_ordering
123
+ class NoneImplemented:
124
+ """Class with nothing implemented."""
@@ -0,0 +1,28 @@
1
+ # SPDX-FileCopyrightText: 2026 Alec Delaney
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ """Tests for wraps."""
5
+
6
+ from circuitpython_functools import wraps
7
+
8
+
9
+ def square_args(func):
10
+ """Square arguments before calling function."""
11
+
12
+ @wraps(func)
13
+ def wrapper(x, y):
14
+ a = x**2
15
+ b = y**2
16
+ return func(a, b)
17
+
18
+ return wrapper
19
+
20
+
21
+ def test_wraps():
22
+ """Tests that x is x."""
23
+
24
+ @square_args
25
+ def add2(aa, bb):
26
+ return aa + bb
27
+
28
+ assert add2(3, 4) == 25 # noqa: PLR2004