python-ulid 3.0.0__tar.gz → 3.2.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.
Files changed (38) hide show
  1. python_ulid-3.2.1/.envrc +1 -0
  2. python_ulid-3.2.1/.github/workflows/lint-and-test.yml +101 -0
  3. python_ulid-3.2.1/.github/workflows/publish.yml +23 -0
  4. {python_ulid-3.0.0 → python_ulid-3.2.1}/.gitignore +1 -1
  5. python_ulid-3.2.1/.pre-commit-config.yaml +18 -0
  6. {python_ulid-3.0.0 → python_ulid-3.2.1}/.readthedocs.yml +1 -1
  7. {python_ulid-3.0.0 → python_ulid-3.2.1}/.ruff_defaults.toml +7 -9
  8. python_ulid-3.2.1/AGENTS.md +77 -0
  9. {python_ulid-3.0.0 → python_ulid-3.2.1}/CHANGELOG.rst +46 -6
  10. python_ulid-3.2.1/CONTRIBUTING.md +146 -0
  11. {python_ulid-3.0.0 → python_ulid-3.2.1}/PKG-INFO +27 -4
  12. {python_ulid-3.0.0 → python_ulid-3.2.1}/README.rst +21 -0
  13. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/source/conf.py +6 -7
  14. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/source/index.rst +4 -0
  15. {python_ulid-3.0.0 → python_ulid-3.2.1}/pyproject.toml +58 -3
  16. {python_ulid-3.0.0 → python_ulid-3.2.1}/tests/test_base32.py +1 -1
  17. {python_ulid-3.0.0 → python_ulid-3.2.1}/tests/test_cli.py +6 -2
  18. {python_ulid-3.0.0 → python_ulid-3.2.1}/tests/test_ulid.py +151 -6
  19. {python_ulid-3.0.0 → python_ulid-3.2.1}/ulid/__init__.py +148 -26
  20. {python_ulid-3.0.0 → python_ulid-3.2.1}/ulid/__main__.py +3 -0
  21. {python_ulid-3.0.0 → python_ulid-3.2.1}/ulid/constants.py +6 -0
  22. python_ulid-3.2.1/uv.lock +1038 -0
  23. python_ulid-3.0.0/.envrc +0 -10
  24. python_ulid-3.0.0/.github/workflows/lint-and-test.yml +0 -113
  25. python_ulid-3.0.0/.github/workflows/publish.yml +0 -29
  26. python_ulid-3.0.0/.pre-commit-config.yaml +0 -10
  27. python_ulid-3.0.0/devbox.json +0 -13
  28. python_ulid-3.0.0/devbox.lock +0 -62
  29. python_ulid-3.0.0/hatch.toml +0 -40
  30. {python_ulid-3.0.0 → python_ulid-3.2.1}/LICENSE +0 -0
  31. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/Makefile +0 -0
  32. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/requirements.txt +0 -0
  33. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/source/api.rst +0 -0
  34. {python_ulid-3.0.0 → python_ulid-3.2.1}/docs/source/changelog.rst +0 -0
  35. {python_ulid-3.0.0 → python_ulid-3.2.1}/logo.png +0 -0
  36. {python_ulid-3.0.0 → python_ulid-3.2.1}/tests/__init__.py +0 -0
  37. {python_ulid-3.0.0 → python_ulid-3.2.1}/ulid/base32.py +0 -0
  38. {python_ulid-3.0.0 → python_ulid-3.2.1}/ulid/py.typed +0 -0
