python-ulid 3.0.0__tar.gz → 3.1.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.
Files changed (34) hide show
  1. {python_ulid-3.0.0 → python_ulid-3.1.0}/.github/workflows/lint-and-test.yml +13 -13
  2. {python_ulid-3.0.0 → python_ulid-3.1.0}/.pre-commit-config.yaml +2 -2
  3. {python_ulid-3.0.0 → python_ulid-3.1.0}/.readthedocs.yml +1 -1
  4. {python_ulid-3.0.0 → python_ulid-3.1.0}/.ruff_defaults.toml +7 -9
  5. {python_ulid-3.0.0 → python_ulid-3.1.0}/CHANGELOG.rst +22 -6
  6. {python_ulid-3.0.0 → python_ulid-3.1.0}/PKG-INFO +3 -2
  7. python_ulid-3.1.0/devbox.json +11 -0
  8. python_ulid-3.1.0/devbox.lock +178 -0
  9. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/source/conf.py +6 -7
  10. {python_ulid-3.0.0 → python_ulid-3.1.0}/hatch.toml +3 -3
  11. {python_ulid-3.0.0 → python_ulid-3.1.0}/pyproject.toml +8 -0
  12. {python_ulid-3.0.0 → python_ulid-3.1.0}/tests/test_ulid.py +21 -1
  13. {python_ulid-3.0.0 → python_ulid-3.1.0}/ulid/__init__.py +62 -24
  14. {python_ulid-3.0.0 → python_ulid-3.1.0}/ulid/constants.py +6 -0
  15. python_ulid-3.1.0/uv.lock +1359 -0
  16. python_ulid-3.0.0/devbox.json +0 -13
  17. python_ulid-3.0.0/devbox.lock +0 -62
  18. {python_ulid-3.0.0 → python_ulid-3.1.0}/.envrc +0 -0
  19. {python_ulid-3.0.0 → python_ulid-3.1.0}/.github/workflows/publish.yml +0 -0
  20. {python_ulid-3.0.0 → python_ulid-3.1.0}/.gitignore +0 -0
  21. {python_ulid-3.0.0 → python_ulid-3.1.0}/LICENSE +0 -0
  22. {python_ulid-3.0.0 → python_ulid-3.1.0}/README.rst +0 -0
  23. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/Makefile +0 -0
  24. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/requirements.txt +0 -0
  25. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/source/api.rst +0 -0
  26. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/source/changelog.rst +0 -0
  27. {python_ulid-3.0.0 → python_ulid-3.1.0}/docs/source/index.rst +0 -0
  28. {python_ulid-3.0.0 → python_ulid-3.1.0}/logo.png +0 -0
  29. {python_ulid-3.0.0 → python_ulid-3.1.0}/tests/__init__.py +0 -0
  30. {python_ulid-3.0.0 → python_ulid-3.1.0}/tests/test_base32.py +0 -0
  31. {python_ulid-3.0.0 → python_ulid-3.1.0}/tests/test_cli.py +0 -0
  32. {python_ulid-3.0.0 → python_ulid-3.1.0}/ulid/__main__.py +0 -0
  33. {python_ulid-3.0.0 → python_ulid-3.1.0}/ulid/base32.py +0 -0
  34. {python_ulid-3.0.0 → python_ulid-3.1.0}/ulid/py.typed +0 -0
@@ -10,11 +10,11 @@ jobs:
10
10
  lint-docs:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v4
14
- - name: Set up Python 3.12
13
+ - uses: actions/checkout@v5
14
+ - name: Set up Python 3.13
15
15
  uses: actions/setup-python@v5
16
16
  with:
17
- python-version: "3.12"
17
+ python-version: "3.13"
18
18
  - name: Install hatch
19
19
  uses: pypa/hatch@install
20
20
  - name: Lint documentation
@@ -24,11 +24,11 @@ jobs:
24
24
  runs-on: ubuntu-latest
25
25
  name: Lint code
26
26
  steps:
