hexconv 0.3.0__tar.gz → 0.3.1__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.
- {hexconv-0.3.0/src/hexconv.egg-info → hexconv-0.3.1}/PKG-INFO +20 -1
- {hexconv-0.3.0 → hexconv-0.3.1}/README.md +17 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/pyproject.toml +21 -1
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv/__init__.py +65 -53
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv/_core.py +35 -34
- {hexconv-0.3.0 → hexconv-0.3.1/src/hexconv.egg-info}/PKG-INFO +20 -1
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv.egg-info/requires.txt +2 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/LICENSE +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/MANIFEST.in +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/setup.cfg +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv/py.typed +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv.egg-info/SOURCES.txt +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv.egg-info/dependency_links.txt +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/src/hexconv.egg-info/top_level.txt +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/tests/test_hexconv.py +0 -0
- {hexconv-0.3.0 → hexconv-0.3.1}/tests/test_properties.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexconv
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Pythonic conversion toolkit for bytes, hex, integers, arrays, binary strings, base64, and text.
|
|
5
5
|
Author: hexconv contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -24,7 +24,9 @@ License-File: LICENSE
|
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: build; extra == "dev"
|
|
26
26
|
Requires-Dist: hypothesis; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy; extra == "dev"
|
|
27
28
|
Requires-Dist: pytest; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
28
30
|
Requires-Dist: twine; extra == "dev"
|
|
29
31
|
Dynamic: license-file
|
|
30
32
|
|
|
@@ -320,6 +322,23 @@ Available format specs all work in their simplest bare form:
|
|
|
320
322
|
- `Bits()`
|
|
321
323
|
- `Auto()`
|
|
322
324
|
|
|
325
|
+
The short names are ergonomic aliases of the explicit long-form specs — pick
|
|
326
|
+
whichever reads better, they resolve to the same format:
|
|
327
|
+
|
|
328
|
+
| Short | Long form |
|
|
329
|
+
| --- | --- |
|
|
330
|
+
| `Hex` | `HexString` |
|
|
331
|
+
| `Binary` | `BinaryString` |
|
|
332
|
+
| `Base64` / `Base32` / `Base85` / `Ascii85` | `Base64String` / `Base32String` / `Base85String` / `Ascii85String` |
|
|
333
|
+
| `Escaped` | `EscapedString` |
|
|
334
|
+
| `Hexdump` | `HexDump` |
|
|
335
|
+
| `Struct` | `StructFormat` |
|
|
336
|
+
| `Bits` | `BitArray` |
|
|
337
|
+
| `DecimalInt` / `DecimalIntArray` | `Int` / `IntArray` |
|
|
338
|
+
| `LargeHexNumber` | `HexInt` |
|
|
339
|
+
| `ASCIIText` / `RawString` | `Text` |
|
|
340
|
+
| `Group` (transform) | `Chunk` |
|
|
341
|
+
|
|
323
342
|
Add options only when you need control over formatting or parsing:
|
|
324
343
|
|
|
325
344
|
- Display: `Hex(sep=" ", prefix=True, uppercase=True)`, `HexArray(width=2)`.
|
|
@@ -290,6 +290,23 @@ Available format specs all work in their simplest bare form:
|
|
|
290
290
|
- `Bits()`
|
|
291
291
|
- `Auto()`
|
|
292
292
|
|
|
293
|
+
The short names are ergonomic aliases of the explicit long-form specs — pick
|
|
294
|
+
whichever reads better, they resolve to the same format:
|
|
295
|
+
|
|
296
|
+
| Short | Long form |
|
|
297
|
+
| --- | --- |
|
|
298
|
+
| `Hex` | `HexString` |
|
|
299
|
+
| `Binary` | `BinaryString` |
|
|
300
|
+
| `Base64` / `Base32` / `Base85` / `Ascii85` | `Base64String` / `Base32String` / `Base85String` / `Ascii85String` |
|
|
301
|
+
| `Escaped` | `EscapedString` |
|
|
302
|
+
| `Hexdump` | `HexDump` |
|
|
303
|
+
| `Struct` | `StructFormat` |
|
|
304
|
+
| `Bits` | `BitArray` |
|
|
305
|
+
| `DecimalInt` / `DecimalIntArray` | `Int` / `IntArray` |
|
|
306
|
+
| `LargeHexNumber` | `HexInt` |
|
|
307
|
+
| `ASCIIText` / `RawString` | `Text` |
|
|
308
|
+
| `Group` (transform) | `Chunk` |
|
|
309
|
+
|
|
293
310
|
Add options only when you need control over formatting or parsing:
|
|
294
311
|
|
|
295
312
|
- Display: `Hex(sep=" ", prefix=True, uppercase=True)`, `HexArray(width=2)`.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hexconv"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Pythonic conversion toolkit for bytes, hex, integers, arrays, binary strings, base64, and text."
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -32,7 +32,9 @@ classifiers = [
|
|
|
32
32
|
dev = [
|
|
33
33
|
"build",
|
|
34
34
|
"hypothesis",
|
|
35
|
+
"mypy",
|
|
35
36
|
"pytest",
|
|
37
|
+
"ruff",
|
|
36
38
|
"twine",
|
|
37
39
|
]
|
|
38
40
|
|
|
@@ -45,3 +47,21 @@ hexconv = ["py.typed"]
|
|
|
45
47
|
[tool.pytest.ini_options]
|
|
46
48
|
testpaths = ["tests"]
|
|
47
49
|
pythonpath = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
line-length = 100
|
|
53
|
+
target-version = "py310"
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = ["E", "F", "I", "B", "UP"]
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint.per-file-ignores]
|
|
59
|
+
# Public re-exports are grouped by concept rather than sorted alphabetically.
|
|
60
|
+
"src/hexconv/__init__.py" = ["I001"]
|
|
61
|
+
|
|
62
|
+
[tool.mypy]
|
|
63
|
+
python_version = "3.10"
|
|
64
|
+
no_implicit_optional = true
|
|
65
|
+
warn_redundant_casts = true
|
|
66
|
+
warn_unused_ignores = true
|
|
67
|
+
strict_equality = true
|
|
@@ -1,52 +1,60 @@
|
|
|
1
1
|
"""Conversion toolkit for bytes, hex, integers, arrays, binary, base64, and text."""
|
|
2
2
|
|
|
3
3
|
from ._core import (
|
|
4
|
-
|
|
5
|
-
Auto,
|
|
4
|
+
# Core types and errors
|
|
6
5
|
AutoResult,
|
|
7
|
-
|
|
6
|
+
Converter,
|
|
7
|
+
HexConvError,
|
|
8
|
+
Pipeline,
|
|
9
|
+
Transform,
|
|
10
|
+
Value,
|
|
11
|
+
# Format specifications (explicit long-form names)
|
|
8
12
|
Ascii85String,
|
|
9
|
-
|
|
10
|
-
Base64,
|
|
11
|
-
Base32,
|
|
13
|
+
Auto,
|
|
12
14
|
Base32String,
|
|
13
|
-
|
|
15
|
+
Base64String,
|
|
14
16
|
Base85String,
|
|
15
17
|
BinaryString,
|
|
16
|
-
Binary,
|
|
17
18
|
BitArray,
|
|
18
|
-
Bits,
|
|
19
19
|
Bytes,
|
|
20
20
|
BytesArray,
|
|
21
21
|
BytesString,
|
|
22
|
-
Chunk,
|
|
23
|
-
Converter,
|
|
24
|
-
DecimalInt,
|
|
25
|
-
DecimalIntArray,
|
|
26
|
-
Escaped,
|
|
27
22
|
EscapedString,
|
|
28
|
-
Group,
|
|
29
|
-
Hex,
|
|
30
23
|
HexArray,
|
|
31
|
-
HexConvError,
|
|
32
24
|
HexDump,
|
|
33
|
-
Hexdump,
|
|
34
25
|
HexInt,
|
|
35
26
|
HexNumbersArray,
|
|
36
27
|
HexString,
|
|
37
28
|
Int,
|
|
38
29
|
IntArray,
|
|
30
|
+
StructFormat,
|
|
31
|
+
Text,
|
|
32
|
+
# Short, ergonomic aliases for the format specifications above
|
|
33
|
+
ASCIIText,
|
|
34
|
+
Ascii85,
|
|
35
|
+
Base32,
|
|
36
|
+
Base64,
|
|
37
|
+
Base85,
|
|
38
|
+
Binary,
|
|
39
|
+
Bits,
|
|
40
|
+
DecimalInt,
|
|
41
|
+
DecimalIntArray,
|
|
42
|
+
Escaped,
|
|
43
|
+
Hex,
|
|
44
|
+
Hexdump,
|
|
39
45
|
LargeHexNumber,
|
|
40
|
-
Pad,
|
|
41
|
-
Pipeline,
|
|
42
46
|
RawString,
|
|
43
|
-
Reverse,
|
|
44
47
|
Struct,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
# Pipeline transforms
|
|
49
|
+
Chunk,
|
|
50
|
+
Group,
|
|
51
|
+
Pad,
|
|
52
|
+
Reverse,
|
|
53
|
+
# One-shot conversion and pipeline builders
|
|
49
54
|
convert,
|
|
55
|
+
infer,
|
|
56
|
+
pipeline,
|
|
57
|
+
# Source helpers
|
|
50
58
|
from_ascii85,
|
|
51
59
|
from_auto,
|
|
52
60
|
from_base32,
|
|
@@ -66,57 +74,63 @@ from ._core import (
|
|
|
66
74
|
from_int_array,
|
|
67
75
|
from_struct,
|
|
68
76
|
from_text,
|
|
69
|
-
infer,
|
|
70
|
-
pipeline,
|
|
71
77
|
)
|
|
72
78
|
|
|
73
79
|
__all__ = [
|
|
74
|
-
|
|
75
|
-
"Auto",
|
|
80
|
+
# Core types and errors
|
|
76
81
|
"AutoResult",
|
|
77
|
-
"
|
|
82
|
+
"Converter",
|
|
83
|
+
"HexConvError",
|
|
84
|
+
"Pipeline",
|
|
85
|
+
"Transform",
|
|
86
|
+
"Value",
|
|
87
|
+
# Format specifications (explicit long-form names)
|
|
78
88
|
"Ascii85String",
|
|
79
|
-
"
|
|
89
|
+
"Auto",
|
|
80
90
|
"Base32String",
|
|
81
91
|
"Base64String",
|
|
82
|
-
"Base64",
|
|
83
|
-
"Base85",
|
|
84
92
|
"Base85String",
|
|
85
|
-
"Binary",
|
|
86
93
|
"BinaryString",
|
|
87
94
|
"BitArray",
|
|
88
|
-
"Bits",
|
|
89
95
|
"Bytes",
|
|
90
96
|
"BytesArray",
|
|
91
97
|
"BytesString",
|
|
92
|
-
"Chunk",
|
|
93
|
-
"Converter",
|
|
94
|
-
"DecimalInt",
|
|
95
|
-
"DecimalIntArray",
|
|
96
|
-
"Escaped",
|
|
97
98
|
"EscapedString",
|
|
98
|
-
"Group",
|
|
99
|
-
"Hex",
|
|
100
99
|
"HexArray",
|
|
101
|
-
"HexConvError",
|
|
102
100
|
"HexDump",
|
|
103
|
-
"Hexdump",
|
|
104
101
|
"HexInt",
|
|
105
102
|
"HexNumbersArray",
|
|
106
103
|
"HexString",
|
|
107
104
|
"Int",
|
|
108
105
|
"IntArray",
|
|
106
|
+
"StructFormat",
|
|
107
|
+
"Text",
|
|
108
|
+
# Short, ergonomic aliases for the format specifications above
|
|
109
|
+
"ASCIIText",
|
|
110
|
+
"Ascii85",
|
|
111
|
+
"Base32",
|
|
112
|
+
"Base64",
|
|
113
|
+
"Base85",
|
|
114
|
+
"Binary",
|
|
115
|
+
"Bits",
|
|
116
|
+
"DecimalInt",
|
|
117
|
+
"DecimalIntArray",
|
|
118
|
+
"Escaped",
|
|
119
|
+
"Hex",
|
|
120
|
+
"Hexdump",
|
|
109
121
|
"LargeHexNumber",
|
|
110
|
-
"Pad",
|
|
111
|
-
"Pipeline",
|
|
112
122
|
"RawString",
|
|
113
|
-
"Reverse",
|
|
114
123
|
"Struct",
|
|
115
|
-
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
124
|
+
# Pipeline transforms
|
|
125
|
+
"Chunk",
|
|
126
|
+
"Group",
|
|
127
|
+
"Pad",
|
|
128
|
+
"Reverse",
|
|
129
|
+
# One-shot conversion and pipeline builders
|
|
119
130
|
"convert",
|
|
131
|
+
"infer",
|
|
132
|
+
"pipeline",
|
|
133
|
+
# Source helpers
|
|
120
134
|
"from_ascii85",
|
|
121
135
|
"from_auto",
|
|
122
136
|
"from_base32",
|
|
@@ -136,6 +150,4 @@ __all__ = [
|
|
|
136
150
|
"from_int_array",
|
|
137
151
|
"from_struct",
|
|
138
152
|
"from_text",
|
|
139
|
-
"infer",
|
|
140
|
-
"pipeline",
|
|
141
153
|
]
|
|
@@ -3,12 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import ast
|
|
4
4
|
import base64
|
|
5
5
|
import binascii
|
|
6
|
+
import builtins
|
|
6
7
|
import codecs
|
|
7
8
|
import re
|
|
8
9
|
import struct
|
|
9
|
-
from collections.abc import Iterable
|
|
10
|
+
from collections.abc import Callable, Iterable
|
|
10
11
|
from dataclasses import dataclass, field
|
|
11
|
-
from typing import Any,
|
|
12
|
+
from typing import Any, Literal, TypeAlias, overload
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class HexConvError(ValueError):
|
|
@@ -18,12 +19,12 @@ class HexConvError(ValueError):
|
|
|
18
19
|
class _Format:
|
|
19
20
|
"""Base class for public format marker classes."""
|
|
20
21
|
|
|
21
|
-
def __call__(self, value: Any) ->
|
|
22
|
+
def __call__(self, value: Any) -> Value:
|
|
22
23
|
"""Parse a value using this configured format."""
|
|
23
24
|
|
|
24
25
|
return _parse(value, self)
|
|
25
26
|
|
|
26
|
-
def __rshift__(self, other: Any) ->
|
|
27
|
+
def __rshift__(self, other: Any) -> Pipeline:
|
|
27
28
|
"""Compose this format with a transform, target format, or pipeline."""
|
|
28
29
|
|
|
29
30
|
return Pipeline(source=self) >> other
|
|
@@ -87,7 +88,7 @@ class HexArray(_Format):
|
|
|
87
88
|
width: int | None = None,
|
|
88
89
|
prefix: bool = False,
|
|
89
90
|
uppercase: bool = False,
|
|
90
|
-
endian:
|
|
91
|
+
endian: Endian = "big",
|
|
91
92
|
pad_odd: bool = True,
|
|
92
93
|
) -> None:
|
|
93
94
|
self.width = width
|
|
@@ -118,7 +119,7 @@ class HexNumbersArray(_Format):
|
|
|
118
119
|
self,
|
|
119
120
|
*,
|
|
120
121
|
width: int | None = 1,
|
|
121
|
-
endian:
|
|
122
|
+
endian: Endian = "big",
|
|
122
123
|
signed: bool = False,
|
|
123
124
|
) -> None:
|
|
124
125
|
self.width = width
|
|
@@ -140,7 +141,7 @@ class HexInt(_Format):
|
|
|
140
141
|
*,
|
|
141
142
|
min_width: int = 1,
|
|
142
143
|
width: int | None = None,
|
|
143
|
-
endian:
|
|
144
|
+
endian: Endian = "big",
|
|
144
145
|
signed: bool = False,
|
|
145
146
|
pad_odd: bool = True,
|
|
146
147
|
) -> None:
|
|
@@ -174,7 +175,7 @@ class Int(_Format):
|
|
|
174
175
|
*,
|
|
175
176
|
min_width: int = 1,
|
|
176
177
|
width: int | None = None,
|
|
177
|
-
endian:
|
|
178
|
+
endian: Endian = "big",
|
|
178
179
|
signed: bool = False,
|
|
179
180
|
) -> None:
|
|
180
181
|
self.min_width = min_width
|
|
@@ -205,7 +206,7 @@ class IntArray(_Format):
|
|
|
205
206
|
self,
|
|
206
207
|
*,
|
|
207
208
|
width: int | None = None,
|
|
208
|
-
endian:
|
|
209
|
+
endian: Endian = "big",
|
|
209
210
|
signed: bool = False,
|
|
210
211
|
) -> None:
|
|
211
212
|
self.width = width
|
|
@@ -258,7 +259,7 @@ class BinaryString(_Format):
|
|
|
258
259
|
sep: str = "",
|
|
259
260
|
prefix: bool = False,
|
|
260
261
|
pad_odd: bool = True,
|
|
261
|
-
bit_order:
|
|
262
|
+
bit_order: BitOrder = "msb",
|
|
262
263
|
) -> None:
|
|
263
264
|
self.sep = sep
|
|
264
265
|
self.prefix = prefix
|
|
@@ -414,9 +415,9 @@ class BitArray(_Format):
|
|
|
414
415
|
def __init__(
|
|
415
416
|
self,
|
|
416
417
|
*,
|
|
417
|
-
bit_order:
|
|
418
|
+
bit_order: BitOrder = "msb",
|
|
418
419
|
pad: bool = True,
|
|
419
|
-
pad_side:
|
|
420
|
+
pad_side: PadSide = "left",
|
|
420
421
|
) -> None:
|
|
421
422
|
self.bit_order = bit_order
|
|
422
423
|
self.pad = pad
|
|
@@ -468,12 +469,12 @@ class Value:
|
|
|
468
469
|
source: str | None = None
|
|
469
470
|
meta: dict[str, Any] = field(default_factory=dict)
|
|
470
471
|
|
|
471
|
-
def with_data(self, data: bytes, *, source: str | None = None) ->
|
|
472
|
+
def with_data(self, data: bytes, *, source: str | None = None) -> Value:
|
|
472
473
|
"""Return a copy with different bytes and preserved metadata."""
|
|
473
474
|
|
|
474
475
|
return Value(bytes(data), source=source or self.source, meta=dict(self.meta))
|
|
475
476
|
|
|
476
|
-
def with_meta(self, **meta: Any) ->
|
|
477
|
+
def with_meta(self, **meta: Any) -> Value:
|
|
477
478
|
"""Return a copy with additional metadata used by composable transforms."""
|
|
478
479
|
|
|
479
480
|
merged = dict(self.meta)
|
|
@@ -773,17 +774,18 @@ class Value:
|
|
|
773
774
|
raise HexConvError("chunk width cannot be None")
|
|
774
775
|
return chunk_width
|
|
775
776
|
|
|
776
|
-
#
|
|
777
|
-
#
|
|
778
|
-
#
|
|
777
|
+
# ``int``/``integer`` are convenience shortcuts whose names shadow the builtin
|
|
778
|
+
# ``int``. They are declared after every method above so those methods keep
|
|
779
|
+
# annotating with the builtin, and they spell their own return type as
|
|
780
|
+
# ``builtins.int`` so their order here does not matter.
|
|
779
781
|
@property
|
|
780
|
-
def
|
|
782
|
+
def int(self) -> builtins.int:
|
|
781
783
|
"""Shortcut for to_int()."""
|
|
782
784
|
|
|
783
785
|
return self.to_int()
|
|
784
786
|
|
|
785
787
|
@property
|
|
786
|
-
def
|
|
788
|
+
def integer(self) -> builtins.int:
|
|
787
789
|
"""Shortcut for to_int()."""
|
|
788
790
|
|
|
789
791
|
return self.to_int()
|
|
@@ -805,7 +807,7 @@ class Transform:
|
|
|
805
807
|
def __call__(self, value: Any) -> Value:
|
|
806
808
|
return self.apply(_ensure_value(value))
|
|
807
809
|
|
|
808
|
-
def __rshift__(self, other: Any) ->
|
|
810
|
+
def __rshift__(self, other: Any) -> Pipeline:
|
|
809
811
|
return Pipeline(transforms=[self]) >> other
|
|
810
812
|
|
|
811
813
|
def apply(self, value: Value) -> Value:
|
|
@@ -861,7 +863,7 @@ class Pad(Transform):
|
|
|
861
863
|
width: int | None = None,
|
|
862
864
|
block_size: int | None = None,
|
|
863
865
|
byte: int = 0,
|
|
864
|
-
) ->
|
|
866
|
+
) -> Pad:
|
|
865
867
|
return cls(width=width, block_size=block_size, byte=byte, side="left")
|
|
866
868
|
|
|
867
869
|
@classmethod
|
|
@@ -871,7 +873,7 @@ class Pad(Transform):
|
|
|
871
873
|
width: int | None = None,
|
|
872
874
|
block_size: int | None = None,
|
|
873
875
|
byte: int = 0,
|
|
874
|
-
) ->
|
|
876
|
+
) -> Pad:
|
|
875
877
|
return cls(width=width, block_size=block_size, byte=byte, side="right")
|
|
876
878
|
|
|
877
879
|
def apply(self, value: Value) -> Value:
|
|
@@ -908,23 +910,23 @@ class Pipeline:
|
|
|
908
910
|
self.transforms = list(transforms or [])
|
|
909
911
|
self.target = target
|
|
910
912
|
|
|
911
|
-
def from_(self, source: FormatLike) ->
|
|
913
|
+
def from_(self, source: FormatLike) -> Pipeline:
|
|
912
914
|
return Pipeline(source=source, transforms=self.transforms, target=self.target)
|
|
913
915
|
|
|
914
|
-
def to(self, target: FormatLike) ->
|
|
916
|
+
def to(self, target: FormatLike) -> Pipeline:
|
|
915
917
|
return Pipeline(source=self.source, transforms=self.transforms, target=target)
|
|
916
918
|
|
|
917
|
-
def then(self, transform: Transform) ->
|
|
919
|
+
def then(self, transform: Transform) -> Pipeline:
|
|
918
920
|
return Pipeline(
|
|
919
921
|
source=self.source,
|
|
920
922
|
transforms=[*self.transforms, transform],
|
|
921
923
|
target=self.target,
|
|
922
924
|
)
|
|
923
925
|
|
|
924
|
-
def chunk(self, width: int, *, strict: bool = True) ->
|
|
926
|
+
def chunk(self, width: int, *, strict: bool = True) -> Pipeline:
|
|
925
927
|
return self.then(Chunk(width, strict=strict))
|
|
926
928
|
|
|
927
|
-
def group(self, width: int, *, strict: bool = True) ->
|
|
929
|
+
def group(self, width: int, *, strict: bool = True) -> Pipeline:
|
|
928
930
|
return self.then(Group(width, strict=strict))
|
|
929
931
|
|
|
930
932
|
def pad(
|
|
@@ -934,13 +936,13 @@ class Pipeline:
|
|
|
934
936
|
block_size: int | None = None,
|
|
935
937
|
byte: int = 0,
|
|
936
938
|
side: PadSide = "left",
|
|
937
|
-
) ->
|
|
939
|
+
) -> Pipeline:
|
|
938
940
|
return self.then(Pad(width=width, block_size=block_size, byte=byte, side=side))
|
|
939
941
|
|
|
940
|
-
def reverse(self) ->
|
|
942
|
+
def reverse(self) -> Pipeline:
|
|
941
943
|
return self.then(Reverse())
|
|
942
944
|
|
|
943
|
-
def __rshift__(self, other: Any) ->
|
|
945
|
+
def __rshift__(self, other: Any) -> Pipeline:
|
|
944
946
|
if isinstance(other, Pipeline):
|
|
945
947
|
source = self.source if self.source is not None else other.source
|
|
946
948
|
return Pipeline(
|
|
@@ -1657,10 +1659,7 @@ def _format_options(format_: FormatLike, direction: str) -> dict[str, Any]:
|
|
|
1657
1659
|
def _ensure_value(value: Any) -> Value:
|
|
1658
1660
|
if isinstance(value, Value):
|
|
1659
1661
|
return value
|
|
1660
|
-
|
|
1661
|
-
if isinstance(parsed, AutoResult):
|
|
1662
|
-
return parsed.value
|
|
1663
|
-
return parsed
|
|
1662
|
+
return from_auto(value)
|
|
1664
1663
|
|
|
1665
1664
|
|
|
1666
1665
|
def _validate_endian(endian: Endian) -> None:
|
|
@@ -1850,6 +1849,8 @@ def _int_to_bytes(
|
|
|
1850
1849
|
|
|
1851
1850
|
|
|
1852
1851
|
def _signed_int_to_minimal_bytes(value: int, *, min_width: int, endian: Endian) -> bytes:
|
|
1852
|
+
# Two's complement needs a bit beyond the magnitude for the sign, so start
|
|
1853
|
+
# one byte wider than the magnitude and widen further until the value fits.
|
|
1853
1854
|
candidate = max(min_width, 1, (abs(value).bit_length() + 8) // 8)
|
|
1854
1855
|
for width in range(candidate, candidate + 2):
|
|
1855
1856
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexconv
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Pythonic conversion toolkit for bytes, hex, integers, arrays, binary strings, base64, and text.
|
|
5
5
|
Author: hexconv contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -24,7 +24,9 @@ License-File: LICENSE
|
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: build; extra == "dev"
|
|
26
26
|
Requires-Dist: hypothesis; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy; extra == "dev"
|
|
27
28
|
Requires-Dist: pytest; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
28
30
|
Requires-Dist: twine; extra == "dev"
|
|
29
31
|
Dynamic: license-file
|
|
30
32
|
|
|
@@ -320,6 +322,23 @@ Available format specs all work in their simplest bare form:
|
|
|
320
322
|
- `Bits()`
|
|
321
323
|
- `Auto()`
|
|
322
324
|
|
|
325
|
+
The short names are ergonomic aliases of the explicit long-form specs — pick
|
|
326
|
+
whichever reads better, they resolve to the same format:
|
|
327
|
+
|
|
328
|
+
| Short | Long form |
|
|
329
|
+
| --- | --- |
|
|
330
|
+
| `Hex` | `HexString` |
|
|
331
|
+
| `Binary` | `BinaryString` |
|
|
332
|
+
| `Base64` / `Base32` / `Base85` / `Ascii85` | `Base64String` / `Base32String` / `Base85String` / `Ascii85String` |
|
|
333
|
+
| `Escaped` | `EscapedString` |
|
|
334
|
+
| `Hexdump` | `HexDump` |
|
|
335
|
+
| `Struct` | `StructFormat` |
|
|
336
|
+
| `Bits` | `BitArray` |
|
|
337
|
+
| `DecimalInt` / `DecimalIntArray` | `Int` / `IntArray` |
|
|
338
|
+
| `LargeHexNumber` | `HexInt` |
|
|
339
|
+
| `ASCIIText` / `RawString` | `Text` |
|
|
340
|
+
| `Group` (transform) | `Chunk` |
|
|
341
|
+
|
|
323
342
|
Add options only when you need control over formatting or parsing:
|
|
324
343
|
|
|
325
344
|
- Display: `Hex(sep=" ", prefix=True, uppercase=True)`, `HexArray(width=2)`.
|
|
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
|