summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libmimetypes.tex25
-rw-r--r--Lib/mimetypes.py162
-rw-r--r--Misc/NEWS5
3 files changed, 154 insertions, 38 deletions
diff --git a/Doc/lib/libmimetypes.tex b/Doc/lib/libmimetypes.tex
index 3747fe1..64296f0 100644
--- a/Doc/lib/libmimetypes.tex
+++ b/Doc/lib/libmimetypes.tex
@@ -47,6 +47,20 @@ IANA types are supported; when \var{strict} is false, some additional
non-standard but commonly used MIME types are also recognized.
\end{funcdesc}
+\begin{funcdesc}{guess_all_extensions}{type\optional{, strict}}
+Guess the extensions for a file based on its MIME type, given by
+\var{type}.
+The return value is a list of strings giving all possible filename extensions,
+including the leading dot (\character{.}). The extensions are not guaranteed
+to have been associated with any particular data stream, but would be mapped
+to the MIME type \var{type} by \function{guess_type()}. If no extension can
+be guessed for \var{type}, \code{None} is returned.
+
+Optional \var{strict} has the same meaning as with the
+\function{guess_type()} function.
+\end{funcdesc}
+
+
\begin{funcdesc}{guess_extension}{type\optional{, strict}}
Guess the extension for a file based on its MIME type, given by
\var{type}.
@@ -83,6 +97,17 @@ not exist or cannot be read, \code{None} is returned.
\end{funcdesc}
+\begin{funcdesc}{add_type}{type, ext\optional{, strict}}
+Add a mapping from the mimetype \var{type} to the extension \var{ext}.
+When the extension is already known, the new type will replace the old
+one. When the type is already known the extension will be added
+to the list of known extensions.
+
+When \var{strict} is the mapping will added to the official
+MIME types, otherwise to the non-standard ones.
+\end{funcdesc}
+
+
\begin{datadesc}{inited}
Flag indicating whether or not the global data structures have been
initialized. This is set to true by \function{init()}.
diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py
index ad13be3..846d56b 100644
--- a/Lib/mimetypes.py
+++ b/Lib/mimetypes.py
@@ -26,16 +26,20 @@ import os
import posixpath
import urllib
-__all__ = ["guess_type","guess_extension","read_mime_types","init"]
+__all__ = [
+ "guess_type","guess_extension","guess_all_extensions",
+ "add_type","read_mime_types","init"
+]
knownfiles = [
+ "/etc/mime.types",
"/usr/local/etc/httpd/conf/mime.types",
"/usr/local/lib/netscape/mime.types",
"/usr/local/etc/httpd/conf/mime.types", # Apache 1.2
"/usr/local/etc/mime.types", # Apache 1.3
]
-inited = 0
+inited = False
class MimeTypes:
@@ -46,17 +50,38 @@ class MimeTypes:
URL, and can guess a reasonable extension given a MIME type.
"""
- def __init__(self, filenames=()):
+ def __init__(self, filenames=(), strict=True):
if not inited:
init()
self.encodings_map = encodings_map.copy()
self.suffix_map = suffix_map.copy()
- self.types_map = types_map.copy()
- self.common_types = common_types.copy()
+ self.types_map = ({}, {}) # dict for (non-strict, strict)
+ self.types_map_inv = ({}, {})
+ for (ext, type) in types_map.items():
+ self.add_type(type, ext, True)
+ for (ext, type) in common_types.items():
+ self.add_type(type, ext, False)
for name in filenames:
- self.read(name)
+ self.read(name, strict)
- def guess_type(self, url, strict=1):
+ def add_type(self, type, ext, strict=True):
+ """Add a mapping between a type and and extension.
+
+ When the extension is already known, the new
+ type will replace the old one. When the type
+ is already known the extension will be added
+ to the list of known extensions.
+
+ If strict is true, information will be added to
+ list of standard types, else to the list of non-standard
+ types.
+ """
+ self.types_map[strict][ext] = type
+ exts = self.types_map_inv[strict].setdefault(type, [])
+ if ext not in exts:
+ exts.append(ext)
+
+ def guess_type(self, url, strict=True):
"""Guess the type of a file based on its URL.
Return value is a tuple (type, encoding) where type is None if
@@ -72,7 +97,7 @@ class MimeTypes:
mapped to '.tar.gz'. (This is table-driven too, using the
dictionary suffix_map.)
- Optional `strict' argument when false adds a bunch of commonly found,
+ Optional `strict' argument when False adds a bunch of commonly found,
but non-standard types.
"""
scheme, url = urllib.splittype(url)
@@ -103,22 +128,44 @@ class MimeTypes:
base, ext = posixpath.splitext(base)
else:
encoding = None
- types_map = self.types_map
- common_types = self.common_types
+ types_map = self.types_map[True]
if ext in types_map:
return types_map[ext], encoding
elif ext.lower() in types_map:
return types_map[ext.lower()], encoding
elif strict:
return None, encoding
- elif ext in common_types:
- return common_types[ext], encoding
- elif ext.lower() in common_types:
- return common_types[ext.lower()], encoding
+ types_map = self.types_map[False]
+ if ext in types_map:
+ return types_map[ext], encoding
+ elif ext.lower() in types_map:
+ return types_map[ext.lower()], encoding
else:
return None, encoding
- def guess_extension(self, type, strict=1):
+ def guess_all_extensions(self, type, strict=True):
+ """Guess the extensions for a file based on its MIME type.
+
+ Return value is a list of strings giving the possible filename
+ extensions, including the leading dot ('.'). The extension is not
+ guaranteed to have been associated with any particular data
+ stream, but would be mapped to the MIME type `type' by
+ guess_type(). If no extension can be guessed for `type', None
+ is returned.
+
+ Optional `strict' argument when false adds a bunch of commonly found,
+ but non-standard types.
+ """
+ type = type.lower()
+ extensions = self.types_map_inv[True].get(type, [])
+ if not strict:
+ for ext in self.types_map_inv[False].get(type, []):
+ if ext not in extensions:
+ extensions.append(ext)
+ if len(extensions):
+ return extensions
+
+ def guess_extension(self, type, strict=True):
"""Guess the extension for a file based on its MIME type.
Return value is a string giving a filename extension,
@@ -131,25 +178,31 @@ class MimeTypes:
Optional `strict' argument when false adds a bunch of commonly found,
but non-standard types.
"""
- type = type.lower()
- for ext, stype in self.types_map.items():
- if type == stype:
- return ext
- if not strict:
- for ext, stype in common_types.items():
- if type == stype:
- return ext
- return None
+ extensions = self.guess_all_extensions(type, strict)
+ if extensions is not None:
+ extensions = extensions[0]
+ return extensions
+
+ def read(self, filename, strict=True):
+ """
+ Read a single mime.types-format file, specified by pathname.
- def read(self, filename):
- """Read a single mime.types-format file, specified by pathname."""
+ If strict is true, information will be added to
+ list of standard types, else to the list of non-standard
+ types.
+ """
fp = open(filename)
self.readfp(fp)
fp.close()
- def readfp(self, fp):
- """Read a single mime.types-format file."""
- map = self.types_map
+ def readfp(self, fp, strict=True):
+ """
+ Read a single mime.types-format file.
+
+ If strict is true, information will be added to
+ list of standard types, else to the list of non-standard
+ types.
+ """
while 1:
line = fp.readline()
if not line:
@@ -162,11 +215,11 @@ class MimeTypes:
if not words:
continue
type, suffixes = words[0], words[1:]
+ suffixes = [ '.' + suff for suff in suffixes ]
for suff in suffixes:
- map['.' + suff] = type
-
+ self.add_type(type, suff, strict)
-def guess_type(url, strict=1):
+def guess_type(url, strict=True):
"""Guess the type of a file based on its URL.
Return value is a tuple (type, encoding) where type is None if the
@@ -188,7 +241,23 @@ def guess_type(url, strict=1):
return guess_type(url, strict)
-def guess_extension(type, strict=1):
+def guess_all_extensions(type, strict=True):
+ """Guess the extensions for a file based on its MIME type.
+
+ Return value is a list of strings giving the possible filename
+ extensions, including the leading dot ('.'). The extension is not
+ guaranteed to have been associated with any particular data
+ stream, but would be mapped to the MIME type `type' by
+ guess_type(). If no extension can be guessed for `type', None
+ is returned.
+
+ Optional `strict' argument when false adds a bunch of commonly found,
+ but non-standard types.
+ """
+ init()
+ return guess_all_extensions(type, strict)
+
+def guess_extension(type, strict=True):
"""Guess the extension for a file based on its MIME type.
Return value is a string giving a filename extension, including the
@@ -203,12 +272,27 @@ def guess_extension(type, strict=1):
init()
return guess_extension(type, strict)
+def add_type(self, type, ext, strict=True):
+ """Add a mapping between a type and and extension.
+
+ When the extension is already known, the new
+ type will replace the old one. When the type
+ is already known the extension will be added
+ to the list of known extensions.
+
+ If strict is true, information will be added to
+ list of standard types, else to the list of non-standard
+ types.
+ """
+ init()
+ return add_type(type, ext, strict)
+
def init(files=None):
- global guess_extension, guess_type
+ global guess_all_extensions, guess_extension, guess_type
global suffix_map, types_map, encodings_map, common_types
- global inited
- inited = 1
+ global add_type, inited
+ inited = True
db = MimeTypes()
if files is None:
files = knownfiles
@@ -217,10 +301,12 @@ def init(files=None):
db.readfp(open(file))
encodings_map = db.encodings_map
suffix_map = db.suffix_map
- types_map = db.types_map
+ types_map = db.types_map[True]
+ guess_all_extensions = db.guess_all_extensions
guess_extension = db.guess_extension
guess_type = db.guess_type
- common_types = db.common_types
+ add_type = db.add_type
+ common_types = db.types_map[False]
def read_mime_types(file):
diff --git a/Misc/NEWS b/Misc/NEWS
index b877703..d08bc34 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -321,6 +321,11 @@ Extension modules
Library
+- mimetypes has two new functions: guess_all_extensions() which
+ returns a list of all known extensions for a mime type, and
+ add_type() which adds one mapping between a mime type and
+ an extension to the database.
+
- New module: sets, defines the class Set that implements a mutable
set type using the keys of a dict to represent the set. There's
also a class ImmutableSet which is useful when you need sets of sets