Skip to main content

fashion-size

PyPI version Python versions License: BSD-3-Clause Tests Ruff Typed Dependencies

Size types (UK dress size, EU adult shoe size, chest in centimetres) and the charts that convert them. Clothing and footwear share this library.

pip install fashion-size

Requires Python 3.12 or newer. There are no runtime dependencies.

Default UK / EU / US / AU charts are in Python. Brand charts that differ from those defaults ship as JSON: the rows, the source page, and notes live with the chart, and the date it was last checked lives in the brand catalog.

This package does not depend on Django. Django model fields are in django-fashion-size.

The source repository is github.com/ababic/fashion-size.

Brand charts

from fashion_size import SUPPORTED_BRANDS, ProductType
from fashion_size.charts import chart_for, load_brand_charts

"Dune London" in SUPPORTED_BRANDS
chart = chart_for("Dune London", "adult-shoe", "adult", "female", product_type=ProductType.SHOES)
chart.updated_at
chart.effective_from
chart.effective_until
chart.source_url
chart.source_notes
chart.rows

ProductType is the list of ranges a brand chart can cover on its own (jeans, trousers, shorts, skirts, bras, swimwear, nightwear, hosiery, outerwear, shoes, boots, and so on). A chart names the product types it replaces.

Each override chart is a JSON file named by id under src/fashion_size/fixtures/charts. The file holds the rows, the source page, and any notes about that table. Which brand it belongs to, the size type and demographic, when it was last checked, and when its rows take effect live in fashion_size.brands. A later chart for the same size type, demographic, and product types replaces the earlier one: effective_until is that next start, or none while the chart is current. A brand with no charts there matches the default charts. Superseded charts stay in the catalog.

chart_for takes an optional as_of timestamp, the instant the raw size was captured. Omit it to use the chart in force now. A capture time before the first chart in a series returns none.

Conversion

from fashion_size import Demographic, ProductType
from fashion_size.types import UK_ADULT_SHOE_SIZE, UK_DRESS_SIZE, Size

women = Demographic("adult", "female")
value = Size.from_raw("10", UK_DRESS_SIZE)
value.convert_to_locale("eu", demographic=women)

shoe = Size.from_raw("7", UK_ADULT_SHOE_SIZE)
shoe.convert_to_locale(
    "eu",
    demographic=women,
    brand_name="Dune London",
    product_type=ProductType.SHOES,
)

convert takes a SizeUnit on the same size type, or "cm" / "in" for a length. convert_to_locale resolves a locale such as "eu" to that size type's SizeUnit and calls convert. Both require a Demographic (age group and gender). Optional brand_name and product_type select a brand chart. Optional as_of is when the raw size was captured; omit it to use the chart in force now. Set strict_brand_name=True to reject a brand name that is not in SUPPORTED_BRANDS.

Both return a ConvertedSize with the resulting size and a ConversionSource (identity, default, brand, or length_formula). When the default chart is used, source.default_reason says why: no brand was passed (no_brand), the name is not in the catalog (unknown_brand), the catalog brand has no override charts (brand_uses_default), or the brand has no chart for this size type, product type, and capture time (no_matching_chart). Band size with a brand name records size_type_uses_default. ConvertedSize has no conversion method, so a converted value is not converted again.

Default charts use the same windows. The charts shipped in this package apply from the first representable instant until a later default for that size type and demographic replaces them. A capture time before a brand's first override uses the default chart that was in force then.

brand_name may be any string. A BrandName selects that brand's chart. Any other name uses the default chart unless strict_brand_name is set. An unknown product_type is an error.

French dress, shoe, cup, and chest labels are the EU size ("fr" converts to that EU value). French band size is the EU centimetre label plus 15. French waist size is not on the chart. Lengths convert between centimetres and inches (1 in = 2.54 cm) for values from 5 to 150 inches. Display rounding (nearest centimetre, nearest half inch) does not change the stored value.

