Issue #4969: The mimetypes module now reads the MIME database from
the registry under Windows. Patch by Gabriel Genellina.
This commit is contained in:
parent
a548deeb29
commit
d5b34d4597
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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__":
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue