xref: /third_party/python/Lib/test/test_mailcap.py (revision 7db96d56)
17db96d56Sopenharmony_ciimport copy
27db96d56Sopenharmony_ciimport os
37db96d56Sopenharmony_ciimport sys
47db96d56Sopenharmony_ciimport test.support
57db96d56Sopenharmony_ciimport unittest
67db96d56Sopenharmony_ciimport warnings
77db96d56Sopenharmony_cifrom test.support import os_helper
87db96d56Sopenharmony_cifrom test.support import warnings_helper
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_cimailcap = warnings_helper.import_deprecated('mailcap')
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci# Location of mailcap file
157db96d56Sopenharmony_ciMAILCAPFILE = test.support.findfile("mailcap.txt")
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci# Dict to act as mock mailcap entry for this test
187db96d56Sopenharmony_ci# The keys and values should match the contents of MAILCAPFILE
197db96d56Sopenharmony_ciMAILCAPDICT = {
207db96d56Sopenharmony_ci    'application/x-movie':
217db96d56Sopenharmony_ci        [{'compose': 'moviemaker %s',
227db96d56Sopenharmony_ci          'x11-bitmap': '"/usr/lib/Zmail/bitmaps/movie.xbm"',
237db96d56Sopenharmony_ci          'description': '"Movie"',
247db96d56Sopenharmony_ci          'view': 'movieplayer %s',
257db96d56Sopenharmony_ci          'lineno': 4}],
267db96d56Sopenharmony_ci    'application/*':
277db96d56Sopenharmony_ci        [{'copiousoutput': '',
287db96d56Sopenharmony_ci          'view': 'echo "This is \\"%t\\" but        is 50 \\% Greek to me" \\; cat %s',
297db96d56Sopenharmony_ci          'lineno': 5}],
307db96d56Sopenharmony_ci    'audio/basic':
317db96d56Sopenharmony_ci        [{'edit': 'audiocompose %s',
327db96d56Sopenharmony_ci          'compose': 'audiocompose %s',
337db96d56Sopenharmony_ci          'description': '"An audio fragment"',
347db96d56Sopenharmony_ci          'view': 'showaudio %s',
357db96d56Sopenharmony_ci          'lineno': 6}],
367db96d56Sopenharmony_ci    'video/mpeg':
377db96d56Sopenharmony_ci        [{'view': 'mpeg_play %s', 'lineno': 13}],
387db96d56Sopenharmony_ci    'application/postscript':
397db96d56Sopenharmony_ci        [{'needsterminal': '', 'view': 'ps-to-terminal %s', 'lineno': 1},
407db96d56Sopenharmony_ci         {'compose': 'idraw %s', 'view': 'ps-to-terminal %s', 'lineno': 2}],
417db96d56Sopenharmony_ci    'application/x-dvi':
427db96d56Sopenharmony_ci        [{'view': 'xdvi %s', 'lineno': 3}],
437db96d56Sopenharmony_ci    'message/external-body':
447db96d56Sopenharmony_ci        [{'composetyped': 'extcompose %s',
457db96d56Sopenharmony_ci          'description': '"A reference to data stored in an external location"',
467db96d56Sopenharmony_ci          'needsterminal': '',
477db96d56Sopenharmony_ci          'view': 'showexternal %s %{access-type} %{name} %{site}     %{directory} %{mode} %{server}',
487db96d56Sopenharmony_ci          'lineno': 10}],
497db96d56Sopenharmony_ci    'text/richtext':
507db96d56Sopenharmony_ci        [{'test': 'test "`echo     %{charset} | tr \'[A-Z]\' \'[a-z]\'`"  = iso-8859-8',
517db96d56Sopenharmony_ci          'copiousoutput': '',
527db96d56Sopenharmony_ci          'view': 'shownonascii iso-8859-8 -e richtext -p %s',
537db96d56Sopenharmony_ci          'lineno': 11}],
547db96d56Sopenharmony_ci    'image/x-xwindowdump':
557db96d56Sopenharmony_ci        [{'view': 'display %s', 'lineno': 9}],
567db96d56Sopenharmony_ci    'audio/*':
577db96d56Sopenharmony_ci        [{'view': '/usr/local/bin/showaudio %t', 'lineno': 7}],
587db96d56Sopenharmony_ci    'video/*':
597db96d56Sopenharmony_ci        [{'view': 'animate %s', 'lineno': 12}],
607db96d56Sopenharmony_ci    'application/frame':
617db96d56Sopenharmony_ci        [{'print': '"cat %s | lp"', 'view': 'showframe %s', 'lineno': 0}],
627db96d56Sopenharmony_ci    'image/rgb':
637db96d56Sopenharmony_ci        [{'view': 'display %s', 'lineno': 8}]
647db96d56Sopenharmony_ci}
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci# For backwards compatibility, readmailcapfile() and lookup() still support
677db96d56Sopenharmony_ci# the old version of mailcapdict without line numbers.
687db96d56Sopenharmony_ciMAILCAPDICT_DEPRECATED = copy.deepcopy(MAILCAPDICT)
697db96d56Sopenharmony_cifor entry_list in MAILCAPDICT_DEPRECATED.values():
707db96d56Sopenharmony_ci    for entry in entry_list:
717db96d56Sopenharmony_ci        entry.pop('lineno')
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ciclass HelperFunctionTest(unittest.TestCase):
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci    def test_listmailcapfiles(self):
777db96d56Sopenharmony_ci        # The return value for listmailcapfiles() will vary by system.
787db96d56Sopenharmony_ci        # So verify that listmailcapfiles() returns a list of strings that is of
797db96d56Sopenharmony_ci        # non-zero length.
807db96d56Sopenharmony_ci        mcfiles = mailcap.listmailcapfiles()
817db96d56Sopenharmony_ci        self.assertIsInstance(mcfiles, list)
827db96d56Sopenharmony_ci        for m in mcfiles:
837db96d56Sopenharmony_ci            self.assertIsInstance(m, str)
847db96d56Sopenharmony_ci        with os_helper.EnvironmentVarGuard() as env:
857db96d56Sopenharmony_ci            # According to RFC 1524, if MAILCAPS env variable exists, use that
867db96d56Sopenharmony_ci            # and only that.
877db96d56Sopenharmony_ci            if "MAILCAPS" in env:
887db96d56Sopenharmony_ci                env_mailcaps = env["MAILCAPS"].split(os.pathsep)
897db96d56Sopenharmony_ci            else:
907db96d56Sopenharmony_ci                env_mailcaps = ["/testdir1/.mailcap", "/testdir2/mailcap"]
917db96d56Sopenharmony_ci                env["MAILCAPS"] = os.pathsep.join(env_mailcaps)
927db96d56Sopenharmony_ci                mcfiles = mailcap.listmailcapfiles()
937db96d56Sopenharmony_ci        self.assertEqual(env_mailcaps, mcfiles)
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci    def test_readmailcapfile(self):
967db96d56Sopenharmony_ci        # Test readmailcapfile() using test file. It should match MAILCAPDICT.
977db96d56Sopenharmony_ci        with open(MAILCAPFILE, 'r') as mcf:
987db96d56Sopenharmony_ci            with self.assertWarns(DeprecationWarning):
997db96d56Sopenharmony_ci                d = mailcap.readmailcapfile(mcf)
1007db96d56Sopenharmony_ci        self.assertDictEqual(d, MAILCAPDICT_DEPRECATED)
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci    def test_lookup(self):
1037db96d56Sopenharmony_ci        # Test without key
1047db96d56Sopenharmony_ci        expected = [{'view': 'animate %s', 'lineno': 12},
1057db96d56Sopenharmony_ci                    {'view': 'mpeg_play %s', 'lineno': 13}]
1067db96d56Sopenharmony_ci        actual = mailcap.lookup(MAILCAPDICT, 'video/mpeg')
1077db96d56Sopenharmony_ci        self.assertListEqual(expected, actual)
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci        # Test with key
1107db96d56Sopenharmony_ci        key = 'compose'
1117db96d56Sopenharmony_ci        expected = [{'edit': 'audiocompose %s',
1127db96d56Sopenharmony_ci                     'compose': 'audiocompose %s',
1137db96d56Sopenharmony_ci                     'description': '"An audio fragment"',
1147db96d56Sopenharmony_ci                     'view': 'showaudio %s',
1157db96d56Sopenharmony_ci                     'lineno': 6}]
1167db96d56Sopenharmony_ci        actual = mailcap.lookup(MAILCAPDICT, 'audio/basic', key)
1177db96d56Sopenharmony_ci        self.assertListEqual(expected, actual)
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci        # Test on user-defined dicts without line numbers
1207db96d56Sopenharmony_ci        expected = [{'view': 'mpeg_play %s'}, {'view': 'animate %s'}]
1217db96d56Sopenharmony_ci        actual = mailcap.lookup(MAILCAPDICT_DEPRECATED, 'video/mpeg')
1227db96d56Sopenharmony_ci        self.assertListEqual(expected, actual)
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci    def test_subst(self):
1257db96d56Sopenharmony_ci        plist = ['id=1', 'number=2', 'total=3']
1267db96d56Sopenharmony_ci        # test case: ([field, MIMEtype, filename, plist=[]], <expected string>)
1277db96d56Sopenharmony_ci        test_cases = [
1287db96d56Sopenharmony_ci            (["", "audio/*", "foo.txt"], ""),
1297db96d56Sopenharmony_ci            (["echo foo", "audio/*", "foo.txt"], "echo foo"),
1307db96d56Sopenharmony_ci            (["echo %s", "audio/*", "foo.txt"], "echo foo.txt"),
1317db96d56Sopenharmony_ci            (["echo %t", "audio/*", "foo.txt"], None),
1327db96d56Sopenharmony_ci            (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"),
1337db96d56Sopenharmony_ci            (["echo \\%t", "audio/*", "foo.txt"], "echo %t"),
1347db96d56Sopenharmony_ci            (["echo foo", "audio/*", "foo.txt", plist], "echo foo"),
1357db96d56Sopenharmony_ci            (["echo %{total}", "audio/*", "foo.txt", plist], "echo 3")
1367db96d56Sopenharmony_ci        ]
1377db96d56Sopenharmony_ci        for tc in test_cases:
1387db96d56Sopenharmony_ci            self.assertEqual(mailcap.subst(*tc[0]), tc[1])
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ciclass GetcapsTest(unittest.TestCase):
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci    def test_mock_getcaps(self):
1447db96d56Sopenharmony_ci        # Test mailcap.getcaps() using mock mailcap file in this dir.
1457db96d56Sopenharmony_ci        # Temporarily override any existing system mailcap file by pointing the
1467db96d56Sopenharmony_ci        # MAILCAPS environment variable to our mock file.
1477db96d56Sopenharmony_ci        with os_helper.EnvironmentVarGuard() as env:
1487db96d56Sopenharmony_ci            env["MAILCAPS"] = MAILCAPFILE
1497db96d56Sopenharmony_ci            caps = mailcap.getcaps()
1507db96d56Sopenharmony_ci            self.assertDictEqual(caps, MAILCAPDICT)
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci    def test_system_mailcap(self):
1537db96d56Sopenharmony_ci        # Test mailcap.getcaps() with mailcap file(s) on system, if any.
1547db96d56Sopenharmony_ci        caps = mailcap.getcaps()
1557db96d56Sopenharmony_ci        self.assertIsInstance(caps, dict)
1567db96d56Sopenharmony_ci        mailcapfiles = mailcap.listmailcapfiles()
1577db96d56Sopenharmony_ci        existingmcfiles = [mcf for mcf in mailcapfiles if os.path.exists(mcf)]
1587db96d56Sopenharmony_ci        if existingmcfiles:
1597db96d56Sopenharmony_ci            # At least 1 mailcap file exists, so test that.
1607db96d56Sopenharmony_ci            for (k, v) in caps.items():
1617db96d56Sopenharmony_ci                self.assertIsInstance(k, str)
1627db96d56Sopenharmony_ci                self.assertIsInstance(v, list)
1637db96d56Sopenharmony_ci                for e in v:
1647db96d56Sopenharmony_ci                    self.assertIsInstance(e, dict)
1657db96d56Sopenharmony_ci        else:
1667db96d56Sopenharmony_ci            # No mailcap files on system. getcaps() should return empty dict.
1677db96d56Sopenharmony_ci            self.assertEqual({}, caps)
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ciclass FindmatchTest(unittest.TestCase):
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci    def test_findmatch(self):
1737db96d56Sopenharmony_ci
1747db96d56Sopenharmony_ci        # default findmatch arguments
1757db96d56Sopenharmony_ci        c = MAILCAPDICT
1767db96d56Sopenharmony_ci        fname = "foo.txt"
1777db96d56Sopenharmony_ci        plist = ["access-type=default", "name=john", "site=python.org",
1787db96d56Sopenharmony_ci                 "directory=/tmp", "mode=foo", "server=bar"]
1797db96d56Sopenharmony_ci        audio_basic_entry = {
1807db96d56Sopenharmony_ci            'edit': 'audiocompose %s',
1817db96d56Sopenharmony_ci            'compose': 'audiocompose %s',
1827db96d56Sopenharmony_ci            'description': '"An audio fragment"',
1837db96d56Sopenharmony_ci            'view': 'showaudio %s',
1847db96d56Sopenharmony_ci            'lineno': 6
1857db96d56Sopenharmony_ci        }
1867db96d56Sopenharmony_ci        audio_entry = {"view": "/usr/local/bin/showaudio %t", 'lineno': 7}
1877db96d56Sopenharmony_ci        video_entry = {'view': 'animate %s', 'lineno': 12}
1887db96d56Sopenharmony_ci        message_entry = {
1897db96d56Sopenharmony_ci            'composetyped': 'extcompose %s',
1907db96d56Sopenharmony_ci            'description': '"A reference to data stored in an external location"', 'needsterminal': '',
1917db96d56Sopenharmony_ci            'view': 'showexternal %s %{access-type} %{name} %{site}     %{directory} %{mode} %{server}',
1927db96d56Sopenharmony_ci            'lineno': 10,
1937db96d56Sopenharmony_ci        }
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci        # test case: (findmatch args, findmatch keyword args, expected output)
1967db96d56Sopenharmony_ci        #   positional args: caps, MIMEtype
1977db96d56Sopenharmony_ci        #   keyword args: key="view", filename="/dev/null", plist=[]
1987db96d56Sopenharmony_ci        #   output: (command line, mailcap entry)
1997db96d56Sopenharmony_ci        cases = [
2007db96d56Sopenharmony_ci            ([{}, "video/mpeg"], {}, (None, None)),
2017db96d56Sopenharmony_ci            ([c, "foo/bar"], {}, (None, None)),
2027db96d56Sopenharmony_ci            ([c, "video/mpeg"], {}, ('animate /dev/null', video_entry)),
2037db96d56Sopenharmony_ci            ([c, "audio/basic", "edit"], {}, ("audiocompose /dev/null", audio_basic_entry)),
2047db96d56Sopenharmony_ci            ([c, "audio/basic", "compose"], {}, ("audiocompose /dev/null", audio_basic_entry)),
2057db96d56Sopenharmony_ci            ([c, "audio/basic", "description"], {}, ('"An audio fragment"', audio_basic_entry)),
2067db96d56Sopenharmony_ci            ([c, "audio/basic", "foobar"], {}, (None, None)),
2077db96d56Sopenharmony_ci            ([c, "video/*"], {"filename": fname}, ("animate %s" % fname, video_entry)),
2087db96d56Sopenharmony_ci            ([c, "audio/basic", "compose"],
2097db96d56Sopenharmony_ci             {"filename": fname},
2107db96d56Sopenharmony_ci             ("audiocompose %s" % fname, audio_basic_entry)),
2117db96d56Sopenharmony_ci            ([c, "audio/basic"],
2127db96d56Sopenharmony_ci             {"key": "description", "filename": fname},
2137db96d56Sopenharmony_ci             ('"An audio fragment"', audio_basic_entry)),
2147db96d56Sopenharmony_ci            ([c, "audio/*"],
2157db96d56Sopenharmony_ci             {"filename": fname},
2167db96d56Sopenharmony_ci             (None, None)),
2177db96d56Sopenharmony_ci            ([c, "audio/wav"],
2187db96d56Sopenharmony_ci             {"filename": fname},
2197db96d56Sopenharmony_ci             ("/usr/local/bin/showaudio audio/wav", audio_entry)),
2207db96d56Sopenharmony_ci            ([c, "message/external-body"],
2217db96d56Sopenharmony_ci             {"plist": plist},
2227db96d56Sopenharmony_ci             ("showexternal /dev/null default john python.org     /tmp foo bar", message_entry))
2237db96d56Sopenharmony_ci        ]
2247db96d56Sopenharmony_ci        self._run_cases(cases)
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ci    @unittest.skipUnless(os.name == "posix", "Requires 'test' command on system")
2277db96d56Sopenharmony_ci    @unittest.skipIf(sys.platform == "vxworks", "'test' command is not supported on VxWorks")
2287db96d56Sopenharmony_ci    @unittest.skipUnless(
2297db96d56Sopenharmony_ci        test.support.has_subprocess_support,
2307db96d56Sopenharmony_ci        "'test' command needs process support."
2317db96d56Sopenharmony_ci    )
2327db96d56Sopenharmony_ci    def test_test(self):
2337db96d56Sopenharmony_ci        # findmatch() will automatically check any "test" conditions and skip
2347db96d56Sopenharmony_ci        # the entry if the check fails.
2357db96d56Sopenharmony_ci        caps = {"test/pass": [{"test": "test 1 -eq 1"}],
2367db96d56Sopenharmony_ci                "test/fail": [{"test": "test 1 -eq 0"}]}
2377db96d56Sopenharmony_ci        # test case: (findmatch args, findmatch keyword args, expected output)
2387db96d56Sopenharmony_ci        #   positional args: caps, MIMEtype, key ("test")
2397db96d56Sopenharmony_ci        #   keyword args: N/A
2407db96d56Sopenharmony_ci        #   output: (command line, mailcap entry)
2417db96d56Sopenharmony_ci        cases = [
2427db96d56Sopenharmony_ci            # findmatch will return the mailcap entry for test/pass because it evaluates to true
2437db96d56Sopenharmony_ci            ([caps, "test/pass", "test"], {}, ("test 1 -eq 1", {"test": "test 1 -eq 1"})),
2447db96d56Sopenharmony_ci            # findmatch will return None because test/fail evaluates to false
2457db96d56Sopenharmony_ci            ([caps, "test/fail", "test"], {}, (None, None))
2467db96d56Sopenharmony_ci        ]
2477db96d56Sopenharmony_ci        self._run_cases(cases)
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci    def _run_cases(self, cases):
2507db96d56Sopenharmony_ci        for c in cases:
2517db96d56Sopenharmony_ci            self.assertEqual(mailcap.findmatch(*c[0], **c[1]), c[2])
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci
2547db96d56Sopenharmony_ciif __name__ == '__main__':
2557db96d56Sopenharmony_ci    unittest.main()
256