diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5bca1a2..3202353 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,14 +49,47 @@ jobs: build-wheels: - name: Build wheels (${{ matrix.os }}, py${{ matrix.python-version }}) + name: Build wheels (${{ matrix.os }}, ${{ matrix.target || 'native' }}, py${{ matrix.python-version }}) runs-on: ${{ matrix.os }} needs: [test-native] strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, windows-latest] python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + include: + # macOS ARM64 (native on macos-latest which is ARM) + - os: macos-latest + target: aarch64-apple-darwin + python-version: "3.10" + - os: macos-latest + target: aarch64-apple-darwin + python-version: "3.11" + - os: macos-latest + target: aarch64-apple-darwin + python-version: "3.12" + - os: macos-latest + target: aarch64-apple-darwin + python-version: "3.13" + - os: macos-latest + target: aarch64-apple-darwin + python-version: "3.14" + # macOS x86_64 (cross-compile from ARM runner) + - os: macos-latest + target: x86_64-apple-darwin + python-version: "3.10" + - os: macos-latest + target: x86_64-apple-darwin + python-version: "3.11" + - os: macos-latest + target: x86_64-apple-darwin + python-version: "3.12" + - os: macos-latest + target: x86_64-apple-darwin + python-version: "3.13" + - os: macos-latest + target: x86_64-apple-darwin + python-version: "3.14" steps: - name: Checkout @@ -71,19 +104,22 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} # Build typeid-python wheel (includes rust extension) - name: Build wheels (maturin) uses: PyO3/maturin-action@v1 with: command: build - args: --release --out dist + args: --release --out dist -i python${{ matrix.python-version }} + target: ${{ matrix.target }} manylinux: "2_28" - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-${{ matrix.os }}-py${{ matrix.python-version }} + name: wheels-${{ matrix.os }}-${{ matrix.target || 'native' }}-py${{ matrix.python-version }} path: dist/*.whl build-sdist: diff --git a/README.md b/README.md index 08fcdc4..7c21cd1 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,6 @@ Included: ```console $ pip install typeid-python[yaml] # YAML schema support $ pip install typeid-python[cli] # CLI tools -$ pip install typeid-python[pydantic] # Pydantic integration ``` Extras are **strictly optional**. @@ -163,10 +162,6 @@ Integrations are provided as optional adapters, installed explicitly and kept se * **Pydantic (v2)** Native field type with validation and JSON Schema support. - ```bash - pip install typeid-python[pydantic] - ``` - ```python from typing import Literal from pydantic import BaseModel @@ -176,19 +171,9 @@ Integrations are provided as optional adapters, installed explicitly and kept se id: TypeIDField[Literal["user"]] ``` -* **FastAPI** - Works automatically via Pydantic (request/response models, OpenAPI). - - ```bash - pip install typeid-python[fastapi] - ``` - -* **SQLAlchemy** - Column types for storing TypeIDs (typically as strings). +* **FastAPI** (Coming Soon 🚧) - ```bash - pip install typeid-python[sqlalchemy] - ``` +* **SQLAlchemy** (Coming Soon 🚧) All integrations are **opt-in via extras** and never affect the core package. diff --git a/docs/integrations/index.md b/docs/integrations/index.md index 88fd536..ebc62ea 100644 --- a/docs/integrations/index.md +++ b/docs/integrations/index.md @@ -20,12 +20,12 @@ Native support for using TypeID in Pydantic v2 models. * Clean JSON Schema / OpenAPI output ```bash -pip install typeid-python[pydantic] +pip install typeid-python pydantic ``` See: [Pydantic v2](https://akhundmurad.github.io/typeid-python/integrations/pydantic/) documentation page for details and examples. -### FastAPI +### FastAPI (Coming Soon 🚧) FastAPI builds on Pydantic v2, so TypeID works automatically in: @@ -35,24 +35,10 @@ FastAPI builds on Pydantic v2, so TypeID works automatically in: No separate FastAPI-specific adapter is required. -```bash -pip install typeid-python[fastapi] -``` - -See: [Pydantic v2](https://akhundmurad.github.io/typeid-python/integrations/fastapi/) documentation page for details and examples. - -### SQLAlchemy +### SQLAlchemy (Coming Soon 🚧) Column types for storing TypeIDs in relational databases. -Typical usage stores the full TypeID string (`prefix_suffix`) for clarity and debuggability. - -```bash -pip install typeid-python[sqlalchemy] -``` - -See: [Pydantic v2](https://akhundmurad.github.io/typeid-python/integrations/sqlalchemy/) documentation page for details and examples. - ## Design notes * The TypeID core never imports framework code diff --git a/docs/integrations/pydantic.md b/docs/integrations/pydantic.md index 809e911..18d883e 100644 --- a/docs/integrations/pydantic.md +++ b/docs/integrations/pydantic.md @@ -12,14 +12,6 @@ The adapter: --- -## Installation - -```bash -pip install typeid-python[pydantic] -``` - -This installs the latest version of Pydantic v2. - ## Basic usage Use `TypeIDField` with a fixed prefix. @@ -161,13 +153,6 @@ This works cleanly with: Using `Literal` makes the prefix a real compile-time constant and avoids annotation edge cases. -## FastAPI - -FastAPI uses Pydantic v2, so no extra integration is needed. - -TypeID fields work automatically in request and response models, -including OpenAPI output, as soon as you use them in a Pydantic model. - ## Design notes * The TypeID core does not import Pydantic. diff --git a/pyproject.toml b/pyproject.toml index 139ce5b..76c369a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "typeid-python" -version = "0.3.7" +version = "0.3.8" description = "Python implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs" authors = [{ name = "Murad Akhundov", email = "akhundov1murad@gmail.com" }] requires-python = ">=3.10,<4" @@ -22,7 +22,6 @@ dependencies = ["uuid-utils>=0.12.0"] [project.optional-dependencies] cli = ["click"] yaml = ["PyYAML"] -pydantic = ["pydantic>=2,<3"] [project.urls] Homepage = "https://github.com/akhundMurad/typeid-python" @@ -51,6 +50,8 @@ dev = [ "pytest-benchmark>=5.0.1", "maturin>=1.5; platform_system != 'Windows'", "pre-commit>=4.5.1", + "httpx>=0.28.1", + "pydantic>=2,<3", ] [tool.black] diff --git a/rust-base32/Cargo.lock b/rust-base32/Cargo.lock index e296c6e..9e73209 100644 --- a/rust-base32/Cargo.lock +++ b/rust-base32/Cargo.lock @@ -154,7 +154,7 @@ checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba" [[package]] name = "typeid-base32" -version = "0.3.7" +version = "0.3.8" dependencies = [ "pyo3", ] diff --git a/rust-base32/Cargo.toml b/rust-base32/Cargo.toml index 08529ae..750f803 100644 --- a/rust-base32/Cargo.toml +++ b/rust-base32/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "typeid-base32" -version = "0.3.7" +version = "0.3.8" edition = "2021" description = "Rust-accelerated base32 codec for typeid-python" diff --git a/uv.lock b/uv.lock index ab119bf..2f90021 100644 --- a/uv.lock +++ b/uv.lock @@ -11,6 +11,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, +] + [[package]] name = "babel" version = "2.17.0" @@ -390,6 +404,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9c/83/3b1d03d36f224edded98e9affd0467630fc09d766c0e56fb1498cbb04a9b/griffe-1.15.0-py3-none-any.whl", hash = "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", size = 150705, upload-time = "2025-11-10T15:03:13.549Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + [[package]] name = "id" version = "1.5.0" @@ -1502,7 +1553,7 @@ wheels = [ [[package]] name = "typeid-python" -version = "0.3.7" +version = "0.3.8" source = { editable = "." } dependencies = [ { name = "uuid-utils" }, @@ -1512,9 +1563,6 @@ dependencies = [ cli = [ { name = "click" }, ] -pydantic = [ - { name = "pydantic" }, -] yaml = [ { name = "pyyaml" }, ] @@ -1522,6 +1570,7 @@ yaml = [ [package.dev-dependencies] dev = [ { name = "black" }, + { name = "httpx" }, { name = "maturin", marker = "sys_platform != 'win32'" }, { name = "mkdocs-gen-files" }, { name = "mkdocs-git-revision-date-localized-plugin" }, @@ -1531,6 +1580,7 @@ dev = [ { name = "mkdocstrings", extra = ["python"] }, { name = "mypy" }, { name = "pre-commit" }, + { name = "pydantic" }, { name = "pytest" }, { name = "pytest-benchmark" }, { name = "pytest-markdown-docs" }, @@ -1543,15 +1593,15 @@ dev = [ [package.metadata] requires-dist = [ { name = "click", marker = "extra == 'cli'" }, - { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2,<3" }, { name = "pyyaml", marker = "extra == 'yaml'" }, { name = "uuid-utils", specifier = ">=0.12.0" }, ] -provides-extras = ["cli", "yaml", "pydantic"] +provides-extras = ["cli", "yaml"] [package.metadata.requires-dev] dev = [ { name = "black", specifier = ">=23.3.0,<24" }, + { name = "httpx", specifier = ">=0.28.1" }, { name = "maturin", marker = "sys_platform != 'win32'", specifier = ">=1.5" }, { name = "mkdocs-gen-files", specifier = ">=0.6.0" }, { name = "mkdocs-git-revision-date-localized-plugin", specifier = ">=1.5.0" }, @@ -1561,6 +1611,7 @@ dev = [ { name = "mkdocstrings", extras = ["python"], specifier = ">=1.0.0" }, { name = "mypy", specifier = ">=1.3.0,<2" }, { name = "pre-commit", specifier = ">=4.5.1" }, + { name = "pydantic", specifier = ">=2,<3" }, { name = "pytest", specifier = ">=7.3.2,<8" }, { name = "pytest-benchmark", specifier = ">=5.0.1" }, { name = "pytest-markdown-docs", specifier = ">=0.9.0" },