def test_type_filter_nonempty_disjoint(self): self.assertEqual( base_matchers.AnyOf( base_matchers.TypeIs(int), base_matchers.TypeIs(float), ).type_filter, frozenset({int, float}), )
def test_multi_bind_first(self): self.assertEqual( base_matchers.AnyOf(base_matchers.Bind('foo'), base_matchers.Bind('bar'), _NOTHING).match(_FAKE_CONTEXT, 1), matcher.MatchInfo( match.ObjectMatch(1), {'foo': matcher.BoundValue(match.ObjectMatch(1))}))
def test_type_filter_skipped_micro(self): """Matchers are skipped if they do not match the type filter.""" m = base_matchers.AnyOf( base_matchers.AllOf( base_matchers.TestOnlyRaise('this should be skipped'), base_matchers.TypeIs(float)), base_matchers.TypeIs(int), ) self.assertIsNotNone(m.match(_FAKE_CONTEXT, 4))
def test_type_filter_ordered(self): """Tests that type optimizations don't mess with matcher order.""" m = base_matchers.AnyOf( base_matchers.Bind('a', base_matchers.Anything()), base_matchers.Bind('b', base_matchers.TypeIs(int)), ) self.assertEqual( m.match(_FAKE_CONTEXT, 4).bindings.keys(), {'a'}, )
def _matcher(self): kwargs = {'body': self._body} # We check for the existence of `returns` as an AST field, instead of # checking the Python version, to support backports of the type annotation # syntax to Python 2. if 'returns' in attr.fields_dict(ast_matchers.FunctionDef): kwargs['returns'] = self._returns function_def = ast_matchers.FunctionDef(**kwargs) if six.PY3: function_def = base_matchers.AnyOf( ast_matchers.AsyncFunctionDef(**kwargs), function_def, ) return function_def
def _in_exception_handler(identifier, on_conflict): """Returns a matcher for a node in the nearest ancestor `except` & binds `identifier`. Args: identifier: Name of variable to bind the identifier in the nearest ancestor exception handler to on_conflict: BindConflict strategy for binding the identifier """ return syntax_matchers.HasFirstAncestor( ast_matchers.ExceptHandler(), ast_matchers.ExceptHandler(name=base_matchers.AnyOf( # In PY2, the name is a `Name` but in PY3 just a # string. # So rather than capturing and merging the Name # nodes, we capture and merge the actual string # identifier. ast_matchers.Name( id=base_matchers.Bind(identifier, on_conflict=on_conflict)), base_matchers.Bind(identifier, on_conflict=on_conflict), )))
matcher=matcher, replacement=replacement, **kwargs) def _function_containing(matcher): """Returns a ast_matchers matcher for a function where any statement in the body matches `matcher`.""" return syntax_matchers.NamedFunctionDefinition(body=base_matchers.Contains( syntax_matchers.IsOrHasDescendant(matcher))) # Matches any function returning Optional[T] for some T. _IN_FUNCTION_RETURNING_OPTIONAL = syntax_matchers.InNamedFunction( syntax_matchers.NamedFunctionDefinition(returns=base_matchers.AnyOf( syntax_matchers.ExprPattern('Optional[$_]'), syntax_matchers.ExprPattern('typing.Optional[$_]'), # TODO: May want to also include Union[None, ...]. # TODO: match type comments as well. ))) # Matches any returning that's not "return" or "return None" (which are two # different ast node values: ast.Return(value=None) and # ast.Return(value=ast.Name(id='None')) respectively) _NON_NONE_RETURN = matcher_.DebugLabeledMatcher( 'Non-none return', ast_matchers.Return(value=base_matchers.Unless( base_matchers.AnyOf(base_matchers.Equals(None), syntax_matchers.ExprPattern('None'))))) _NONE_RETURNS_FIXERS = [ fixer.SimplePythonFixer( message=
def test_type_filter_empty(self): self.assertEqual(base_matchers.AnyOf().type_filter, frozenset())
def matcher_default(self): return base_matchers.AnyOf(*(fixer.matcher_with_meta for fixer in self.fixers))