cuid2 2.0.0__tar.gz → 2.0.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.
- {cuid2-2.0.0 → cuid2-2.0.1}/PKG-INFO +2 -2
- {cuid2-2.0.0 → cuid2-2.0.1}/pyproject.toml +47 -39
- {cuid2-2.0.0 → cuid2-2.0.1}/src/cuid2/__init__.py +1 -0
- {cuid2-2.0.0 → cuid2-2.0.1}/src/cuid2/generator.py +8 -7
- {cuid2-2.0.0 → cuid2-2.0.1}/src/cuid2/utils.py +6 -4
- {cuid2-2.0.0 → cuid2-2.0.1}/LICENSE +0 -0
- {cuid2-2.0.0 → cuid2-2.0.1}/README.md +0 -0
- {cuid2-2.0.0 → cuid2-2.0.1}/src/cuid2/cli.py +0 -0
- {cuid2-2.0.0 → cuid2-2.0.1}/src/cuid2/py.typed +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cuid2
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: Next generation GUIDs. Collision-resistant ids optimized for horizontal scaling and performance.
|
|
5
|
-
Keywords: crypt
|
|
5
|
+
Keywords: crypt,security,uuid,guid,cuid,cryptography
|
|
6
6
|
Author-Email: Will Gordon <wgordon@redhat.com>
|
|
7
7
|
License: The MIT License (MIT)
|
|
8
8
|
|
|
@@ -31,7 +31,7 @@ keywords = [
|
|
|
31
31
|
"cuid",
|
|
32
32
|
"cryptography",
|
|
33
33
|
]
|
|
34
|
-
version = "2.0.
|
|
34
|
+
version = "2.0.1"
|
|
35
35
|
|
|
36
36
|
[project.license]
|
|
37
37
|
file = "LICENSE"
|
|
@@ -46,60 +46,61 @@ cuid2 = "cuid2.cli:main"
|
|
|
46
46
|
source = "scm"
|
|
47
47
|
|
|
48
48
|
[tool.pdm.scripts]
|
|
49
|
-
|
|
50
|
-
ruff = "ruff
|
|
49
|
+
ruff-check = "ruff check --fix --exit-zero {args:src/ local/tests/}"
|
|
50
|
+
ruff-format = "ruff format {args:src/ local/tests/}"
|
|
51
51
|
spelling = "codespell {args:src/ local/tests/}"
|
|
52
52
|
pylint = "pylint {args:src/ local/tests/}"
|
|
53
|
-
safety = "safety check --bare"
|
|
53
|
+
safety = "safety {args:check --bare}"
|
|
54
54
|
typing = "mypy {args:src/ local/tests/}"
|
|
55
|
+
update-pip = "pip install --upgrade pip"
|
|
55
56
|
testing = "pytest local/tests"
|
|
56
57
|
testing-slow = "pytest local/tests --runslow"
|
|
57
58
|
tox = "tox --parallel auto"
|
|
58
59
|
|
|
59
|
-
[tool.pdm.scripts.
|
|
60
|
+
[tool.pdm.scripts.ruff-fix]
|
|
60
61
|
composite = [
|
|
61
|
-
"
|
|
62
|
-
"ruff",
|
|
62
|
+
"ruff-check",
|
|
63
|
+
"ruff-format",
|
|
63
64
|
]
|
|
64
65
|
|
|
65
66
|
[tool.pdm.scripts.lint-full]
|
|
66
67
|
composite = [
|
|
67
|
-
"
|
|
68
|
+
"ruff-fix",
|
|
68
69
|
"spelling",
|
|
69
70
|
"pylint",
|
|
70
71
|
"typing",
|
|
71
72
|
"safety",
|
|
72
73
|
]
|
|
73
74
|
|
|
75
|
+
[tool.pdm.scripts.tox-full]
|
|
76
|
+
composite = [
|
|
77
|
+
"update-pip",
|
|
78
|
+
"lint-full",
|
|
79
|
+
]
|
|
80
|
+
|
|
74
81
|
[tool.pdm.dev-dependencies]
|
|
75
82
|
lint = [
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"ruff~=0.
|
|
80
|
-
"safety==
|
|
83
|
+
"codespell~=2.2.6",
|
|
84
|
+
"pylint~=3.1.0",
|
|
85
|
+
"requests>=2.31.0",
|
|
86
|
+
"ruff~=0.3.7",
|
|
87
|
+
"safety==3.1.0",
|
|
81
88
|
]
|
|
82
89
|
test = [
|
|
83
|
-
"pytest~=
|
|
84
|
-
"pytest-mock~=3.
|
|
85
|
-
"pytest-sugar~=0.
|
|
90
|
+
"pytest~=8.1.1",
|
|
91
|
+
"pytest-mock~=3.14.0",
|
|
92
|
+
"pytest-sugar~=1.0.0",
|
|
86
93
|
]
|
|
87
94
|
tox = [
|
|
88
|
-
"tox~=4.
|
|
89
|
-
"tox-pdm~=0.
|
|
95
|
+
"tox~=4.14.2",
|
|
96
|
+
"tox-pdm~=0.7.2",
|
|
90
97
|
]
|
|
91
98
|
typing = [
|
|
92
|
-
"mypy~=1.
|
|
99
|
+
"mypy~=1.9.0",
|
|
93
100
|
]
|
|
94
101
|
|
|
95
102
|
[tool.tox]
|
|
96
|
-
legacy_tox_ini = " [tox]\n min_version = 4\n env_list = py3{8,9,10,11}, check\n work_dir = local/.tox\n isolated_build = True\n\n [testenv]\n description = run unit tests\n groups = test\n commands = testing\n\n [testenv:check]\n description = run linters and typing\n skip_install = true\n groups = lint, typing, test\n commands =
|
|
97
|
-
|
|
98
|
-
[tool.black]
|
|
99
|
-
line-length = 120
|
|
100
|
-
target_version = [
|
|
101
|
-
"py38",
|
|
102
|
-
]
|
|
103
|
+
legacy_tox_ini = " [tox]\n min_version = 4\n env_list = py3{8,9,10,11,12}, check\n work_dir = local/.tox\n isolated_build = True\n\n [testenv]\n description = run unit tests\n groups = test\n commands = testing\n\n [testenv:check]\n description = run linters and typing\n skip_install = true\n groups = lint, typing, test\n commands = tox-full\n"
|
|
103
104
|
|
|
104
105
|
[tool.ruff]
|
|
105
106
|
line-length = 120
|
|
@@ -108,12 +109,18 @@ src = [
|
|
|
108
109
|
]
|
|
109
110
|
target-version = "py38"
|
|
110
111
|
cache-dir = "local/.ruff_cache"
|
|
111
|
-
|
|
112
|
+
force-exclude = true
|
|
113
|
+
|
|
114
|
+
[tool.ruff.lint]
|
|
115
|
+
select = [
|
|
116
|
+
"F",
|
|
117
|
+
"E",
|
|
112
118
|
"W",
|
|
113
119
|
"C90",
|
|
114
120
|
"I",
|
|
115
121
|
"N",
|
|
116
|
-
"
|
|
122
|
+
"ASYNC",
|
|
123
|
+
"TRIO",
|
|
117
124
|
"S",
|
|
118
125
|
"BLE",
|
|
119
126
|
"B",
|
|
@@ -123,6 +130,7 @@ extend-select = [
|
|
|
123
130
|
"DTZ",
|
|
124
131
|
"T10",
|
|
125
132
|
"EM",
|
|
133
|
+
"FA",
|
|
126
134
|
"ISC",
|
|
127
135
|
"ICN",
|
|
128
136
|
"G",
|
|
@@ -134,6 +142,7 @@ extend-select = [
|
|
|
134
142
|
"RSE",
|
|
135
143
|
"RET",
|
|
136
144
|
"SLF",
|
|
145
|
+
"SLOT",
|
|
137
146
|
"SIM",
|
|
138
147
|
"INT",
|
|
139
148
|
"ARG",
|
|
@@ -141,36 +150,35 @@ extend-select = [
|
|
|
141
150
|
"PGH",
|
|
142
151
|
"PL",
|
|
143
152
|
"TRY",
|
|
153
|
+
"FLY",
|
|
154
|
+
"PERF",
|
|
155
|
+
"LOG",
|
|
144
156
|
"RUF",
|
|
145
|
-
"D",
|
|
146
|
-
"ANN",
|
|
147
|
-
"PYI",
|
|
148
|
-
"TCH",
|
|
149
|
-
"ERA",
|
|
150
157
|
]
|
|
151
|
-
|
|
158
|
+
ignore = [
|
|
152
159
|
"D100",
|
|
153
160
|
"D101",
|
|
154
161
|
"D102",
|
|
155
162
|
"D104",
|
|
156
163
|
"D205",
|
|
157
164
|
"D401",
|
|
165
|
+
"COM812",
|
|
166
|
+
"ISC001",
|
|
158
167
|
]
|
|
159
168
|
unfixable = [
|
|
160
169
|
"T201",
|
|
161
170
|
"F401",
|
|
162
171
|
"F841",
|
|
163
172
|
]
|
|
164
|
-
force-exclude = true
|
|
165
173
|
|
|
166
|
-
[tool.ruff.per-file-ignores]
|
|
174
|
+
[tool.ruff.lint.per-file-ignores]
|
|
167
175
|
"test_*.py" = [
|
|
168
176
|
"S101",
|
|
169
177
|
"PLR2004",
|
|
170
178
|
"SLF001",
|
|
171
179
|
]
|
|
172
180
|
|
|
173
|
-
[tool.ruff.isort]
|
|
181
|
+
[tool.ruff.lint.isort]
|
|
174
182
|
known-first-party = [
|
|
175
183
|
"src",
|
|
176
184
|
]
|
|
@@ -182,11 +190,11 @@ section-order = [
|
|
|
182
190
|
"local-folder",
|
|
183
191
|
]
|
|
184
192
|
|
|
185
|
-
[tool.ruff.pydocstyle]
|
|
193
|
+
[tool.ruff.lint.pydocstyle]
|
|
186
194
|
convention = "numpy"
|
|
187
195
|
|
|
188
196
|
[tool.pytest.ini_options]
|
|
189
|
-
minversion = "
|
|
197
|
+
minversion = "8.1"
|
|
190
198
|
cache_dir = "local/.pytest_cache"
|
|
191
199
|
python_files = "test_*.py"
|
|
192
200
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import time
|
|
2
4
|
from math import floor
|
|
3
5
|
from secrets import SystemRandom
|
|
@@ -9,8 +11,7 @@ if TYPE_CHECKING:
|
|
|
9
11
|
from _random import Random
|
|
10
12
|
|
|
11
13
|
class FingerprintCallable(Protocol): # pylint: disable=too-few-public-methods
|
|
12
|
-
def __call__(self:
|
|
13
|
-
...
|
|
14
|
+
def __call__(self: FingerprintCallable, random_generator: Random) -> str: ...
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
# ~22k hosts before 50% chance of initial counter collision
|
|
@@ -22,11 +23,11 @@ MAXIMUM_LENGTH: Final = 98
|
|
|
22
23
|
|
|
23
24
|
class Cuid: # pylint: disable=too-few-public-methods
|
|
24
25
|
def __init__(
|
|
25
|
-
self:
|
|
26
|
-
random_generator: Callable[[],
|
|
26
|
+
self: Cuid,
|
|
27
|
+
random_generator: Callable[[], Random] = SystemRandom,
|
|
27
28
|
counter: Callable[[int], Callable[[], int]] = utils.create_counter,
|
|
28
29
|
length: int = DEFAULT_LENGTH,
|
|
29
|
-
fingerprint:
|
|
30
|
+
fingerprint: FingerprintCallable = utils.create_fingerprint,
|
|
30
31
|
) -> None:
|
|
31
32
|
"""Initialization function for the Cuid class that generates a universally unique,
|
|
32
33
|
base36 encoded string.
|
|
@@ -55,12 +56,12 @@ class Cuid: # pylint: disable=too-few-public-methods
|
|
|
55
56
|
msg = "Length must never exceed 98 characters."
|
|
56
57
|
raise ValueError(msg)
|
|
57
58
|
|
|
58
|
-
self._random:
|
|
59
|
+
self._random: Random = random_generator()
|
|
59
60
|
self._counter: Callable[[], int] = counter(floor(self._random.random() * INITIAL_COUNT_MAX))
|
|
60
61
|
self._length: int = length
|
|
61
62
|
self._fingerprint: str = fingerprint(random_generator=self._random)
|
|
62
63
|
|
|
63
|
-
def generate(self:
|
|
64
|
+
def generate(self: Cuid, length: Optional[int] = None) -> str:
|
|
64
65
|
"""Generates a universally unique, base36 encoded string with a specified length.
|
|
65
66
|
|
|
66
67
|
Parameters
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import os
|
|
2
4
|
import socket
|
|
3
5
|
import string
|
|
@@ -46,7 +48,7 @@ def create_counter(count: int) -> Callable[[], int]:
|
|
|
46
48
|
return counter
|
|
47
49
|
|
|
48
50
|
|
|
49
|
-
def create_fingerprint(random_generator:
|
|
51
|
+
def create_fingerprint(random_generator: Random, fingerprint_data: Optional[str] = "") -> str:
|
|
50
52
|
"""Creates a fingerprint, by default combining process ID, hostname, and environment variables
|
|
51
53
|
with entropy and then hashing the result.
|
|
52
54
|
|
|
@@ -76,7 +78,7 @@ def create_fingerprint(random_generator: "Random", fingerprint_data: Optional[st
|
|
|
76
78
|
return create_hash(fingerprint)[0:BIG_LENGTH]
|
|
77
79
|
|
|
78
80
|
|
|
79
|
-
def create_entropy(random_generator:
|
|
81
|
+
def create_entropy(random_generator: Random, length: int = 4) -> str:
|
|
80
82
|
"""Creates a random string of specified length using a base36 encoding.
|
|
81
83
|
|
|
82
84
|
Parameters
|
|
@@ -126,14 +128,14 @@ def create_hash(data: str = "") -> str:
|
|
|
126
128
|
Base36 encoding of the SHA-512 hash of the input string `data`, with the first character dropped.
|
|
127
129
|
|
|
128
130
|
"""
|
|
129
|
-
hashed_value:
|
|
131
|
+
hashed_value: _Hash = sha512(data.encode())
|
|
130
132
|
hashed_int: int = int.from_bytes(hashed_value.digest(), byteorder="big")
|
|
131
133
|
|
|
132
134
|
# Drop the first character because it will bias the histogram to the left.
|
|
133
135
|
return base36_encode(hashed_int)[1:]
|
|
134
136
|
|
|
135
137
|
|
|
136
|
-
def create_letter(random_generator:
|
|
138
|
+
def create_letter(random_generator: Random) -> str:
|
|
137
139
|
"""Generates a random lowercase letter using a given random number generator.
|
|
138
140
|
|
|
139
141
|
Parameters
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|