27
- - uses: actions/checkout@v4
28
- - name: Set up Python 3.12
27
+ - uses: actions/checkout@v5
28
+ - name: Set up Python 3.13
29
29
  uses: actions/setup-python@v5
30
30
  with:
31
- python-version: "3.12"
31
+ python-version: "3.13"
32
32
  - name: Install hatch
33
33
  uses: pypa/hatch@install
34
34
  - name: Lint code
@@ -38,11 +38,11 @@ jobs:
38
38
  runs-on: ubuntu-latest
39
39
  name: Lint type annotations
40
40
  steps:
41
- - uses: actions/checkout@v4
42
- - name: Set up Python 3.12
41
+ - uses: actions/checkout@v5
42
+ - name: Set up Python 3.13
43
43
  uses: actions/setup-python@v5
44
44
  with:
45
- python-version: "3.12"
45
+ python-version: "3.13"
46
46
  - name: Install hatch
47
47
  uses: pypa/hatch@install
48
48
  - name: Lint typing
@@ -53,9 +53,9 @@ jobs:
53
53
  name: Run tests
54
54
  strategy:
55
55
  matrix:
56
- python-version: ["3.9", "3.10", "3.11", "3.12"]
56
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
57
57
  steps:
58
- - uses: actions/checkout@v4
58
+ - uses: actions/checkout@v5
59
59
  - name: Set up Python ${{ matrix.python-version }}
60
60
  uses: actions/setup-python@v5
61
61
  with:
@@ -84,7 +84,7 @@ jobs:
84
84
  needs:
85
85
  - test
86
86
  steps:
87
- - uses: actions/checkout@v4
87
+ - uses: actions/checkout@v5
88
88
  - name: Install Hatch
89
89
  uses: pypa/hatch@install
90
90
 
@@ -109,5 +109,5 @@ jobs:
109
109
  name: Build & verify package
110
110
  runs-on: ubuntu-latest
111
111
  steps:
112
- - uses: actions/checkout@v4
112
+ - uses: actions/checkout@v5
113
113
  - uses: hynek/build-and-inspect-python-package@v2
@@ -1,10 +1,10 @@
1
1
  repos:
2
2
  - repo: https://github.com/astral-sh/ruff-pre-commit
3
- rev: v0.6.9
3
+ rev: v0.12.9
4
4
  hooks:
5
5
  - id: ruff
6
6
  - id: ruff-format
7
7
  - repo: https://github.com/pycqa/doc8
8
- rev: v1.1.2
8
+ rev: v2.0.0
9
9
  hooks:
10
10
  - id: doc8
@@ -3,7 +3,7 @@ version: 2
3
3
  build:
4
4
  os: ubuntu-22.04
5
5
  tools:
6
- python: "3.11"
6
+ python: "3.13"
7
7
 
8
8
  sphinx:
9
9
  configuration: docs/source/conf.py
