Bowler

Bowler

  • Getting Started
  • API Reference
  • Roadmap
  • Contribute
  • Github

›API Reference

Basics

  • Introduction
  • Refactoring
  • Setup
  • Usage

API Reference

  • Queries
  • Selectors
  • Filters
  • Modifiers
  • CLI Commands

Contributing

  • Developing Bowler
  • Roadmap to the Future

Selectors

Selectors are defined using the lib2to3 pattern syntax to search the syntax tree for elements matching that pattern, and capturing specific nested nodes when matches are found. Patterns can be nested, with alternate branches, allowing arbitrarily complex matching.

Pattern Syntax

Selector patterns follow a very simple syntax, as defined in the lib2to3 pattern grammar. Matching elements of the Python grammar is done by listing the grammar element, optionally followed by angle brackets containing nested match expressions. The any keyword can be used to match grammar elements, regardless of their type, while * denotes elements that repeat zero or more times.

Make sure to include necessary string literal tokens when using nested expressions, and any* to match remaining grammar elements.

# any* does not capture the '=' string literal
expr_stmt<
    attr_name='{name}' attr_value=any*
>
# but declare '(' and ')' string literals to differentiate from '[' and ']'
trailer< '(' function_arguments=any* ')' >

Example pattern to match class definitions that contain a function definition (the "suite" denotes the body of the class definition):

PATTERN = """
    classdef<
        any*
        suite<
            any* funcdef any*
        >
    >
"""

The root element of the expression is what will be passed to filters and modifiers by default when matched. Capturing nested elements is done by preceding elements in the expressions with the desired name and an equals sign – these elements will then show up in the Capture argument to filters and modifiers. Square brackets can denote optional (zero or one) elements.

Building on the example above, we can capture the defined classname, any ancestors, and the function name:

PATTERN = """
    classdef<
        "class" name=NAME ["(" [ancestors=arglist] ")"] ":"
        suite<
            any*
            funcdef< "def" func_name=NAME any* >
            any*
        >
    >
"""

To capture multiple possible arrangements of grammar elements, the | can be used with parentheses to combine expressions. You can reuse capture names for each expression, and you can further nest alternative expressions.

To find both function definitions and function calls in a single selector:

PATTERN = """
    (
        funcdef< "def" name=NAME "(" [args=typedargslist] ")" any* >
    |
        power< name=NAME trailer< "(" [args=arglist] ")" > any* >
    )
"""

Selector Reference

All selectors are accessed as methods on the Query class:

  • .select()
  • .select_root()
  • .select_module()
  • .select_class()
  • .select_subclass()
  • .select_attribute()
  • .select_method()
  • .select_function()
  • .select_var()

Note: Bowler's API is still in a "provisional" phase. The core concepts will likely stay the same, but individual method signatures may change as the tool matures or gains new functionality.

.select()

Supply a custom selector pattern as the given string, and auto-format it with any supplied keyword arguments. Captures are defined by the supplied pattern.

query.select(pattern: str, **kwargs: str)

.select_root()

Select only the root node of the syntax tree, the file_input node. No captures.

query.select_root()

.select_module()

Select specified modules when imported and referenced.

query.select_module(name: str)
CaptureDescriptionExampleMatch
module_accessAttributes accessedfoo.bar()bar
module_importsAttributes importedfrom foo import bar[bar]
module_nameName of moduleimport foofoo
module_nicknameNickname at importimport foo as barbar

.select_class()

Select specified classes when imported, defined, subclassed, or instantiated.

query.select_class(name: str)
CaptureDescriptionExampleMatch
class_argumentsArguments of instantiationFoo(bar)bar
class_callClass being instantiatedFoo()Foo
class_defRoot of the class definitionclass Foo:class
class_importRoot of the importfrom foo import Barfrom
class_nameName of classclass Bar(Foo):Bar
class_subclassRoot of the subclass definitionclass Bar(Foo):class

.select_subclass()

Select subclasses of specified classes when defined.

query.select_subclass(name: str)
CaptureDescriptionExampleMatch
class_ancestorName of ancestor classclass Bar(Foo):Foo
class_defRoot of the class definitionclass Bar(Foo):class
class_nameName of classclass Bar(Foo):Bar

.select_attribute()

Select specified class attributes when defined, assigned, or accessed.

query.select_attribute(name: str)
CaptureDescriptionExampleMatch
attr_classRoot of class definitionn/an/a
attr_accessAttribute accessvalue = self.foovalue
attr_assignmentAttribute assignmentself.foo = 42self.foo
attr_nameName of attributeself.foo = 42foo
attr_valueValue of attributeself.foo = 4242

.select_method()

Select specified class methods when defined or called.

query.select_method(name: str)
CaptureDescriptionExampleMatch
decoratorsMethod decorators@classmethod@classmethod
function_argumentsMethod argumentsdef foo(self):[self]
function_callMethod invocationfoo.bar()foo
function_defMethod definitiondef foo(self):def
function_nameMethod namedef foo(self):foo

.select_function()

Select specified functions when imported, defined, or called.

query.select_function(name: str)
CaptureDescriptionExampleMatch
decoratorsFunction decorators@wraps@wraps
function_argumentsFunction argumentsdef foo(a, b):[a, b]
function_callFunction invocationfoo()foo
function_defFunction definitiondef foo(self):def
function_importFunction importfrom foo import barfrom
function_nameFunction namedef foo(self):foo

.select_var()

Select arbitrary names when assigned or referenced.

query.select_var(name: str)
CaptureDescriptionExampleMatch
var_assignmentVariable assignmentfoo = 42foo = 42
var_nameVariable namefoo = 42foo
var_valueAssignment valuefoo = 4242
← QueriesFilters →
  • Pattern Syntax
  • Selector Reference
    • .select()
    • .select_root()
    • .select_module()
    • .select_class()
    • .select_subclass()
    • .select_attribute()
    • .select_method()
    • .select_function()
    • .select_var()
Facebook Open SourcePrivacyTermsNewsTwitterGitHubContribute to BowlerBowler
Copyright © 2022 Facebook Inc.