Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable pytype for a couple of things in fix. #53

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions refex/python/matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,7 @@ def _coerce_list(values):
_IS_SUBMATCHER_LIST_ATTRIB = __name__ + '._IS_SUBMATCHER_LIST_ATTRIB'


def submatcher_attrib(
*args,
**kwargs: Any): # TODO: make walk a kwarg when Py2 support is dropped.
def submatcher_attrib(*args, walk: bool = True, **kwargs: Any):
"""Creates an attr.ib that is marked as a submatcher.

This will cause the matcher to be automatically walked as part of the
Expand All @@ -199,15 +197,13 @@ def submatcher_attrib(
Returns:
An attr.ib()
"""
if kwargs.pop('walk', True):
if walk:
kwargs.setdefault('metadata', {})[_IS_SUBMATCHER_ATTRIB] = True
kwargs.setdefault('converter', coerce)
return attr.ib(*args, **kwargs)


def submatcher_list_attrib(
*args,
**kwargs: Any): # TODO: make walk a kwarg when Py2 support is dropped.
def submatcher_list_attrib(*args, walk: bool = True, **kwargs: Any):
"""Creates an attr.ib that is marked as an iterable of submatchers.

This will cause the matcher to be automatically walked as part of the
Expand All @@ -222,7 +218,7 @@ def submatcher_list_attrib(
Returns:
An attr.ib()
"""
if kwargs.pop('walk', True):
if walk:
kwargs.setdefault('metadata', {})[_IS_SUBMATCHER_LIST_ATTRIB] = True
kwargs.setdefault('converter', _coerce_list)
return attr.ib(*args, **kwargs)
Expand Down Expand Up @@ -666,8 +662,8 @@ class MatchInfo(object):
"""
match = attr.ib(type=_match.Match)
# TODO: also add a top-level `replacement` variable, replacing the magic root.
bindings = attr.ib(factory=dict, type=Dict[str, _match.Match])
replacements = attr.ib(factory=dict, type=Dict[str, _match.Match])
bindings = attr.ib(factory=dict, type=Dict[str, BoundValue])
replacements = attr.ib(factory=dict, type=Dict[str, formatting.Template])


def _stringify_candidate(context, candidate):
Expand Down
4 changes: 2 additions & 2 deletions refex/python/syntactic_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ class _BasePythonTemplate(formatting.Template):
template: The source template
"""
template = attr.ib(type=Text)
_lexical_template = attr.ib(repr=False, init=False) # type: _LexicalTemplate
_ast_matcher = attr.ib(repr=False, init=False) # type: matcher.Matcher
_lexical_template = attr.ib(repr=False, init=False, type=_LexicalTemplate)
_ast_matcher = attr.ib(repr=False, init=False, type=matcher.Matcher)

def __attrs_post_init__(self):
if not isinstance(self.template, six.text_type):
Expand Down
15 changes: 8 additions & 7 deletions refex/rxerr_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,19 @@ def main(argv):
source = failure['content']
except KeyError:
pass
with tempfile.NamedTemporaryFile(
mode='w', encoding='utf-8', suffix='.py', delete=False) as out_f:
out_f.write(source)
print('Content:', out_f.name)
else:
with tempfile.NamedTemporaryFile(
mode='w', encoding='utf-8', suffix='.py', delete=False) as out_f:
out_f.write(source)
print('Content:', out_f.name)
try:
tb = failure['traceback']
except KeyError:
pass
else:
print(
pygments.highlight(tb, lexers.PythonTracebackLexer(),
formatters.Terminal256Formatter()))
lexer = lexers.PythonTracebackLexer() # pytype: disable=module-attr
formatter = formatters.Terminal256Formatter() # pytype: disable=module-attr
print(pygments.highlight(tb, lexer, formatter))


if __name__ == '__main__':
Expand Down
14 changes: 6 additions & 8 deletions refex/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ class CombinedSearcher(AbstractSearcher):
# could walk once and only run the searchers that could possibly match
# at a given point using an O(1) type lookup -- which would generally cut
# down the number of results.
searchers = attr.ib(type=Tuple[AbstractSearcher, ...], converter=tuple,)
searchers = attr.ib(type=Sequence[AbstractSearcher], converter=tuple)

def parse(self, data: Text, filename: str):
"""Parses using each sub-searcher, returning the most specific parsed file.
Expand Down Expand Up @@ -630,7 +630,7 @@ def find_dicts_parsed(
def key_span_for_dict(
self,
parsed: parsed_file.ParsedFile,
match_dict: Iterable[Mapping[MatchKey, match.Match]],
match_dict: Mapping[MatchKey, match.Match],
) -> Optional[Tuple[int, int]]:
"""Returns the ``key_span`` that the final ``Substitution`` will have."""
return None
Expand Down Expand Up @@ -682,12 +682,10 @@ def __attrs_post_init__(self):
missing_labels = formatting.template_variables(
self.templates) - pattern_labels
if missing_labels:
groups = ', '.join(f'`{g}`' for g in sorted(map(str, missing_labels)))
raise ValueError(
'The substitution template(s) referenced groups not available in the regex (`{self._compiled.pattern}`): {groups}'
.format(
self=self,
groups=', '.join(
'`{}`'.format(g) for g in sorted(map(str, missing_labels)))))
f'The substitution template(s) referenced groups not available in the regex (`{self._compiled.pattern}`): {groups}'
)

@classmethod
def from_pattern(cls, pattern: str, templates: Optional[Dict[str, formatting.Template]]):
Expand Down Expand Up @@ -734,7 +732,7 @@ class BasePythonRewritingSearcher(BasePythonSearcher, BaseRewritingSearcher):
_matcher = attr.ib()

@classmethod
def from_matcher(cls, matcher, templates: Optional[Dict[str, formatting.Template]]):
def from_matcher(cls, matcher, templates: Dict[str, formatting.Template]):
"""Creates a searcher from an evaluated matcher, and adds a root label."""
# We wrap the evaluated matcher in a SystemBind() that is sort of like
# "group 0" for regexes.
Expand Down
2 changes: 1 addition & 1 deletion refex/substitution.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def _validate(self):
expected_type=six.text_type.__name__,
actual_type=type(replacement).__name__))

def relative_to_span(self, start: int, end: int) -> "Substitution":
def relative_to_span(self, start: int, end: int) -> Optional['Substitution']:
"""Returns a new substitution that is offset relative to the provided span.

If ``sub`` is a :class:`Substitution` for ``s``, then
Expand Down
18 changes: 18 additions & 0 deletions refex/test_rxerr_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ def test_argv(self):
# Instead, we can just run shlex.split() over it as a quick safety check.
self.assertEqual(shlex.split(stdout.getvalue()), ['Command:'] + argv)

def test_traceback(self):
"""Tests that the traceback shows up, ish."""
tb = ('Traceback (most recent call last):\n'
' File "<stdin>", line 1, in <module>\n'
'SomeError: description\n')
path = self.create_tempfile(
content=json.dumps({'failures': {
'path': {
'traceback': tb
}
}})).full_path
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
rxerr_debug.main(['rxerr_debug', path])
stdout = stdout.getvalue()
self.assertIn('SomeError', stdout)
self.assertIn('description', stdout)


if __name__ == '__main__':
absltest.main()