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.
- circuitpython_functools-3.0.0/.github/workflows/codecov.yml +43 -0
- {circuitpython_functools-2.0.3/circuitpython_functools.egg-info → circuitpython_functools-3.0.0}/PKG-INFO +1 -1
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0/circuitpython_functools.egg-info}/PKG-INFO +1 -1
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/SOURCES.txt +7 -1
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.py +68 -2
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/pyproject.toml +1 -1
- circuitpython_functools-3.0.0/tests/test_cache.py +34 -0
- circuitpython_functools-3.0.0/tests/test_lru_cache.py +165 -0
- circuitpython_functools-3.0.0/tests/test_partial.py +26 -0
- circuitpython_functools-3.0.0/tests/test_total_ordering.py +124 -0
- circuitpython_functools-3.0.0/tests/test_wraps.py +28 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/dependabot.yml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/build.yml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/failure-help-text.yml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_gh.yml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_pypi.yml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.gitignore +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.pre-commit-config.yaml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.readthedocs.yaml +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/CODE_OF_CONDUCT.md +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSE-MIT +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSE-PSF +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/CC-BY-4.0.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/MIT.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/PSF-2.0.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/LICENSES/Unlicense.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/README.rst +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/README.rst.license +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/dependency_links.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/requires.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/circuitpython_functools.egg-info/top_level.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/_static/favicon.ico +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/_static/favicon.ico.license +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/api.rst +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/api.rst.license +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/conf.py +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/examples.rst +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/examples.rst.license +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/index.rst +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/index.rst.license +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/requirements.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/examples/functools_simpletest.py +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/optional_requirements.txt +0 -0
- {circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/requirements.txt +0 -0
- {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
|
|
@@ -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__ = "
|
|
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
|
-
|
|
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 = "
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_gh.yml
RENAMED
|
File without changes
|
{circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/.github/workflows/release_pypi.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/docs/_static/favicon.ico.license
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{circuitpython_functools-2.0.3 → circuitpython_functools-3.0.0}/examples/functools_simpletest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|