@@ -0,0 +1 @@
1
+ use flox
@@ -0,0 +1,101 @@
1
+ name: lint-and-test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint-docs:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v7
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
16
+ with:
17
+ python-version: "3.14"
18
+ - name: Lint documentation
19
+ run: uv run doc8 docs/source
20
+
21
+ lint-code:
22
+ runs-on: ubuntu-latest
23
+ name: Lint code
24
+ steps:
25
+ - uses: actions/checkout@v7
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
28
+ with:
29
+ python-version: "3.14"
30
+ - name: Lint style
31
+ run: uv run ruff check
32
+
33
+ lint-typing:
34
+ runs-on: ubuntu-latest
35
+ name: Lint type annotations
36
+ steps:
37
+ - uses: actions/checkout@v7
38
+ - name: Install uv
39
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
40
+ with:
41
+ python-version: "3.14"
42
+ - name: Lint typing
43
+ run: uv run poe check-types
44
+
45
+ test:
46
+ runs-on: ubuntu-latest
47
+ name: Run tests
48
+ strategy:
49
+ matrix:
50
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
51
+ steps:
52
+ - uses: actions/checkout@v7
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
55
+ with:
56
+ python-version: ${{ matrix.python-version }}
57
+
58
+ - name: Test
59
+ run: uv run poe test
60
+
61
+ - name: Upload coverage data
62
+ uses: actions/upload-artifact@v7
63
+ with:
64
+ include-hidden-files: true
65
+ name: coverage-${{ matrix.python-version }}
66
+ path: .coverage*
67
+
68
+
69
+ coverage:
70
+ runs-on: ubuntu-latest
71
+ name: Report coverage
72
+ needs:
73
+ - test
74
+ steps:
75
+ - uses: actions/checkout@v7
76
+ - name: Install uv
77
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
78
+
79
+ - name: Download coverage data
80
+ uses: actions/download-artifact@v8
81
+ with:
82
+ pattern: coverage-*
83
+ merge-multiple: true
84
+
85
+ - name: Combine coverage data
86
+ run: uv run poe cov-combine
87
+
88
+ - name: Export coverage reports
89
+ run: uv run poe cov-xml
90
+
91
+ - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
92
+ with:
93
+ token: ${{ secrets.CODECOV_TOKEN }}
94
+
95
+
96
+ package:
97
+ name: Build & verify package
98
+ runs-on: ubuntu-latest
99
+ steps:
100
+ - uses: actions/checkout@v7
101
+ - uses: hynek/build-and-inspect-python-package@v2
@@ -0,0 +1,23 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["*"]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v7
13
+ - name: Install uv
14
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
15
+ with:
16
+ python-version: "3.14"
17
+ - name: Build
18
+ run: uv build
19
+ - name: Publish
20
+ env:
21
+ UV_PUBLISH_USERNAME: ${{ secrets.PYPI_USERNAME }}
22
+ UV_PUBLISH_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
23
+ run: uv publish
@@ -4,12 +4,12 @@ __pycache__
4
4
 
5
5
  /.tox
6
6
  /.coverage
7
+ /.coverage.*
7
8
  /.cache
8
9
  /.eggs
9
10
  /.mypy_cache
10
11
  /.pytest_cache
11
12
  /.ruff_cache
12
- /.devbox
13
13
 
14
14
  /coverage.xml
15
15
  /dist/
