python-ta 2.8.0__tar.gz → 2.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_ta-2.8.0/python_ta.egg-info → python_ta-2.9.0}/PKG-INFO +162 -159
- {python_ta-2.8.0 → python_ta-2.9.0}/README.md +1 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/pyproject.toml +6 -4
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/__init__.py +10 -11
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/__main__.py +4 -2
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/cfg/cfg_generator.py +26 -7
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/cfg/graph.py +86 -36
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/cfg/visitor.py +2 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/global_variables_checker.py +3 -2
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/inconsistent_or_missing_returns_checker.py +20 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/invalid_name_checker.py +11 -9
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/one_iteration_checker.py +24 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/possibly_undefined_checker.py +31 -8
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/pycodestyle_checker.py +2 -2
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/redundant_assignment_checker.py +64 -15
- python_ta-2.9.0/python_ta/checkers/unmentioned_parameter_checker.py +54 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/unnecessary_indexing_checker.py +4 -2
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/config/.pylintrc +2 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/contracts/__init__.py +92 -17
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/contracts/__main__.py +6 -4
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/debug/__init__.py +1 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/debug/snapshot.py +53 -6
- python_ta-2.9.0/python_ta/debug/snapshot_tracer.py +181 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/patches/__init__.py +2 -2
- python_ta-2.9.0/python_ta/patches/transforms.py +36 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/core.py +7 -5
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/json_reporter.py +4 -3
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/node_printers.py +3 -3
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/plain_reporter.py +2 -2
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/stat_reporter.py +1 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/transforms/z3_visitor.py +7 -5
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/upload.py +5 -3
- python_ta-2.9.0/python_ta/util/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/utils.py +0 -11
- python_ta-2.9.0/python_ta/z3/__init__.py +0 -0
- python_ta-2.8.0/python_ta/transforms/ExprWrapper.py → python_ta-2.9.0/python_ta/z3/z3_parser.py +27 -33
- {python_ta-2.8.0 → python_ta-2.9.0/python_ta.egg-info}/PKG-INFO +162 -159
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/SOURCES.txt +4 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/not-zip-safe +1 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/requires.txt +5 -3
- {python_ta-2.8.0 → python_ta-2.9.0}/setup.cfg +4 -4
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_check.py +1 -9
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_examples.py +10 -7
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_init_logging.py +0 -12
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_setendings.py +19 -19
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_subclass_contracts.py +2 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_validate_invariants.py +2 -0
- python_ta-2.8.0/python_ta/patches/transforms.py +0 -21
- python_ta-2.8.0/python_ta/transforms/__init__.py +0 -1
- {python_ta-2.8.0 → python_ta-2.9.0}/LICENSE +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/MANIFEST.in +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/cfg/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/forbidden_import_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/forbidden_io_function_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/forbidden_python_syntax_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/invalid_for_target_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/invalid_range_index_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/missing_space_in_doctest_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/shadowing_in_comprehension_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/top_level_code_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/checkers/type_annotation_checker.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/config/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/config/messages_config.toml +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/debug/accumulation_table.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/debug/recursion_table.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/patches/checkers.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/patches/error_messages.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/patches/messages.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/color_reporter.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/html_reporter.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/templates/jquery-3.7.1.slim.min.js +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/templates/pyta_logo_markdown.png +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/templates/script.js +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/templates/stylesheet.css +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/reporters/templates/template.html.jinja +0 -0
- {python_ta-2.8.0/python_ta/util → python_ta-2.9.0/python_ta/transforms}/__init__.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/transforms/setendings.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta/util/tree.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/dependency_links.txt +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/entry_points.txt +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/python_ta.egg-info/top_level.txt +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/setup.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_black.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_main.py +0 -0
- {python_ta-2.8.0 → python_ta-2.9.0}/tests/test_z3_visitor.py +0 -0
|
@@ -1,159 +1,162 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: python-ta
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary: Code checking tool for teaching Python
|
|
5
|
-
Author-email: David Liu <david@cs.toronto.edu>
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/pyta-uoft/pyta
|
|
8
|
-
Project-URL: Documentation, https://www.cs.toronto.edu/~david/pyta/
|
|
9
|
-
Project-URL: Repository, https://github.com/pyta-uoft/pyta.git
|
|
10
|
-
Project-URL: Changelog, https://github.com/pyta-uoft/pyta/blob/master/CHANGELOG.md
|
|
11
|
-
Requires-Python: >=3.
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: astroid~=3.
|
|
15
|
-
Requires-Dist: click<9,>=8.0.1
|
|
16
|
-
Requires-Dist: colorama~=0.4.6
|
|
17
|
-
Requires-Dist: jinja2~=3.1.2
|
|
18
|
-
Requires-Dist: pycodestyle~=2.11
|
|
19
|
-
Requires-Dist: pygments<2.19,>=2.14
|
|
20
|
-
Requires-Dist: pylint~=3.
|
|
21
|
-
Requires-Dist: requests<2.33,>=2.28
|
|
22
|
-
Requires-Dist: six
|
|
23
|
-
Requires-Dist: tabulate~=0.9.0
|
|
24
|
-
Requires-Dist: toml~=0.10.2
|
|
25
|
-
Requires-Dist: typeguard<5,>=4.1.0
|
|
26
|
-
Requires-Dist: wrapt<2,>=1.15.0
|
|
27
|
-
Requires-Dist: black
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist: pytest
|
|
35
|
-
Requires-Dist: pytest-cov<
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Provides-Extra:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
PyTA
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
For
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
>>> python_ta.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: python-ta
|
|
3
|
+
Version: 2.9.0
|
|
4
|
+
Summary: Code checking tool for teaching Python
|
|
5
|
+
Author-email: David Liu <david@cs.toronto.edu>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pyta-uoft/pyta
|
|
8
|
+
Project-URL: Documentation, https://www.cs.toronto.edu/~david/pyta/
|
|
9
|
+
Project-URL: Repository, https://github.com/pyta-uoft/pyta.git
|
|
10
|
+
Project-URL: Changelog, https://github.com/pyta-uoft/pyta/blob/master/CHANGELOG.md
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: astroid~=3.3.5
|
|
15
|
+
Requires-Dist: click<9,>=8.0.1
|
|
16
|
+
Requires-Dist: colorama~=0.4.6
|
|
17
|
+
Requires-Dist: jinja2~=3.1.2
|
|
18
|
+
Requires-Dist: pycodestyle~=2.11
|
|
19
|
+
Requires-Dist: pygments<2.19,>=2.14
|
|
20
|
+
Requires-Dist: pylint~=3.3.1
|
|
21
|
+
Requires-Dist: requests<2.33,>=2.28
|
|
22
|
+
Requires-Dist: six
|
|
23
|
+
Requires-Dist: tabulate~=0.9.0
|
|
24
|
+
Requires-Dist: toml~=0.10.2
|
|
25
|
+
Requires-Dist: typeguard<5,>=4.1.0
|
|
26
|
+
Requires-Dist: wrapt<2,>=1.15.0
|
|
27
|
+
Requires-Dist: black
|
|
28
|
+
Requires-Dist: beautifulsoup4
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: hypothesis; extra == "dev"
|
|
31
|
+
Requires-Dist: inflection; extra == "dev"
|
|
32
|
+
Requires-Dist: myst-parser; extra == "dev"
|
|
33
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov<6.1,>=4.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-snapshot; extra == "dev"
|
|
38
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
39
|
+
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
40
|
+
Provides-Extra: cfg
|
|
41
|
+
Requires-Dist: graphviz; extra == "cfg"
|
|
42
|
+
Provides-Extra: z3
|
|
43
|
+
Requires-Dist: z3-solver; extra == "z3"
|
|
44
|
+
Requires-Dist: importlib_resources; python_version < "3.9" and extra == "z3"
|
|
45
|
+
|
|
46
|
+
# PyTA
|
|
47
|
+
|
|
48
|
+
PyTA is a Python program which uses static code analysis to help students find
|
|
49
|
+
and fix common coding errors in introductory Python courses. Python already
|
|
50
|
+
has great static analysis tools like pep8 and pylint, but these tools do not
|
|
51
|
+
necessarily have the most beginner-friendly format. PyTA has two central goals:
|
|
52
|
+
|
|
53
|
+
1. Statically identify common coding errors by using existing linting tools and
|
|
54
|
+
building custom linters (e.g., as pylint checkers).
|
|
55
|
+
2. Present beautiful, intuitive messages to students that are both helpful for
|
|
56
|
+
fixing errors, and good preparation for the terser messages they will see
|
|
57
|
+
in their careers.
|
|
58
|
+
|
|
59
|
+
This is a new project started in the Summer of 2016, and takes the form
|
|
60
|
+
of a wrapper around [pylint](https://pylint.org) (with custom checkers) that operates
|
|
61
|
+
directly on Python modules, as well as a website with some supplementary
|
|
62
|
+
material going into further detail for the emitted errors.
|
|
63
|
+
|
|
64
|
+
For greater details on the errors PyTA checks for: [Help Documentation](https://www.cs.toronto.edu/~david/pyta/).
|
|
65
|
+
|
|
66
|
+
For help getting started using PyTA: [Quick Start](https://www.cs.toronto.edu/~david/pyta/usage/quick_start.html).
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
If you're interested in using PyTA, you can install it using `pip` (or `pip3`, on OSX/Linux):
|
|
71
|
+
|
|
72
|
+
```console
|
|
73
|
+
> pip install python-ta
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Development
|
|
77
|
+
|
|
78
|
+
If you're developing PyTA:
|
|
79
|
+
|
|
80
|
+
1. First, clone this repository.
|
|
81
|
+
2. Open a terminal in this repo, and run `pip install -e ".[dev, cfg, z3]"` to install the dependencies.
|
|
82
|
+
3. Then run `pre-commit install` to install the pre-commit hooks (for automatically formatting and checking your code on each commit).
|
|
83
|
+
|
|
84
|
+
While not strictly necessary for debugging, some debugging tools require [graphviz](https://www.graphviz.org/download/) to be installed on your system.
|
|
85
|
+
|
|
86
|
+
### Tests
|
|
87
|
+
|
|
88
|
+
To run the test suite, run the following command from inside the `pyta` directory:
|
|
89
|
+
|
|
90
|
+
```console
|
|
91
|
+
> python -m pytest tests # Or python3 on OSX/Linux
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Generating the docs
|
|
95
|
+
|
|
96
|
+
The PyTA documentation is generated using [Sphinx](https://www.sphinx-doc.org/en/master/index.html).
|
|
97
|
+
To generate the documentation locally, run the commands:
|
|
98
|
+
|
|
99
|
+
```console
|
|
100
|
+
> cd docs
|
|
101
|
+
> make html
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then open the file `docs/_build/html/index.html` in your web browser!
|
|
105
|
+
|
|
106
|
+
## Demo
|
|
107
|
+
|
|
108
|
+
You can currently see a proof of concept in this repository. Clone it,
|
|
109
|
+
and then run `python` in this directory (PyTA is primarily meant to be
|
|
110
|
+
included as a library). In the Python interpreter, try running:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
>>> import python_ta
|
|
114
|
+
>>> python_ta.check_all('examples.custom_checkers.e9999_forbidden_import')
|
|
115
|
+
[Some output should be shown]
|
|
116
|
+
>>> python_ta.doc('E9999')
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Contributors
|
|
120
|
+
|
|
121
|
+
Lorena Buciu,
|
|
122
|
+
Simon Chen,
|
|
123
|
+
Freeman Cheng,
|
|
124
|
+
Ivan Chepelev,
|
|
125
|
+
Yianni Culmone,
|
|
126
|
+
Nigel Fong,
|
|
127
|
+
Adam Gleizer,
|
|
128
|
+
Ibrahim Hasan,
|
|
129
|
+
Niayesh Ilkhani,
|
|
130
|
+
Craig Katsube,
|
|
131
|
+
Rebecca Kay,
|
|
132
|
+
Christopher Koehler,
|
|
133
|
+
David Kim,
|
|
134
|
+
Simeon Krastnikov,
|
|
135
|
+
Ryan Lee,
|
|
136
|
+
Christopher Li,
|
|
137
|
+
Hayley Lin,
|
|
138
|
+
Bruce Liu,
|
|
139
|
+
Merrick Liu,
|
|
140
|
+
Wendy Liu,
|
|
141
|
+
Yibing (Amy) Lu,
|
|
142
|
+
Maria Shurui Ma,
|
|
143
|
+
Aina Fatema Asim Merchant,
|
|
144
|
+
Shweta Mogalapalli,
|
|
145
|
+
Ignas Panero Armoska,
|
|
146
|
+
Justin Park,
|
|
147
|
+
Harshkumar Patel,
|
|
148
|
+
Varun Sahni,
|
|
149
|
+
Eleonora Scognamiglio,
|
|
150
|
+
Stephen Scott,
|
|
151
|
+
Amr Sharaf,
|
|
152
|
+
Richard Shi,
|
|
153
|
+
Kavin Singh,
|
|
154
|
+
Alexey Strokach,
|
|
155
|
+
Sophy Sun,
|
|
156
|
+
Utku Egemen Umut,
|
|
157
|
+
Sarah Wang,
|
|
158
|
+
Lana Wehbeh,
|
|
159
|
+
Jasmine Wu,
|
|
160
|
+
Raine Yang,
|
|
161
|
+
Philippe Yu,
|
|
162
|
+
Yi Cheng (Michael) Zhao
|
|
@@ -7,13 +7,13 @@ authors = [
|
|
|
7
7
|
license = {text = "MIT"}
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"astroid ~= 3.
|
|
10
|
+
"astroid ~= 3.3.5",
|
|
11
11
|
"click >= 8.0.1, < 9",
|
|
12
12
|
"colorama ~= 0.4.6",
|
|
13
13
|
"jinja2 ~= 3.1.2",
|
|
14
14
|
"pycodestyle ~= 2.11",
|
|
15
15
|
"pygments >= 2.14,< 2.19",
|
|
16
|
-
"pylint ~= 3.
|
|
16
|
+
"pylint ~= 3.3.1",
|
|
17
17
|
"requests >= 2.28,< 2.33",
|
|
18
18
|
"six",
|
|
19
19
|
"tabulate ~= 0.9.0",
|
|
@@ -21,9 +21,10 @@ dependencies = [
|
|
|
21
21
|
"typeguard >= 4.1.0, < 5",
|
|
22
22
|
"wrapt >= 1.15.0, < 2",
|
|
23
23
|
"black",
|
|
24
|
+
"beautifulsoup4"
|
|
24
25
|
]
|
|
25
26
|
dynamic = ["version"]
|
|
26
|
-
requires-python = ">=3.
|
|
27
|
+
requires-python = ">=3.9"
|
|
27
28
|
|
|
28
29
|
[project.optional-dependencies]
|
|
29
30
|
dev = [
|
|
@@ -32,8 +33,9 @@ dev = [
|
|
|
32
33
|
"myst-parser",
|
|
33
34
|
"pre-commit",
|
|
34
35
|
"pytest",
|
|
36
|
+
"pytest-cov >= 4.0,< 6.1",
|
|
37
|
+
"pytest-mock",
|
|
35
38
|
"pytest-snapshot",
|
|
36
|
-
"pytest-cov >= 4.0,< 5.1",
|
|
37
39
|
"sphinx",
|
|
38
40
|
"sphinx-rtd-theme",
|
|
39
41
|
]
|
|
@@ -15,8 +15,9 @@ if __name__ == '__main__':
|
|
|
15
15
|
python_ta.check_all()
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
from __future__ import annotations
|
|
19
19
|
|
|
20
|
+
__version__ = "2.9.0" # Version number
|
|
20
21
|
# First, remove underscore from builtins if it has been bound in the REPL.
|
|
21
22
|
# Must appear before other imports from pylint/python_ta.
|
|
22
23
|
import builtins
|
|
@@ -36,7 +37,7 @@ import tokenize
|
|
|
36
37
|
import webbrowser
|
|
37
38
|
from builtins import FileNotFoundError
|
|
38
39
|
from os import listdir
|
|
39
|
-
from typing import AnyStr, Generator,
|
|
40
|
+
from typing import AnyStr, Generator, Optional, TextIO, Union
|
|
40
41
|
|
|
41
42
|
import pylint.config
|
|
42
43
|
import pylint.lint
|
|
@@ -64,7 +65,7 @@ PYLINT_PATCHED = False
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def check_errors(
|
|
67
|
-
module_name: Union[
|
|
68
|
+
module_name: Union[list[str], str] = "",
|
|
68
69
|
config: Union[dict, str] = "",
|
|
69
70
|
output: Optional[TextIO] = None,
|
|
70
71
|
load_default_config: bool = True,
|
|
@@ -82,7 +83,7 @@ def check_errors(
|
|
|
82
83
|
|
|
83
84
|
|
|
84
85
|
def check_all(
|
|
85
|
-
module_name: Union[
|
|
86
|
+
module_name: Union[list[str], str] = "",
|
|
86
87
|
config: Union[dict, str] = "",
|
|
87
88
|
output: Optional[TextIO] = None,
|
|
88
89
|
load_default_config: bool = True,
|
|
@@ -100,7 +101,7 @@ def check_all(
|
|
|
100
101
|
|
|
101
102
|
|
|
102
103
|
def _check(
|
|
103
|
-
module_name: Union[
|
|
104
|
+
module_name: Union[list[str], str] = "",
|
|
104
105
|
level: str = "all",
|
|
105
106
|
local_config: Union[dict, str] = "",
|
|
106
107
|
output: Optional[TextIO] = None,
|
|
@@ -123,10 +124,6 @@ def _check(
|
|
|
123
124
|
# Configuring logger
|
|
124
125
|
logging.basicConfig(format="[%(levelname)s] %(message)s", level=logging.NOTSET)
|
|
125
126
|
|
|
126
|
-
# check the python version
|
|
127
|
-
if sys.version_info < (3, 7, 0):
|
|
128
|
-
logging.warning("You need Python 3.7 or later to run PythonTA.")
|
|
129
|
-
|
|
130
127
|
linter = reset_linter(config=local_config, load_default_config=load_default_config)
|
|
131
128
|
current_reporter = linter.reporter
|
|
132
129
|
current_reporter.set_output(output)
|
|
@@ -139,7 +136,9 @@ def _check(
|
|
|
139
136
|
|
|
140
137
|
global PYLINT_PATCHED
|
|
141
138
|
if not PYLINT_PATCHED:
|
|
142
|
-
patch_all(
|
|
139
|
+
patch_all(
|
|
140
|
+
messages_config, linter.config.z3
|
|
141
|
+
) # Monkeypatch pylint (override certain methods)
|
|
143
142
|
PYLINT_PATCHED = True
|
|
144
143
|
|
|
145
144
|
# Try to check file, issue error message for invalid files.
|
|
@@ -441,7 +440,7 @@ def _verify_pre_check(filepath: AnyStr, allow_pylint_comments: bool) -> bool:
|
|
|
441
440
|
return True
|
|
442
441
|
|
|
443
442
|
|
|
444
|
-
def _get_valid_files_to_check(module_name: Union[
|
|
443
|
+
def _get_valid_files_to_check(module_name: Union[list[str], str]) -> Generator[AnyStr, None, None]:
|
|
445
444
|
"""A generator for all valid files to check."""
|
|
446
445
|
# Allow call to check with empty args
|
|
447
446
|
if module_name == "":
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import sys
|
|
2
4
|
from os import path
|
|
3
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
4
6
|
|
|
5
7
|
import click
|
|
6
8
|
|
|
@@ -41,7 +43,7 @@ def main(
|
|
|
41
43
|
version: bool,
|
|
42
44
|
config: Optional[str],
|
|
43
45
|
errors_only: bool,
|
|
44
|
-
filenames:
|
|
46
|
+
filenames: list[str],
|
|
45
47
|
exit_zero: bool,
|
|
46
48
|
generate_config: bool,
|
|
47
49
|
output_format: str,
|
|
@@ -2,15 +2,25 @@
|
|
|
2
2
|
Provides a function to generate and display the control flow graph of a given module.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import importlib.util
|
|
6
8
|
import os.path
|
|
7
9
|
import sys
|
|
8
|
-
from typing import Any,
|
|
10
|
+
from typing import Any, Optional
|
|
9
11
|
|
|
10
12
|
import graphviz
|
|
11
13
|
from astroid import nodes
|
|
12
14
|
from astroid.builder import AstroidBuilder
|
|
13
15
|
|
|
16
|
+
try:
|
|
17
|
+
from ..transforms.z3_visitor import Z3Visitor
|
|
18
|
+
|
|
19
|
+
z3_dependency_available = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
Z3Visitor = Any
|
|
22
|
+
z3_dependency_available = False
|
|
23
|
+
|
|
14
24
|
from .graph import CFGBlock, ControlFlowGraph
|
|
15
25
|
from .visitor import CFGVisitor
|
|
16
26
|
|
|
@@ -19,7 +29,7 @@ SUBGRAPH_OPTIONS = {"fontname": "Courier New"}
|
|
|
19
29
|
|
|
20
30
|
|
|
21
31
|
def generate_cfg(
|
|
22
|
-
mod: str = "", auto_open: bool = False, visitor_options: Optional[
|
|
32
|
+
mod: str = "", auto_open: bool = False, visitor_options: Optional[dict[str, Any]] = None
|
|
23
33
|
) -> None:
|
|
24
34
|
"""Generate a control flow graph for the given module.
|
|
25
35
|
|
|
@@ -43,7 +53,7 @@ def generate_cfg(
|
|
|
43
53
|
|
|
44
54
|
|
|
45
55
|
def _generate(
|
|
46
|
-
mod: str = "", auto_open: bool = False, visitor_options: Optional[
|
|
56
|
+
mod: str = "", auto_open: bool = False, visitor_options: Optional[dict[str, Any]] = None
|
|
47
57
|
) -> None:
|
|
48
58
|
"""Generate a control flow graph for the given module.
|
|
49
59
|
|
|
@@ -59,6 +69,12 @@ def _generate(
|
|
|
59
69
|
|
|
60
70
|
file_name = os.path.splitext(os.path.basename(abs_path))[0]
|
|
61
71
|
module = AstroidBuilder().file_build(abs_path)
|
|
72
|
+
|
|
73
|
+
# invoke Z3Visitor if z3 dependency is available
|
|
74
|
+
if z3_dependency_available:
|
|
75
|
+
z3v = Z3Visitor()
|
|
76
|
+
module = z3v.visitor.visit(module)
|
|
77
|
+
|
|
62
78
|
visitor = CFGVisitor(options=visitor_options)
|
|
63
79
|
module.accept(visitor)
|
|
64
80
|
|
|
@@ -92,7 +108,7 @@ def _get_valid_file_path(mod: str = "") -> Optional[str]:
|
|
|
92
108
|
|
|
93
109
|
|
|
94
110
|
def _display(
|
|
95
|
-
cfgs:
|
|
111
|
+
cfgs: dict[nodes.NodeNG, ControlFlowGraph], filename: str, auto_open: bool = False
|
|
96
112
|
) -> None:
|
|
97
113
|
graph = graphviz.Digraph(name=filename, **GRAPH_OPTIONS)
|
|
98
114
|
for node, cfg in cfgs.items():
|
|
@@ -116,7 +132,7 @@ def _display(
|
|
|
116
132
|
graph.render(filename, view=auto_open)
|
|
117
133
|
|
|
118
134
|
|
|
119
|
-
def _visit(block: CFGBlock, graph: graphviz.Digraph, visited:
|
|
135
|
+
def _visit(block: CFGBlock, graph: graphviz.Digraph, visited: set[int], end: CFGBlock) -> None:
|
|
120
136
|
"""
|
|
121
137
|
Visit a CFGBlock and add it to the control flow graph.
|
|
122
138
|
"""
|
|
@@ -138,8 +154,11 @@ def _visit(block: CFGBlock, graph: graphviz.Digraph, visited: Set[int], end: CFG
|
|
|
138
154
|
visited.add(node_id)
|
|
139
155
|
|
|
140
156
|
for edge in block.successors:
|
|
157
|
+
color = "black" if edge.is_feasible else "lightgrey"
|
|
141
158
|
if edge.get_label() is not None:
|
|
142
|
-
graph.edge(
|
|
159
|
+
graph.edge(
|
|
160
|
+
node_id, f"{graph.name}_{edge.target.id}", label=edge.get_label(), color=color
|
|
161
|
+
)
|
|
143
162
|
else:
|
|
144
|
-
graph.edge(node_id, f"{graph.name}_{edge.target.id}")
|
|
163
|
+
graph.edge(node_id, f"{graph.name}_{edge.target.id}", color=color)
|
|
145
164
|
_visit(edge.target, graph, visited, end)
|