forked from pyta-uoft/pyta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpyta.py
64 lines (49 loc) · 1.91 KB
/
pyta.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Python Teaching Assistant
The goal of this module is to provide automated feedback to students in our
introductory Python courses, using static analysis of their code.
To run the checker, call the check function on the name of the module to check.
> import pyta
> pyta.check('mymodule')
"""
import importlib.util
import pylint.lint as lint
from pylint.reporters import BaseReporter
import webbrowser
import os
from urllib.request import pathname2url
# Local version of website; will be updated later.
HELP_URL = 'file:' + pathname2url(os.path.abspath('website/index.html'))
def check(module_name):
"""Check a module for errors, printing a report.
The name of the module should be passed in as a string,
without a file extension (.py).
"""
spec = importlib.util.find_spec(module_name)
reporter = PyTAReporter()
linter = lint.PyLinter(reporter=reporter)
linter.load_default_plugins()
linter.load_plugin_modules(['checkers'])
linter.check([spec.origin])
reporter.print_message_ids()
def doc(msg_id):
"""Open a webpage explaining the error for the given message."""
msg_url = HELP_URL + '#' + msg_id
print('Opening {} in a browser.'.format(msg_url))
webbrowser.open(msg_url)
class PyTAReporter(BaseReporter):
def __init__(self):
super().__init__(self)
self._messages = []
def handle_message(self, msg):
"""Handle a new message triggered on the current file."""
self._messages.append(msg)
def print_message_ids(self):
# Sort the messages by their type.
self._messages.sort(key=lambda s: s[0])
for msg in self._messages:
if msg.msg_id.startswith('E'):
# Error codes appear in red
code = '\033[1;31m' + msg.msg_id + '\033[0m:'
else:
code = '\033[1m' + msg.msg_id + '\033[0m:'
print(code, '({})\n {}'.format(msg.symbol, msg.msg))