diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2009-11-15 14:10:48 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2009-11-15 14:10:48 (GMT) |
commit | d5b34d4597a7163edf20f831db620b0a4fe57d5d (patch) | |
tree | 59f31e437e8495b6a19835fb217288b89e0c69b6 | |
parent | a548deeb29badee88dc6fc7a2853b6f56558347f (diff) | |
download | cpython-d5b34d4597a7163edf20f831db620b0a4fe57d5d.zip cpython-d5b34d4597a7163edf20f831db620b0a4fe57d5d.tar.gz cpython-d5b34d4597a7163edf20f831db620b0a4fe57d5d.tar.bz2 |
Issue #4969: The mimetypes module now reads the MIME database from
the registry under Windows. Patch by Gabriel Genellina.
-rw-r--r-- | Doc/library/mimetypes.rst | 22 | ||||
-rw-r--r-- | Lib/mimetypes.py | 56 | ||||
-rw-r--r-- | Lib/test/test_mimetypes.py | 26 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 102 insertions, 5 deletions
diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst index 818f39f..956a1f1 100644 --- a/Doc/library/mimetypes.rst +++ b/Doc/library/mimetypes.rst @@ -77,9 +77,13 @@ behavior of the module. Initialize the internal data structures. If given, *files* must be a sequence of file names which should be used to augment the default type map. If omitted, - the file names to use are taken from :const:`knownfiles`. Each file named in - *files* or :const:`knownfiles` takes precedence over those named before it. - Calling :func:`init` repeatedly is allowed. + the file names to use are taken from :const:`knownfiles`; on Windows, the + current registry settings are loaded. Each file named in *files* or + :const:`knownfiles` takes precedence over those named before it. Calling + :func:`init` repeatedly is allowed. + + .. versionchanged:: 2.7 + Previously, Windows registry settings were ignored. .. function:: read_mime_types(filename) @@ -213,6 +217,12 @@ MimeTypes Objects of the object. +.. method:: MimeTypes.guess_all_extensions(type[, strict]) + + Similar to the :func:`guess_all_extensions` function, using the tables stored as part + of the object. + + .. method:: MimeTypes.guess_type(url[, strict]) Similar to the :func:`guess_type` function, using the tables stored as part of @@ -230,3 +240,9 @@ MimeTypes Objects Load MIME type information from an open file. The file must have the format of the standard :file:`mime.types` files. + +.. method:: MimeTypes.read_windows_registry() + + Load MIME type information from the Windows registry. Availability: Windows. + + .. versionadded:: 2.7 diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index f0a5ecf..aead656 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -18,13 +18,19 @@ types_map -- dictionary mapping suffixes to types Functions: -init([files]) -- parse a list of files, default knownfiles +init([files]) -- parse a list of files, default knownfiles (on Windows, the + default values are taken from the registry) read_mime_types(file) -- parse one file, return a dictionary or None """ import os +import sys import posixpath import urllib +try: + import _winreg +except ImportError: + _winreg = None __all__ = [ "guess_type","guess_extension","guess_all_extensions", @@ -220,6 +226,52 @@ class MimeTypes: for suff in suffixes: self.add_type(type, '.' + suff, strict) + def read_windows_registry(self, strict=True): + """ + Load the MIME types database from Windows registry. + + If strict is true, information will be added to + list of standard types, else to the list of non-standard + types. + """ + + # Windows only + if not _winreg: + return + + def enum_types(mimedb): + i = 0 + while True: + try: + ctype = _winreg.EnumKey(mimedb, i) + except EnvironmentError: + break + try: + ctype = ctype.encode(default_encoding) # omit in 3.x! + except UnicodeEncodeError: + pass + else: + yield ctype + i += 1 + + default_encoding = sys.getdefaultencoding() + with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, + r'MIME\Database\Content Type') as mimedb: + for ctype in enum_types(mimedb): + with _winreg.OpenKey(mimedb, ctype) as key: + try: + suffix, datatype = _winreg.QueryValueEx(key, 'Extension') + except EnvironmentError: + continue + if datatype != _winreg.REG_SZ: + continue + try: + suffix = suffix.encode(default_encoding) # omit in 3.x! + except UnicodeEncodeError: + continue + self.add_type(ctype, suffix, strict) + + def guess_type(url, strict=True): """Guess the type of a file based on its URL. @@ -299,6 +351,8 @@ def init(files=None): inited = True # so that MimeTypes.__init__() doesn't call us again db = MimeTypes() if files is None: + if _winreg: + db.read_windows_registry() files = knownfiles for file in files: if os.path.isfile(file): diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index cc1790e..3508b56 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -1,6 +1,7 @@ import mimetypes import StringIO import unittest +import sys from test import test_support @@ -62,8 +63,31 @@ class MimeTypesTestCase(unittest.TestCase): eq(all, []) +@unittest.skipUnless(sys.platform.startswith("win"), "Windows only") +class Win32MimeTypesTestCase(unittest.TestCase): + def setUp(self): + # ensure all entries actually come from the Windows registry + self.original_types_map = mimetypes.types_map.copy() + mimetypes.types_map.clear() + mimetypes.init() + self.db = mimetypes.MimeTypes() + + def tearDown(self): + # restore default settings + mimetypes.types_map.clear() + mimetypes.types_map.update(self.original_types_map) + + def test_registry_parsing(self): + # the original, minimum contents of the MIME database in the + # Windows registry is undocumented AFAIK. + # Use file types that should *always* exist: + eq = self.assertEqual + eq(self.db.guess_type("foo.txt"), ("text/plain", None)) + def test_main(): - test_support.run_unittest(MimeTypesTestCase) + test_support.run_unittest(MimeTypesTestCase, + Win32MimeTypesTestCase + ) if __name__ == "__main__": @@ -429,6 +429,9 @@ Core and Builtins Library ------- +- Issue #4969: The mimetypes module now reads the MIME database from + the registry under Windows. Patch by Gabriel Genellina. + - Issue #6816: runpy now provides a run_path function that allows Python code to execute file paths that refer to source or compiled Python files as well as zipfiles, directories and other valid sys.path entries that contain a |