summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-11-15 14:10:48 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-11-15 14:10:48 (GMT)
commitd5b34d4597a7163edf20f831db620b0a4fe57d5d (patch)
tree59f31e437e8495b6a19835fb217288b89e0c69b6
parenta548deeb29badee88dc6fc7a2853b6f56558347f (diff)
downloadcpython-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.rst22
-rw-r--r--Lib/mimetypes.py56
-rw-r--r--Lib/test/test_mimetypes.py26
-rw-r--r--Misc/NEWS3
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__":
diff --git a/Misc/NEWS b/Misc/NEWS
index 3feccda..051bff8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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