Variants¶
Variants define a named group of image versions, each with its own
transformation. Pass a mapping of names to Transform
objects to variants() to generate a dictionary of
URLs. Pass a dataclass class to return a typed instance with URL attributes.
Tip
Use the local Docker server on port 8080 for the examples in this chapter.
Generate variants¶
Define a complete transformation for each name, then generate URLs for a source image:
from imgproxykit import Client, Transform
# Public URL of your imgproxy server.
client = Client('http://localhost:8080')
source_url = 'https://picsum.photos/id/237/1600/1200'
# Define a complete transformation for each variant name.
products = {
'small': Transform(width=320),
'medium': Transform(width=640),
'large': Transform(width=1280),
}
# Build one URL per variant for the same source image.
product_urls = client.variants(source=source_url, variants=products)
small_url = product_urls['small'] # Access a URL by its variant name.
print(small_url)
product_urls contains a URL for each of the three widths. Access a URL
by its name, or pass the dictionary to a template or API response.
The names belong to your application; each URL uses its transformation and
the client’s signing settings.
Reuse a variant set¶
Define a set once and reuse it across source images. Keep shared settings
in a base transformation and use extend() to
add a width for each variant:
from imgproxykit import Client, Transform
# Public URL of your imgproxy server.
client = Client('http://localhost:8080')
dog_source = 'https://picsum.photos/id/237/1600/1200'
pug_source = 'https://picsum.photos/id/1025/1600/1200'
# Share quality and output format across all variants.
base = Transform(quality=85, format='webp')
sizes = {
'small': base.extend(width=320),
'medium': base.extend(width=640),
'large': base.extend(width=1280),
}
# Reuse the same set for different source images.
dog_urls = client.variants(source=dog_source, variants=sizes)
pug_urls = client.variants(source=pug_source, variants=sizes)
print(dog_urls['small'])
print(pug_urls['small'])
Both dictionaries contain the same names and processing settings, with
URLs pointing to their respective sources. The shared sizes mapping
can be kept at module level and reused across requests.
Type variant names¶
Annotate the input mapping with a Literal union to check variant names
when accessing the generated URLs:
from typing import Literal, assert_type
from imgproxykit import Client, Transform
# Public URL of your imgproxy server.
client = Client('http://localhost:8080')
source_url = 'https://picsum.photos/id/237/1600/1200'
# Limit the allowed variant names with a literal union.
type ProductKeys = Literal['small', 'medium', 'large']
products: dict[ProductKeys, Transform] = {
'small': Transform(width=320),
'medium': Transform(width=640),
'large': Transform(width=1280),
}
# The returned dictionary preserves the annotated key type.
product_urls = client.variants(source=source_url, variants=products)
assert_type(product_urls, dict[ProductKeys, str])
print(product_urls['small'])
product_urls has type dict[ProductKeys, str]. A type checker accepts
product_urls['small'] and reports product_urls['profile'] as an
invalid key. Without an explicit key annotation, a regular string-keyed
mapping typically produces dict[str, str].
Return a dataclass¶
Declare a standard-library dataclass when you want a named result type
for an API response or application code. Each field combines its result
type, str, with a transformation in Annotated:
from dataclasses import dataclass
from typing import Annotated, assert_type
from imgproxykit import Client, Transform
# Share processing settings across all variants.
base = Transform(quality=85, format='webp')
@dataclass(frozen=True, slots=True)
class ProductImages:
"""Declare the result fields and their transformations together."""
small: Annotated[str, base.extend(width=320)]
medium: Annotated[str, base.extend(width=640)]
large: Annotated[str, base.extend(width=1280)]
client = Client('http://localhost:8080')
source_url = 'https://picsum.photos/id/237/1600/1200'
# Pass the class to build an instance containing the generated URLs.
product_urls = client.variants(source_url, variants=ProductImages)
assert_type(product_urls, ProductImages)
assert_type(product_urls.small, str)
print(product_urls.small)
Pass the class as variants=ProductImages and access the generated URLs
as attributes, such as product_urls.small. Reuse the class with other
sources or clients.
Note
Each field must declare exactly one Transform in
Annotated[str, Transform(...)]. Use Transform() for a URL without
processing options. InitVar and init=False fields are unsupported.
Use ProductImages as a field type in a Pydantic model or msgspec Struct,
and pass the result of client.variants() to that field. See the
FastAPI example.
Next steps¶
See the Client API reference for the complete
variants() signature and return type.