didyoumean/didyoumean_re.py
# -*- coding: utf-8
"""Regular expressions to parse error messages."""
import re
# https://docs.python.org/3/reference/grammar.html
IDENTIFIER = r"[^\d\W]\w*"
VAR_NAME = IDENTIFIER
# This ATTR_NAME may be misleading because using getattr, any string may be
# appear in an AttributeError message. The same limitation is probably true
# for any property that can be set to pretty much any string.
# In any case, the whole point of having these pieces of regexp defined here
# is to make things easier to change if we ever have to.
ATTR_NAME = IDENTIFIER
ARG_NAME = IDENTIFIER
TYPE_NAME = r"[\w\.-]+"
MODULE_NAME = r"[\w\.-]+"
FUNC_NAME = r"<?\w+>?"
QUAL_FUNC_NAME = r"(?:{0}\.)*{0}".format(FUNC_NAME)
VARREFBEFOREASSIGN_RE = r"^(?:cannot access )?(?:local|free) variable " \
r"'(?P<name>{0})' " \
r"(?:where it is not associated with a value|referenced before assignment)" \
r"(?: in enclosing scope)?$".format(VAR_NAME)
NAMENOTDEFINED_RE = r"^(?:global )?name '(?P<name>{0})' " \
r"is not defined$".format(VAR_NAME)
ATTRIBUTEERROR_RE = r"^(?:class |type object )?'?({0})'? " \
r"(?:object |instance )?has no attribute " \
r"'(?P<attr>{1})'$".format(TYPE_NAME, ATTR_NAME)
MODULEHASNOATTRIBUTE_RE = r"^module '?({0})' has no attribute " \
r"'(?P<attr>{1})'$".format(MODULE_NAME, ATTR_NAME)
UNSUBSCRIPTABLE_RE = r"^'({0})' object " \
r"(?:is (?:not |un)subscriptable)(?: \(key .*\))?$".format(TYPE_NAME)
CANNOT_BE_INTERPRETED_INT_RE = r"^'({0})' object cannot be interpreted " \
r"as an integer$".format(TYPE_NAME)
INTEGER_EXPECTED_GOT_RE = r"^" \
r"(?:range\(\) integer \w+ argument expected|expected integer), " \
r"got ({0})(?: object|\.)$".format(TYPE_NAME)
INDICES_MUST_BE_INT_RE = "^{0} ind(?:ices|ex)? must be " \
r"(?:an integer|integers)(?: or slices)?, not ({0})$".format(TYPE_NAME)
UNEXPECTED_KEYWORDARG_RE = r"^(?P<func>{1})\(\) " \
r"got an unexpected keyword argument " \
r"'(?P<arg>{0})'$".format(ARG_NAME, QUAL_FUNC_NAME)
UNEXPECTED_KEYWORDARG_SUGG_RE = r"^(?P<func>{1})\(\) " \
r"got an unexpected keyword argument " \
r"'(?P<arg>{0})'\. Did you mean '(?P<sugg>.*)'\?$".format(ARG_NAME, QUAL_FUNC_NAME)
UNEXPECTED_KEYWORDARG2_RE = r"^'(?P<arg>{0})' is an " \
r"invalid keyword argument for this function$".format(ARG_NAME)
UNEXPECTED_KEYWORDARG3_RE = r"^invalid keyword arguments to " \
r"(?P<func>{0})\(\)$".format(FUNC_NAME)
UNEXPECTED_KEYWORDARG4_RE = r"^'(?P<arg>{0})' is an " \
r"invalid keyword argument for " \
r"(?P<func>{1})\(\)$".format(ARG_NAME, FUNC_NAME)
FUNC_TAKES_NO_KEYWORDARG_RE = r"^(?P<func>{0})(?:\(\))? " \
r"(?:takes no|does not take) keyword arguments$".format(QUAL_FUNC_NAME)
NOMODULE_RE = r"^No module named '?({0})'?$".format(MODULE_NAME)
CANNOTIMPORT_RE = r"^cannot import name '?(?P<name>{0})'?" \
r"(?: from '{1}' \(.*\))?$".format(IDENTIFIER, MODULE_NAME)
INDEXOUTOFRANGE_RE = r"^list index out of range$"
ZERO_LEN_FIELD_RE = r"^zero length field name in format$"
MATH_DOMAIN_ERROR_RE = r"^math domain error$"
TOO_MANY_VALUES_UNPACK_RE = r"^too many values " \
r"to unpack(?: \(expected \d+\))?$"
OUTSIDE_FUNCTION_RE = r"^'?(\w+)'? outside function$"
NEED_MORE_VALUES_RE = r"^(?:need more than \d+|not enough) values to unpack" \
r"(?: \(expected \d+, got \d+\))?$"
UNHASHABLE_RE = r"^(?:unhashable type: )?'({0})'" \
r"(?: objects are unhashable)?$".format(TYPE_NAME)
MISSING_PARENT_RE = r"^Missing parentheses in call to " \
r"'(?P<func>{0})'(?:. Did you mean.*)?$".format(FUNC_NAME)
INVALID_LITERAL_RE = r"^invalid literal for (\w+)\(\) with base \d+: '(.*)'$"
NB_ARG_RE = r"^(?P<func>{0})(?:\(\) takes| expected) " \
r"(?:exactly |at least |at most |from )?(?P<expected>no|\d+|\d+ to \d+) " \
r"(?:positional |non-keyword )?arguments?,? " \
r"\(?(?:but |got )?(?P<actual>\d+)" \
r"(?: were given| was given| given)?\)?" \
r"(?:\. Did you forget 'self' in the function definition\?)?" \
r"$".format(QUAL_FUNC_NAME)
MISSING_POS_ARG_RE = r"^(?P<func>{0})\(\) missing \d+ required positional " \
r"arguments?: .*$".format(QUAL_FUNC_NAME)
INVALID_SYNTAX_RE = r"^(?:invalid syntax(?:. Maybe you meant .*)?|" \
r"invalid syntax \(expected '.*'\)|" \
r"expected '.*')$"
FUNC_PARAM_CANNOT_BE_PARENTH_RE = r"^Function parameters cannot " \
r"be parenthesized$"
INVALID_COMP_RE = r"^invalid comparison$"
INVALID_TOKEN_RE = r"^invalid token$"
LEADING_ZEROS_RE = r"^leading zeros in decimal integer literals are " \
r"not permitted; use an 0o prefix for octal integers$"
EXC_GROUP_PARENTH_RE = r"^(?:exception group|multiple exception types) " \
r"must be parenthesized$"
EXPECTED_LENGTH_RE = r"^expected length (\d+), got (\d+)$"
FUTURE_FIRST_RE = r"^(?:from )?__future__ (?:imports|statements) must " \
r"(?:occur|appear) at (?:the )?beginning of (?:the )?file$"
FUTURE_FEATURE_NOT_DEF_RE = r"^future feature (\w+) is not defined$"
RESULT_TOO_MANY_ITEMS_RE = r"^(?P<func>{0})\(\) result has too many items" \
r"$".format(FUNC_NAME)
UNQUALIFIED_EXEC_RE = r"^unqualified exec is not allowed in function '{0}' " \
r"(?:because )?it" \
r" (?:is a nested function|" \
r"contains a nested function with free variables)$".format(FUNC_NAME)
IMPORTSTAR_RE = r"^import \* (?:only allowed at module level|" \
r"is not allowed in function '{0}' because it (?:is )?" \
r"(?:is a nested function|" \
r"(?:)contains a nested function with free variables))" \
r"$".format(FUNC_NAME)
UNSUPPORTED_OP_RE = r"^unsupported operand type\(s\) for (?P<op>.*): " \
r"'(?P<t1>{0})' and '(?P<t2>{0})'" \
r"$".format(TYPE_NAME)
UNSUPPORTED_OP_SUGG_RE = r"^unsupported operand type\(s\) for (?P<op>.*): " \
r"'(?P<t1>{0})' and '(?P<t2>{0})'\. Did you mean \"(?P<sugg>.*)\"\?" \
r"$".format(TYPE_NAME)
BAD_OPERAND_UNARY_RE = r"^(?:bad|unsupported) operand type for " \
r"(?:unary )?(.*): '(.*)'$"
OBJ_DOES_NOT_SUPPORT_RE = r"^\'({0})\' object (?:does not|doesn't) support " \
r"(.*)$".format(TYPE_NAME)
CANNOT_CONCAT_RE = r"^cannot concatenate '({0})' and '({0})' " \
r"objects$".format(TYPE_NAME)
ONLY_CONCAT_RE = r'^can only concatenate {0} \(not "{0}"\) ' \
r"to {0}$".format(TYPE_NAME)
CANT_CONVERT_RE = r"^Can't convert '({0})' object to ({0}) " \
r"implicitly$".format(TYPE_NAME)
MUST_BE_TYPE1_NOT_TYPE2_RE = r"^must be ({0}), not ({0})$".format(TYPE_NAME)
NOT_CALLABLE_RE = r"^'({0})' object is not callable$".format(TYPE_NAME)
DESCRIPT_REQUIRES_TYPE_RE = r"^descriptor '(\w+)' " \
r"(?:requires a|for) '({0})' " \
r"(?:object but received|objects doesn't apply to) (?:a )?" \
r"'({0})'(?:| object)$".format(TYPE_NAME)
ARG_NOT_ITERABLE_RE = r"^(?:argument of type )?'({0})'" \
r"(?: object)? is not iterable$".format(TYPE_NAME)
MUST_BE_CALLED_WITH_INST_RE = r"^unbound method (\w+)\(\) must be called " \
r"with ({0}) instance as first argument " \
r"\(got ({0}) instance instead\)$".format(TYPE_NAME)
OBJECT_HAS_NO_FUNC_RE = r"^(?:object of type )?'({0})' has no " \
r"(\w+)(?:\(\))?$".format(TYPE_NAME)
INSTANCE_HAS_NO_METH_RE = r"^({0}) instance has no " \
r"({1}) method$".format(TYPE_NAME, ATTR_NAME)
NO_BINDING_NONLOCAL_RE = r"^no binding for nonlocal '({0})' " \
r"found$".format(VAR_NAME)
NONLOCAL_AT_MODULE_RE = r"^nonlocal declaration not allowed at module level$"
UNEXPECTED_EOF_RE = r"^unexpected EOF while parsing$"
NO_SUCH_FILE_RE = r"^No such file or directory$"
TIME_DATA_DOES_NOT_MATCH_FORMAT_RE = r"^time data " \
r"(?P<timedata>.*) does not match format (?P<format>.*)$"
MAX_RECURSION_DEPTH_RE = r"^maximum recursion depth exceeded.*$"
SIZE_CHANGED_DURING_ITER_RE = r"^(\w+) changed size during iteration$"
EXC_MUST_DERIVE_FROM_RE = r"^exceptions must .*derive.*from.*BaseException.*$"
UNORDERABLE_TYPES_RE = r"^unorderable types: " \
r"{0}(?:\(\))? [<=>]+ {0}(?:\(\))?$".format(TYPE_NAME)
OP_NOT_SUPP_BETWEEN_INSTANCES_RE = r"^'[<=>]+' not supported between " \
r"instances of '{0}' and '{0}'$".format(TYPE_NAME)
ALL_REGEXPS = dict((k, v)
for k, v in dict(locals()).items()
if k.endswith('_RE'))
def match(pattern, string):
"""Wrap function from the re module.
Wrapper around re.match to be able to import this module as re
without having name collisions.
"""
return re.match(pattern, string)
if __name__ == '__main__':
for name, val in ALL_REGEXPS.items():
if not (val.startswith('^') and val.endswith('$')):
print("Missing ^$ for ", name)