crcmod-plus 2.3.1__tar.gz → 2.3.6__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.
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/PKG-INFO +2 -3
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/README.md +1 -1
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/pyproject.toml +13 -14
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/setup.py +9 -10
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/__init__.py +3 -3
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/_crcfunpy.py +1 -1
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/_version.py +1 -1
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/crcmod.py +37 -35
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/predefined.py +33 -19
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/types.py +3 -7
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod_plus.egg-info/PKG-INFO +2 -3
- crcmod_plus-2.3.6/src/crcmod_plus.egg-info/requires.txt +3 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/tests/test_crcmod.py +32 -36
- crcmod_plus-2.3.1/src/crcmod_plus.egg-info/requires.txt +0 -6
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/LICENSE.txt +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/lib/_crcfunext.c +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/setup.cfg +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod/py.typed +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod_plus.egg-info/SOURCES.txt +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod_plus.egg-info/dependency_links.txt +0 -0
- {crcmod_plus-2.3.1 → crcmod_plus-2.3.6}/src/crcmod_plus.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crcmod-plus
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.6
|
|
4
4
|
Summary: CRC generator - modernized
|
|
5
5
|
Author-email: Ray Buvel <rlbuvel@gmail.com>
|
|
6
6
|
Maintainer-email: Tamas Nepusz <tamas@sxd.hu>
|
|
@@ -33,7 +33,6 @@ Classifier: Topic :: Utilities
|
|
|
33
33
|
Requires-Python: >=3.9
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE.txt
|
|
36
|
-
Requires-Dist: typing_extensions; python_version < "3.8"
|
|
37
36
|
Provides-Extra: dev
|
|
38
37
|
Requires-Dist: pytest; extra == "dev"
|
|
39
38
|
Dynamic: license-file
|
|
@@ -88,7 +87,7 @@ a model for the new version.
|
|
|
88
87
|
|
|
89
88
|
### Python version
|
|
90
89
|
|
|
91
|
-
This package supports Python 3.
|
|
90
|
+
This package supports Python 3.9 and newer.
|
|
92
91
|
|
|
93
92
|
### Building C extension
|
|
94
93
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "crcmod-plus"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.6"
|
|
8
8
|
authors = [{ name = "Ray Buvel", email = "rlbuvel@gmail.com" }]
|
|
9
9
|
description = "CRC generator - modernized"
|
|
10
10
|
readme = "README.md"
|
|
@@ -35,7 +35,6 @@ classifiers = [
|
|
|
35
35
|
"Topic :: Scientific/Engineering :: Mathematics",
|
|
36
36
|
"Topic :: Utilities",
|
|
37
37
|
]
|
|
38
|
-
dependencies = ["typing_extensions; python_version < '3.8'"]
|
|
39
38
|
|
|
40
39
|
[project.urls]
|
|
41
40
|
Changelog = "https://github.com/ntamas/crcmod-plus/blob/main/CHANGELOG.md"
|
|
@@ -47,7 +46,18 @@ Source = "https://github.com/ntamas/crcmod-plus"
|
|
|
47
46
|
dev = ["pytest"]
|
|
48
47
|
|
|
49
48
|
[tool.cibuildwheel]
|
|
50
|
-
enable = ["
|
|
49
|
+
enable = ["pypy"]
|
|
50
|
+
test-requires = ["pytest"]
|
|
51
|
+
test-command = [
|
|
52
|
+
'python -c "import crcmod.crcmod as m; assert m._usingExtension"',
|
|
53
|
+
"pytest {project}/tests",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
target-version = "py39"
|
|
58
|
+
|
|
59
|
+
[tool.ruff.lint]
|
|
60
|
+
extend-select = ["I", "UP035"]
|
|
51
61
|
|
|
52
62
|
[tool.ruff.lint.extend-per-file-ignores]
|
|
53
63
|
"predefined.py" = ["E501"]
|
|
@@ -64,17 +74,6 @@ legacy_tox_ini = """
|
|
|
64
74
|
min_version = 4.0
|
|
65
75
|
env_list = py314t, py314, py313t, py313, py312, py311, py310, py39, type
|
|
66
76
|
|
|
67
|
-
[gh-actions]
|
|
68
|
-
python =
|
|
69
|
-
3.9: py39
|
|
70
|
-
3.10: py310
|
|
71
|
-
3.11: py311
|
|
72
|
-
3.12: py312
|
|
73
|
-
3.13: py313
|
|
74
|
-
3.13t: py313t
|
|
75
|
-
3.14: py314, type
|
|
76
|
-
3.14t: py314t
|
|
77
|
-
|
|
78
77
|
[testenv]
|
|
79
78
|
deps = pytest
|
|
80
79
|
commands = pytest tests
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
+
import sysconfig
|
|
1
2
|
from platform import python_implementation
|
|
2
|
-
from setuptools import setup, Extension
|
|
3
3
|
from sys import version_info
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
from setuptools import Extension, setup
|
|
5
6
|
from wheel.bdist_wheel import bdist_wheel
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def is_freethread():
|
|
9
|
-
|
|
10
|
-
return True
|
|
11
|
-
return False
|
|
10
|
+
return bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
# fmt: off
|
|
@@ -37,12 +36,12 @@ if can_use_limited_api:
|
|
|
37
36
|
define_macros=[("Py_LIMITED_API", "0x030b0000")], py_limited_api=True
|
|
38
37
|
)
|
|
39
38
|
|
|
40
|
-
setup_args =
|
|
41
|
-
ext_modules
|
|
39
|
+
setup_args = {
|
|
40
|
+
"ext_modules": [
|
|
42
41
|
Extension("crcmod._crcfunext", ["lib/_crcfunext.c"], **extension_kwargs)
|
|
43
42
|
],
|
|
44
|
-
package_dir
|
|
45
|
-
cmdclass
|
|
46
|
-
|
|
43
|
+
"package_dir": {"": "src"},
|
|
44
|
+
"cmdclass": {"bdist_wheel": bdist_wheel_abi3},
|
|
45
|
+
}
|
|
47
46
|
|
|
48
47
|
setup(**setup_args) # type: ignore
|
|
@@ -13,8 +13,8 @@ polynomial and initial value. This provides a much simpler interface if
|
|
|
13
13
|
all you need is a function for CRC calculation.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
from .crcmod import Crc, mkCrcFun
|
|
17
|
-
from ._version import __version__
|
|
18
16
|
from . import predefined # Auto-import for drop-in compatibility with original crcmod
|
|
17
|
+
from ._version import __version__
|
|
18
|
+
from .crcmod import Crc, mkCrcFun
|
|
19
19
|
|
|
20
|
-
__all__ = ("Crc", "
|
|
20
|
+
__all__ = ("Crc", "__version__", "mkCrcFun", "predefined")
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version_tuple__ = (2, 3,
|
|
1
|
+
__version_tuple__ = (2, 3, 6)
|
|
2
2
|
__version__ = ".".join(map(str, __version_tuple__))
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
# -----------------------------------------------------------------------------
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
__all__ = ("Crc", "mkCrcFun")
|
|
25
27
|
|
|
26
28
|
# Select the appropriate set of low-level CRC functions for this installation.
|
|
27
29
|
# If the extension module was not built, drop back to the Python implementation
|
|
@@ -36,8 +38,8 @@ except ImportError:
|
|
|
36
38
|
_usingExtension = False
|
|
37
39
|
|
|
38
40
|
import struct
|
|
39
|
-
|
|
40
|
-
from typing import
|
|
41
|
+
from collections.abc import Sequence
|
|
42
|
+
from typing import IO
|
|
41
43
|
|
|
42
44
|
from .types import Buffer, CrcFun, CrcFunNoDefaultArgs
|
|
43
45
|
|
|
@@ -88,7 +90,7 @@ class Crc:
|
|
|
88
90
|
crcValue: int
|
|
89
91
|
|
|
90
92
|
_crc: CrcFun
|
|
91
|
-
table:
|
|
93
|
+
table: list[int]
|
|
92
94
|
|
|
93
95
|
def __init__(
|
|
94
96
|
self,
|
|
@@ -118,16 +120,16 @@ class Crc:
|
|
|
118
120
|
self.crcValue = self.initCrc
|
|
119
121
|
|
|
120
122
|
def __str__(self) -> str:
|
|
121
|
-
lst:
|
|
122
|
-
lst.append("poly = 0x
|
|
123
|
-
lst.append("reverse =
|
|
124
|
-
fmt = "0x
|
|
123
|
+
lst: list[str] = []
|
|
124
|
+
lst.append(f"poly = 0x{self.poly:X}")
|
|
125
|
+
lst.append(f"reverse = {self.reverse}")
|
|
126
|
+
fmt = f"0x%0{self.digest_size * 2}X"
|
|
125
127
|
lst.append("initCrc = %s" % (fmt % self.initCrc))
|
|
126
128
|
lst.append("xorOut = %s" % (fmt % self.xorOut))
|
|
127
129
|
lst.append("crcValue = %s" % (fmt % self.crcValue))
|
|
128
130
|
return "\n".join(lst)
|
|
129
131
|
|
|
130
|
-
def new(self, arg:
|
|
132
|
+
def new(self, arg: Buffer | None = None) -> Crc:
|
|
131
133
|
"""Create a new instance of the Crc class initialized to the same
|
|
132
134
|
values as the original instance. The current CRC is set to the initial
|
|
133
135
|
value. If a string is provided in the optional arg parameter, it is
|
|
@@ -146,7 +148,7 @@ class Crc:
|
|
|
146
148
|
n.update(arg)
|
|
147
149
|
return n
|
|
148
150
|
|
|
149
|
-
def copy(self) ->
|
|
151
|
+
def copy(self) -> Crc:
|
|
150
152
|
"""Create a new instance of the Crc class initialized to the same
|
|
151
153
|
values as the original instance. The current CRC is set to the current
|
|
152
154
|
value. This allows multiple CRC calculations using a common initial
|
|
@@ -168,7 +170,7 @@ class Crc:
|
|
|
168
170
|
"""
|
|
169
171
|
n = self.digest_size
|
|
170
172
|
crc = self.crcValue
|
|
171
|
-
lst:
|
|
173
|
+
lst: list[int] = []
|
|
172
174
|
while n > 0:
|
|
173
175
|
lst.append(crc & 0xFF)
|
|
174
176
|
crc = crc >> 8
|
|
@@ -182,7 +184,7 @@ class Crc:
|
|
|
182
184
|
"""
|
|
183
185
|
n = self.digest_size
|
|
184
186
|
crc = self.crcValue
|
|
185
|
-
lst:
|
|
187
|
+
lst: list[str] = []
|
|
186
188
|
while n > 0:
|
|
187
189
|
lst.append("%02X" % (crc & 0xFF))
|
|
188
190
|
crc = crc >> 8
|
|
@@ -194,8 +196,8 @@ class Crc:
|
|
|
194
196
|
self,
|
|
195
197
|
functionName: str,
|
|
196
198
|
out: IO[str],
|
|
197
|
-
dataType:
|
|
198
|
-
crcType:
|
|
199
|
+
dataType: str | None = None,
|
|
200
|
+
crcType: str | None = None,
|
|
199
201
|
) -> None:
|
|
200
202
|
"""Generate a C/C++ function.
|
|
201
203
|
|
|
@@ -218,7 +220,7 @@ class Crc:
|
|
|
218
220
|
size = 8 * self.digest_size
|
|
219
221
|
if size == 24:
|
|
220
222
|
size = 32
|
|
221
|
-
crcType = "UINT
|
|
223
|
+
crcType = f"UINT{size}"
|
|
222
224
|
|
|
223
225
|
if self.digest_size == 1:
|
|
224
226
|
# Both 8-bit CRC algorithms are the same
|
|
@@ -231,9 +233,9 @@ class Crc:
|
|
|
231
233
|
# The forward CRC algorithms larger than 8 bits have an extra shift
|
|
232
234
|
# operation to get the high byte.
|
|
233
235
|
shift = 8 * (self.digest_size - 1)
|
|
234
|
-
crcAlgor = "table[*data ^ (
|
|
236
|
+
crcAlgor = f"table[*data ^ (%s)(crc >> {shift})] ^ (crc << 8)"
|
|
235
237
|
|
|
236
|
-
fmt = "0x
|
|
238
|
+
fmt = f"0x%0{2 * self.digest_size}X"
|
|
237
239
|
if self.digest_size <= 4:
|
|
238
240
|
fmt = fmt + "U,"
|
|
239
241
|
else:
|
|
@@ -243,13 +245,13 @@ class Crc:
|
|
|
243
245
|
# Select the number of entries per row in the output code.
|
|
244
246
|
n = {1: 8, 2: 8, 3: 4, 4: 4, 8: 2}[self.digest_size]
|
|
245
247
|
|
|
246
|
-
lst:
|
|
248
|
+
lst: list[str] = []
|
|
247
249
|
for i, val in enumerate(self.table):
|
|
248
250
|
if (i % n) == 0:
|
|
249
251
|
lst.append("\n ")
|
|
250
252
|
lst.append(fmt % val)
|
|
251
253
|
|
|
252
|
-
poly = "polynomial: 0x
|
|
254
|
+
poly = f"polynomial: 0x{self.poly:X}"
|
|
253
255
|
if self.reverse:
|
|
254
256
|
poly = poly + ", bit reverse algorithm"
|
|
255
257
|
|
|
@@ -279,7 +281,7 @@ class Crc:
|
|
|
279
281
|
"preCondition": preCondition,
|
|
280
282
|
"postCondition": postCondition,
|
|
281
283
|
}
|
|
282
|
-
out.write(_codeTemplate % parms)
|
|
284
|
+
_ = out.write(_codeTemplate % parms)
|
|
283
285
|
|
|
284
286
|
|
|
285
287
|
# -----------------------------------------------------------------------------
|
|
@@ -341,7 +343,7 @@ def _bitrev(x: int, n: int) -> int:
|
|
|
341
343
|
|
|
342
344
|
def _bytecrc(crc: int, poly: int, n: int) -> int:
|
|
343
345
|
mask = 1 << (n - 1)
|
|
344
|
-
for
|
|
346
|
+
for _ in range(8):
|
|
345
347
|
if crc & mask:
|
|
346
348
|
crc = (crc << 1) ^ poly
|
|
347
349
|
else:
|
|
@@ -352,7 +354,7 @@ def _bytecrc(crc: int, poly: int, n: int) -> int:
|
|
|
352
354
|
|
|
353
355
|
|
|
354
356
|
def _bytecrc_r(crc: int, poly: int, n: int) -> int:
|
|
355
|
-
for
|
|
357
|
+
for _ in range(8):
|
|
356
358
|
if crc & 1:
|
|
357
359
|
crc = (crc >> 1) ^ poly
|
|
358
360
|
else:
|
|
@@ -371,14 +373,14 @@ def _bytecrc_r(crc: int, poly: int, n: int) -> int:
|
|
|
371
373
|
# have been checked for validity by the caller.
|
|
372
374
|
|
|
373
375
|
|
|
374
|
-
def _mkTable(poly: int, n: int) ->
|
|
376
|
+
def _mkTable(poly: int, n: int) -> list[int]:
|
|
375
377
|
mask = (1 << n) - 1
|
|
376
378
|
poly = poly & mask
|
|
377
379
|
table = [_bytecrc(i << (n - 8), poly, n) for i in range(256)]
|
|
378
380
|
return table
|
|
379
381
|
|
|
380
382
|
|
|
381
|
-
def _mkTable_r(poly: int, n: int) ->
|
|
383
|
+
def _mkTable_r(poly: int, n: int) -> list[int]:
|
|
382
384
|
mask = (1 << n) - 1
|
|
383
385
|
poly = _bitrev(poly & mask, n)
|
|
384
386
|
table = [_bytecrc_r(i, poly, n) for i in range(256)]
|
|
@@ -388,7 +390,7 @@ def _mkTable_r(poly: int, n: int) -> List[int]:
|
|
|
388
390
|
# -----------------------------------------------------------------------------
|
|
389
391
|
# Map the CRC size onto the functions that handle these sizes.
|
|
390
392
|
|
|
391
|
-
_sizeMap:
|
|
393
|
+
_sizeMap: dict[int, tuple[CrcFunNoDefaultArgs, CrcFunNoDefaultArgs]] = {
|
|
392
394
|
8: (_crcfun._crc8, _crcfun._crc8r),
|
|
393
395
|
16: (_crcfun._crc16, _crcfun._crc16r),
|
|
394
396
|
24: (_crcfun._crc24, _crcfun._crc24r),
|
|
@@ -402,12 +404,12 @@ _sizeMap: Dict[int, Tuple[CrcFunNoDefaultArgs, CrcFunNoDefaultArgs]] = {
|
|
|
402
404
|
# code to use for the platform we are running on. This should properly adapt
|
|
403
405
|
# to 32 and 64 bit machines.
|
|
404
406
|
|
|
405
|
-
_sizeToTypeCode:
|
|
407
|
+
_sizeToTypeCode: dict[int, str] = {}
|
|
406
408
|
|
|
407
|
-
for typeCode in "B H I L Q"
|
|
409
|
+
for typeCode in ["B", "H", "I", "L", "Q"]:
|
|
408
410
|
size = {1: 8, 2: 16, 4: 32, 8: 64}.get(struct.calcsize(typeCode), None)
|
|
409
411
|
if size is not None and size not in _sizeToTypeCode:
|
|
410
|
-
_sizeToTypeCode[size] = "256
|
|
412
|
+
_sizeToTypeCode[size] = f"256{typeCode}"
|
|
411
413
|
|
|
412
414
|
_sizeToTypeCode[24] = _sizeToTypeCode[32]
|
|
413
415
|
|
|
@@ -419,7 +421,7 @@ del typeCode, size # type: ignore
|
|
|
419
421
|
# It returns the size of the CRC (in bits), and "sanitized" initial/final XOR values.
|
|
420
422
|
|
|
421
423
|
|
|
422
|
-
def _verifyParams(poly: int, initCrc: int, xorOut: int) ->
|
|
424
|
+
def _verifyParams(poly: int, initCrc: int, xorOut: int) -> tuple[int, int, int]:
|
|
423
425
|
sizeBits = _verifyPoly(poly)
|
|
424
426
|
|
|
425
427
|
mask = (1 << sizeBits) - 1
|
|
@@ -448,17 +450,17 @@ def _verifyParams(poly: int, initCrc: int, xorOut: int) -> Tuple[int, int, int]:
|
|
|
448
450
|
|
|
449
451
|
def _mkCrcFun(
|
|
450
452
|
poly: int, sizeBits: int, initCrc: int, rev: bool, xorOut: int
|
|
451
|
-
) ->
|
|
453
|
+
) -> tuple[CrcFun, list[int]]:
|
|
452
454
|
if rev:
|
|
453
|
-
|
|
455
|
+
tablelist = _mkTable_r(poly, sizeBits)
|
|
454
456
|
_fun = _sizeMap[sizeBits][1]
|
|
455
457
|
else:
|
|
456
|
-
|
|
458
|
+
tablelist = _mkTable(poly, sizeBits)
|
|
457
459
|
_fun = _sizeMap[sizeBits][0]
|
|
458
460
|
|
|
459
|
-
_table: Sequence[int] =
|
|
461
|
+
_table: Sequence[int] = tablelist
|
|
460
462
|
if _usingExtension:
|
|
461
|
-
_table = struct.pack(_sizeToTypeCode[sizeBits], *
|
|
463
|
+
_table = struct.pack(_sizeToTypeCode[sizeBits], *tablelist)
|
|
462
464
|
|
|
463
465
|
if xorOut == 0:
|
|
464
466
|
|
|
@@ -480,7 +482,7 @@ def _mkCrcFun(
|
|
|
480
482
|
) -> int:
|
|
481
483
|
return xorOut ^ fun(data, xorOut ^ crc, table)
|
|
482
484
|
|
|
483
|
-
return crcfun,
|
|
485
|
+
return crcfun, tablelist
|
|
484
486
|
|
|
485
487
|
|
|
486
488
|
# -----------------------------------------------------------------------------
|
|
@@ -32,11 +32,10 @@ crcmod.predefined.Crc is an alias for crcmod.predefined.PredefinedCrc
|
|
|
32
32
|
But if doing 'from crc.predefined import *', only PredefinedCrc is imported.
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
import crcmod
|
|
37
|
-
|
|
38
|
-
from typing import Any, Dict, List, Tuple
|
|
35
|
+
from typing import TypedDict
|
|
39
36
|
|
|
37
|
+
# local imports
|
|
38
|
+
from . import crcmod
|
|
40
39
|
from .types import CrcFun
|
|
41
40
|
|
|
42
41
|
__all__ = (
|
|
@@ -47,14 +46,22 @@ __all__ = (
|
|
|
47
46
|
REVERSE = True
|
|
48
47
|
NON_REVERSE = False
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
Definition
|
|
49
|
+
|
|
50
|
+
class Definition(TypedDict):
|
|
51
|
+
name: str
|
|
52
|
+
identifier: str
|
|
53
|
+
poly: int
|
|
54
|
+
reverse: bool
|
|
55
|
+
init: int
|
|
56
|
+
xor_out: int
|
|
57
|
+
check: int
|
|
58
|
+
|
|
52
59
|
|
|
53
60
|
# The following table defines the parameters of well-known CRC algorithms.
|
|
54
61
|
# The "Check" value is the CRC for the ASCII byte sequence b"123456789". It
|
|
55
62
|
# can be used for unit tests.
|
|
56
63
|
# fmt: off
|
|
57
|
-
_crc_definitions_table:
|
|
64
|
+
_crc_definitions_table: list[tuple[str, str, int, bool, int, int, int]] = [
|
|
58
65
|
# Name Identifier-name, Poly Reverse Init-value XOR-out Check
|
|
59
66
|
( 'crc-8', 'Crc8', 0x107, NON_REVERSE, 0x00, 0x00, 0xF4, ),
|
|
60
67
|
( 'crc-8-darc', 'Crc8Darc', 0x139, REVERSE, 0x00, 0x00, 0x15, ),
|
|
@@ -122,16 +129,15 @@ def _simplify_name(name: str) -> str:
|
|
|
122
129
|
name = name.lower()
|
|
123
130
|
name = name.replace("-", "")
|
|
124
131
|
name = name.replace(" ", "")
|
|
125
|
-
|
|
126
|
-
name = name[len("crc") :]
|
|
132
|
+
name = name.removeprefix("crc")
|
|
127
133
|
return name
|
|
128
134
|
|
|
129
135
|
|
|
130
|
-
_crc_definitions_by_name:
|
|
131
|
-
_crc_definitions_by_identifier:
|
|
132
|
-
_crc_definitions:
|
|
136
|
+
_crc_definitions_by_name: dict[str, Definition] = {}
|
|
137
|
+
_crc_definitions_by_identifier: dict[str, Definition] = {}
|
|
138
|
+
_crc_definitions: list[Definition] = []
|
|
133
139
|
|
|
134
|
-
_crc_table_headings:
|
|
140
|
+
_crc_table_headings: list[str] = [
|
|
135
141
|
"name",
|
|
136
142
|
"identifier",
|
|
137
143
|
"poly",
|
|
@@ -141,14 +147,22 @@ _crc_table_headings: List[str] = [
|
|
|
141
147
|
"check",
|
|
142
148
|
]
|
|
143
149
|
|
|
144
|
-
for
|
|
145
|
-
crc_definition
|
|
150
|
+
for name_str, identifier, poly, reverse, init, xor_out, check in _crc_definitions_table:
|
|
151
|
+
crc_definition = Definition(
|
|
152
|
+
name=name_str,
|
|
153
|
+
identifier=identifier,
|
|
154
|
+
poly=poly,
|
|
155
|
+
reverse=reverse,
|
|
156
|
+
init=init,
|
|
157
|
+
xor_out=xor_out,
|
|
158
|
+
check=check,
|
|
159
|
+
)
|
|
146
160
|
_crc_definitions.append(crc_definition)
|
|
147
|
-
name = _simplify_name(
|
|
161
|
+
name = _simplify_name(name_str)
|
|
148
162
|
if name in _crc_definitions_by_name:
|
|
149
|
-
raise
|
|
163
|
+
raise ValueError(f"Duplicate entry for '{name}' in CRC table")
|
|
150
164
|
_crc_definitions_by_name[name] = crc_definition
|
|
151
|
-
_crc_definitions_by_identifier[
|
|
165
|
+
_crc_definitions_by_identifier[identifier] = crc_definition
|
|
152
166
|
|
|
153
167
|
|
|
154
168
|
def _get_definition_by_name(crc_name: str) -> Definition:
|
|
@@ -156,7 +170,7 @@ def _get_definition_by_name(crc_name: str) -> Definition:
|
|
|
156
170
|
if not definition:
|
|
157
171
|
definition = _crc_definitions_by_identifier.get(crc_name, None)
|
|
158
172
|
if not definition:
|
|
159
|
-
raise KeyError("Unkown CRC name '{
|
|
173
|
+
raise KeyError(f"Unkown CRC name '{crc_name}'")
|
|
160
174
|
return definition
|
|
161
175
|
|
|
162
176
|
|
|
@@ -21,17 +21,13 @@
|
|
|
21
21
|
# -----------------------------------------------------------------------------
|
|
22
22
|
|
|
23
23
|
from array import array
|
|
24
|
-
from
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
from typing import Protocol
|
|
28
|
-
except ImportError:
|
|
29
|
-
from typing_extensions import Protocol # type: ignore
|
|
24
|
+
from collections.abc import Sequence
|
|
25
|
+
from typing import Callable, Protocol, Union
|
|
30
26
|
|
|
31
27
|
__all__ = ("Buffer",)
|
|
32
28
|
|
|
33
29
|
|
|
34
|
-
Buffer = Union[str, bytes, bytearray, memoryview, array]
|
|
30
|
+
Buffer = Union[str, bytes, bytearray, memoryview, "array[int]"]
|
|
35
31
|
"""Type alias for objects supported by the CRC functions as inputs."""
|
|
36
32
|
|
|
37
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crcmod-plus
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.6
|
|
4
4
|
Summary: CRC generator - modernized
|
|
5
5
|
Author-email: Ray Buvel <rlbuvel@gmail.com>
|
|
6
6
|
Maintainer-email: Tamas Nepusz <tamas@sxd.hu>
|
|
@@ -33,7 +33,6 @@ Classifier: Topic :: Utilities
|
|
|
33
33
|
Requires-Python: >=3.9
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE.txt
|
|
36
|
-
Requires-Dist: typing_extensions; python_version < "3.8"
|
|
37
36
|
Provides-Extra: dev
|
|
38
37
|
Requires-Dist: pytest; extra == "dev"
|
|
39
38
|
Dynamic: license-file
|
|
@@ -88,7 +87,7 @@ a model for the new version.
|
|
|
88
87
|
|
|
89
88
|
### Python version
|
|
90
89
|
|
|
91
|
-
This package supports Python 3.
|
|
90
|
+
This package supports Python 3.9 and newer.
|
|
92
91
|
|
|
93
92
|
### Building C extension
|
|
94
93
|
|
|
@@ -22,20 +22,19 @@
|
|
|
22
22
|
# -----------------------------------------------------------------------------
|
|
23
23
|
"""Unit tests for crcmod functionality"""
|
|
24
24
|
|
|
25
|
-
import
|
|
25
|
+
from __future__ import annotations
|
|
26
26
|
|
|
27
|
-
from array import array
|
|
28
27
|
import binascii
|
|
28
|
+
import unittest
|
|
29
|
+
from array import array
|
|
30
|
+
from functools import total_ordering
|
|
31
|
+
from typing import Callable, ClassVar
|
|
29
32
|
|
|
30
|
-
from crcmod import
|
|
33
|
+
from crcmod import Crc, mkCrcFun
|
|
31
34
|
from crcmod.crcmod import _usingExtension
|
|
32
|
-
from crcmod.predefined import PredefinedCrc
|
|
33
|
-
from crcmod.predefined import mkPredefinedCrcFun
|
|
35
|
+
from crcmod.predefined import PredefinedCrc, mkPredefinedCrcFun
|
|
34
36
|
from crcmod.predefined import _crc_definitions as _predefined_crc_definitions
|
|
35
37
|
|
|
36
|
-
from functools import total_ordering
|
|
37
|
-
|
|
38
|
-
|
|
39
38
|
# -----------------------------------------------------------------------------
|
|
40
39
|
# This polynomial was chosen because it is the product of two irreducible
|
|
41
40
|
# polynomials.
|
|
@@ -246,7 +245,7 @@ class poly:
|
|
|
246
245
|
return self.__divmod__(other)[1]
|
|
247
246
|
|
|
248
247
|
def __repr__(self):
|
|
249
|
-
return "poly(0x
|
|
248
|
+
return f"poly(0x{self.p:X}L)"
|
|
250
249
|
|
|
251
250
|
def __str__(self):
|
|
252
251
|
p = self.p
|
|
@@ -257,7 +256,7 @@ class poly:
|
|
|
257
256
|
n = 2
|
|
258
257
|
while p:
|
|
259
258
|
if p & 1:
|
|
260
|
-
lst.append("x
|
|
259
|
+
lst.append(f"x^{n}")
|
|
261
260
|
p = p >> 1
|
|
262
261
|
n += 1
|
|
263
262
|
lst.reverse()
|
|
@@ -356,12 +355,12 @@ def crc64bp(d):
|
|
|
356
355
|
|
|
357
356
|
|
|
358
357
|
class KnownAnswerTests(unittest.TestCase):
|
|
359
|
-
test_messages = [
|
|
358
|
+
test_messages: ClassVar[list[bytes]] = [
|
|
360
359
|
b"T",
|
|
361
360
|
b"CatMouse987654321",
|
|
362
361
|
]
|
|
363
362
|
|
|
364
|
-
known_answers = [
|
|
363
|
+
known_answers: ClassVar[list[list[tuple[int, ...]]]] = [
|
|
365
364
|
[(g8, 0, 0), (0xFE, 0x9D)],
|
|
366
365
|
[(g8, -1, 1), (0x4F, 0x9B)],
|
|
367
366
|
[(g8, 0, 1), (0xFE, 0x62)],
|
|
@@ -383,38 +382,35 @@ class KnownAnswerTests(unittest.TestCase):
|
|
|
383
382
|
self.assertEqual(
|
|
384
383
|
crcfun(b"", 0),
|
|
385
384
|
0,
|
|
386
|
-
"Wrong answer for CRC parameters
|
|
385
|
+
f"Wrong answer for CRC parameters {crcfun_params}, input ''",
|
|
387
386
|
)
|
|
388
387
|
for i, msg in enumerate(self.test_messages):
|
|
389
388
|
self.assertEqual(
|
|
390
389
|
crcfun(msg),
|
|
391
390
|
v[i],
|
|
392
|
-
"Wrong answer for CRC parameters
|
|
393
|
-
% (crcfun_params, msg),
|
|
391
|
+
f"Wrong answer for CRC parameters {crcfun_params}, input '{msg}'",
|
|
394
392
|
)
|
|
395
393
|
self.assertEqual(
|
|
396
394
|
crcfun(msg[4:], crcfun(msg[:4])),
|
|
397
395
|
v[i],
|
|
398
|
-
"Wrong answer for CRC parameters
|
|
399
|
-
% (crcfun_params, msg),
|
|
396
|
+
f"Wrong answer for CRC parameters {crcfun_params}, input '{msg}'",
|
|
400
397
|
)
|
|
401
398
|
self.assertEqual(
|
|
402
399
|
crcfun(msg[-1:], crcfun(msg[:-1])),
|
|
403
400
|
v[i],
|
|
404
|
-
"Wrong answer for CRC parameters
|
|
405
|
-
% (crcfun_params, msg),
|
|
401
|
+
f"Wrong answer for CRC parameters {crcfun_params}, input '{msg}'",
|
|
406
402
|
)
|
|
407
403
|
|
|
408
404
|
|
|
409
405
|
class CompareReferenceCrcTest(unittest.TestCase):
|
|
410
|
-
test_messages = [
|
|
406
|
+
test_messages: ClassVar[list[bytes]] = [
|
|
411
407
|
b"",
|
|
412
408
|
b"T",
|
|
413
409
|
b"123456789",
|
|
414
410
|
b"CatMouse987654321",
|
|
415
411
|
]
|
|
416
412
|
|
|
417
|
-
test_poly_crcs = [
|
|
413
|
+
test_poly_crcs: ClassVar[list[tuple[tuple[int, ...], Callable[[bytes], int]]]] = [
|
|
418
414
|
[(g8, 0, 0), crc8p],
|
|
419
415
|
[(g16, 0, 0), crc16p],
|
|
420
416
|
[(g24, 0, 0), crc24p],
|
|
@@ -537,13 +533,13 @@ crcValue = 0x00000000"""
|
|
|
537
533
|
class PredefinedCrcTest(unittest.TestCase):
|
|
538
534
|
"""Verify the predefined CRCs"""
|
|
539
535
|
|
|
540
|
-
test_messages_for_known_answers = [
|
|
536
|
+
test_messages_for_known_answers: ClassVar[list[bytes]] = [
|
|
541
537
|
b"", # Test cases below depend on this first entry being the empty string.
|
|
542
538
|
b"T",
|
|
543
539
|
b"CatMouse987654321",
|
|
544
540
|
]
|
|
545
541
|
|
|
546
|
-
known_answers = [
|
|
542
|
+
known_answers: ClassVar[list[list[str | tuple[int, ...]]]] = [
|
|
547
543
|
["crc-aug-ccitt", (0x1D0F, 0xD6ED, 0x5637)],
|
|
548
544
|
["x-25", (0x0000, 0xE4D9, 0x0A91)],
|
|
549
545
|
["crc-32", (0x00000000, 0xBE047A60, 0x084BFF58)],
|
|
@@ -553,23 +549,23 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
553
549
|
for crcfun_name, v in self.known_answers:
|
|
554
550
|
crcfun = mkPredefinedCrcFun(crcfun_name)
|
|
555
551
|
self.assertEqual(
|
|
556
|
-
crcfun(b"", 0), 0, "Wrong answer for CRC '
|
|
552
|
+
crcfun(b"", 0), 0, f"Wrong answer for CRC '{crcfun_name}', input ''"
|
|
557
553
|
)
|
|
558
554
|
for i, msg in enumerate(self.test_messages_for_known_answers):
|
|
559
555
|
self.assertEqual(
|
|
560
556
|
crcfun(msg),
|
|
561
557
|
v[i],
|
|
562
|
-
"Wrong answer for CRC
|
|
558
|
+
f"Wrong answer for CRC {crcfun_name}, input '{msg}'",
|
|
563
559
|
)
|
|
564
560
|
self.assertEqual(
|
|
565
561
|
crcfun(msg[4:], crcfun(msg[:4])),
|
|
566
562
|
v[i],
|
|
567
|
-
"Wrong answer for CRC
|
|
563
|
+
f"Wrong answer for CRC {crcfun_name}, input '{msg}'",
|
|
568
564
|
)
|
|
569
565
|
self.assertEqual(
|
|
570
566
|
crcfun(msg[-1:], crcfun(msg[:-1])),
|
|
571
567
|
v[i],
|
|
572
|
-
"Wrong answer for CRC
|
|
568
|
+
f"Wrong answer for CRC {crcfun_name}, input '{msg}'",
|
|
573
569
|
)
|
|
574
570
|
|
|
575
571
|
def test_class_with_known_answers(self):
|
|
@@ -580,7 +576,7 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
580
576
|
self.assertEqual(
|
|
581
577
|
crc1.crcValue,
|
|
582
578
|
v[i],
|
|
583
|
-
"Wrong answer for crc1
|
|
579
|
+
f"Wrong answer for crc1 {crcfun_name}, input '{msg}'",
|
|
584
580
|
)
|
|
585
581
|
|
|
586
582
|
crc2 = crc1.new()
|
|
@@ -588,7 +584,7 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
588
584
|
self.assertEqual(
|
|
589
585
|
crc1.crcValue,
|
|
590
586
|
v[i],
|
|
591
|
-
"Wrong state for crc1
|
|
587
|
+
f"Wrong state for crc1 {crcfun_name}, input '{msg}'",
|
|
592
588
|
)
|
|
593
589
|
# Check that the new class instance created by .new() contains
|
|
594
590
|
# the initialisation value. This depends on the first string in
|
|
@@ -596,7 +592,7 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
596
592
|
self.assertEqual(
|
|
597
593
|
crc2.crcValue,
|
|
598
594
|
v[0],
|
|
599
|
-
"Wrong state for crc2
|
|
595
|
+
f"Wrong state for crc2 {crcfun_name}, input '{msg}'",
|
|
600
596
|
)
|
|
601
597
|
|
|
602
598
|
crc2.update(msg)
|
|
@@ -605,13 +601,13 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
605
601
|
self.assertEqual(
|
|
606
602
|
crc1.crcValue,
|
|
607
603
|
v[i],
|
|
608
|
-
"Wrong state for crc1
|
|
604
|
+
f"Wrong state for crc1 {crcfun_name}, input '{msg}'",
|
|
609
605
|
)
|
|
610
606
|
# Check that crc2 contains the right value after calling .update()
|
|
611
607
|
self.assertEqual(
|
|
612
608
|
crc2.crcValue,
|
|
613
609
|
v[i],
|
|
614
|
-
"Wrong state for crc2
|
|
610
|
+
f"Wrong state for crc2 {crcfun_name}, input '{msg}'",
|
|
615
611
|
)
|
|
616
612
|
|
|
617
613
|
def test_function_predefined_table(self):
|
|
@@ -622,7 +618,7 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
622
618
|
self.assertEqual(
|
|
623
619
|
calc_value,
|
|
624
620
|
table_entry["check"],
|
|
625
|
-
"Wrong answer for CRC '
|
|
621
|
+
f"Wrong answer for CRC '{table_entry['name']}'",
|
|
626
622
|
)
|
|
627
623
|
|
|
628
624
|
def test_class_predefined_table(self):
|
|
@@ -633,7 +629,7 @@ class PredefinedCrcTest(unittest.TestCase):
|
|
|
633
629
|
self.assertEqual(
|
|
634
630
|
crc1.crcValue,
|
|
635
631
|
table_entry["check"],
|
|
636
|
-
"Wrong answer for CRC '
|
|
632
|
+
f"Wrong answer for CRC '{table_entry['name']}'",
|
|
637
633
|
)
|
|
638
634
|
|
|
639
635
|
|
|
@@ -642,13 +638,13 @@ class InputTypesTest(unittest.TestCase):
|
|
|
642
638
|
|
|
643
639
|
msg = b"CatMouse987654321"
|
|
644
640
|
|
|
645
|
-
check_crc_names = [
|
|
641
|
+
check_crc_names: ClassVar[list[str]] = [
|
|
646
642
|
"crc-aug-ccitt",
|
|
647
643
|
"x-25",
|
|
648
644
|
"crc-32",
|
|
649
645
|
]
|
|
650
646
|
|
|
651
|
-
array_check_types = [
|
|
647
|
+
array_check_types: ClassVar[list[str]] = [
|
|
652
648
|
"B",
|
|
653
649
|
"H",
|
|
654
650
|
"I",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|