• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pyta-uoft / pyta / 23815219921

30 Mar 2026 07:28PM UTC coverage: 90.003% (+0.02%) from 89.987%
23815219921

Pull #1297

github

web-flow
Merge 9d2d5da4f into b7941c915
Pull Request #1297: Fix accumulating memory issue

4 of 4 new or added lines in 1 file covered. (100.0%)

2 existing lines in 1 file now uncovered.

3484 of 3871 relevant lines covered (90.0%)

17.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.15
/packages/python-ta/src/python_ta/__init__.py
1
"""Python Teaching Assistant
2

3
The goal of this module is to provide automated feedback to students in our
4
introductory Python courses, using static analysis of their code.
5

6
To run the checker, call the check function on the name of the module to check.
7

8
> import python_ta
9
> python_ta.check_all('mymodule.py')
10

11
Or, put the following code in your Python module:
12

13
if __name__ == '__main__':
14
    import python_ta
15
    python_ta.check_all()
16
"""
17

18
from __future__ import annotations
20✔
19

20
import gc
20✔
21
from importlib.metadata import version
20✔
22

23
__version__ = version("python-ta")
20✔
24

25
# First, remove underscore from builtins if it has been bound in the REPL.
26
# Must appear before other imports from pylint/python_ta.
27
import builtins
20✔
28

29
try:
20✔
30
    del builtins._
20✔
31
except AttributeError:
20✔
32
    pass
20✔
33

34

35
import logging
20✔
36
import webbrowser
20✔
37
from typing import IO, TYPE_CHECKING, Any, Literal, Optional, Union
20✔
38

39
from .check.helpers import (
20✔
40
    check_file,
41
    get_file_paths,
42
    get_valid_files_to_check,
43
    setup_linter,
44
    upload_linter_results,
45
    verify_pre_check,
46
)
47

48
if TYPE_CHECKING:
49
    from .reporters.core import PythonTaReporter
50

51
HELP_URL = "http://www.cs.toronto.edu/~david/pyta/checkers/index.html"
20✔
52

53

54
def check_errors(
20✔
55
    module_name: Union[list[str], str] = "",
56
    config: Union[dict[str, Any], str] = "",
57
    output: Optional[Union[str, IO]] = None,
58
    load_default_config: bool = True,
59
    autoformat: Optional[bool] = False,
60
    on_verify_fail: Literal["log", "raise"] = "log",
61
) -> PythonTaReporter:
62
    """Check a module for errors, printing a report."""
63
    return _check(
20✔
64
        module_name=module_name,
65
        level="error",
66
        local_config=config,
67
        output=output,
68
        load_default_config=load_default_config,
69
        autoformat=autoformat,
70
        on_verify_fail=on_verify_fail,
71
    )
72

73

74
def check_all(
20✔
75
    module_name: Union[list[str], str] = "",
76
    config: Union[dict[str, Any], str] = "",
77
    output: Optional[Union[str, IO]] = None,
78
    load_default_config: bool = True,
79
    autoformat: Optional[bool] = False,
80
    on_verify_fail: Literal["log", "raise"] = "log",
81
) -> PythonTaReporter:
82
    """Analyse one or more Python modules for code issues and display the results.
83

84
    Args:
85
        module_name:
86
            If an empty string (default), the module where this function is called is checked.
87
            If a non-empty string, it is interpreted as a path to a single Python module or a
88
            directory containing Python modules. If the latter, all Python modules in the directory
89
            are checked.
90
            If a list of strings, each string is interpreted as a path to a module or directory,
91
            and all modules across all paths are checked.
92
        config:
93
            If a string, a path to a configuration file to use.
94
            If a dictionary, a map of configuration options (each key is the name of an option).
95
        output:
96
            If a string, a path to a file to which the PythonTA report is written.
97
            If a typing.IO object, the report is written to this stream.
98
            If None, the report is written to standard out or automatically displayed in a
99
            web browser, depending on which reporter is used.
100
        load_default_config:
101
            If True (default), additional configuration passed with the ``config`` option is
102
            merged with the default PythonTA configuration file.
103
            If False, the default PythonTA configuration is not used.
104
        autoformat:
105
            If True, autoformat all modules using the black formatting tool before analyzing code.
106
        on_verify_fail:
107
            Determines how to handle files that cannot be checked. If set to "log" (default), an error
108
            message is logged and execution continues. If set to "raise", an error is raised immediately to stop
109
            execution.
110

111
    Returns:
112
        The ``PythonTaReporter`` object that generated the report.
113
    """
