python-ulid 2.2.0__py3-none-any.whl → 2.4.0__py3-none-any.whl
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.
- {python_ulid-2.2.0.dist-info → python_ulid-2.4.0.dist-info}/METADATA +65 -6
- python_ulid-2.4.0.dist-info/RECORD +10 -0
- {python_ulid-2.2.0.dist-info → python_ulid-2.4.0.dist-info}/WHEEL +1 -1
- ulid/__init__.py +58 -9
- ulid/__main__.py +26 -27
- ulid/constants.py +1 -0
- python_ulid-2.2.0.dist-info/RECORD +0 -10
- {python_ulid-2.2.0.dist-info → python_ulid-2.4.0.dist-info}/entry_points.txt +0 -0
- {python_ulid-2.2.0.dist-info → python_ulid-2.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: python-ulid
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Universally unique lexicographically sortable identifier
|
|
5
|
+
Project-URL: Homepage, https://github.com/mdomke/python-ulid
|
|
6
|
+
Project-URL: Repository, https://github.com/mdomke/python-ulid
|
|
7
|
+
Project-URL: Documentation, https://python-ulid.readthedocs.io/
|
|
5
8
|
Author-email: Martin Domke <mail@martindomke.net>
|
|
6
9
|
License-Expression: MIT
|
|
7
10
|
License-File: LICENSE
|
|
@@ -15,8 +18,11 @@ Classifier: Programming Language :: Python
|
|
|
15
18
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
22
|
Classifier: Topic :: Software Development :: Libraries
|
|
19
23
|
Requires-Python: >=3.9
|
|
24
|
+
Provides-Extra: pydantic
|
|
25
|
+
Requires-Dist: pydantic>=2.0; extra == 'pydantic'
|
|
20
26
|
Description-Content-Type: text/x-rst
|
|
21
27
|
|
|
22
28
|
|
|
@@ -57,6 +63,12 @@ Use ``pip`` to install the library
|
|
|
57
63
|
|
|
58
64
|
$ pip install python-ulid
|
|
59
65
|
|
|
66
|
+
to include Pydantic support install the optional dependency like so
|
|
67
|
+
|
|
68
|
+
.. code-block:: bash
|
|
69
|
+
|
|
70
|
+
$ pip install python-ulid[pydantic]
|
|
71
|
+
|
|
60
72
|
.. installation-end
|
|
61
73
|
|
|
62
74
|
.. usage-begin
|
|
@@ -82,8 +94,8 @@ or use one of the named constructors
|
|
|
82
94
|
>>> ULID.from_datetime(datetime.datetime.now())
|
|
83
95
|
ULID(01E75J2XBK390V2XRH44EHC10X)
|
|
84
96
|
|
|
85
|
-
There are several options for encoding the ``ULID`` object
|
|
86
|
-
|
|
97
|
+
There are several options for encoding the ``ULID`` object
|
|
98
|
+
(e.g. string, hex, int, bytes, UUID):
|
|
87
99
|
|
|
88
100
|
.. code-block:: pycon
|
|
89
101
|
|
|
@@ -91,15 +103,47 @@ as well as to access the timestamp attribute in different formats:
|
|
|
91
103
|
'01BTGNYV6HRNK8K8VKZASZCFPE'
|
|
92
104
|
>>> ulid.hex
|
|
93
105
|
'015ea15f6cd1c56689a373fab3f63ece'
|
|
106
|
+
>>> int(ulid)
|
|
107
|
+
1820576928786795198723644692628913870
|
|
108
|
+
>>> bytes(ulid)
|
|
109
|
+
b'\x01^\xa1_l\xd1\xc5f\x89\xa3s\xfa\xb3\xf6>\xce'
|
|
110
|
+
>>> ulid.to_uuid()
|
|
111
|
+
UUID('015ea15f-6cd1-c566-89a3-73fab3f63ece')
|
|
112
|
+
|
|
113
|
+
It is also possible to directly access the timestamp component of a ``ULID``,
|
|
114
|
+
either in UNIX epoch or as ``datetime.datetime``
|
|
115
|
+
|
|
116
|
+
.. code-block:: pycon
|
|
117
|
+
|
|
94
118
|
>>> ulid.timestamp
|
|
95
119
|
1505945939.153
|
|
96
120
|
>>> ulid.datetime
|
|
97
121
|
datetime.datetime(2017, 9, 20, 22, 18, 59, 153000, tzinfo=datetime.timezone.utc)
|
|
98
|
-
>>> ulid.to_uuid()
|
|
99
|
-
UUID('015ea15f-6cd1-c566-89a3-73fab3f63ece')
|
|
100
122
|
|
|
101
123
|
.. usage-end
|
|
102
124
|
|
|
125
|
+
.. pydantic-begin
|
|
126
|
+
|
|
127
|
+
Pydantic integration
|
|
128
|
+
---------------------
|
|
129
|
+
|
|
130
|
+
The ``ULID`` class can be directly used for the popular data validation library
|
|
131
|
+
`Pydantic <https://docs.pydantic.dev/latest/>`_ like so
|
|
132
|
+
|
|
133
|
+
.. code-block:: python
|
|
134
|
+
|
|
135
|
+
from pydantic import BaseModel
|
|
136
|
+
from ulid import ULID
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class Model(BaseModel):
|
|
140
|
+
ulid: ULID
|
|
141
|
+
|
|
142
|
+
model = Model(ulid="DX89370400440532013000") # OK
|
|
143
|
+
model = Model(ulid="not-a-ulid") # Raises ValidationError
|
|
144
|
+
|
|
145
|
+
.. pydantic-end
|
|
146
|
+
|
|
103
147
|
.. cli-begin
|
|
104
148
|
|
|
105
149
|
Command line interface
|
|
@@ -124,6 +168,14 @@ and convert ULIDs, e.g.
|
|
|
124
168
|
Timestamp: 1695219822.248
|
|
125
169
|
Datetime: 2023-09-20 14:23:42.248000+00:00
|
|
126
170
|
|
|
171
|
+
There are several flags to select specific output formats for the ``show`` command, e.g.
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
.. code-block:: bash
|
|
175
|
+
|
|
176
|
+
$ ulid show --datetime 01HASFKBN8SKZTSVVS03K5AMMS
|
|
177
|
+
2023-09-20 14:23:42.248000+00:00
|
|
178
|
+
|
|
127
179
|
The special character ``-`` allows to read values from ``stdin`` so that they can be piped. E.g.
|
|
128
180
|
|
|
129
181
|
.. code-block:: bash
|
|
@@ -134,6 +186,9 @@ The special character ``-`` allows to read values from ``stdin`` so that they ca
|
|
|
134
186
|
$ date --iso-8601 | python -m ulid build --from-datetime -
|
|
135
187
|
01HAT9PVR02T3S13XB48S7GEHE
|
|
136
188
|
|
|
189
|
+
For a full overview of flags for the ``build`` and ``show`` commands use the ``--help`` option
|
|
190
|
+
(e.g. ``ulid show --help``).
|
|
191
|
+
|
|
137
192
|
.. cli-end
|
|
138
193
|
|
|
139
194
|
Other implementations
|
|
@@ -142,3 +197,7 @@ Other implementations
|
|
|
142
197
|
* `ahawker/ulid <https://github.com/ahawker/ulid>`_
|
|
143
198
|
* `valohai/ulid2 <https://github.com/valohai/ulid2>`_
|
|
144
199
|
* `mdipierro/ulid <https://github.com/mdipierro/ulid>`_
|
|
200
|
+
* `oklog/ulid <https://github.com/oklog/ulid>`_
|
|
201
|
+
* `ulid/javascript <https://github.com/ulid/javascript>`_
|
|
202
|
+
* `RobThree/NUlid <https://github.com/RobThree/NUlid>`_
|
|
203
|
+
* `imdario/go-ulid <https://github.com/imdario/go-ulid>`_
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
ulid/__init__.py,sha256=7wY5wUQGwcUhreFESFX6MCrimPbaJOjXUY0XEZvU9Cg,9235
|
|
2
|
+
ulid/__main__.py,sha256=Cmg0NEz3GUZ2WhsZVpY3-Kq-JOkxJFaLsRNgj3Aosyw,5341
|
|
3
|
+
ulid/base32.py,sha256=OkU4FBqohJgV_ZRc3dTbjPlUTSSeC9ddFlPXD2vA8vc,5832
|
|
4
|
+
ulid/constants.py,sha256=N_nw4W2ciXO8C1IeuO3YK3j4_x9QW-0KyvrSQUuM-G4,241
|
|
5
|
+
ulid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
python_ulid-2.4.0.dist-info/METADATA,sha256=ET_sWGfqWfhjEiThmFtNrpHet16cPGEsJe4NKVOgKbU,5570
|
|
7
|
+
python_ulid-2.4.0.dist-info/WHEEL,sha256=uNdcs2TADwSd5pVaP0Z_kcjcvvTUklh2S7bxZMF8Uj0,87
|
|
8
|
+
python_ulid-2.4.0.dist-info/entry_points.txt,sha256=9214ghzfSgS8a-TjjlWDF7bI7KSaeewOCBKn5uz7bdU,50
|
|
9
|
+
python_ulid-2.4.0.dist-info/licenses/LICENSE,sha256=DiDPNhW5yUHIqaKowvX0c1c9xWiI0xW4ji8R9N2NJbw,1056
|
|
10
|
+
python_ulid-2.4.0.dist-info/RECORD,,
|
ulid/__init__.py
CHANGED
|
@@ -9,15 +9,21 @@ from datetime import datetime
|
|
|
9
9
|
from datetime import timezone
|
|
10
10
|
from typing import Any
|
|
11
11
|
from typing import Generic
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
12
13
|
from typing import TypeVar
|
|
13
14
|
|
|
14
15
|
from ulid import base32
|
|
15
16
|
from ulid import constants
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
20
|
+
from pydantic import GetCoreSchemaHandler
|
|
21
|
+
from pydantic import ValidatorFunctionWrapHandler
|
|
22
|
+
from pydantic_core import CoreSchema
|
|
23
|
+
|
|
18
24
|
try:
|
|
19
25
|
from importlib.metadata import version
|
|
20
|
-
except ImportError:
|
|
26
|
+
except ImportError: # pragma: no cover
|
|
21
27
|
from importlib_metadata import version # type: ignore
|
|
22
28
|
|
|
23
29
|
|
|
@@ -44,6 +50,9 @@ class validate_type(Generic[T]): # noqa: N801
|
|
|
44
50
|
return wrapped
|
|
45
51
|
|
|
46
52
|
|
|
53
|
+
U = TypeVar("U", bound="ULID")
|
|
54
|
+
|
|
55
|
+
|
|
47
56
|
@functools.total_ordering
|
|
48
57
|
class ULID:
|
|
49
58
|
"""The :class:`ULID` object consists of a timestamp part of 48 bits and of 80 random bits.
|
|
@@ -67,11 +76,13 @@ class ULID:
|
|
|
67
76
|
def __init__(self, value: bytes | None = None) -> None:
|
|
68
77
|
if value is not None and len(value) != constants.BYTES_LEN:
|
|
69
78
|
raise ValueError("ULID has to be exactly 16 bytes long.")
|
|
70
|
-
self.bytes: bytes =
|
|
79
|
+
self.bytes: bytes = (
|
|
80
|
+
value or ULID.from_timestamp(time.time_ns() // constants.NANOSECS_IN_MILLISECS).bytes
|
|
81
|
+
)
|
|
71
82
|
|
|
72
83
|
@classmethod
|
|
73
84
|
@validate_type(datetime)
|
|
74
|
-
def from_datetime(cls, value: datetime) ->
|
|
85
|
+
def from_datetime(cls: type[U], value: datetime) -> U:
|
|
75
86
|
"""Create a new :class:`ULID`-object from a :class:`datetime`. The timestamp part of the
|
|
76
87
|
`ULID` will be set to the corresponding timestamp of the datetime.
|
|
77
88
|
|
|
@@ -85,7 +96,7 @@ class ULID:
|
|
|
85
96
|
|
|
86
97
|
@classmethod
|
|
87
98
|
@validate_type(int, float)
|
|
88
|
-
def from_timestamp(cls, value: int | float) ->
|
|
99
|
+
def from_timestamp(cls: type[U], value: int | float) -> U:
|
|
89
100
|
"""Create a new :class:`ULID`-object from a timestamp. The timestamp can be either a
|
|
90
101
|
`float` representing the time in seconds (as it would be returned by :func:`time.time()`)
|
|
91
102
|
or an `int` in milliseconds.
|
|
@@ -104,7 +115,7 @@ class ULID:
|
|
|
104
115
|
|
|
105
116
|
@classmethod
|
|
106
117
|
@validate_type(uuid.UUID)
|
|
107
|
-
def from_uuid(cls, value: uuid.UUID) ->
|
|
118
|
+
def from_uuid(cls: type[U], value: uuid.UUID) -> U:
|
|
108
119
|
"""Create a new :class:`ULID`-object from a :class:`uuid.UUID`. The timestamp part will be
|
|
109
120
|
random in that case.
|
|
110
121
|
|
|
@@ -118,25 +129,25 @@ class ULID:
|
|
|
118
129
|
|
|
119
130
|
@classmethod
|
|
120
131
|
@validate_type(bytes)
|
|
121
|
-
def from_bytes(cls, bytes_: bytes) ->
|
|
132
|
+
def from_bytes(cls: type[U], bytes_: bytes) -> U:
|
|
122
133
|
"""Create a new :class:`ULID`-object from sequence of 16 bytes."""
|
|
123
134
|
return cls(bytes_)
|
|
124
135
|
|
|
125
136
|
@classmethod
|
|
126
137
|
@validate_type(str)
|
|
127
|
-
def from_hex(cls, value: str) ->
|
|
138
|
+
def from_hex(cls: type[U], value: str) -> U:
|
|
128
139
|
"""Create a new :class:`ULID`-object from 32 character string of hex values."""
|
|
129
140
|
return cls.from_bytes(bytes.fromhex(value))
|
|
130
141
|
|
|
131
142
|
@classmethod
|
|
132
143
|
@validate_type(str)
|
|
133
|
-
def from_str(cls, string: str) ->
|
|
144
|
+
def from_str(cls: type[U], string: str) -> U:
|
|
134
145
|
"""Create a new :class:`ULID`-object from a 26 char long string representation."""
|
|
135
146
|
return cls(base32.decode(string))
|
|
136
147
|
|
|
137
148
|
@classmethod
|
|
138
149
|
@validate_type(int)
|
|
139
|
-
def from_int(cls, value: int) ->
|
|
150
|
+
def from_int(cls: type[U], value: int) -> U:
|
|
140
151
|
"""Create a new :class:`ULID`-object from an `int`."""
|
|
141
152
|
return cls(int.to_bytes(value, constants.BYTES_LEN, "big"))
|
|
142
153
|
|
|
@@ -209,6 +220,10 @@ class ULID:
|
|
|
209
220
|
"""Encode this object as an integer."""
|
|
210
221
|
return int.from_bytes(self.bytes, byteorder="big")
|
|
211
222
|
|
|
223
|
+
def __bytes__(self) -> bytes:
|
|
224
|
+
"""Encode this object as byte sequence."""
|
|
225
|
+
return self.bytes
|
|
226
|
+
|
|
212
227
|
def __lt__(self, other: Any) -> bool:
|
|
213
228
|
if isinstance(other, ULID):
|
|
214
229
|
return self.bytes < other.bytes
|
|
@@ -233,3 +248,37 @@ class ULID:
|
|
|
233
248
|
|
|
234
249
|
def __hash__(self) -> int:
|
|
235
250
|
return hash(self.bytes)
|
|
251
|
+
|
|
252
|
+
@classmethod
|
|
253
|
+
def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> CoreSchema:
|
|
254
|
+
from pydantic_core import core_schema
|
|
255
|
+
|
|
256
|
+
return core_schema.no_info_wrap_validator_function(
|
|
257
|
+
cls._pydantic_validate,
|
|
258
|
+
core_schema.union_schema(
|
|
259
|
+
[
|
|
260
|
+
core_schema.is_instance_schema(ULID),
|
|
261
|
+
core_schema.no_info_plain_validator_function(ULID),
|
|
262
|
+
]
|
|
263
|
+
),
|
|
264
|
+
serialization=core_schema.to_string_ser_schema(
|
|
265
|
+
when_used="json-unless-none",
|
|
266
|
+
),
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
@classmethod
|
|
270
|
+
def _pydantic_validate(cls, value: Any, handler: ValidatorFunctionWrapHandler) -> Any:
|
|
271
|
+
from pydantic_core import PydanticCustomError
|
|
272
|
+
|
|
273
|
+
try:
|
|
274
|
+
if isinstance(value, int):
|
|
275
|
+
ulid = cls.from_int(value)
|
|
276
|
+
elif isinstance(value, str):
|
|
277
|
+
ulid = cls.from_str(value)
|
|
278
|
+
elif isinstance(value, ULID):
|
|
279
|
+
ulid = value
|
|
280
|
+
else:
|
|
281
|
+
ulid = cls.from_bytes(value)
|
|
282
|
+
except ValueError as err:
|
|
283
|
+
raise PydanticCustomError("ulid_format", "Unrecognized format") from err
|
|
284
|
+
return handler(ulid)
|
ulid/__main__.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import argparse
|
|
2
4
|
import shutil
|
|
3
5
|
import sys
|
|
@@ -7,7 +9,6 @@ from collections.abc import Sequence
|
|
|
7
9
|
from datetime import datetime
|
|
8
10
|
from functools import partial
|
|
9
11
|
from typing import Any
|
|
10
|
-
from typing import Optional
|
|
11
12
|
from uuid import UUID
|
|
12
13
|
|
|
13
14
|
import ulid
|
|
@@ -92,12 +93,12 @@ def make_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
|
|
92
93
|
return parser
|
|
93
94
|
|
|
94
95
|
|
|
95
|
-
def main(argv: Sequence[str], prog: str | None = None) ->
|
|
96
|
+
def main(argv: Sequence[str], prog: str | None = None) -> str:
|
|
96
97
|
args = make_parser(prog).parse_args(argv)
|
|
97
|
-
args.func(args)
|
|
98
|
+
return args.func(args)
|
|
98
99
|
|
|
99
100
|
|
|
100
|
-
def from_value_or_stdin(value: str, convert:
|
|
101
|
+
def from_value_or_stdin(value: str, convert: Callable[[str], Any] | None = None) -> Any:
|
|
101
102
|
value = sys.stdin.readline().strip() if value == "-" else value
|
|
102
103
|
if convert is not None:
|
|
103
104
|
return convert(value)
|
|
@@ -111,7 +112,7 @@ def parse_numeric(s: str) -> int | float:
|
|
|
111
112
|
return float(s)
|
|
112
113
|
|
|
113
114
|
|
|
114
|
-
def build(args: argparse.Namespace) ->
|
|
115
|
+
def build(args: argparse.Namespace) -> str:
|
|
115
116
|
ulid: ULID
|
|
116
117
|
if args.from_int is not None:
|
|
117
118
|
ulid = ULID.from_int(from_value_or_stdin(args.from_int, int))
|
|
@@ -127,40 +128,38 @@ def build(args: argparse.Namespace) -> None:
|
|
|
127
128
|
ulid = ULID.from_uuid(from_value_or_stdin(args.from_uuid, UUID))
|
|
128
129
|
else:
|
|
129
130
|
ulid = ULID()
|
|
130
|
-
|
|
131
|
+
return str(ulid)
|
|
131
132
|
|
|
132
133
|
|
|
133
|
-
def show(args: argparse.Namespace) ->
|
|
134
|
+
def show(args: argparse.Namespace) -> str:
|
|
134
135
|
ulid: ULID = ULID.from_str(from_value_or_stdin(args.ulid))
|
|
135
136
|
if args.uuid:
|
|
136
|
-
|
|
137
|
+
return str(ulid.to_uuid())
|
|
137
138
|
elif args.uuid4:
|
|
138
|
-
|
|
139
|
+
return str(ulid.to_uuid4())
|
|
139
140
|
elif args.hex:
|
|
140
|
-
|
|
141
|
+
return ulid.hex
|
|
141
142
|
elif args.int:
|
|
142
|
-
|
|
143
|
+
return str(int(ulid))
|
|
143
144
|
elif args.timestamp:
|
|
144
|
-
|
|
145
|
+
return str(ulid.timestamp)
|
|
145
146
|
elif args.datetime:
|
|
146
|
-
|
|
147
|
+
return ulid.datetime.isoformat()
|
|
147
148
|
else:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
).strip()
|
|
158
|
-
)
|
|
149
|
+
return textwrap.dedent(
|
|
150
|
+
f"""
|
|
151
|
+
ULID: {ulid!s}
|
|
152
|
+
Hex: {ulid.hex}
|
|
153
|
+
Int: {int(ulid)}
|
|
154
|
+
Timestamp: {ulid.timestamp}
|
|
155
|
+
Datetime: {ulid.datetime.isoformat()}
|
|
156
|
+
"""
|
|
157
|
+
).strip()
|
|
159
158
|
|
|
160
159
|
|
|
161
|
-
def entrypoint() -> None:
|
|
162
|
-
main(sys.argv[1:])
|
|
160
|
+
def entrypoint() -> None: # pragma: no cover
|
|
161
|
+
print(main(sys.argv[1:]))
|
|
163
162
|
|
|
164
163
|
|
|
165
|
-
if __name__ == "__main__":
|
|
164
|
+
if __name__ == "__main__": # pragma: no cover
|
|
166
165
|
main(sys.argv[1:], "python -m ulid")
|
ulid/constants.py
CHANGED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
ulid/__init__.py,sha256=QctfUYCnmrMlSxlxFVol47UOC5wzc5kPR0CAMUXxdVI,7516
|
|
2
|
-
ulid/__main__.py,sha256=HXSnwi6_a_2RNSKJMyZ2ndX_LwyCcxNCW2l2uiflmSk,5290
|
|
3
|
-
ulid/base32.py,sha256=OkU4FBqohJgV_ZRc3dTbjPlUTSSeC9ddFlPXD2vA8vc,5832
|
|
4
|
-
ulid/constants.py,sha256=LHZ167q6iOJJ3giBcbNEwM-ahJYIrSvQ-1hHhpvLhHE,209
|
|
5
|
-
ulid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
python_ulid-2.2.0.dist-info/METADATA,sha256=8dBkMNE00iscfhhgMeM1fEzriT6ynyJ-6nXrO1lN66g,3893
|
|
7
|
-
python_ulid-2.2.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
|
8
|
-
python_ulid-2.2.0.dist-info/entry_points.txt,sha256=9214ghzfSgS8a-TjjlWDF7bI7KSaeewOCBKn5uz7bdU,50
|
|
9
|
-
python_ulid-2.2.0.dist-info/licenses/LICENSE,sha256=DiDPNhW5yUHIqaKowvX0c1c9xWiI0xW4ji8R9N2NJbw,1056
|
|
10
|
-
python_ulid-2.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|