Issue #4969: The mimetypes module now reads the MIME database from

the registry under Windows.  Patch by Gabriel Genellina.
This commit is contained in:
Antoine Pitrou 2009-11-15 14:10:48 +00:00
parent a548deeb29
commit d5b34d4597
4 changed files with 102 additions and 5 deletions

View File

@ -77,9 +77,13 @@ behavior of the module.
Initialize the internal data structures. If given, *files* must be a sequence 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, 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 the file names to use are taken from :const:`knownfiles`; on Windows, the
*files* or :const:`knownfiles` takes precedence over those named before it. current registry settings are loaded. Each file named in *files* or
Calling :func:`init` repeatedly is allowed. :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) .. function:: read_mime_types(filename)
@ -213,6 +217,12 @@ MimeTypes Objects
of the object. 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]) .. method:: MimeTypes.guess_type(url[, strict])
Similar to the :func:`guess_type` function, using the tables stored as part of 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 Load MIME type information from an open file. The file must have the format of
the standard :file:`mime.types` files. the standard :file:`mime.types` files.
.. method:: MimeTypes.read_windows_registry()
Load MIME type information from the Windows registry. Availability: Windows.
.. versionadded:: 2.7

View File

@ -18,13 +18,19 @@ types_map -- dictionary mapping suffixes to types
Functions: 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 read_mime_types(file) -- parse one file, return a dictionary or None
""" """
import os import os
import sys
import posixpath import posixpath
import urllib import urllib
try:
import _winreg
except ImportError:
_winreg = None
__all__ = [ __all__ = [
"guess_type","guess_extension","guess_all_extensions", "guess_type","guess_extension","guess_all_extensions",
@ -220,6 +226,52 @@ class MimeTypes:
for suff in suffixes: for suff in suffixes:
self.add_type(type, '.' + suff, strict) 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): def guess_type(url, strict=True):
"""Guess the type of a file based on its URL. """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 inited = True # so that MimeTypes.__init__() doesn't call us again
db = MimeTypes() db = MimeTypes()
if files is None: if files is None:
if _winreg:
db.read_windows_registry()
files = knownfiles files = knownfiles
for file in files: for file in files:
if os.path.isfile(file): if os.path.isfile(file):

View File

@ -1,6 +1,7 @@
import mimetypes import mimetypes
import StringIO import StringIO
import unittest import unittest
import sys
from test import test_support from test import test_support
@ -62,8 +63,31 @@ class MimeTypesTestCase(unittest.TestCase):
eq(all, []) 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(): def test_main():
test_support.run_unittest(MimeTypesTestCase) test_support.run_unittest(MimeTypesTestCase,
Win32MimeTypesTestCase
)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -429,6 +429,9 @@ Core and Builtins
Library 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 - 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 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 as zipfiles, directories and other valid sys.path entries that contain a