114
    reporter = _check(
20✔
115
        module_name=module_name,
116
        level="all",
117
        local_config=config,
118
        output=output,
119
        load_default_config=load_default_config,
120
        autoformat=autoformat,
121
        on_verify_fail=on_verify_fail,
122
    )
123
    reporter.linter.msgs_store.get_message_definitions.cache_clear()
20✔
124
    gc.collect()
20✔
125
    return reporter
20✔
126

127

128
def _check(
20✔
129
    module_name: Union[list[str], str] = "",
130
    level: str = "all",
131
    local_config: Union[dict[str, Any], str] = "",
132
    output: Optional[Union[str, IO]] = None,
133
    load_default_config: bool = True,
134
    autoformat: Optional[bool] = False,
135
    on_verify_fail: Literal["log", "raise"] = "log",
136
) -> PythonTaReporter:
137
    """Check a module for problems, printing a report.
138

139
    The `module_name` can take several inputs:
140
      - string of a directory, or file to check (`.py` extension optional).
141
      - list of strings of directories or files -- can have multiple.
142
      - no argument -- checks the python file containing the function call.
143
    `level` is used to specify which checks should be made.
144
    `local_config` is a dict of config options or string (config file name).
145
    `output` is an absolute or relative path to a file, or a typing.IO object to capture pyta data
146
    output. If None, stdout is used.
147
    `load_default_config` is used to specify whether to load the default .pylintrc file that comes
148
    with PythonTA. It will load it by default.
149
    `autoformat` is used to specify whether the black formatting tool is run. It is not run by default.
150
    `on_verify_fail` determines how to handle files that cannot be checked. If set to "log" (default), an error
151
     message is logged and execution continues. If set to "raise", an error is raised immediately to stop execution.
152
    """
153
    # Configuring logger
154
    logging.basicConfig(format="[%(levelname)s] %(message)s", level=logging.INFO)
20✔
155
    linter, current_reporter = setup_linter(local_config, load_default_config, output)
20✔
156
    try:
20✔
157
        # Flag indicating whether at least one file has been checked
158
        is_any_file_checked = False
20✔
159
        linted_files = set()
20✔
160
        f_paths = []  # Paths to files for data submission
20✔
161
        for locations in get_valid_files_to_check(module_name):
20✔
162
            f_paths = []
20✔
163
            for file_py in get_file_paths(locations):
20✔
164
                linted_files.add(file_py)
20✔
165
                if not verify_pre_check(
20✔
166
                    file_py,
167
                    linter.config.allow_pylint_comments,
168
                    on_verify_fail=on_verify_fail,
169
                ):
170
                    # The only way to reach this is if verify_pre_check returns False, and `on_verify_fail="log"`.
171
                    continue
20✔
172
                is_any_file_checked, linter = check_file(
20✔
173
                    file_py=file_py,
174
                    local_config=local_config,
175
                    load_default_config=load_default_config,
176
                    autoformat=autoformat,
177
                    is_any_file_checked=is_any_file_checked,
178
                    current_reporter=current_reporter,
179
                    f_paths=f_paths,
180
                )
181
                current_reporter = linter.reporter
20✔
182
                current_reporter.print_messages(level)
20✔
183
            upload_linter_results(linter, current_reporter, f_paths, local_config)
20✔
184
        # Only generate reports (display the webpage) if there were valid files to check
185
        if is_any_file_checked:
20✔
186
            linter.generate_reports()
20✔
187
            if linter.config.watch:
20✔
188
                # import only when needed to avoid dragging in watchdog
UNCOV
189
                from .check.watch import watch_files
×
190

UNCOV
191
                watch_files(
×
192
                    file_paths=linted_files,
193
                    level=level,
194
                    local_config=local_config,
195
                    load_default_config=load_default_config,
196
                    autoformat=autoformat,
197
                    linter=linter,
198
                    f_paths=f_paths,
199
                )
200

201
        return current_reporter
20✔
202
    except Exception as e:
20✔
203
        logging.error(
20✔
204
            "Unexpected error encountered! Please report this to your instructor (and attach the code that caused the error)."
205
        )
206
        logging.error('Error message: "{}"'.format(e))
20✔
207
        raise e
20✔
208

209

210
def doc(msg_id: str) -> None:
20✔
211
    """Open the PythonTA documentation page for the given error message id.
212

213
    Args:
214
        msg_id: The five-character error code, e.g. ``"E0401"``.
215
    """
216
    msg_url = HELP_URL + "#" + msg_id.lower()
20✔
217
    print("Opening {} in a browser.".format(msg_url))
20✔
218
    webbrowser.open(msg_url)
20✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc