Skip to main content

Polymorphic URI types for Python: AnyUri, HttpUri, FileUri, GSUri, S3Uri, AzureUri, R2Uri, B2Uri

Project description

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 dispatchAnyUri(value) returns the right subtype for the scheme; your code branches on type, not string prefixes.
  • Dual representationas_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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anyuri-0.1.0.tar.gz (32.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anyuri-0.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file anyuri-0.1.0.tar.gz.

File metadata

  • Download URL: anyuri-0.1.0.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for anyuri-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fae46bfeccc76ca112c1155a4058eb07ac42b6d405e9e8e4fd9eca79350e0496
MD5 4fba24a6ea4683c8f9eca7a976f6bebe
BLAKE2b-256 63d609d9e42e03e749576905a72c24927e6947e5d6d49585ae9f5ddc338fe6b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for anyuri-0.1.0.tar.gz:

Publisher: release.yml on lucemia/anyuri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file anyuri-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: anyuri-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for anyuri-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96f1abbb0ff647022c354174a77a5f54b17982d6c829bd7fbd4326980783228e
MD5 8ffeea0cf67ee9e05e41b0ef5a6021c7
BLAKE2b-256 03741b3c3d43d9319ab6f841849062ba6ba2576704643bf7fe25461a29037d8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for anyuri-0.1.0-py3-none-any.whl:

Publisher: release.yml on lucemia/anyuri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page