Skip to main content

anyuri

Tests codecov Docs

Polymorphic URI types for Python. AnyUri auto-dispatches to the right subclass based on the input string, works as a plain str, and integrates with Pydantic v1/v2.

The Problem

Python data pipelines routinely handle assets from multiple backends — a thumbnail might live at gs://bucket/img.jpg, a report at s3://bucket/report.pdf, and a local fixture at /tmp/test.png. Without a shared abstraction, code degrades into scattered if uri.startswith("gs://") checks, duplicated normalization logic, and type annotations that lie (str accepts anything).

Cloud storage also has a dual-representation problem: the same GCS object is gs://bucket/key in SDK calls but https://storage.googleapis.com/bucket/key in HTTP clients and CDNs. Converting between them by hand is error-prone and leaks storage-specific logic everywhere.

anyuri solves both:

  • Polymorphic dispatch — AnyUri(value) returns the right subtype for the scheme; your code branches on type, not string prefixes.
  • Dual representation — as_uri() gives the canonical SDK form; str(uri) gives the HTTPS form accepted by any HTTP client. Conversion is automatic.
  • Zero friction — every AnyUri subclass is a str, so it passes to any existing API without casting or adapters.
from anyuri import AnyUri
from anyuri.providers import GSUri, S3Uri  # registers cloud providers

AnyUri("https://example.com/1.jpg")    # → HttpUri
AnyUri("gs://bucket/key.jpg")          # → GSUri
AnyUri("s3://bucket/key.jpg")          # → S3Uri
AnyUri("/local/path.jpg")              # → FileUri

uri = AnyUri("gs://bucket/key.jpg")
uri.as_uri()     # "gs://bucket/key.jpg"
uri.as_source()  # "https://storage.googleapis.com/bucket/key.jpg"
str(uri)         # "https://storage.googleapis.com/bucket/key.jpg"
uri == "https://storage.googleapis.com/bucket/key.jpg"  # True

Installation

pip install anyuri                  # core only (HttpUri, FileUri)
pip install anyuri[gcs]             # + GSUri
pip install anyuri[s3]              # + S3Uri
pip install anyuri[azure]           # + AzureUri
pip install anyuri[all]             # all cloud providers
pip install anyuri[all,pydantic]    # + Pydantic integration

Supported URI Types

Class Schemes accepted as_uri() as_source()
HttpUri http://, https:// original URL original URL
FileUri /path, file:///path file://localhost/path /path
GSUri gs://, https://storage.googleapis.com/ gs://bucket/key https://storage.googleapis.com/bucket/key
S3Uri s3://, virtual-hosted/path-style HTTPS s3://bucket/key https://bucket.s3.amazonaws.com/key
AzureUri abfs://, abfss://, https://*.blob.core.windows.net/ abfs://container@account.dfs.core.windows.net/path https://account.blob.core.windows.net/container/path
R2Uri r2://, https://*.r2.cloudflarestorage.com/ r2://account/bucket/key https://account.r2.cloudflarestorage.com/bucket/key
B2Uri b2://, https://f*.backblazeb2.com/file/ b2://bucket/key b2://bucket/key

Custom URI Types

from anyuri import AnyUri
from anyuri._exceptions import UriSchemaError

@AnyUri.register
class SFTPUri(AnyUri):
    def __new__(cls, value):
        return str.__new__(cls, cls._validate(value))

    @classmethod
    def _validate(cls, value):
        v = str(value)
        if not v.startswith("sftp://"):
            raise UriSchemaError(f"Not an SFTP URI: {v!r}")
        return v

    @classmethod
    def validate(cls, value):
        return cls(cls._validate(value))

AnyUri("sftp://host/path")  # → SFTPUri

Acknowledgements

This project would not exist without the support of my wife, Agnes, whose patience and encouragement make everything possible.

Pydantic Integration

from pydantic import BaseModel
from anyuri import AnyUri
from anyuri.providers import GSUri

class Asset(BaseModel):
    uri: AnyUri

Asset(uri="gs://bucket/key.jpg").uri  # GSUri instance
Asset(uri="https://example.com").uri  # HttpUri instance

Metadata

Release files for anyuri 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for anyuri 0.1.0
File Size Uploaded
anyuri-0.1.0.tar.gz 32.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for anyuri 0.1.0
File Interpreter ABI Platform
anyuri-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 44.7 kB

Release files / anyuri-0.1.0.tar.gz

Download URL anyuri-0.1.0.tar.gz
Size 32.6 kB
Tags Source
SHA-256 checksum
How to use checksums
fae46bfeccc76ca112c1155a4058eb07ac42b6d405e9e8e4fd9eca79350e0496
BLAKE2b-256 checksum
How to use checksums
63d609d9e42e03e749576905a72c24927e6947e5d6d49585ae9f5ddc338fe6b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 18, 2026.

Transparency log

Release files / anyuri-0.1.0-py3-none-any.whl

Download URL anyuri-0.1.0-py3-none-any.whl
Size 12.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
96f1abbb0ff647022c354174a77a5f54b17982d6c829bd7fbd4326980783228e
BLAKE2b-256 checksum
How to use checksums
03741b3c3d43d9319ab6f841849062ba6ba2576704643bf7fe25461a29037d8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page