* :mod:`!idlelib`
* :ref:`inspect <inspect-module-cli>`
* :ref:`json <json-commandline>`
-* :mod:`mimetypes`
+* :ref:`mimetypes <mimetypes-cli>`
* :mod:`pdb`
* :mod:`pickle`
* :ref:`pickletools <pickletools-cli>`
.. _mimetypes-objects:
-MimeTypes Objects
+MimeTypes objects
-----------------
The :class:`MimeTypes` class may be useful for applications which may want more
When *strict* is ``True`` (the default), the mapping will be added to the
official MIME types, otherwise to the non-standard ones.
+
+
+.. _mimetypes-cli:
+
+Command-line usage
+------------------
+
+The :mod:`!mimetypes` module can be executed as a script from the command line.
+
+.. code-block:: sh
+
+ python -m mimetypes [-h] [-e] [-l] type [type ...]
+
+The following options are accepted:
+
+.. program:: mimetypes
+
+.. cmdoption:: -h
+ --help
+
+ Show the help message and exit.
+
+.. cmdoption:: -e
+ --extension
+
+ Guess extension instead of type.
+
+.. cmdoption:: -l
+ --lenient
+
+ Additionally search for some common, but non-standard types.
+
+By default the script converts MIME types to file extensions.
+However, if ``--extension`` is specified,
+it converts file extensions to MIME types.
+
+For each ``type`` entry, the script writes a line into the standard output
+stream. If an unknown type occurs, it writes an error message into the
+standard error stream and exits with the return code ``1``.
+
+
+.. mimetypes-cli-example:
+
+Command-line example
+--------------------
+
+Here are some examples of typical usage of the :mod:`!mimetypes` command-line
+interface:
+
+.. code-block:: console
+
+ $ # get a MIME type by a file name
+ $ python -m mimetypes filename.png
+ type: image/png encoding: None
+
+ $ # get a MIME type by a URL
+ $ python -m mimetypes https://example.com/filename.txt
+ type: text/plain encoding: None
+
+ $ # get a complex MIME type
+ $ python -m mimetypes filename.tar.gz
+ type: application/x-tar encoding: gzip
+
+ $ # get a MIME type for a rare file extension
+ $ python -m mimetypes filename.pict
+ error: unknown extension of filename.pict
+
+ $ # now look in the extended database built into Python
+ $ python -m mimetypes --lenient filename.pict
+ type: image/pict encoding: None
+
+ $ # get a file extension by a MIME type
+ $ python -m mimetypes --extension text/javascript
+ .js
+
+ $ # get a file extension by a rare MIME type
+ $ python -m mimetypes --extension text/xul
+ error: unknown type text/xul
+
+ $ # now look in the extended database again
+ $ python -m mimetypes --extension --lenient text/xul
+ .xul
+
+ $ # try to feed an unknown file extension
+ $ python -m mimetypes filename.sh filename.nc filename.xxx filename.txt
+ type: application/x-sh encoding: None
+ type: application/x-netcdf encoding: None
+ error: unknown extension of filename.xxx
+
+ $ # try to feed an unknown MIME type
+ $ python -m mimetypes --extension audio/aac audio/opus audio/future audio/x-wav
+ .aac
+ .opus
+ error: unknown type audio/future
mimetypes
---------
+* Document the command-line for :mod:`mimetypes`.
+ It now exits with ``1`` on failure instead of ``0``
+ and ``2`` on incorrect command-line parameters instead of ``1``.
+ Also, errors are printed to stderr instead of stdout and their text is made
+ tighter.
+ (Contributed by Oleg Iarygin and Hugo van Kemenade in :gh:`93096`.)
+
* Add MS and :rfc:`8081` MIME types for fonts:
* Embedded OpenType: ``application/vnd.ms-fontobject``
def _main():
- import getopt
+ """Run the mimetypes command-line interface."""
import sys
-
- USAGE = """\
-Usage: mimetypes.py [options] type
-
-Options:
- --help / -h -- print this message and exit
- --lenient / -l -- additionally search of some common, but non-standard
- types.
- --extension / -e -- guess extension instead of type
-
-More than one type argument may be given.
-"""
-
- def usage(code, msg=''):
- print(USAGE)
- if msg: print(msg)
- sys.exit(code)
-
- try:
- opts, args = getopt.getopt(sys.argv[1:], 'hle',
- ['help', 'lenient', 'extension'])
- except getopt.error as msg:
- usage(1, msg)
-
- strict = 1
- extension = 0
- for opt, arg in opts:
- if opt in ('-h', '--help'):
- usage(0)
- elif opt in ('-l', '--lenient'):
- strict = 0
- elif opt in ('-e', '--extension'):
- extension = 1
- for gtype in args:
- if extension:
- guess = guess_extension(gtype, strict)
- if not guess: print("I don't know anything about type", gtype)
- else: print(guess)
- else:
- guess, encoding = guess_type(gtype, strict)
- if not guess: print("I don't know anything about type", gtype)
- else: print('type:', guess, 'encoding:', encoding)
+ from argparse import ArgumentParser
+
+ parser = ArgumentParser(description='map filename extensions to MIME types')
+ parser.add_argument(
+ '-e', '--extension',
+ action='store_true',
+ help='guess extension instead of type'
+ )
+ parser.add_argument(
+ '-l', '--lenient',
+ action='store_true',
+ help='additionally search for common but non-standard types'
+ )
+ parser.add_argument('type', nargs='+', help='a type to search')
+ args = parser.parse_args()
+
+ if args.extension:
+ for gtype in args.type:
+ guess = guess_extension(gtype, not args.lenient)
+ if guess:
+ print(guess)
+ else:
+ sys.exit(f"error: unknown type {gtype}")
+ else:
+ for gtype in args.type:
+ guess, encoding = guess_type(gtype, not args.lenient)
+ if guess:
+ print('type:', guess, 'encoding:', encoding)
+ else:
+ sys.exit(f"error: media type unknown for {gtype}")
if __name__ == '__main__':
import os
import sys
import unittest.mock
+from os import linesep
from test import support
from test.support import os_helper
+from test.support.script_helper import run_python_until_end
from platform import win32_edition
try:
class MimetypesCliTestCase(unittest.TestCase):
- def mimetypes_cmd(self, *args, **kwargs):
- support.patch(self, sys, "argv", [sys.executable, *args])
- with support.captured_stdout() as output:
- mimetypes._main()
- return output.getvalue().strip()
+ def mimetypes_cmd(cls, *args, **kwargs):
+ result, _ = run_python_until_end('-m', 'mimetypes', *args)
+ return result.rc, result.out.decode(), result.err.decode()
def test_help_option(self):
- support.patch(self, sys, "argv", [sys.executable, "-h"])
- with support.captured_stdout() as output:
- with self.assertRaises(SystemExit) as cm:
- mimetypes._main()
-
- self.assertIn("Usage: mimetypes.py", output.getvalue())
- self.assertEqual(cm.exception.code, 0)
+ retcode, out, err = self.mimetypes_cmd('-h')
+ self.assertEqual(retcode, 0)
+ self.assertStartsWith(out, 'usage: ')
+ self.assertEqual(err, '')
def test_invalid_option(self):
- support.patch(self, sys, "argv", [sys.executable, "--invalid"])
- with support.captured_stdout() as output:
- with self.assertRaises(SystemExit) as cm:
- mimetypes._main()
-
- self.assertIn("Usage: mimetypes.py", output.getvalue())
- self.assertEqual(cm.exception.code, 1)
+ retcode, out, err = self.mimetypes_cmd('--invalid')
+ self.assertEqual(retcode, 2)
+ self.assertEqual(out, '')
+ self.assertStartsWith(err, 'usage: ')
def test_guess_extension(self):
- eq = self.assertEqual
-
- extension = self.mimetypes_cmd("-l", "-e", "image/jpg")
- eq(extension, ".jpg")
+ retcode, out, err = self.mimetypes_cmd('-l', '-e', 'image/jpg')
+ self.assertEqual(retcode, 0)
+ self.assertEqual(out, f'.jpg{linesep}')
+ self.assertEqual(err, '')
- extension = self.mimetypes_cmd("-e", "image/jpg")
- eq(extension, "I don't know anything about type image/jpg")
+ retcode, out, err = self.mimetypes_cmd('-e', 'image/jpg')
+ self.assertEqual(retcode, 1)
+ self.assertEqual(out, '')
+ self.assertEqual(err, f'error: unknown type image/jpg{linesep}')
- extension = self.mimetypes_cmd("-e", "image/jpeg")
- eq(extension, ".jpg")
+ retcode, out, err = self.mimetypes_cmd('-e', 'image/jpeg')
+ self.assertEqual(retcode, 0)
+ self.assertEqual(out, f'.jpg{linesep}')
+ self.assertEqual(err, '')
def test_guess_type(self):
- eq = self.assertEqual
-
- type_info = self.mimetypes_cmd("-l", "foo.pic")
- eq(type_info, "type: image/pict encoding: None")
-
- type_info = self.mimetypes_cmd("foo.pic")
- eq(type_info, "I don't know anything about type foo.pic")
+ retcode, out, err = self.mimetypes_cmd('-l', 'foo.webp')
+ self.assertEqual(retcode, 0)
+ self.assertEqual(out, f'type: image/webp encoding: None{linesep}')
+ self.assertEqual(err, '')
+
+ @unittest.skipIf(
+ sys.platform == 'darwin',
+ 'macOS lists common_types in mime.types thus making them always known'
+ )
+ def test_guess_type_conflicting_with_mimetypes(self):
+ retcode, out, err = self.mimetypes_cmd('foo.pic')
+ self.assertEqual(retcode, 1)
+ self.assertEqual(out, '')
+ self.assertEqual(err, f'error: media type unknown for foo.pic{linesep}')
if __name__ == "__main__":
unittest.main()
Robert Hölzl
Stefan Hölzl
Catalin Iacob
+Oleg Iarygin
Mihai Ibanescu
Ali Ikinci
Aaron Iles
--- /dev/null
+Document the command-line for :mod:`mimetypes`.
+It now exits with ``1`` on failure instead of ``0``
+and ``2`` on incorrect command-line parameters instead of ``1``.
+Also, errors are printed to stderr instead of stdout and their text is made
+tighter. Patch by Oleg Iarygin and Hugo van Kemenade.