diff options
author | Jean Abou-Samra <jean@abou-samra.fr> | 2022-05-12 08:35:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-12 08:35:59 +0200 |
commit | 49c757cab5e4ca80af109581b83a3527df02d29c (patch) | |
tree | c6153eb458cc0289f5e538881a6fdbbb60cf688e | |
parent | 4d2a285bd14f4dc153360e171bebdc52d1921089 (diff) | |
download | pygments-git-49c757cab5e4ca80af109581b83a3527df02d29c.tar.gz |
Improve heuristic to warn about passing lexer/formatter class (#2123)
Don't rely on the error message since 'missing 1 required positional
argument' can give false positives. Instead, use issubclass().
-rw-r--r-- | pygments/__init__.py | 13 | ||||
-rw-r--r-- | tests/test_basic_api.py | 22 |
2 files changed, 28 insertions, 7 deletions
diff --git a/pygments/__init__.py b/pygments/__init__.py index 52ff035d..1c107f33 100644 --- a/pygments/__init__.py +++ b/pygments/__init__.py @@ -39,9 +39,9 @@ def lex(code, lexer): try: return lexer.get_tokens(code) except TypeError as err: - if (isinstance(err.args[0], str) and - ('unbound method get_tokens' in err.args[0] or - 'missing 1 required positional argument' in err.args[0])): + # Heuristic to catch a common mistake. + from pygments.lexer import RegexLexer + if isinstance(lexer, type) and issubclass(lexer, RegexLexer): raise TypeError('lex() argument must be a lexer instance, ' 'not a class') raise @@ -63,9 +63,9 @@ def format(tokens, formatter, outfile=None): # pylint: disable=redefined-builti else: formatter.format(tokens, outfile) except TypeError as err: - if (isinstance(err.args[0], str) and - ('unbound method format' in err.args[0] or - 'missing 1 required positional argument' in err.args[0])): + # Heuristic to catch a common mistake. + from pygments.formatter import Formatter + if isinstance(formatter, type) and issubclass(formatter, Formatter): raise TypeError('format() argument must be a formatter instance, ' 'not a class') raise @@ -80,4 +80,3 @@ def highlight(code, lexer, formatter, outfile=None): it is returned as a string. """ return format(lex(code, lexer), formatter, outfile) - diff --git a/tests/test_basic_api.py b/tests/test_basic_api.py index 1767572f..62ea4895 100644 --- a/tests/test_basic_api.py +++ b/tests/test_basic_api.py @@ -15,6 +15,7 @@ import pytest from pygments import lexers, formatters, lex, format from pygments.token import _TokenType, Text from pygments.lexer import RegexLexer +from pygments.formatter import Formatter from pygments.formatters.img import FontNotFound from pygments.util import ClassNotFound @@ -250,6 +251,27 @@ def test_bare_class_handler(): else: assert False, 'nothing raised' + # These cases should not trigger this heuristic. + class BuggyLexer(RegexLexer): + def get_tokens(self, text, extra_argument): + pass + tokens = {'root': []} + try: + list(lex('dummy', BuggyLexer())) + except TypeError as e: + assert 'lex() argument must be a lexer instance' not in str(e) + else: + assert False, 'no error raised by buggy lexer?' + + class BuggyFormatter(Formatter): + def format(self, tokensource, outfile, extra_argument): + pass + try: + format([], BuggyFormatter()) + except TypeError as e: + assert 'format() argument must be a formatter instance' not in str(e) + else: + assert False, 'no error raised by buggy formatter?' class TestFilters: |