UK, US, and AU waist and chest labels are the inch measurement, so they display like a length (30", 30 in). A UK or US band is the underbust in inches; an EU band is centimetres (75cm, 75 cm). An EU waist or chest label stays regional (EU 46): adult charts use a different number, and children's charts store centimetres, on one shared size unit. An AU band is a dress-style number (AU 12). A French band keeps its own number (FR 90).

Sports bras and bralettes can use alpha cup labels on the same size type. Stored values are XXS, XS, S, MD, LG, XL, and XXL (CUP_ALPHA_ORDER). Common aliases (small, med, medium, lg, large, x-large, 2xl) normalise to those. They convert identically across UK / EU / US / AU. Size.display shows MD / LG as M / L; raw stays MD / LG. Single-letter m and l are bra cup letters, so a feed that means alpha must send MD / LG (or medium / large) — do not persist the short display and parse it again. These labels are not rows on the letter chart. cup_attribute_values appends them after the chart letters for a locale, and cup_sort_key orders letters by chart row, then alpha from XXS to XXL.

Shoe sizes can also use alpha labels (XXS, XS, S, M, L, XL, XXL) on the existing shoe size types (adult-shoe, kids-shoe, baby-shoe). Common aliases (small, medium, large, x-large, 2xl) normalise to canonical tokens. These alpha labels convert identically across UK / EU / US / AU and are not rows on numeric charts. shoe_attribute_values(size_unit, age_group=..., gender=...) appends them after the chart values for that demographic.

Display language defaults to en-gb. A host application can register its own getter (Django's get_language, for example) with fashion_size.register_display_language.

Development

pip install -e ".[testing,development]"
pytest
ruff check src tests

Releasing

Publishing uses PyPI trusted publishing. On PyPI, add a pending publisher for the fashion-size project:

  • Owner: ababic
  • Repository: fashion-size
  • Workflow: release.yml
  • Environment: pypi

Create a GitHub environment named pypi (no secrets).

Version numbers (CalVer)

Releases use calendar versioning: YYYY.M.D (UTC date when the release is tagged), for example 2026.10.5. Git tags are v plus that string (v2026.10.5). The tag without the v must match fashion_size.__version__.

For a second release on the same UTC day, bump the micro segment: 2026.10.5.1 and tag v2026.10.5.1 (or use .post1 if you prefer PEP 440 post-releases).

Before tagging, bump src/fashion_size/__version__.py, update CHANGELOG.md, commit, then push the tag. The tagged commit must be on main or a branch named release-*. The workflow runs tests, checks that the tag matches the package version, builds wheels, creates a GitHub release, and publishes to PyPI. A tag whose commit is not on one of those branches fails before anything is published.

License

BSD 3-Clause. See LICENSE.

Metadata

Release files for fashion-size 2026.10.10

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

Source distribution (sdist)

Source distribution for fashion-size 2026.10.10
File Size Uploaded
fashion_size-2026.10.10.tar.gz 40.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fashion-size 2026.10.10
File Interpreter ABI Platform
fashion_size-2026.10.10-py3-none-any.whl Python 3 none any Details

Total release size: 82.8 kB

Release files / fashion_size-2026.10.10.tar.gz

Download URL fashion_size-2026.10.10.tar.gz
Size 40.0 kB
Tags Source
SHA-256 checksum
How to use checksums
426b7dbcc71417060e83dadcb66d9ca67a640091db21c4999218c830a5a55626
BLAKE2b-256 checksum
How to use checksums
c8ac4a282312c899d1f883aa9b5210a54ce3cfa52a5fefe5b3bffe719a0aff93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 10, 2026.

Transparency log

Release files / fashion_size-2026.10.10-py3-none-any.whl

Download URL fashion_size-2026.10.10-py3-none-any.whl
Size 42.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
156eb2ffa16d92b92942108986a8715a75c631561ea0ad5e606d8bc845ac4fc3
BLAKE2b-256 checksum
How to use checksums
596540f72598d1349c6435bc8233839f1e6241b6cf830965a940d3250de58bef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 10, 2026.

Transparency log
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