@@ -0,0 +1,18 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.4
4
+ hooks:
5
+ - id: ruff-check
6
+ - id: ruff-format
7
+ - repo: https://github.com/pycqa/doc8
8
+ rev: v2.0.0
9
+ hooks:
10
+ - id: doc8
11
+ - repo: local
12
+ hooks:
13
+ - id: pyrefly-check
14
+ name: pyrefly
15
+ entry: uv run pyrefly check
16
+ language: system
17
+ types: [python]
18
+ pass_filenames: false
@@ -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",
@@ -0,0 +1,77 @@
1
+ # Guidelines for AI Coding Agents
2
+
3
+ Welcome! If you are an AI assistant, coding agent, or language model (e.g., Antigravity, Claude Code, Cursor, Copilot) helping to develop `python-ulid`, please adhere to the guidelines in this document.
4
+
5
+ These instructions ensure consistency, prevent common development errors, and keep code quality aligned with the project's standards.
6
+
7
+ ---
8
+
9
+ ## 🏗️ Project Stack & Tooling
10
+
11
+ We use modern, fast, and strict tooling for Python development. Always use the specified commands below.
12
+
13
+ - **Dependency Manager**: We use **[uv](https://github.com/astral-sh/uv)**.
14
+ - Do *not* use raw `pip`, `poetry`, or `pdm`.
15
+ - To install dependencies, run: `uv sync`.
16
+ - Always prefix commands with `uv run` to execute them in the correct environment (e.g., `uv run pytest`).
17
+ - **Task Runner**: We use **[Poe the Poet](https://github.com/nat-n/poethepoet)**.
18
+ - Development tasks are defined in `pyproject.toml` under `[tool.poe.tasks]`.
19
+ - Run checks with `uv run poe check`.
20
+ - **Linting & Formatting**: We use **[Ruff](https://github.com/astral-sh/ruff)**.
21
+ - Standard line-length limit is **100 characters**.
22
+ - Auto-format code using `uv run poe fmt`.
23
+ - **Static Typing**: We use **[pyrefly](https://github.com/mdomke/pyrefly)** for strict static analysis.
24
+ - Run type checking using `uv run poe check-types`.
25
+
26
+ ---
27
+
28
+ ## 🎯 Coding Standards for Agents
29
+
30
+ ### 1. Mandatory Type Annotations
31
+ We require full, strict type annotations across the entire codebase.
32
+ - **Rules**:
33
+ - Always annotate all function parameters and return values.
34
+ - Avoid `Any` where possible; use specific types, unions, or generics.
35
+ - Run type checking to verify compliance: `uv run poe check-types`.
36
+
37
+ ### 2. Ruff Compliance
38
+ - **Formatting**: Run formatting before finalizing any file modifications.
39
+ - Use `uv run poe fmt` to auto-format.
40
+ - Code style rules are detailed in `pyproject.toml` and `.ruff_defaults.toml`.
41
+ - **Imports**: We use single-line imports and specific import order (`isort` rules). Let Ruff handle this automatically.
42
+
43
+ ### 3. Production-Ready Code Only
44
+ - Never generate code with comments like `# TODO: implement this`, `# placeholder`, or partial code blocks.
45
+ - Implement the full logic requested, ensuring error handling and correct edge cases are covered.
46
+
47
+ ---
48
+
49
+ ## 🛠️ Verification Workflow
50
+
51
+ Before completing any task, you **MUST** run the verification commands to ensure no regressions or style issues are introduced.
52
+
53
+ 1. **Format Code**:
54
+ ```bash
55
+ uv run poe fmt
56
+ ```
57
+ 2. **Run Lints, Types & Style Checks**:
58
+ ```bash
59
+ uv run poe check
60
+ ```
61
+ 3. **Run Test Suite**:
62
+ ```bash
63
+ uv run poe test
64
+ ```
65
+
66
+ Make sure all checks pass without errors.
67
+
68
+ ---
69
+
70
+ ## 📂 Codebase Navigation
71
+
72
+ - **`/ulid`**: Contains the source code of the `python-ulid` package.
73
+ - **`/tests`**: Contains all unit and integration tests. Write corresponding test cases here for any new logic.
74
+ - **`/docs`**: Contains Sphinx-based documentation.
75
+ - **`pyproject.toml`**: The single source of truth for dependencies, tools configuration, and Poe tasks.
76
+
77
+ Refer to the primary developer documentation and [CONTRIBUTING.md](file:///Users/martin.domke/Source/private/ulid/CONTRIBUTING.md) for more details.
@@ -5,11 +5,49 @@ Changelog
5
5
 
6
6
  Versions follow `Semantic Versioning <http://www.semver.org>`_
7
7
 
8
+ `3.2.0`_ - 2026-07-17
9
+ ---------------------
10
+ Added
11
+ ~~~~~
12
+ * Added transparent bidirectional UUIDv7 conversion methods (``ULID.to_uuid7`` and
13
+ ``ULID.from_uuidv7``) `@pirate <https://github.com/pirate>`_.
14
+ * Added a ``--uuid7`` option to the CLI's ``show`` command to convert and output a ULID as an
15
+ RFC 4122 compliant UUIDv7.
16
+
17
+ Changed
18
+ ~~~~~~~
19
+ * Dropped support for Python 3.9 and added support for Python 3.14
20
+ `@Avihais12344 <https://github.com/Avihais12344>`_.
21
+ * Depend on ``typing-extensions`` only when running on Python < 3.11 `@musicinmybrain <https://github.com/musicinmybrain>`_.
22
+ * Migrated package and development workflow from Hatch to ``uv`` and ``poethepoet``.
23
+ * Configured Flox for bootstrapping the development environment.
24
+
25
+ Fixed
26
+ ~~~~~
27
+ * Fixed a clock-skew bug where non-monotonic ULIDs could be generated when crossing a millisecond boundary between timestamp and randomness sampling `@gaoflow <https://github.com/gaoflow>`_.
28
+ * Fixed warning from ``uv`` during synchronization `@jaseemabid <https://github.com/jaseemabid>`_.
29
+ * Resolved various Ruff linter warnings and Pyrefly type checker issues.
30
+
31
+ `3.1.0`_ - 2025-08-18
32
+ ---------------------
33
+ Changed
34
+ ~~~~~~~
35
+ * Added Python 3.13 to the trove classifiers.
36
+ * Optimze ``@property`` to ``@cached_property`` `@WH-2099 <https://github.com/WH-2099>`_.
37
+ * When generating ULIDs within the same millisecond, the library will ensure monotonic sort order by
38
+ incrementing the randomness component by 1 bit. This process is descrbied in the
39
+ `spec <https://github.com/ulid/spec/blob/master/README.md#monotonicity>`_.
40
+
41
+ Fixed
42
+ ~~~~~
43
+ * Sharpen regular expression for Pydantic `@aplhk <https://github.com/aplhk>`_.
44
+ * Fix Sphinx warnings when referencing ULID from an external project. `@BoboTiG <https://github.com/BoboTiG>`_.
45
+
8
46
  `3.0.0`_ - 2024-10-11
9
47
  ---------------------
10
48
  Changed
11
49
  ~~~~~~~
12
- * Raise `TypeError` instead of `ValueError` if constructor is called with value of wrong type.
50
+ * Raise ``TypeError`` instead of ``ValueError`` if constructor is called with value of wrong type.
13
51
  * Update ``ruff`` linter rules and switch to ``hatch fmt``.
14
52
 
15
53
  Added
@@ -71,7 +109,7 @@ Added
71
109
  ~~~~~
72
110
  * Added a new flag ``--uuid4`` to the CLI ``show`` command, that converts the provided ``ULID``
73
111
  into an RFC 4122 compliant ``UUID``.
74
- * The `ulid build` command allows the use of the special value ``-`` for all options to read its
112
+ * The ``ulid build`` command allows the use of the special value ``-`` for all options to read its
75
113
  inputs from ``stdin``. E.g.
76
114
 
77
115
  .. code-block:: bash
@@ -128,7 +166,7 @@ Changed
128
166
  Added
129
167
  ~~~~~
130
168
  * Added support for Python 3.10.
131
- * Added :attr:`__version__` variable to package.
169
+ * Added ``__version__`` variable to package.
132
170
 
133
171
 
134
172
  `1.0.3`_ - 2021-07-14
@@ -153,7 +191,7 @@ Added
153
191
  Changed
154
192
  ~~~~~~~
155
193
  * 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
194
+ * The named constructor ``ULID.new`` has been removed. Use one of the specifc named
157
195
  constructors instead. For a new :class:`.ULID` created from the current timestamp use the
158
196
  standard constructor.
159
197
 
@@ -169,8 +207,8 @@ Changed
169
207
  ulid = ULID.from_timestamp(time.time())
170
208
  ulid = ULID.from_datetime(datetime.now())
171
209
 
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.
210
+ * The ``ULID.str`` and ``ULID.int`` methods have been removed in favour of the more
211
+ Pythonic special dunder-methods. Use ``str(ulid)`` and ``int(ulid)`` instead.
174
212
  * Added the property :meth:`.ULID.hex` that returns a hex representation of the :class:`.ULID`.
175
213
 
176
214
  .. code-block:: python
@@ -182,6 +220,8 @@ Changed
182
220
  * The package now has no external dependencies.
183
221
  * The test-coverage has been raised to 100%.
184
222
 
223
+ .. _3.2.0: https://github.com/mdomke/python-ulid/compare/3.1.0...3.2.0
224
+ .. _3.1.0: https://github.com/mdomke/python-ulid/compare/3.0.0...3.1.0
185
225
  .. _3.0.0: https://github.com/mdomke/python-ulid/compare/2.7.0...3.0.0
186
226
  .. _2.7.0: https://github.com/mdomke/python-ulid/compare/2.6.0...2.7.0
187
227
  .. _2.6.0: https://github.com/mdomke/python-ulid/compare/2.5.0...2.6.0
@@ -0,0 +1,146 @@
1
+ # Contributing to python-ulid
2
+
3
+ Thank you for your interest in contributing to `python-ulid`! We appreciate all kinds of contributions: fixing bugs, improving documentation, submitting feature requests, or writing code.
4
+
5
+ This document guides you through setting up your local environment and details our development workflow and coding standards.
6
+
7
+ ---
8
+
9
+ ## 🚀 Getting Started
10
+
11
+ We support two ways to set up your local development environment: **Flox** (recommended, zero-configuration setup) or a **Manual** setup.
12
+
13
+ ### Option 1: Using Flox (Recommended)
14
+
15
+ If you have [Flox](https://flox.dev/) installed, setting up your environment is completely automated. Flox will automatically handle installing `uv`, Python, project dependencies, and pre-commit hooks inside a reproducible environment.
16
+
17
+ 1. **Fork and clone** the repository:
18
+ ```bash
19
+ git clone https://github.com/<your-username>/python-ulid.git
20
+ cd python-ulid
21
+ ```
22
+
23
+ 2. **Activate the Flox environment**:
24
+ ```bash
25
+ flox activate
26
+ ```
27
+ That's it! Flox automatically sets up everything for you and activates your python virtual environment.
28
+
29
+ ---
30
+
31
+ ### Option 2: Manual Setup
32
+
33
+ If Flox is not an option, you can set up your environment manually. We use [uv](https://github.com/astral-sh/uv) for fast, robust package and dependency management.
34
+
35
+ 1. **Prerequisites**:
36
+ - **Python**: `>= 3.10`
37
+ - **uv**: Install via `curl -LsSf https://astral.sh/uv/install.sh | sh` (or your preferred package manager)
38
+
39
+ 2. **Fork and clone** the repository:
40
+ ```bash
41
+ git clone https://github.com/<your-username>/python-ulid.git
42
+ cd python-ulid
43
+ ```
44
+
45
+ 3. **Sync the dependencies**:
46
+ This will automatically create a `.venv` virtual environment and install all packages in the developer and documentation groups:
47
+ ```bash
48
+ uv sync
49
+ ```
50
+
51
+ 4. **Install pre-commit hooks**:
52
+ We use `prek` (a fast, Rust-based alternative to pre-commit) to manage our Git hooks, ensuring code style, formatting, and static typing checks run automatically before each commit.
53
+ ```bash
54
+ uv run prek install
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 🛠️ Development Tasks & Commands
60
+
61
+ We use [Poe the Poet](https://github.com/nat-n/poethepoet) as our task runner. Depending on how you set up your development environment, you can invoke the tasks directly or via `uv run`:
62
+
63
+ - **With Flox (Recommended)**: Since the virtual environment is automatically activated in your shell, you can run all commands directly:
64
+ ```bash
65
+ poe test
66
+ ```
67
+ - **With Manual Setup**: If you did not use Flox, prefix all tasks with `uv run`:
68
+ ```bash
69
+ uv run poe test
70
+ ```
71
+ (You can also manually activate the virtual environment to get the same shorthands as above).
72
+
73
+ ### Common Development Tasks
74
+
75
+ | Task | Command (Flox) | Command (Manual) | Description |
76
+ | :--- | :--- | :--- | :--- |
77
+ | **All Checks** | `poe check` | `uv run poe check` | Run linter, formatter checks, type checking, and docs check. |
78
+ | **Formatting** | `poe fmt` | `uv run poe fmt` | Auto-format Python source files using `ruff format`. |
79
+ | **Lint** | `poe check-code` | `uv run poe check-code` | Check source files for lint and code style issues using `ruff`. |
80
+ | **Format Check** | `poe check-fmt` | `uv run poe check-fmt` | Dry-run format check without modifying files. |
81
+ | **Type Check** | `poe check-types` | `uv run poe check-types` | Run strict static analysis and type verification with `pyrefly`. |
82
+ | **Docs Lint** | `poe check-docs` | `uv run poe check-docs` | Lint documentation style using `doc8`. |
83
+ | **Run Tests** | `poe test` | `uv run poe test` | Run pytest with code coverage tracking. |
84
+ | **Build Docs** | `poe docs` | `uv run poe docs` | Build the HTML documentation locally using Sphinx. |
85
+
86
+ > [!TIP]
87
+ > Before pushing any changes or opening a Pull Request, always make sure to run the complete checks suite with **`poe check`** (or `uv run poe check`) and run the test suite with **`poe test`** (or `uv run poe test`).
88
+
89
+ ### Manual Hook Execution with prek
90
+
91
+ If you want to run all checks against your staged or unstaged files manually:
92
+
93
+ - **With Flox**:
94
+ ```bash
95
+ prek run --all-files
96
+ ```
97
+ - **With Manual Setup**:
98
+ ```bash
99
+ uv run prek run --all-files
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 🎨 Coding Standards
105
+
106
+ To maintain a clean, readable, and highly maintainable codebase, we enforce the following development standards:
107
+
108
+ ### 1. Type Annotations
109
+ - **Strictly Required**: We enforce type annotations across the entire codebase. This includes all function signatures, arguments, and return types.
110
+ - **Static Analysis**: Our configuration has `disallow_untyped_defs = true` set for Mypy and uses strict `pyrefly` checks. Untyped or partially-typed code will fail the lint pipelines.
111
+ - **Example**:
112
+ ```python
113
+ def generate_ulid(timestamp: float | None = None) -> ULID:
114
+ ...
115
+ ```
116
+
117
+ ### 2. Ruff Formatting & Linting
118
+ - **Formatting**: We use [Ruff](https://github.com/astral-sh/ruff) for automatic code formatting (`ruff format`).
119
+ - **Code Style**: Ruff also handles our lint checks, including import sorting (`isort`), code complexity limits (`mccabe`), and code style conventions.
120
+ - **Configuration**:
121
+ - Line length limit: **100 characters**.
122
+ - Imports are forced to single lines and ordered.
123
+ - Standard Ruff defaults apply (see `.ruff_defaults.toml`).
124
+
125
+ ---
126
+
127
+ ## 📬 Submitting a Pull Request
128
+
129
+ 1. **Create a branch** for your feature or bugfix:
130
+ ```bash
131
+ git checkout -b feature/my-cool-improvement
132
+ ```
133
+ 2. **Make your changes**, ensuring you write comprehensive unit tests.
134
+ 3. **Format and verify** your code (e.g. using `poe` directly if using Flox, or prefixed with `uv run` if manual):
135
+ ```bash
136
+ poe fmt
137
+ poe check
138
+ poe test
139
+ ```
140
+ 4. **Commit your changes**:
141
+ Our pre-commit hooks will automatically trigger to verify your work.
142
+ 5. **Push and open a PR** on GitHub! Please provide a descriptive title and detailed explanation of your changes in the PR description.
143
+
144
+ ---
145
+
146
+ Thank you for helping make `python-ulid` better! 🌟
@@ -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.2.1
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
@@ -18,12 +18,14 @@ Classifier: License :: OSI Approved :: MIT License
18
18
  Classifier: Operating System :: MacOS :: MacOS X
19
19
  Classifier: Operating System :: POSIX :: Linux
20
20
  Classifier: Programming Language :: Python
21
- Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Programming Language :: Python :: 3.11
24
23
  Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
25
26
  Classifier: Topic :: Software Development :: Libraries
26
- Requires-Python: >=3.9
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: typing-extensions; python_version < '3.11'
27
29
  Provides-Extra: pydantic
28
30
  Requires-Dist: pydantic>=2.0; extra == 'pydantic'
29
31
  Description-Content-Type: text/x-rst
@@ -39,6 +41,7 @@ A ``ULID`` is a *universally unique lexicographically sortable identifier*. It i
39
41
  * Uses Crockford's base32 for better efficiency and readability (5 bits per character)
40
42
  * Case insensitive
41
43
  * No special characters (URL safe)
44
+ * Monotonic sort order (correctly detects and handles the same millisecond)
42
45
 
43
46
  In general the structure of a ULID is as follows:
44
47
 
@@ -147,6 +150,20 @@ The ``ULID`` class can be directly used for the popular data validation library
147
150
 
148
151
  .. pydantic-end
149
152
 
153
+ .. monotonic-begin
154
+
155
+ Monotonic Support
156
+ -----------------
157
+
158
+ This library by default supports the implementation for monotonic sort order suggested by the
159
+ official ULID specification.
160
+
161
+ This means that ULID values generated in the same millisecond will have linear increasing randomness
162
+ values. If :math:`r_1` and :math:`r_2` are the randomness values of two ULIDs with the same
163
+ timestamp, then :math:`r_2 = r_1 + 1`.
164
+
165
+ .. monotonic-end
166
+
150
167
  .. cli-begin
151
168
 
152
169
  Command line interface
@@ -204,3 +221,9 @@ Other implementations
204
221
  * `ulid/javascript <https://github.com/ulid/javascript>`_
205
222
  * `RobThree/NUlid <https://github.com/RobThree/NUlid>`_
206
223
  * `imdario/go-ulid <https://github.com/imdario/go-ulid>`_
224
+
225
+ Contributions
226
+ -------------
227
+
228
+ Contributions are welcome! Feel free to create pull-requests for issues or feature requests.
229
+ It might be worth creating an issue upfront to discuss the matter.
@@ -42,6 +42,7 @@ A ``ULID`` is a *universally unique lexicographically sortable identifier*. It i
42
42
  * Uses Crockford's base32 for better efficiency and readability (5 bits per character)
43
43
  * Case insensitive
44
44
  * No special characters (URL safe)
45
+ * Monotonic sort order (correctly detects and handles the same millisecond)
45
46
 
46
47
  In general the structure of a ULID is as follows:
47
48
 
@@ -150,6 +151,20 @@ The ``ULID`` class can be directly used for the popular data validation library
150
151
 
151
152
  .. pydantic-end
152
153
 
154
+ .. monotonic-begin
155
+
156
+ Monotonic Support
157
+ -----------------
158
+
159
+ This library by default supports the implementation for monotonic sort order suggested by the
160
+ official ULID specification.
161
+
162
+ This means that ULID values generated in the same millisecond will have linear increasing randomness
163
+ values. If :math:`r_1` and :math:`r_2` are the randomness values of two ULIDs with the same
164
+ timestamp, then :math:`r_2 = r_1 + 1`.
165
+
166
+ .. monotonic-end
167
+
153
168
  .. cli-begin
154
169
 
155
170
  Command line interface
@@ -207,3 +222,9 @@ Other implementations
207
222
  * `ulid/javascript <https://github.com/ulid/javascript>`_
208
223
  * `RobThree/NUlid <https://github.com/RobThree/NUlid>`_
209
224
  * `imdario/go-ulid <https://github.com/imdario/go-ulid>`_
225
+
226
+ Contributions
227
+ -------------
228
+
229
+ Contributions are welcome! Feel free to create pull-requests for issues or feature requests.
230
+ It might be worth creating an issue upfront to discuss the matter.
@@ -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)}