Name the everyday media type extensions, refuse an emptied table, and cut the false register claim
Tests / vet + fmt + tests (pull_request) Successful in 1m26s
Tests / Gitea release from CHANGELOG.md (pull_request) Has been skipped

This commit is contained in:
2026-09-18 21:55:54 +02:00
parent 69d0db9431
commit ecc0b475ae
7 changed files with 24 additions and 25 deletions
+5 -4
View File
@@ -26,10 +26,11 @@ replacement, and each removed path, column or flag.
capital, a currency and a TLD, with the columns `calling-code`, `capital`, capital, a currency and a TLD, with the columns `calling-code`, `capital`,
`currency`, `flag`, `languages`, `numeric` and `tld` added; `misc.currency` the `currency`, `flag`, `languages`, `numeric` and `tld` added; `misc.currency` the
current ISO 4217 currencies with a minor unit, with `decimals` and `numeric` current ISO 4217 currencies with a minor unit, with `decimals` and `numeric`
added, and its symbols from CLDR; `misc.language` every ISO 639-1 language, with added, and its symbols from CLDR; `misc.language` every ISO 639-2 entry carrying a
a `code3` column carrying its ISO 639-2 code; `misc.httpstatus` every HTTP status 639-1 code, with a `code3` column holding its 639-2/T code; `misc.httpstatus` each
code in use in the IANA registry; and `misc.mimetype` every IANA media type that code the IANA registry lists with a plain reason phrase; and `misc.mimetype` each
has a filename extension. `DATA-LICENSES.md` lists each source. type mime-db records as IANA-registered and gives a filename extension.
`DATA-LICENSES.md` lists each source.
- `geo.SE` and `geo.US`: five linked tables per country, `region`, `municipality`, - `geo.SE` and `geo.US`: five linked tables per country, `region`, `municipality`,
`locality`, `postal-code` and `street`, weighted by population and address counts `locality`, `postal-code` and `street`, weighted by population and address counts
and built from SCB, GeoNames, Trafikverket NVDB and the US Census Bureau, and an and built from SCB, GeoNames, Trafikverket NVDB and the US Census Bureau, and an
+1 -1
View File
@@ -19,6 +19,6 @@ Every shipped dataset, its source, its licence and the attribution it asks for.
| `misc/currency.tsv` | [datasets/currency-codes](https://github.com/datasets/currency-codes); symbols from [Unicode CLDR](https://github.com/unicode-org/cldr) `en.xml` and `root.xml` | PDDL 1.0; [Unicode License v3](https://www.unicode.org/license.txt) | CLDR: "Copyright © 1991-2025 Unicode, Inc. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the United States and other countries." | `data-import/currency.py` | | `misc/currency.tsv` | [datasets/currency-codes](https://github.com/datasets/currency-codes); symbols from [Unicode CLDR](https://github.com/unicode-org/cldr) `en.xml` and `root.xml` | PDDL 1.0; [Unicode License v3](https://www.unicode.org/license.txt) | CLDR: "Copyright © 1991-2025 Unicode, Inc. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the United States and other countries." | `data-import/currency.py` |
| `misc/httpstatus.tsv` | [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/) | [public domain](https://www.iana.org/help/licensing-terms) | none required | `data-import/httpstatus.py` | | `misc/httpstatus.tsv` | [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/) | [public domain](https://www.iana.org/help/licensing-terms) | none required | `data-import/httpstatus.py` |
| `misc/language.tsv` | [datasets/language-codes](https://github.com/datasets/language-codes), the [Library of Congress](https://www.loc.gov/standards/iso639-2/) ISO 639-2 register | [PDDL 1.0](https://opendatacommons.org/licenses/pddl/1-0/) | none required | `data-import/language.py` | | `misc/language.tsv` | [datasets/language-codes](https://github.com/datasets/language-codes), the [Library of Congress](https://www.loc.gov/standards/iso639-2/) ISO 639-2 register | [PDDL 1.0](https://opendatacommons.org/licenses/pddl/1-0/) | none required | `data-import/language.py` |
| `misc/mimetype.tsv` | [mime-db](https://github.com/jshttp/mime-db), the IANA media type registry with filename extensions | [MIT](https://github.com/jshttp/mime-db/blob/master/LICENSE) | none required | `data-import/mimetype.py` | | `misc/mimetype.tsv` | [mime-db](https://github.com/jshttp/mime-db), the IANA media type registry with filename extensions | [MIT](https://github.com/jshttp/mime-db/blob/master/LICENSE) | "Copyright (c) 2014 Jonathan Ong, Copyright (c) 2015-2022 Douglas Christopher Wilson" | `data-import/mimetype.py` |
Every other category is hand-written JSON under [`data/`](data), MIT like the code. Every other category is hand-written JSON under [`data/`](data), MIT like the code.
+4 -7
View File
@@ -163,15 +163,12 @@ Each locale carries `address`, `color`, `company`, `date`, `email`, `first-name`
`personnummer` and `samordningsnummer`, `en_US` adds `ssn` and `itin`. `misc` `personnummer` and `samordningsnummer`, `en_US` adds `ssn` and `itin`. `misc`
carries `car`, `coordinate`, `country` (ISO 3166), `creditcard` (Luhn-valid), carries `car`, `coordinate`, `country` (ISO 3166), `creditcard` (Luhn-valid),
`currency` (ISO 4217), `datetime` (RFC 3339), `emoji`, `httpstatus`, `language` `currency` (ISO 4217), `datetime` (RFC 3339), `emoji`, `httpstatus`, `language`
(ISO 639-1 and -2), `mac`, `mimetype`, `objectid`, `timezone` (IANA), `useragent` and (ISO 639-1, with its 639-2/T code), `mac`, `mimetype`, `objectid`, `timezone` (IANA),
`uuid` (v4). Many carry sub-fields — `misc.currency.symbol`, `useragent` and `uuid` (v4). Many carry sub-fields — `misc.currency.symbol`,
`misc.country.alpha2`, `misc.httpstatus.code` — which `--list` shows. `country`, `misc.country.alpha2`, `misc.httpstatus.code` — which `--list` shows. `country`,
`currency`, `httpstatus`, `language` and `mimetype` are [tables](#table), so `currency`, `httpstatus`, `language` and `mimetype` are [tables](#table), so
`misc.country[SE].capital` and `misc.currency[Euro].symbol` select a row. Each `misc.country[SE].capital` and `misc.currency[Euro].symbol` select a row;
holds its whole register: every ISO 3166 country, ISO 4217 currency and ISO 639-1 [`DATA-LICENSES.md`](DATA-LICENSES.md) names each table's source and licence.
language, every HTTP status code in use, and every IANA media type that has a
filename extension. [`DATA-LICENSES.md`](DATA-LICENSES.md) names each table's
source and licence.
`sex`, `first-name` and `last-name` are tables weighted by bearers, from SCB, the `sex`, `first-name` and `last-name` are tables weighted by bearers, from SCB, the
SSA and the Census Bureau. `first-name` links to `sex`, so `sv_SE.sex[f].first-name` SSA and the Census Bureau. `first-name` links to `sex`, so `sv_SE.sex[f].first-name`
+4 -2
View File
@@ -3,7 +3,7 @@
data-import/mimetype.py [--source URL_OR_FILE] [--cache DIR] [--out FILE] data-import/mimetype.py [--source URL_OR_FILE] [--cache DIR] [--out FILE]
Only IANA-registered types with a filename extension ship; the first extension is the one listed. Only types mime-db records as IANA-registered, with a filename extension, ship.
""" """
import argparse import argparse
import json import json
@@ -16,12 +16,14 @@ SOURCE = "https://raw.githubusercontent.com/jshttp/mime-db/master/db.json"
OUT = Path(__file__).resolve().parent.parent / "data" / "misc" / "mimetype.tsv" OUT = Path(__file__).resolve().parent.parent / "data" / "misc" / "mimetype.tsv"
CACHE = Path(__file__).resolve().parent / "cache" CACHE = Path(__file__).resolve().parent / "cache"
COLUMNS = ["ext", "type"] COLUMNS = ["ext", "type"]
# mime-db lists extensions in no particular order, so where the everyday one is not first, name it.
FIXUPS = {"application/mp4": "mp4s", "audio/mpeg": "mp3", "audio/ogg": "ogg", "video/quicktime": "mov"}
def rows(db): def rows(db):
for mimetype, entry in db.items(): for mimetype, entry in db.items():
if entry.get("source") == "iana" and entry.get("extensions"): if entry.get("source") == "iana" and entry.get("extensions"):
yield {"ext": "." + entry["extensions"][0], "type": mimetype} yield {"ext": "." + FIXUPS.get(mimetype, entry["extensions"][0]), "type": mimetype}
def main(): def main():
+3 -1
View File
@@ -5,12 +5,14 @@ from pathlib import Path
def write(path, columns, rows): def write(path, columns, rows):
"""Write the rows as a TSV; every cell must be non-empty and free of tabs, newlines and braces.""" """Write the rows as a TSV; the table needs a row, and every cell must be non-empty and free of tabs, newlines and braces."""
lines = ["\t".join(columns)] lines = ["\t".join(columns)]
for row in rows: for row in rows:
cells = [str(row[c]) for c in columns] cells = [str(row[c]) for c in columns]
if not all(cells) or any(re.search(r"[\t\n{}]", c) for c in cells): if not all(cells) or any(re.search(r"[\t\n{}]", c) for c in cells):
raise ValueError(f"{path}: a cell is empty or holds a tab, newline or brace: {row}") raise ValueError(f"{path}: a cell is empty or holds a tab, newline or brace: {row}")
lines.append("\t".join(cells)) lines.append("\t".join(cells))
if len(lines) < 2:
raise ValueError(f"{path}: has no rows below its header; a table is at least two rows")
Path(path).write_text("\n".join(lines) + "\n", encoding="utf-8") Path(path).write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"{path}: {len(lines) - 1} rows", file=sys.stderr) print(f"{path}: {len(lines) - 1} rows", file=sys.stderr)
+4 -4
View File
@@ -62,7 +62,7 @@ ext type
.musd application/mmt-usd+xml .musd application/mmt-usd+xml
.mods application/mods+xml .mods application/mods+xml
.m21 application/mp21 .m21 application/mp21
.mp4 application/mp4 .mp4s application/mp4
.doc application/msword .doc application/msword
.mxf application/mxf .mxf application/mxf
.nq application/n-quads .nq application/n-quads
@@ -511,8 +511,8 @@ ext type
.mka audio/matroska .mka audio/matroska
.mxmf audio/mobile-xmf .mxmf audio/mobile-xmf
.m4a audio/mp4 .m4a audio/mp4
.mpga audio/mpeg .mp3 audio/mpeg
.oga audio/ogg .ogg audio/ogg
.uva audio/vnd.dece.audio .uva audio/vnd.dece.audio
.eol audio/vnd.digital-winds .eol audio/vnd.digital-winds
.dra audio/vnd.dra .dra audio/vnd.dra
@@ -688,7 +688,7 @@ ext type
.mp4 video/mp4 .mp4 video/mp4
.mpeg video/mpeg .mpeg video/mpeg
.ogv video/ogg .ogv video/ogg
.qt video/quicktime .mov video/quicktime
.uvh video/vnd.dece.hd .uvh video/vnd.dece.hd
.uvm video/vnd.dece.mobile .uvm video/vnd.dece.mobile
.uvp video/vnd.dece.pd .uvp video/vnd.dece.pd
1 ext type
62 .musd application/mmt-usd+xml
63 .mods application/mods+xml
64 .m21 application/mp21
65 .mp4 .mp4s application/mp4
66 .doc application/msword
67 .mxf application/mxf
68 .nq application/n-quads
511 .mka audio/matroska
512 .mxmf audio/mobile-xmf
513 .m4a audio/mp4
514 .mpga .mp3 audio/mpeg
515 .oga .ogg audio/ogg
516 .uva audio/vnd.dece.audio
517 .eol audio/vnd.digital-winds
518 .dra audio/vnd.dra
688 .mp4 video/mp4
689 .mpeg video/mpeg
690 .ogv video/ogg
691 .qt .mov video/quicktime
692 .uvh video/vnd.dece.hd
693 .uvm video/vnd.dece.mobile
694 .uvp video/vnd.dece.pd
+3 -6
View File
@@ -22,8 +22,7 @@ value is composed; TSV says which values exist.
- In a data file, refuse a choice whose items are templates with one identical - In a data file, refuse a choice whose items are templates with one identical
field set, naming the TSV to write; an inline template is exempt, having no field set, naming the TSV to write; an inline template is exempt, having no
file. A choice of strings stays a choice. file. A choice of strings stays a choice.
- Convert `misc.timezone`, `car` and `useragent` to tables; `country`, `currency`, - Convert `misc.timezone`, `car` and `useragent` to tables.
`language`, `httpstatus` and `mimetype` are done.
- Let a path select a row by key or by name, `geo.SE.municipality[0180]` and - Let a path select a row by key or by name, `geo.SE.municipality[0180]` and
`geo.SE.municipality[Stockholm]`, and descend to a linked table by name, `geo.SE.municipality[Stockholm]`, and descend to a linked table by name,
`geo.SE.region[Skåne län].street`; a key or a linked table name may not equal `geo.SE.region[Skåne län].street`; a key or a linked table name may not equal
@@ -171,10 +170,8 @@ address, phone, national id, company and date names each.
conflicts with sits inside another category. Give the national ids one conflicts with sits inside another category. Give the national ids one
record shape in step 6, and report a struct column's draw conflict with the path record shape in step 6, and report a struct column's draw conflict with the path
spelling a tag takes rather than the reference spelling. spelling a tag takes rather than the reference spelling.
4. `misc` conversions and the new `misc` tables. `language`, `httpstatus` and 4. `misc` conversions and the new `misc` tables. Convert `timezone`, `car` and
`mimetype` read their registers now, and `misc.country` keeps a currency code `useragent`, and add the new `misc` tables.
rather than a `parent` link to `misc.currency` (README Decisions). Convert
`timezone`, `car` and `useragent`, and add the new `misc` tables.
5. The remaining locale categories: company, phone, finance, vehicle, words. 5. The remaining locale categories: company, phone, finance, vehicle, words.
6. Records with building-block columns across the shipped set; shape re-pin. 6. Records with building-block columns across the shipped set; shape re-pin.