diff options
Diffstat (limited to 'tests/test_cmdline.py')
-rw-r--r-- | tests/test_cmdline.py | 495 |
1 files changed, 250 insertions, 245 deletions
diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 11b53896..d56e2ae5 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -3,7 +3,7 @@ Command line test ~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -14,9 +14,10 @@ import os import re import sys import tempfile -import unittest from os import path +from pytest import raises + from pygments import cmdline, highlight from pygments.util import BytesIO, StringIO @@ -66,249 +67,253 @@ def run_cmdline(*args, **kwds): return (ret, _decode_output(out), _decode_output(err)) -class CmdLineTest(unittest.TestCase): - - def check_success(self, *cmdline, **kwds): - code, out, err = run_cmdline(*cmdline, **kwds) - self.assertEqual(code, 0) - self.assertEqual(err, '') - return out - - def check_failure(self, *cmdline, **kwds): - expected_code = kwds.pop('code', 1) - code, out, err = run_cmdline(*cmdline, **kwds) - self.assertEqual(code, expected_code) - self.assertEqual(out, '') - return err - - def test_normal(self): - # test that cmdline gives the same output as library api - from pygments.lexers import PythonLexer - from pygments.formatters import HtmlFormatter - filename = TESTFILE - with open(filename, 'rb') as fp: - code = fp.read() - - output = highlight(code, PythonLexer(), HtmlFormatter()) - - o = self.check_success('-lpython', '-fhtml', filename) - self.assertEqual(o, output) - - def test_stdin(self): - o = self.check_success('-lpython', '-fhtml', stdin=TESTCODE) - o = re.sub('<[^>]*>', '', o) - # rstrip is necessary since HTML inserts a \n after the last </div> - self.assertEqual(o.rstrip(), TESTCODE.rstrip()) - - # guess if no lexer given - o = self.check_success('-fhtml', stdin=TESTCODE) - o = re.sub('<[^>]*>', '', o) - # rstrip is necessary since HTML inserts a \n after the last </div> - self.assertEqual(o.rstrip(), TESTCODE.rstrip()) - - def test_outfile(self): - # test that output file works with and without encoding - fd, name = tempfile.mkstemp() - os.close(fd) - for opts in [['-fhtml', '-o', name, TESTFILE], - ['-flatex', '-o', name, TESTFILE], - ['-fhtml', '-o', name, '-O', 'encoding=utf-8', TESTFILE]]: - try: - self.check_success(*opts) - finally: - os.unlink(name) - - def test_load_from_file(self): - lexer_file = os.path.join(TESTDIR, 'support', 'python_lexer.py') - formatter_file = os.path.join(TESTDIR, 'support', 'html_formatter.py') - - # By default, use CustomLexer - o = self.check_success('-l', lexer_file, '-f', 'html', - '-x', stdin=TESTCODE) - o = re.sub('<[^>]*>', '', o) - # rstrip is necessary since HTML inserts a \n after the last </div> - self.assertEqual(o.rstrip(), TESTCODE.rstrip()) - - # If user specifies a name, use it - o = self.check_success('-f', 'html', '-x', '-l', - lexer_file + ':LexerWrapper', stdin=TESTCODE) - o = re.sub('<[^>]*>', '', o) - # rstrip is necessary since HTML inserts a \n after the last </div> - self.assertEqual(o.rstrip(), TESTCODE.rstrip()) - - # Should also work for formatters - o = self.check_success('-lpython', '-f', - formatter_file + ':HtmlFormatterWrapper', - '-x', stdin=TESTCODE) - o = re.sub('<[^>]*>', '', o) - # rstrip is necessary since HTML inserts a \n after the last </div> - self.assertEqual(o.rstrip(), TESTCODE.rstrip()) - - def test_stream_opt(self): - o = self.check_success('-lpython', '-s', '-fterminal', stdin=TESTCODE) - o = re.sub(r'\x1b\[.*?m', '', o) - self.assertEqual(o.replace('\r\n', '\n'), TESTCODE) - - def test_h_opt(self): - o = self.check_success('-h') - self.assertTrue('Usage:' in o) - - def test_L_opt(self): - o = self.check_success('-L') - self.assertTrue('Lexers' in o and 'Formatters' in o and - 'Filters' in o and 'Styles' in o) - o = self.check_success('-L', 'lexer') - self.assertTrue('Lexers' in o and 'Formatters' not in o) - self.check_success('-L', 'lexers') - - def test_O_opt(self): - filename = TESTFILE - o = self.check_success('-Ofull=1,linenos=true,foo=bar', - '-fhtml', filename) - self.assertTrue('<html' in o) - self.assertTrue('class="linenos"' in o) - - # "foobar" is invalid for a bool option - e = self.check_failure('-Ostripnl=foobar', TESTFILE) - self.assertTrue('Error: Invalid value' in e) - e = self.check_failure('-Ostripnl=foobar', '-lpy') - self.assertTrue('Error: Invalid value' in e) - - def test_P_opt(self): - filename = TESTFILE - o = self.check_success('-Pfull', '-Ptitle=foo, bar=baz=,', - '-fhtml', filename) - self.assertTrue('<title>foo, bar=baz=,</title>' in o) - - def test_F_opt(self): - filename = TESTFILE - o = self.check_success('-Fhighlight:tokentype=Name.Blubb,' - 'names=TESTFILE filename', - '-fhtml', filename) - self.assertTrue('<span class="n n-Blubb' in o) - - def test_H_opt(self): - o = self.check_success('-H', 'formatter', 'html') - self.assertTrue('HTML' in o) - o = self.check_success('-H', 'lexer', 'python') - self.assertTrue('Python' in o) - o = self.check_success('-H', 'filter', 'raiseonerror') - self.assertTrue('raiseonerror', o) - e = self.check_failure('-H', 'lexer', 'foobar') - self.assertTrue('not found' in e) - - def test_S_opt(self): - o = self.check_success('-S', 'default', '-f', 'html', '-O', 'linenos=1') - lines = o.splitlines() - for line in lines: - # every line is for a token class - parts = line.split() - self.assertTrue(parts[0].startswith('.')) - self.assertTrue(parts[1] == '{') - if parts[0] != '.hll': - self.assertTrue(parts[-4] == '}') - self.assertTrue(parts[-3] == '/*') - self.assertTrue(parts[-1] == '*/') - self.check_failure('-S', 'default', '-f', 'foobar') - - def test_N_opt(self): - o = self.check_success('-N', 'test.py') - self.assertEqual('python', o.strip()) - o = self.check_success('-N', 'test.unknown') - self.assertEqual('text', o.strip()) - - def test_invalid_opts(self): - for opts in [ - ('-X',), - ('-L', '-lpy'), - ('-L', '-fhtml'), - ('-L', '-Ox'), - ('-S', 'default', '-l', 'py', '-f', 'html'), - ('-S', 'default'), - ('-a', 'arg'), - ('-H',), - (TESTFILE, TESTFILE), - ('-H', 'formatter'), - ('-H', 'foo', 'bar'), - ('-s',), - ('-s', TESTFILE), - ]: - self.check_failure(*opts, code=2) - - def test_errors(self): - # input file not found - e = self.check_failure('-lpython', 'nonexistent.py') - self.assertTrue('Error: cannot read infile' in e) - self.assertTrue('nonexistent.py' in e) - - # lexer not found - e = self.check_failure('-lfooo', TESTFILE) - self.assertTrue('Error: no lexer for alias' in e) - - # cannot load .py file without load_from_file flag - e = self.check_failure('-l', 'nonexistent.py', TESTFILE) - self.assertTrue('Error: no lexer for alias' in e) - - # lexer file is missing/unreadable - e = self.check_failure('-l', 'nonexistent.py', - '-x', TESTFILE) - self.assertTrue('Error: cannot read' in e) - - # lexer file is malformed - e = self.check_failure('-l', path.join(TESTDIR, 'support', 'empty.py'), - '-x', TESTFILE) - self.assertTrue('Error: no valid CustomLexer class found' in e) - - # formatter not found - e = self.check_failure('-lpython', '-ffoo', TESTFILE) - self.assertTrue('Error: no formatter found for name' in e) - - # formatter for outfile not found - e = self.check_failure('-ofoo.foo', TESTFILE) - self.assertTrue('Error: no formatter found for file name' in e) - - # cannot load .py file without load_from_file flag - e = self.check_failure('-f', 'nonexistent.py', TESTFILE) - self.assertTrue('Error: no formatter found for name' in e) - - # formatter file is missing/unreadable - e = self.check_failure('-f', 'nonexistent.py', - '-x', TESTFILE) - self.assertTrue('Error: cannot read' in e) - - # formatter file is malformed - e = self.check_failure('-f', path.join(TESTDIR, 'support', 'empty.py'), - '-x', TESTFILE) - self.assertTrue('Error: no valid CustomFormatter class found' in e) - - # output file not writable - e = self.check_failure('-o', os.path.join('nonexistent', 'dir', 'out.html'), - '-lpython', TESTFILE) - self.assertTrue('Error: cannot open outfile' in e) - self.assertTrue('out.html' in e) - - # unknown filter - e = self.check_failure('-F', 'foo', TESTFILE) - self.assertTrue('Error: filter \'foo\' not found' in e) - - def test_exception(self): - cmdline.highlight = None # override callable to provoke TypeError +def check_success(*cmdline, **kwds): + code, out, err = run_cmdline(*cmdline, **kwds) + assert code == 0 + assert err == '' + return out + + +def check_failure(*cmdline, **kwds): + expected_code = kwds.pop('code', 1) + code, out, err = run_cmdline(*cmdline, **kwds) + assert code == expected_code + assert out == '' + return err + + +def test_normal(): + # test that cmdline gives the same output as library api + from pygments.lexers import PythonLexer + from pygments.formatters import HtmlFormatter + filename = TESTFILE + with open(filename, 'rb') as fp: + code = fp.read() + + output = highlight(code, PythonLexer(), HtmlFormatter()) + + o = check_success('-lpython', '-fhtml', filename) + assert o == output + + +def test_stdin(): + o = check_success('-lpython', '-fhtml', stdin=TESTCODE) + o = re.sub('<[^>]*>', '', o) + # rstrip is necessary since HTML inserts a \n after the last </div> + assert o.rstrip() == TESTCODE.rstrip() + + # guess if no lexer given + o = check_success('-fhtml', stdin=TESTCODE) + o = re.sub('<[^>]*>', '', o) + # rstrip is necessary since HTML inserts a \n after the last </div> + assert o.rstrip() == TESTCODE.rstrip() + + +def test_outfile(): + # test that output file works with and without encoding + fd, name = tempfile.mkstemp() + os.close(fd) + for opts in [['-fhtml', '-o', name, TESTFILE], + ['-flatex', '-o', name, TESTFILE], + ['-fhtml', '-o', name, '-O', 'encoding=utf-8', TESTFILE]]: try: - # unexpected exception while highlighting - e = self.check_failure('-lpython', TESTFILE) - self.assertTrue('*** Error while highlighting:' in e) - self.assertTrue('TypeError' in e) - - # same with -v: should reraise the exception - try: - self.check_failure('-lpython', '-v', TESTFILE) - except Exception: - pass - else: - self.fail('exception not reraised') + check_success(*opts) finally: - cmdline.highlight = highlight + os.unlink(name) + + +def test_load_from_file(): + lexer_file = os.path.join(TESTDIR, 'support', 'python_lexer.py') + formatter_file = os.path.join(TESTDIR, 'support', 'html_formatter.py') + + # By default, use CustomLexer + o = check_success('-l', lexer_file, '-f', 'html', '-x', stdin=TESTCODE) + o = re.sub('<[^>]*>', '', o) + # rstrip is necessary since HTML inserts a \n after the last </div> + assert o.rstrip() == TESTCODE.rstrip() + + # If user specifies a name, use it + o = check_success('-f', 'html', '-x', '-l', + lexer_file + ':LexerWrapper', stdin=TESTCODE) + o = re.sub('<[^>]*>', '', o) + # rstrip is necessary since HTML inserts a \n after the last </div> + assert o.rstrip() == TESTCODE.rstrip() + + # Should also work for formatters + o = check_success('-lpython', '-f', + formatter_file + ':HtmlFormatterWrapper', + '-x', stdin=TESTCODE) + o = re.sub('<[^>]*>', '', o) + # rstrip is necessary since HTML inserts a \n after the last </div> + assert o.rstrip() == TESTCODE.rstrip() + + +def test_stream_opt(): + o = check_success('-lpython', '-s', '-fterminal', stdin=TESTCODE) + o = re.sub(r'\x1b\[.*?m', '', o) + assert o.replace('\r\n', '\n') == TESTCODE + + +def test_h_opt(): + o = check_success('-h') + assert 'Usage:' in o + + +def test_L_opt(): + o = check_success('-L') + assert 'Lexers' in o and 'Formatters' in o and 'Filters' in o and 'Styles' in o + o = check_success('-L', 'lexer') + assert 'Lexers' in o and 'Formatters' not in o + check_success('-L', 'lexers') + + +def test_O_opt(): + filename = TESTFILE + o = check_success('-Ofull=1,linenos=true,foo=bar', '-fhtml', filename) + assert '<html' in o + assert 'class="linenos"' in o + + # "foobar" is invalid for a bool option + e = check_failure('-Ostripnl=foobar', TESTFILE) + assert 'Error: Invalid value' in e + e = check_failure('-Ostripnl=foobar', '-lpy') + assert 'Error: Invalid value' in e + + +def test_P_opt(): + filename = TESTFILE + o = check_success('-Pfull', '-Ptitle=foo, bar=baz=,', '-fhtml', filename) + assert '<title>foo, bar=baz=,</title>' in o + + +def test_F_opt(): + filename = TESTFILE + o = check_success('-Fhighlight:tokentype=Name.Blubb,' + 'names=TESTFILE filename', '-fhtml', filename) + assert '<span class="n n-Blubb' in o + + +def test_H_opt(): + o = check_success('-H', 'formatter', 'html') + assert 'HTML' in o + o = check_success('-H', 'lexer', 'python') + assert 'Python' in o + o = check_success('-H', 'filter', 'raiseonerror') + assert 'raiseonerror' in o + e = check_failure('-H', 'lexer', 'foobar') + assert 'not found' in e + + +def test_S_opt(): + o = check_success('-S', 'default', '-f', 'html', '-O', 'linenos=1') + lines = o.splitlines() + for line in lines: + # every line is for a token class + parts = line.split() + assert parts[0].startswith('.') + assert parts[1] == '{' + if parts[0] != '.hll': + assert parts[-4] == '}' + assert parts[-3] == '/*' + assert parts[-1] == '*/' + check_failure('-S', 'default', '-f', 'foobar') + + +def test_N_opt(): + o = check_success('-N', 'test.py') + assert 'python' == o.strip() + o = check_success('-N', 'test.unknown') + assert 'text' == o.strip() + + +def test_invalid_opts(): + for opts in [ + ('-X',), + ('-L', '-lpy'), + ('-L', '-fhtml'), + ('-L', '-Ox'), + ('-S', 'default', '-l', 'py', '-f', 'html'), + ('-S', 'default'), + ('-a', 'arg'), + ('-H',), + (TESTFILE, TESTFILE), + ('-H', 'formatter'), + ('-H', 'foo', 'bar'), + ('-s',), + ('-s', TESTFILE), + ]: + check_failure(*opts, code=2) + + +def test_errors(): + # input file not found + e = check_failure('-lpython', 'nonexistent.py') + assert 'Error: cannot read infile' in e + assert 'nonexistent.py' in e + + # lexer not found + e = check_failure('-lfooo', TESTFILE) + assert 'Error: no lexer for alias' in e + + # cannot load .py file without load_from_file flag + e = check_failure('-l', 'nonexistent.py', TESTFILE) + assert 'Error: no lexer for alias' in e + + # lexer file is missing/unreadable + e = check_failure('-l', 'nonexistent.py', '-x', TESTFILE) + assert 'Error: cannot read' in e + + # lexer file is malformed + e = check_failure('-l', path.join(TESTDIR, 'support', 'empty.py'), + '-x', TESTFILE) + assert 'Error: no valid CustomLexer class found' in e + + # formatter not found + e = check_failure('-lpython', '-ffoo', TESTFILE) + assert 'Error: no formatter found for name' in e + + # formatter for outfile not found + e = check_failure('-ofoo.foo', TESTFILE) + assert 'Error: no formatter found for file name' in e + + # cannot load .py file without load_from_file flag + e = check_failure('-f', 'nonexistent.py', TESTFILE) + assert 'Error: no formatter found for name' in e + + # formatter file is missing/unreadable + e = check_failure('-f', 'nonexistent.py', '-x', TESTFILE) + assert 'Error: cannot read' in e + + # formatter file is malformed + e = check_failure('-f', path.join(TESTDIR, 'support', 'empty.py'), + '-x', TESTFILE) + assert 'Error: no valid CustomFormatter class found' in e + + # output file not writable + e = check_failure('-o', os.path.join('nonexistent', 'dir', 'out.html'), + '-lpython', TESTFILE) + assert 'Error: cannot open outfile' in e + assert 'out.html' in e + + # unknown filter + e = check_failure('-F', 'foo', TESTFILE) + assert 'Error: filter \'foo\' not found' in e + + +def test_exception(): + cmdline.highlight = None # override callable to provoke TypeError + try: + # unexpected exception while highlighting + e = check_failure('-lpython', TESTFILE) + assert '*** Error while highlighting:' in e + assert 'TypeError' in e + + # same with -v: should reraise the exception + assert raises(Exception, check_failure, '-lpython', '-v', TESTFILE) + finally: + cmdline.highlight = highlight + - def test_parse_opts(self): - self.assertEqual(cmdline._parse_options([' ', 'keyonly,key = value ']), - {'keyonly': True, 'key': 'value'}) +def test_parse_opts(): + assert cmdline._parse_options([' ', 'keyonly,key = value ']) == \ + {'keyonly': True, 'key': 'value'} |