Skip to content

Commit

Permalink
ending-locations: Register transformer as pylint plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
david-yz-liu committed Dec 9, 2021
1 parent bf441d7 commit fee49b4
Show file tree
Hide file tree
Showing 5 changed files with 9 additions and 55 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
(`$ python -m python_ta.contracts FILE`)
- Added two new command line interfaces. User can print out the default PythonTA configuration file in the command line using `python -m python_ta -g` and can specify the output format of the reporter using `python -m python_ta --output-format FILE`.
- Updated to Pylint v2.12. See "New checks" below for the new checkers enabled by default.
- Register ending location setter as pylint plugin.

### Bug fixes

Expand Down
1 change: 1 addition & 0 deletions python_ta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ def reset_linter(config=None, file_linted=None):
linter = pylint.lint.PyLinter(options=new_checker_options)
linter.load_default_plugins() # Load checkers, reporters
linter.load_plugin_modules(custom_checkers)
linter.load_plugin_modules(["python_ta.transforms.setendings"])

if isinstance(config, str) and config != "":
# Use config file at the specified path instead of the default.
Expand Down
3 changes: 1 addition & 2 deletions python_ta/patches/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
from .checkers import patch_checkers
from .error_messages import patch_error_messages
from .messages import patch_linter_transform, patch_messages
from .messages import patch_messages
from .transforms import patch_ast_transforms


Expand All @@ -11,5 +11,4 @@ def patch_all():
patch_checkers()
patch_ast_transforms()
patch_messages()
patch_linter_transform()
patch_error_messages()
20 changes: 0 additions & 20 deletions python_ta/patches/messages.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
"""Patch pylint message-handling behaviour."""
from astroid.transforms import TransformVisitor
from pylint.interfaces import UNDEFINED
from pylint.lint import PyLinter

from python_ta.transforms.setendings import register_transforms


def patch_messages():
"""Patch PyLinter to pass the node to reporter."""
Expand All @@ -30,20 +27,3 @@ def new_add_message(
self.reporter.handle_node(msg_info, node)

PyLinter.add_message = new_add_message


def patch_linter_transform():
"""Patch PyLinter class to apply message transform with source code."""
old_get_ast = PyLinter.get_ast

def new_get_ast(self, filepath, modname):
ast = old_get_ast(self, filepath, modname)
if ast is not None:
with open(filepath, encoding="utf-8") as f:
source_code = f.readlines()
ending_transformer = TransformVisitor()
register_transforms(source_code, ending_transformer)
ending_transformer.visit(ast)
return ast

PyLinter.get_ast = new_get_ast
39 changes: 6 additions & 33 deletions python_ta/transforms/setendings.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,43 +647,16 @@ def h(node):

# Make this module a pylint plugin
def register(linter):
"""Patch linter to apply message transform with source code."""
old_get_ast = linter.get_ast

def new_get_ast(filepath, modname):
ast = old_get_ast(filepath, modname)
with open(filepath) as f:
source_code = f.readlines()
ending_transformer = TransformVisitor()
register_transforms(source_code, ending_transformer)
ending_transformer.visit(ast)
if ast is not None:
with open(filepath, encoding="utf-8") as f:
source_code = f.readlines()
ending_transformer = init_register_ending_setters(source_code)
ending_transformer.visit(ast)
return ast

linter.get_ast = new_get_ast


def register_transforms(source_code, obj):
# Check consistency of astroid-provided fromlineno and col_offset attributes.
for node_class in nodes.ALL_NODE_CLASSES:
obj.register_transform(
node_class,
fix_start_attributes,
lambda node: (
getattr(node, "fromlineno", None) is None
or getattr(node, "col_offset", None) is None
),
)

# Ad hoc transformations
obj.register_transform(nodes.Arguments, fix_arguments(source_code))

for node_class in NODES_WITH_CHILDREN:
obj.register_transform(node_class, set_from_last_child)
for node_class in NODES_WITHOUT_CHILDREN:
obj.register_transform(node_class, set_without_children)

# Nodes where the source code must also be provided.
for node_class, start_pred, end_pred in NODES_REQUIRING_SOURCE:
if start_pred is not None:
obj.register_transform(node_class, start_setter_from_source(source_code, start_pred))
if end_pred is not None:
obj.register_transform(node_class, end_setter_from_source(source_code, end_pred))

0 comments on commit fee49b4

Please sign in to comment.