Skip to content

Commit 9677b45

Browse files
committed
Support all registered IANA mime types
build_mime_types: Add tool to create ContentType enum from all IANA mime type CSVS pyproject.toml: Run build_mime_types.py during `poetry build` src/tests: Add more tests around mime types and adjust to mime_types.ContentType from enumeration.ContentType
1 parent 8c64153 commit 9677b45

26 files changed

+4399
-80
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ clean: ## Remove build files
3030
@echo "Temporary files were clear"
3131

3232
test: ## Run code tests
33-
@poetry run pytest
33+
@poetry run pytest -vv
3434

3535
lint: ## Run code linters
3636
@echo "Run code linters..."

build_mime_types/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# build-mime-types
2+
3+
Builds a class file for ContentType enum from the IANA mime types list.
4+
5+
Contents:
6+
7+
8+
- *.csv - Lists of media-types [from IANA](https://www.iana.org/assignments/media-types/media-types.xhtml)
9+
- [build_mime_types.py](build_mime_types.py) - Script to build class file (run automatically by poetry build)

build_mime_types/application.csv

Lines changed: 1575 additions & 0 deletions
Large diffs are not rendered by default.

build_mime_types/audio.csv

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
Name,Template,Reference
2+
1d-interleaved-parityfec,audio/1d-interleaved-parityfec,[RFC6015]
3+
32kadpcm,audio/32kadpcm,[RFC3802][RFC2421]
4+
3gpp,audio/3gpp,[RFC3839][RFC6381]
5+
3gpp2,audio/3gpp2,[RFC4393][RFC6381]
6+
aac,audio/aac,[ISO-IEC_JTC_1][Max_Neuendorf]
7+
ac3,audio/ac3,[RFC4184]
8+
AMR,audio/AMR,[RFC4867]
9+
AMR-WB,audio/AMR-WB,[RFC4867]
10+
amr-wb+,audio/amr-wb+,[RFC4352]
11+
aptx,audio/aptx,[RFC7310]
12+
asc,audio/asc,[RFC6295]
13+
ATRAC-ADVANCED-LOSSLESS,audio/ATRAC-ADVANCED-LOSSLESS,[RFC5584]
14+
ATRAC-X,audio/ATRAC-X,[RFC5584]
15+
ATRAC3,audio/ATRAC3,[RFC5584]
16+
basic,audio/basic,[RFC2045][RFC2046]
17+
BV16,audio/BV16,[RFC4298]
18+
BV32,audio/BV32,[RFC4298]
19+
clearmode,audio/clearmode,[RFC4040]
20+
CN,audio/CN,[RFC3389]
21+
DAT12,audio/DAT12,[RFC3190]
22+
dls,audio/dls,[RFC4613]
23+
dsr-es201108,audio/dsr-es201108,[RFC3557]
24+
dsr-es202050,audio/dsr-es202050,[RFC4060]
25+
dsr-es202211,audio/dsr-es202211,[RFC4060]
26+
dsr-es202212,audio/dsr-es202212,[RFC4060]
27+
DV,audio/DV,[RFC6469]
28+
DVI4,audio/DVI4,[RFC4856]
29+
eac3,audio/eac3,[RFC4598]
30+
encaprtp,audio/encaprtp,[RFC6849]
31+
EVRC,audio/EVRC,[RFC4788]
32+
EVRC-QCP,audio/EVRC-QCP,[RFC3625]
33+
EVRC0,audio/EVRC0,[RFC4788]
34+
EVRC1,audio/EVRC1,[RFC4788]
35+
EVRCB,audio/EVRCB,[RFC5188]
36+
EVRCB0,audio/EVRCB0,[RFC5188]
37+
EVRCB1,audio/EVRCB1,[RFC4788]
38+
EVRCNW,audio/EVRCNW,[RFC6884]
39+
EVRCNW0,audio/EVRCNW0,[RFC6884]
40+
EVRCNW1,audio/EVRCNW1,[RFC6884]
41+
EVRCWB,audio/EVRCWB,[RFC5188]
42+
EVRCWB0,audio/EVRCWB0,[RFC5188]
43+
EVRCWB1,audio/EVRCWB1,[RFC5188]
44+
EVS,audio/EVS,[_3GPP][Kyunghun_Jung]
45+
example,audio/example,[RFC4735]
46+
flexfec,audio/flexfec,[RFC8627]
47+
fwdred,audio/fwdred,[RFC6354]
48+
G711-0,audio/G711-0,[RFC7655]
49+
G719,audio/G719,[RFC5404][RFC Errata 3245]
50+
G7221,audio/G7221,[RFC5577]
51+
G722,audio/G722,[RFC4856]
52+
G723,audio/G723,[RFC4856]
53+
G726-16,audio/G726-16,[RFC4856]
54+
G726-24,audio/G726-24,[RFC4856]
55+
G726-32,audio/G726-32,[RFC4856]
56+
G726-40,audio/G726-40,[RFC4856]
57+
G728,audio/G728,[RFC4856]
58+
G729,audio/G729,[RFC4856]
59+
G7291,audio/G7291,[RFC4749][RFC5459]
60+
G729D,audio/G729D,[RFC4856]
61+
G729E,audio/G729E,[RFC4856]
62+
GSM,audio/GSM,[RFC4856]
63+
GSM-EFR,audio/GSM-EFR,[RFC4856]
64+
GSM-HR-08,audio/GSM-HR-08,[RFC5993]
65+
iLBC,audio/iLBC,[RFC3952]
66+
ip-mr_v2.5,audio/ip-mr_v2.5,[RFC6262]
67+
L8,audio/L8,[RFC4856]
68+
L16,audio/L16,[RFC4856]
69+
L20,audio/L20,[RFC3190]
70+
L24,audio/L24,[RFC3190]
71+
LPC,audio/LPC,[RFC4856]
72+
matroska,audio/matroska,[RFC-ietf-cellar-matroska-21]
73+
MELP,audio/MELP,[RFC8130]
74+
MELP600,audio/MELP600,[RFC8130]
75+
MELP1200,audio/MELP1200,[RFC8130]
76+
MELP2400,audio/MELP2400,[RFC8130]
77+
mhas,audio/mhas,[ISO-IEC_JTC_1][Nils_Peters][Ingo_Hofmann]
78+
mobile-xmf,audio/mobile-xmf,[RFC4723]
79+
MPA,audio/MPA,[RFC3555]
80+
mp4,audio/mp4,[RFC4337][RFC6381]
81+
MP4A-LATM,audio/MP4A-LATM,[RFC6416]
82+
mpa-robust,audio/mpa-robust,[RFC5219]
83+
mpeg,audio/mpeg,[RFC3003]
84+
mpeg4-generic,audio/mpeg4-generic,[RFC3640][RFC5691][RFC6295]
85+
ogg,audio/ogg,[RFC5334][RFC7845]
86+
opus,audio/opus,[RFC7587]
87+
parityfec,audio/parityfec,[RFC3009]
88+
PCMA,audio/PCMA,[RFC4856]
89+
PCMA-WB,audio/PCMA-WB,[RFC5391]
90+
PCMU,audio/PCMU,[RFC4856]
91+
PCMU-WB,audio/PCMU-WB,[RFC5391]
92+
prs.sid,audio/prs.sid,[Linus_Walleij]
93+
QCELP,audio/QCELP,[RFC3555][RFC3625]
94+
raptorfec,audio/raptorfec,[RFC6682]
95+
RED,audio/RED,[RFC3555]
96+
rtp-enc-aescm128,audio/rtp-enc-aescm128,[_3GPP]
97+
rtploopback,audio/rtploopback,[RFC6849]
98+
rtp-midi,audio/rtp-midi,[RFC6295]
99+
rtx,audio/rtx,[RFC4588]
100+
scip,audio/scip,[SCIP][Michael_Faller][Daniel_Hanson]
101+
SMV,audio/SMV,[RFC3558]
102+
SMV0,audio/SMV0,[RFC3558]
103+
SMV-QCP,audio/SMV-QCP,[RFC3625]
104+
sofa,audio/sofa,[AES][Piotr_Majdak]
105+
sp-midi,audio/sp-midi,[Athan_Billias][MIDI_Association]
106+
speex,audio/speex,[RFC5574]
107+
t140c,audio/t140c,[RFC4351]
108+
t38,audio/t38,[RFC4612]
109+
telephone-event,audio/telephone-event,[RFC4733]
110+
TETRA_ACELP,audio/TETRA_ACELP,[ETSI][Miguel_Angel_Reina_Ortega]
111+
TETRA_ACELP_BB,audio/TETRA_ACELP_BB,[ETSI][Miguel_Angel_Reina_Ortega]
112+
tone,audio/tone,[RFC4733]
113+
TSVCIS,audio/TSVCIS,[RFC8817]
114+
UEMCLIP,audio/UEMCLIP,[RFC5686]
115+
ulpfec,audio/ulpfec,[RFC5109]
116+
usac,audio/usac,[ISO-IEC_JTC_1][Max_Neuendorf]
117+
VDVI,audio/VDVI,[RFC4856]
118+
VMR-WB,audio/VMR-WB,[RFC4348][RFC4424]
119+
vnd.3gpp.iufp,audio/vnd.3gpp.iufp,[Thomas_Belling]
120+
vnd.4SB,audio/vnd.4SB,[Serge_De_Jaham]
121+
vnd.audiokoz,audio/vnd.audiokoz,[Vicki_DeBarros]
122+
vnd.CELP,audio/vnd.CELP,[Serge_De_Jaham]
123+
vnd.cisco.nse,audio/vnd.cisco.nse,[Rajesh_Kumar]
124+
vnd.cmles.radio-events,audio/vnd.cmles.radio-events,[Jean-Philippe_Goulet]
125+
vnd.cns.anp1,audio/vnd.cns.anp1,[Ann_McLaughlin]
126+
vnd.cns.inf1,audio/vnd.cns.inf1,[Ann_McLaughlin]
127+
vnd.dece.audio,audio/vnd.dece.audio,[Michael_A_Dolan]
128+
vnd.digital-winds,audio/vnd.digital-winds,[Armands_Strazds]
129+
vnd.dlna.adts,audio/vnd.dlna.adts,[Edwin_Heredia]
130+
vnd.dolby.heaac.1,audio/vnd.dolby.heaac.1,[Steve_Hattersley]
131+
vnd.dolby.heaac.2,audio/vnd.dolby.heaac.2,[Steve_Hattersley]
132+
vnd.dolby.mlp,audio/vnd.dolby.mlp,[Mike_Ward]
133+
vnd.dolby.mps,audio/vnd.dolby.mps,[Steve_Hattersley]
134+
vnd.dolby.pl2,audio/vnd.dolby.pl2,[Steve_Hattersley]
135+
vnd.dolby.pl2x,audio/vnd.dolby.pl2x,[Steve_Hattersley]
136+
vnd.dolby.pl2z,audio/vnd.dolby.pl2z,[Steve_Hattersley]
137+
vnd.dolby.pulse.1,audio/vnd.dolby.pulse.1,[Steve_Hattersley]
138+
vnd.dra,audio/vnd.dra,[Jiang_Tian]
139+
vnd.dts,audio/vnd.dts,[William_Zou]
140+
vnd.dts.hd,audio/vnd.dts.hd,[William_Zou]
141+
vnd.dts.uhd,audio/vnd.dts.uhd,[Phillip_Maness]
142+
vnd.dvb.file,audio/vnd.dvb.file,[Peter_Siebert]
143+
vnd.everad.plj,audio/vnd.everad.plj,[Shay_Cicelsky]
144+
vnd.hns.audio,audio/vnd.hns.audio,[Swaminathan]
145+
vnd.lucent.voice,audio/vnd.lucent.voice,[Greg_Vaudreuil]
146+
vnd.ms-playready.media.pya,audio/vnd.ms-playready.media.pya,[Steve_DiAcetis]
147+
vnd.nokia.mobile-xmf,audio/vnd.nokia.mobile-xmf,[Nokia]
148+
vnd.nortel.vbk,audio/vnd.nortel.vbk,[Glenn_Parsons]
149+
vnd.nuera.ecelp4800,audio/vnd.nuera.ecelp4800,[Michael_Fox]
150+
vnd.nuera.ecelp7470,audio/vnd.nuera.ecelp7470,[Michael_Fox]
151+
vnd.nuera.ecelp9600,audio/vnd.nuera.ecelp9600,[Michael_Fox]
152+
vnd.octel.sbc,audio/vnd.octel.sbc,[Greg_Vaudreuil]
153+
vnd.presonus.multitrack,audio/vnd.presonus.multitrack,[Matthias_Juwan]
154+
vnd.qcelp - DEPRECATED in favor of audio/qcelp,audio/vnd.qcelp,[RFC3625]
155+
vnd.rhetorex.32kadpcm,audio/vnd.rhetorex.32kadpcm,[Greg_Vaudreuil]
156+
vnd.rip,audio/vnd.rip,[Martin_Dawe]
157+
vnd.sealedmedia.softseal.mpeg,audio/vnd.sealedmedia.softseal.mpeg,[David_Petersen]
158+
vnd.vmx.cvsd,audio/vnd.vmx.cvsd,[Greg_Vaudreuil]
159+
vorbis,audio/vorbis,[RFC5215]
160+
vorbis-config,audio/vorbis-config,[RFC5215]
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import csv
2+
import os
3+
import re
4+
from inspect import getsourcefile
5+
from os.path import abspath
6+
from string import Template
7+
from typing import List, Dict, Final
8+
9+
INT_MAP: Final = {
10+
0: "ZERO",
11+
1: "ONE",
12+
2: "TWO",
13+
3: "THREE",
14+
4: "FOUR",
15+
5: "FIVE",
16+
6: "SIX",
17+
7: "SEVEN",
18+
8: "EIGHT",
19+
9: "NINE"
20+
}
21+
22+
CSV_FILES: Final = {
23+
"application.csv",
24+
"audio.csv",
25+
"font.csv",
26+
"image.csv",
27+
"message.csv",
28+
"model.csv",
29+
"multipart.csv",
30+
"text.csv",
31+
"video.csv"
32+
}
33+
34+
35+
def _to_enum_name(template: str) -> str:
36+
"""
37+
Converts the IANA template to an enum name
38+
:param template: IANA template value
39+
:return: parsed and formatted name
40+
"""
41+
# Of course there is one outlier with a + at the end of it
42+
name_suffix: str = ""
43+
if template.endswith('+'):
44+
name_suffix = "_PLUS"
45+
46+
name_parts: List[str] = [x for x in re.split(r'[+.\-/]+', template) if x]
47+
enum_name: str = "_".join(name_parts)
48+
enum_name += name_suffix
49+
50+
return enum_name.upper()
51+
52+
53+
class MimeType:
54+
"""
55+
Holds a representation of an IANA mime type
56+
"""
57+
def __init__(self, template: str):
58+
"""
59+
Information about a mime type
60+
:param template: Template / header value
61+
"""
62+
self.enum_value = template
63+
self.enum_name = _to_enum_name(template=template)
64+
65+
66+
def build_mime_types_file():
67+
"""
68+
Loads application.csv and outputs a ContentType() class in
69+
src/openapi_parser/mime_types.py.
70+
71+
Allows for easy update of ContentTypes when the IANA list changes
72+
73+
:return: None
74+
"""
75+
76+
template_string = '''""" AUTO_GENERATED BY build_mime_types.py - DO NOT EDIT """
77+
78+
from enum import Enum, unique
79+
80+
81+
@unique
82+
class ContentType(Enum):\n'''
83+
84+
mime_types: Dict = {}
85+
86+
cur_file: str = abspath(getsourcefile(lambda: 0))
87+
cur_dir: str = cur_file.rstrip("build_mime_types.py")
88+
89+
i: int = 0
90+
for file in CSV_FILES:
91+
with open(f"{cur_dir}{file}", mode='r', encoding='utf-8') as csvfile:
92+
mime_extension: str = file.rstrip(".csv")
93+
reader: csv.reader = csv.reader(csvfile, delimiter=',')
94+
next(reader)
95+
for row in reader:
96+
if (
97+
row[0] is not None
98+
and row[0] != ''
99+
and "OBSOLETE" not in row[0]
100+
and "DEPRECATED" not in row[0]
101+
102+
):
103+
if row[1] is None or row[1] == '':
104+
row[1] = f"{mime_extension}/{row[0]}"
105+
106+
mime_type = MimeType(template=row[1])
107+
mime_types[f"name_{i}"] = mime_type.enum_name
108+
mime_types[f"value_{i}"] = mime_type.enum_value
109+
template_string += f" $name_{i} = '$value_{i}'\n"
110+
i += 1
111+
csvfile.close()
112+
113+
template_string += "\n"
114+
template: Template = Template(template=template_string)
115+
class_file_path = os.path.join(cur_dir, "../src/openapi_parser/mime_types.py")
116+
117+
with open(class_file_path, mode='w', encoding='utf-8') as class_file:
118+
class_file.write(template.safe_substitute(mime_types))
119+
class_file.close()
120+
121+
122+
if __name__ == "__main__":
123+
build_mime_types_file()

build_mime_types/font.csv

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Name,Template,Reference
2+
collection,font/collection,[RFC8081]
3+
otf,font/otf,[RFC8081]
4+
sfnt,font/sfnt,[RFC8081]
5+
ttf,font/ttf,[RFC8081]
6+
woff,font/woff,[RFC8081]
7+
woff2,font/woff2,[RFC8081]

build_mime_types/image.csv

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Name,Template,Reference
2+
aces,image/aces,[SMPTE][Howard_Lukk]
3+
apng,image/apng,[W3C][W3C_PNG_Working_Group]
4+
avci,image/avci,[ISO-IEC_JTC_1][David_Singer]
5+
avcs,image/avcs,[ISO-IEC_JTC_1][David_Singer]
6+
avif,image/avif,[Alliance_for_Open_Media][Cyril_Concolato]
7+
bmp,image/bmp,[RFC7903]
8+
cgm,image/cgm,[Alan_Francis]
9+
dicom-rle,image/dicom-rle,[DICOM_Standard_Committee][David_Clunie]
10+
dpx,image/dpx,[SMPTE][SMPTE_Director_of_Standards_Development]
11+
emf,image/emf,[RFC7903]
12+
example,image/example,[RFC4735]
13+
fits,image/fits,[RFC4047]
14+
g3fax,image/g3fax,[RFC1494]
15+
gif,,[RFC2045][RFC2046]
16+
heic,image/heic,[ISO-IEC_JTC_1][David_Singer]
17+
heic-sequence,image/heic-sequence,[ISO-IEC_JTC_1][David_Singer]
18+
heif,image/heif,[ISO-IEC_JTC_1][David_Singer]
19+
heif-sequence,image/heif-sequence,[ISO-IEC_JTC_1][David_Singer]
20+
hej2k,image/hej2k,[ISO-IEC_JTC_1][ITU-T]
21+
hsj2,image/hsj2,[ISO-IEC_JTC_1][ITU-T]
22+
ief,,[RFC1314]
23+
j2c,image/j2c,[ISO-IEC_JTC_1_SC_29_WG_1][ISO-IEC_JTC_1][ITU-T]
24+
jls,image/jls,[DICOM_Standard_Committee][David_Clunie]
25+
jp2,image/jp2,[RFC3745]
26+
jpeg,,[RFC2045][RFC2046]
27+
jph,image/jph,[ISO-IEC_JTC_1][ITU-T]
28+
jphc,image/jphc,[ISO-IEC_JTC_1][ITU-T]
29+
jpm,image/jpm,[RFC3745]
30+
jpx,image/jpx,[RFC3745]
31+
jxr,image/jxr,[ISO-IEC_JTC_1][ITU-T]
32+
jxrA,image/jxrA,[ISO-IEC_JTC_1][ITU-T]
33+
jxrS,image/jxrS,[ISO-IEC_JTC_1][ITU-T]
34+
jxs,image/jxs,[ISO-IEC_JTC_1]
35+
jxsc,image/jxsc,[ISO-IEC_JTC_1]
36+
jxsi,image/jxsi,[ISO-IEC_JTC_1]
37+
jxss,image/jxss,[ISO-IEC_JTC_1]
38+
ktx,image/ktx,[Khronos][Mark_Callow]
39+
ktx2,image/ktx2,[Khronos][Mark_Callow]
40+
naplps,image/naplps,[Ilya_Ferber]
41+
png,image/png,[W3C][PNG_Working_Group]
42+
prs.btif,image/prs.btif,[Ben_Simon]
43+
prs.pti,image/prs.pti,[Juern_Laun]
44+
pwg-raster,image/pwg-raster,[Michael_Sweet]
45+
svg+xml,image/svg+xml,[W3C][http://www.w3.org/TR/SVG/mimereg.html]
46+
t38,image/t38,[RFC3362]
47+
tiff,image/tiff,[RFC3302]
48+
tiff-fx,image/tiff-fx,[RFC3950]
49+
vnd.adobe.photoshop,image/vnd.adobe.photoshop,[Kim_Scarborough]
50+
vnd.airzip.accelerator.azv,image/vnd.airzip.accelerator.azv,[Gary_Clueit]
51+
vnd.cns.inf2,image/vnd.cns.inf2,[Ann_McLaughlin]
52+
vnd.dece.graphic,image/vnd.dece.graphic,[Michael_A_Dolan]
53+
vnd.djvu,image/vnd.djvu,[Leon_Bottou]
54+
vnd.dwg,image/vnd.dwg,[Jodi_Moline]
55+
vnd.dxf,image/vnd.dxf,[Jodi_Moline]
56+
vnd.dvb.subtitle,image/vnd.dvb.subtitle,[Peter_Siebert][Michael_Lagally]
57+
vnd.fastbidsheet,image/vnd.fastbidsheet,[Scott_Becker]
58+
vnd.fpx,image/vnd.fpx,[Marc_Douglas_Spencer]
59+
vnd.fst,image/vnd.fst,[Arild_Fuldseth]
60+
vnd.fujixerox.edmics-mmr,image/vnd.fujixerox.edmics-mmr,[Masanori_Onda]
61+
vnd.fujixerox.edmics-rlc,image/vnd.fujixerox.edmics-rlc,[Masanori_Onda]
62+
vnd.globalgraphics.pgb,image/vnd.globalgraphics.pgb,[Martin_Bailey]
63+
vnd.microsoft.icon,image/vnd.microsoft.icon,[Simon_Butcher]
64+
vnd.mix,image/vnd.mix,[Saveen_Reddy]
65+
vnd.ms-modi,image/vnd.ms-modi,[Gregory_Vaughan]
66+
vnd.mozilla.apng,image/vnd.mozilla.apng,[Stuart_Parmenter]
67+
vnd.net-fpx,image/vnd.net-fpx,[Marc_Douglas_Spencer]
68+
vnd.pco.b16,image/vnd.pco.b16,[PCO_AG][Jan_Zeman]
69+
vnd.radiance,image/vnd.radiance,[Randolph_Fritz][Greg_Ward]
70+
vnd.sealed.png,image/vnd.sealed.png,[David_Petersen]
71+
vnd.sealedmedia.softseal.gif,image/vnd.sealedmedia.softseal.gif,[David_Petersen]
72+
vnd.sealedmedia.softseal.jpg,image/vnd.sealedmedia.softseal.jpg,[David_Petersen]
73+
vnd.svf,image/vnd.svf,[Jodi_Moline]
74+
vnd.tencent.tap,image/vnd.tencent.tap,[Ni_Hui]
75+
vnd.valve.source.texture,image/vnd.valve.source.texture,[Henrik_Andersson]
76+
vnd.wap.wbmp,image/vnd.wap.wbmp,[Peter_Stark]
77+
vnd.xiff,image/vnd.xiff,[Steven_Martin]
78+
vnd.zbrush.pcx,image/vnd.zbrush.pcx,[Chris_Charabaruk]
79+
webp,image/webp,[RFC-zern-webp-12]
80+
wmf,image/wmf,[RFC7903]
81+
x-emf - DEPRECATED in favor of image/emf,image/emf,[RFC7903]
82+
x-wmf - DEPRECATED in favor of image/wmf,image/wmf,[RFC7903]

0 commit comments

Comments
 (0)