Skip to content

Commit

Permalink
Merge loadMimeTypes-5717: use available system MIME types
Browse files Browse the repository at this point in the history
Author: lvh
Reviewer: rwall
Fixes: twisted#5717

MIME type definition file path used to be hardcoded. Now, we rely on the stdlib to discover MIME types the system knows about. This greatly increases the number of known MIME types on most platforms.


git-svn-id: svn://svn.twistedmatrix.com/svn/Twisted/trunk@39880 bbbe8e31-12d6-0310-92fd-ac37d47ddeeb
  • Loading branch information
lvh committed Sep 8, 2013
1 parent 0890085 commit e079edf
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 23 deletions.
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Jonathan D. Simms
Jürgen Hermann
Kevin Horn
Kevin Turner
Laurens Van Houtven
Mary Gardiner
Matthew Lefkowitz
Massachusetts Institute of Technology
Expand Down
41 changes: 20 additions & 21 deletions twisted/web/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import itertools
import cgi
import time
import mimetypes

from zope.interface import implements

Expand Down Expand Up @@ -97,44 +98,42 @@ def getCachedPath(self, path):
return self._pathCache.get(path)


def loadMimeTypes(mimetype_locations=['/etc/mime.types']):
def loadMimeTypes(mimetype_locations=None, init=mimetypes.init):
"""
Produces a mapping of extensions (with leading dot) to MIME types.
It does this by calling the C{init} function of the L{mimetypes} module.
This will have the side effect of modifying the global MIME types cache
in that module.
Multiple file locations containing mime-types can be passed as a list.
The files will be sourced in that order, overriding mime-types from the
files sourced beforehand, but only if a new entry explicitly overrides
the current entry.
@param mimetype_locations: Optional. List of paths to C{mime.types} style
files that should be used.
@type mimetype_locations: iterable of paths or C{None}
@param init: The init function to call. Defaults to the global C{init}
function of the C{mimetypes} module. For internal use (testing) only.
@type init: callable
"""
import mimetypes
# Grab Python's built-in mimetypes dictionary.
contentTypes = mimetypes.types_map
# Update Python's semi-erroneous dictionary with a few of the
# usual suspects.
contentTypes.update(
init(mimetype_locations)
mimetypes.types_map.update(
{
'.conf': 'text/plain',
'.diff': 'text/plain',
'.exe': 'application/x-executable',
'.flac': 'audio/x-flac',
'.java': 'text/plain',
'.ogg': 'application/ogg',
'.oz': 'text/x-oz',
'.swf': 'application/x-shockwave-flash',
'.tgz': 'application/x-gtar',
'.wml': 'text/vnd.wap.wml',
'.xul': 'application/vnd.mozilla.xul+xml',
'.py': 'text/plain',
'.patch': 'text/plain',
'.patch': 'text/plain'
}
)
# Users can override these mime-types by loading them out configuration
# files (this defaults to ['/etc/mime.types']).
for location in mimetype_locations:
if os.path.exists(location):
more = mimetypes.read_mime_types(location)
if more is not None:
contentTypes.update(more)

return contentTypes
return mimetypes.types_map


def getTypeAndEncoding(filename, types, encodings, defaultType):
p, ext = os.path.splitext(filename)
Expand Down
59 changes: 57 additions & 2 deletions twisted/web/test/test_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
"""
Tests for L{twisted.web.static}.
"""

import os, re, StringIO
import inspect
import mimetypes
import os
import re
import StringIO

from zope.interface.verify import verifyObject

Expand Down Expand Up @@ -1483,3 +1486,55 @@ def test_formatFileSize(self):
self.assertEqual(static.formatFileSize(1234000000), "1G")
self.assertEqual(static.formatFileSize(1234567890000), "1149G")



class LoadMimeTypesTests(TestCase):
"""
Tests for the MIME type loading routine.
@cvar UNSET: A sentinel to signify that C{self.paths} has not been set by
the mock init.
"""
UNSET = object()

def setUp(self):
self.paths = self.UNSET


def _fakeInit(self, paths):
"""
A mock L{mimetypes.init} that records the value of the passed C{paths}
argument.
@param paths: The paths that will be recorded.
"""
self.paths = paths


def test_defaultArgumentIsNone(self):
"""
By default, C{None} is passed to C{mimetypes.init}.
"""
static.loadMimeTypes(init=self._fakeInit)
self.assertIdentical(self.paths, None)


def test_extraLocationsWork(self):
"""
Passed MIME type files are passed to C{mimetypes.init}.
"""
paths = ["x", "y", "z"]
static.loadMimeTypes(paths, init=self._fakeInit)
self.assertIdentical(self.paths, paths)


def test_usesGlobalInitFunction(self):
"""
By default, C{mimetypes.init} is called.
"""
# Checking mimetypes.inited doesn't always work, because
# something, somewhere, calls mimetypes.init. Yay global
# mutable state :)
args, _, _, defaults = inspect.getargspec(static.loadMimeTypes)
defaultInit = defaults[args.index("init")]
self.assertIdentical(defaultInit, mimetypes.init)
1 change: 1 addition & 0 deletions twisted/web/topfiles/5717.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
twisted.web.static.loadMimeTypes now uses all available system MIME types.

0 comments on commit e079edf

Please sign in to comment.