@@ -386,7 +386,6 @@ select = [
386
386
  "S317",
387
387
  "S318",
388
388
  "S319",
389
- "S320",
390
389
  "S321",
391
390
  "S323",
392
391
  "S324",
@@ -446,12 +445,12 @@ select = [
446
445
  "T100",
447
446
  "T201",
448
447
  "T203",
449
- "TCH001",
450
- "TCH002",
451
- "TCH003",
452
- "TCH004",
453
- "TCH005",
454
- "TCH010",
448
+ "TC001",
449
+ "TC002",
450
+ "TC003",
451
+ "TC004",
452
+ "TC005",
453
+ "TC010",
455
454
  "TD004",
456
455
  "TD005",
457
456
  "TD006",
@@ -463,9 +462,9 @@ select = [
463
462
  "TRY003",
464
463
  "TRY004",
465
464
  "TRY201",
465
+ "TRY203",
466
466
  "TRY300",
467
467
  "TRY301",
468
- "TRY302",
469
468
  "TRY400",
470
469
  "TRY401",
471
470
  "UP001",
@@ -502,7 +501,6 @@ select = [
502
501
  "UP035",
503
502
  "UP036",
504
503
  "UP037",
505
- "UP038",
506
504
  "UP039",
507
505
  "UP040",
508
506
  "UP041",
@@ -5,11 +5,26 @@ Changelog
5
5
 
6
6
  Versions follow `Semantic Versioning <http://www.semver.org>`_
7
7
 
8
+ `3.1.0`_ - 2025-08-18
9
+ ---------------------
10
+ Changed
11
+ ~~~~~~~
12
+ * Added Python 3.13 to the trove classifiers.
13
+ * Optimze ``@property`` to ``@cached_property`` `@WH-2099 <https://github.com/WH-2099>`_.
14
+ * When generating ULIDs within the same millisecond, the library will ensure monotonic sort order by
15
+ incrementing the randomness component by 1 bit. This process is descrbied in the
16
+ `spec <https://github.com/ulid/spec/blob/master/README.md#monotonicity>`_.
17
+
18
+ Fixed
19
+ ~~~~~
20
+ * Sharpen regular expression for Pydantic `@aplhk <https://github.com/aplhk>`_.
21
+ * Fix Sphinx warnings when referencing ULID from an external project. `@BoboTiG <https://github.com/BoboTiG>`_.
22
+
8
23
  `3.0.0`_ - 2024-10-11
9
24
  ---------------------
10
25
  Changed
11
26
  ~~~~~~~
12
- * Raise `TypeError` instead of `ValueError` if constructor is called with value of wrong type.
27
+ * Raise ``TypeError`` instead of ``ValueError`` if constructor is called with value of wrong type.
13
28
  * Update ``ruff`` linter rules and switch to ``hatch fmt``.
14
29
 
15
30
  Added
@@ -71,7 +86,7 @@ Added
71
86
  ~~~~~
72
87
  * Added a new flag ``--uuid4`` to the CLI ``show`` command, that converts the provided ``ULID``
73
88
  into an RFC 4122 compliant ``UUID``.
74
- * The `ulid build` command allows the use of the special value ``-`` for all options to read its
89
+ * The ``ulid build`` command allows the use of the special value ``-`` for all options to read its
75
90
  inputs from ``stdin``. E.g.
76
91
 
77
92
  .. code-block:: bash
@@ -128,7 +143,7 @@ Changed
128
143
  Added
129
144
  ~~~~~
130
145
  * Added support for Python 3.10.
131
- * Added :attr:`__version__` variable to package.
146
+ * Added ``__version__`` variable to package.
132
147
 
133
148
 
134
149
  `1.0.3`_ - 2021-07-14
@@ -153,7 +168,7 @@ Added
153
168
  Changed
154
169
  ~~~~~~~
155
170
  * Dropped support for Python 2. Only Python 3.6+ is supported.
156
- * The named constructor :meth:`.ULID.new` has been removed. Use one of the specifc named
171
+ * The named constructor ``ULID.new`` has been removed. Use one of the specifc named
157
172
  constructors instead. For a new :class:`.ULID` created from the current timestamp use the
158
173
  standard constructor.
159
174
 
@@ -169,8 +184,8 @@ Changed
169
184
  ulid = ULID.from_timestamp(time.time())
170
185
  ulid = ULID.from_datetime(datetime.now())
171
186
 
172
- * The :meth:`.ULID.str` and :meth:`.ULID.int` methods have been removed in favour of the more
173
- Pythonic special dunder-methods. Use `str(ulid)` and `int(ulid)` instead.
187
+ * The ``ULID.str`` and ``ULID.int`` methods have been removed in favour of the more
188
+ Pythonic special dunder-methods. Use ``str(ulid)`` and ``int(ulid)`` instead.
174
189
  * Added the property :meth:`.ULID.hex` that returns a hex representation of the :class:`.ULID`.
175
190
 
176
191
  .. code-block:: python
@@ -182,6 +197,7 @@ Changed
182
197
  * The package now has no external dependencies.
183
198
  * The test-coverage has been raised to 100%.
184
199
 
200
+ .. _3.1.0: https://github.com/mdomke/python-ulid/compare/3.0.0...3.1.0
185
201
  .. _3.0.0: https://github.com/mdomke/python-ulid/compare/2.7.0...3.0.0
186
202
  .. _2.7.0: https://github.com/mdomke/python-ulid/compare/2.6.0...2.7.0
187
203
  .. _2.6.0: https://github.com/mdomke/python-ulid/compare/2.5.0...2.6.0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: python-ulid
3
- Version: 3.0.0
3
+ Version: 3.1.0
4
4
  Summary: Universally unique lexicographically sortable identifier
5
5
  Project-URL: Homepage, https://github.com/mdomke/python-ulid
6
6
  Project-URL: Documentation, https://python-ulid.readthedocs.io
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.9
22
22
  Classifier: Programming Language :: Python :: 3.10
23
23
  Classifier: Programming Language :: Python :: 3.11
24
24
  Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
25
26
  Classifier: Topic :: Software Development :: Libraries
26
27
  Requires-Python: >=3.9
27
28
  Provides-Extra: pydantic
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.3/.schema/devbox.schema.json",
3
+ "packages": [
4
+ "python@3.13",
5
+ "pre-commit@4.2",
6
+ "uv@latest"
7
+ ],
8
+ "shell": {
9
+ "init_hook": ". ${VENV_DIR}/bin/activate"
10
+ }
11
+ }
@@ -0,0 +1,178 @@
1
+ {
2
+ "lockfile_version": "1",
3
+ "packages": {
4
+ "github:NixOS/nixpkgs/nixpkgs-unstable": {
5
+ "last_modified": "2025-07-24T23:24:55Z",
6
+ "resolved": "github:NixOS/nixpkgs/0d00f23f023b7215b3f1035adb5247c8ec180dbc?lastModified=1753399495&narHash=sha256-7XG%2FQBqhrYOyA2houjRTL2NMa7IKZZ%2FsomBqr%2BQ%2F6Wo%3D"
7
+ },
8
+ "pre-commit@4.2": {
9
+ "last_modified": "2025-08-11T07:05:29Z",
10
+ "resolved": "github:NixOS/nixpkgs/9585e9192aadc13ec3e49f33f8333bd3cda524df#pre-commit",
11
+ "source": "devbox-search",
12
+ "version": "4.2.0",
13
+ "systems": {
14
+ "aarch64-darwin": {
15
+ "outputs": [
16
+ {
17
+ "name": "out",
18
+ "path": "/nix/store/awyg4wwb7w117sr32zbw453yylzy1sv5-pre-commit-4.2.0",
19
+ "default": true
20
+ },
21
+ {
22
+ "name": "dist",
23
+ "path": "/nix/store/6j8b2k8vcm8ff3fwrwpkxr2q796yqwzl-pre-commit-4.2.0-dist"
24
+ }
25
+ ],
26
+ "store_path": "/nix/store/awyg4wwb7w117sr32zbw453yylzy1sv5-pre-commit-4.2.0"
27
+ },
28
+ "aarch64-linux": {
29
+ "outputs": [
30
+ {
31
+ "name": "out",
32
+ "path": "/nix/store/z7aiyfndjqrzk0igjdzjf2sab137083p-pre-commit-4.2.0",
33
+ "default": true
34
+ },
35
+ {
36
+ "name": "dist",
37
+ "path": "/nix/store/mr9jivn3fc4g4ncb25ij73481ilmba4k-pre-commit-4.2.0-dist"
38
+ }
39
+ ],
40
+ "store_path": "/nix/store/z7aiyfndjqrzk0igjdzjf2sab137083p-pre-commit-4.2.0"
41
+ },
42
+ "x86_64-darwin": {
43
+ "outputs": [
44
+ {
45
+ "name": "out",
46
+ "path": "/nix/store/mx4vjrjzfxsarwkx12ddvn18kvphsds4-pre-commit-4.2.0",
47
+ "default": true
48
+ },
49
+ {
50
+ "name": "dist",
51
+ "path": "/nix/store/hgf3j4hj0ng2xwq71n5a8j02y6zha5gq-pre-commit-4.2.0-dist"
52
+ }
53
+ ],
54
+ "store_path": "/nix/store/mx4vjrjzfxsarwkx12ddvn18kvphsds4-pre-commit-4.2.0"
55
+ },
56
+ "x86_64-linux": {
57
+ "outputs": [
58
+ {
59
+ "name": "out",
60
+ "path": "/nix/store/h9f0ac5z0scz7fp4p8xznw2m04xx45in-pre-commit-4.2.0",
61
+ "default": true
62
+ },
63
+ {
64
+ "name": "dist",
65
+ "path": "/nix/store/k9svwjpac38jf5c1zlxdhvhpk3ljf57r-pre-commit-4.2.0-dist"
66
+ }
67
+ ],
68
+ "store_path": "/nix/store/h9f0ac5z0scz7fp4p8xznw2m04xx45in-pre-commit-4.2.0"
69
+ }
70
+ }
71
+ },
72
+ "python@3.13": {
73
+ "last_modified": "2025-05-16T20:19:48Z",
74
+ "plugin_version": "0.0.4",
75
+ "resolved": "github:NixOS/nixpkgs/12a55407652e04dcf2309436eb06fef0d3713ef3#python313",
76
+ "source": "devbox-search",
77
+ "version": "3.13.3",
78
+ "systems": {
79
+ "aarch64-darwin": {
80
+ "outputs": [
81
+ {
82
+ "name": "out",
83
+ "path": "/nix/store/1a8xg8l3m67hxinxzzcsak9736qm9vsf-python3-3.13.3",
84
+ "default": true
85
+ }
86
+ ],
87
+ "store_path": "/nix/store/1a8xg8l3m67hxinxzzcsak9736qm9vsf-python3-3.13.3"
88
+ },
89
+ "aarch64-linux": {
90
+ "outputs": [
91
+ {
92
+ "name": "out",
93
+ "path": "/nix/store/yy0xvc2rydhrs0h1v8d7r3sql347xzz5-python3-3.13.3",
94
+ "default": true
95
+ },
96
+ {
97
+ "name": "debug",
98
+ "path": "/nix/store/42bxfqfrh8cwspl7szr0cw8739xv8qlq-python3-3.13.3-debug"
99
+ }
100
+ ],
101
+ "store_path": "/nix/store/yy0xvc2rydhrs0h1v8d7r3sql347xzz5-python3-3.13.3"
102
+ },
103
+ "x86_64-darwin": {
104
+ "outputs": [
105
+ {
106
+ "name": "out",
107
+ "path": "/nix/store/gbrigjhghz9v2p0zf9b2fnvs0g0yx7q4-python3-3.13.3",
108
+ "default": true
109
+ }
110
+ ],
111
+ "store_path": "/nix/store/gbrigjhghz9v2p0zf9b2fnvs0g0yx7q4-python3-3.13.3"
112
+ },
113
+ "x86_64-linux": {
114
+ "outputs": [
115
+ {
116
+ "name": "out",
117
+ "path": "/nix/store/2mab9iiwhcqwk75qwvp3zv0bvbiaq6cs-python3-3.13.3",
118
+ "default": true
119
+ },
120
+ {
121
+ "name": "debug",
122
+ "path": "/nix/store/9z6k8ijl2md0y2n95yprbjj4vxbfsi15-python3-3.13.3-debug"
123
+ }
124
+ ],
125
+ "store_path": "/nix/store/2mab9iiwhcqwk75qwvp3zv0bvbiaq6cs-python3-3.13.3"
126
+ }
127
+ }
128
+ },
129
+ "uv@latest": {
130
+ "last_modified": "2025-07-28T17:09:23Z",
131
+ "resolved": "github:NixOS/nixpkgs/648f70160c03151bc2121d179291337ad6bc564b#uv",
132
+ "source": "devbox-search",
133
+ "version": "0.8.2",
134
+ "systems": {
135
+ "aarch64-darwin": {
136
+ "outputs": [
137
+ {
138
+ "name": "out",
139
+ "path": "/nix/store/db9y1b002zlnyjgpsnbl9hvlwsiqajl4-uv-0.8.2",
140
+ "default": true
141
+ }
142
+ ],
143
+ "store_path": "/nix/store/db9y1b002zlnyjgpsnbl9hvlwsiqajl4-uv-0.8.2"
144
+ },
145
+ "aarch64-linux": {
146
+ "outputs": [
147
+ {
148
+ "name": "out",
149
+ "path": "/nix/store/bdps6h2gn2rysavc3cq2slqnjlsyyk03-uv-0.8.2",
150
+ "default": true
151
+ }
152
+ ],
153
+ "store_path": "/nix/store/bdps6h2gn2rysavc3cq2slqnjlsyyk03-uv-0.8.2"
154
+ },
155
+ "x86_64-darwin": {
156
+ "outputs": [
157
+ {
158
+ "name": "out",
159
+ "path": "/nix/store/91g6383zq1wbiik2an7g6yfrj294c19v-uv-0.8.2",
160
+ "default": true
161
+ }
162
+ ],
163
+ "store_path": "/nix/store/91g6383zq1wbiik2an7g6yfrj294c19v-uv-0.8.2"
164
+ },
165
+ "x86_64-linux": {
166
+ "outputs": [
167
+ {
168
+ "name": "out",
169
+ "path": "/nix/store/swq8qrr7n5gkc1b4940q62a3ll52prgl-uv-0.8.2",
170
+ "default": true
171
+ }
172
+ ],
173
+ "store_path": "/nix/store/swq8qrr7n5gkc1b4940q62a3ll52prgl-uv-0.8.2"
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
@@ -12,7 +12,7 @@ import ulid
12
12
  copyright = f"{datetime.now(timezone.utc).year}, Martin Domke"
13
13
  author = "Martin Domke"
14
14
  master_doc = "index"
15
- source_suffix = [".rst", ".md"]
15
+ source_suffix = {".rst": "restructuredtext", ".md": "restructuredtext"}
16
16
 
17
17
  # The full version, including alpha/beta/rc tags
18
18
  release = ulid.__version__
@@ -23,6 +23,7 @@ version = release.rsplit(".", 1)[0]
23
23
  # ones.
24
24
  extensions = [
25
25
  "sphinx.ext.autodoc",
26
+ "sphinx.ext.intersphinx",
26
27
  "sphinx.ext.napoleon",
27
28
  "sphinx.ext.viewcode",
28
29
  "sphinx_copybutton",
@@ -31,11 +32,6 @@ extensions = [
31
32
  # Add any paths that contain templates here, relative to this directory.
32
33
  templates_path = ["_templates"]
33
34
 
34
- # List of patterns, relative to source directory, that match files and
35
- # directories to ignore when looking for source files.
36
- # This pattern also affects html_static_path and html_extra_path.
37
- exclude_patterns = []
38
-
39
35
 
40
36
  # -- Options for HTML output -------------------------------------------------
41
37
 
@@ -76,7 +72,10 @@ html_sidebars = {
76
72
  # Add any paths that contain custom static files (such as style sheets) here,
77
73
  # relative to this directory. They are copied after the builtin static files,
78
74
  # so a file named "default.css" will overwrite the builtin "default.css".
79
- html_static_path = ["_static"]
80
75
  pygments_style = "sphinx"
81
76
 
82
77
  autodoc_member_order = "groupwise"
78
+ # ----------------------------------------------
79
+
80
+ # Example configuration for intersphinx: refer to the Python standard library.
81
+ intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
@@ -5,7 +5,7 @@ features = [
5
5
  ]
6
6
 
7
7
  [envs.hatch-static-analysis]
8
- dependencies = ["ruff==0.6.*"]
8
+ dependencies = ["ruff==0.12.*"]
9
9
  config-path = ".ruff_defaults.toml"
10
10
 
11
11
  [envs.hatch-test]
@@ -29,12 +29,12 @@ xml = "coverage xml"
29
29
 
30
30
  [envs.types]
31
31
  extra-dependencies = [
32
- "mypy==1.11.*",
32
+ "mypy==1.17.*",
33
33
  ]
34
34
  scripts = { check = "mypy --install-types --non-interactive {args:ulid}" }
35
35
 
36
36
  [envs.docs]
37
37
  extra-dependencies = [
38
- "doc8==1.1.*",
38
+ "doc8==2.0.*",
39
39
  ]
40
40
  scripts = { check = "doc8 docs" }
@@ -23,6 +23,7 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.10",
24
24
  "Programming Language :: Python :: 3.11",
25
25
  "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
26
27
  "Topic :: Software Development :: Libraries",
27
28
  ]
28
29
 
@@ -104,6 +105,13 @@ source = ["ulid"]
104
105
  [tool.doc8]
105
106
  max-line-length = 100
106
107
 
108
+ [tool.uv]
109
+ dev-dependencies = [
110
+ "hatch>=1.14.1",
111
+ "freezegun>=1.5",
112
+ "sphinx>=7.4.7",
113
+ ]
114
+
107
115
  [tool.hatch.metadata.hooks.fancy-pypi-readme]
108
116
  content-type = "text/x-rst"
109
117
 
@@ -61,6 +61,19 @@ def test_ulid_monotonic_sorting(tick: int) -> None:
61
61
  assert_sorted([v.bytes for v in ulids])
62
62
 
63
63
 
64
+ @freeze_time()
65
+ def test_same_millisecond_monotonic_sorting() -> None:
66
+ ulids = [ULID() for _ in range(1000)]
67
+ assert_sorted(ulids)
68
+
69
+
70
+ @freeze_time()
71
+ def test_same_millisecond_overflow() -> None:
72
+ ULID.provider.prev_randomness = constants.MAX_RANDOMNESS
73
+ with pytest.raises(ValueError, match="Randomness within same millisecond exhausted"):
74
+ ULID()
75
+
76
+
64
77
  def assert_sorted(seq: list) -> None:
65
78
  last = seq[0]
66
79
  for item in seq[1:]:
@@ -154,6 +167,11 @@ def test_ulid_from_timestamp() -> None:
154
167
  assert ulid1.timestamp == ulid2.timestamp
155
168
 
156
169
 
170
+ def test_ulid_from_timestamp_overflow() -> None:
171
+ with pytest.raises(ValueError, match="Value exceeds maximum possible timestamp"):
172
+ ULID.from_timestamp(constants.MAX_TIMESTAMP + 1)
173
+
174
+
157
175
  Params = Union[bytes, str, int, float]
158
176
 
159
177
 
@@ -217,6 +235,7 @@ def test_pydantic_protocol() -> None:
217
235
  class Model(BaseModel):
218
236
  ulid: Optional[ULID] = None # noqa: FA100
219
237
 
238
+ model: Model | None = None
220
239
  for value in [ulid, str(ulid), int(ulid), bytes(ulid)]:
221
240
  model = Model(ulid=value)
222
241
  assert isinstance(model.ulid, ULID)
@@ -226,6 +245,7 @@ def test_pydantic_protocol() -> None:
226
245
  with pytest.raises(ValidationError):
227
246
  Model(ulid=value)
228
247
 
248
+ assert model is not None
229
249
  model_dict = model.model_dump()
230
250
  ulid_from_dict = model_dict["ulid"]
231
251
  assert ulid_from_dict == ulid
@@ -243,7 +263,7 @@ def test_pydantic_protocol() -> None:
243
263
  assert {
244
264
  "maxLength": 26,
245
265
  "minLength": 26,
246
- "pattern": "[A-Z0-9]{26}",
266
+ "pattern": "[0-7][0123456789ABCDEFGHJKMNPQRSTVWXYZ]{25}",
247
267
  "type": "string",
248
268
  } in model_json_schema["properties"]["ulid"]["anyOf"]
249
269
  assert {