]> granicus.if.org Git - python/commitdiff
Apply diff3.txt (plus additional documentation)
authorWalter Dörwald <walter@livinglogic.de>
Fri, 6 Sep 2002 16:15:58 +0000 (16:15 +0000)
committerWalter Dörwald <walter@livinglogic.de>
Fri, 6 Sep 2002 16:15:58 +0000 (16:15 +0000)
from SF patch http://www.python.org/sf/554192

This adds two new functions to mimetypes:
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.

Doc/lib/libmimetypes.tex
Lib/mimetypes.py
Misc/NEWS

index 3747fe1e1bd123dc19846a43e5d07fc8bbd695e6..64296f0301232073a5e3708729e3c8884aea037d 100644 (file)
@@ -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()}.
index ad13be374edeb75e4f29677bb6a961303e0d55d0..846d56b2cd5f3fb754d86740dd51cca7c92c7c69 100644 (file)
@@ -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):
index b877703afb16a957fb9d2c18f800ce2d3629abb6..d08bc34286109c2028a5db0cf19f207496f12dfd 100644 (file)
--- 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