prospector 1.7.1__tar.gz → 1.14.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.
- {prospector-1.7.1 → prospector-1.14.0}/PKG-INFO +81 -29
- {prospector-1.7.1 → prospector-1.14.0}/README.rst +60 -13
- {prospector-1.7.1 → prospector-1.14.0}/prospector/__main__.py +1 -3
- {prospector-1.7.1 → prospector-1.14.0}/prospector/autodetect.py +30 -29
- {prospector-1.7.1 → prospector-1.14.0}/prospector/blender.py +19 -12
- prospector-1.14.0/prospector/blender_combinations.yaml +287 -0
- prospector-1.14.0/prospector/compat.py +14 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/config/__init__.py +110 -62
- {prospector-1.7.1 → prospector-1.14.0}/prospector/config/configuration.py +20 -15
- {prospector-1.7.1 → prospector-1.14.0}/prospector/config/datatype.py +3 -3
- prospector-1.14.0/prospector/encoding.py +36 -0
- prospector-1.14.0/prospector/exceptions.py +36 -0
- prospector-1.14.0/prospector/finder.py +132 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/__init__.py +5 -3
- prospector-1.14.0/prospector/formatters/base.py +56 -0
- prospector-1.14.0/prospector/formatters/base_summary.py +43 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/emacs.py +5 -10
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/grouped.py +9 -8
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/json.py +4 -7
- prospector-1.14.0/prospector/formatters/pylint.py +80 -0
- prospector-1.14.0/prospector/formatters/pylint_parseable.py +74 -0
- prospector-1.14.0/prospector/formatters/text.py +52 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/vscode.py +17 -8
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/xunit.py +6 -7
- {prospector-1.7.1 → prospector-1.14.0}/prospector/formatters/yaml.py +5 -4
- prospector-1.14.0/prospector/message.py +119 -0
- prospector-1.14.0/prospector/pathutils.py +37 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/postfilter.py +16 -11
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/__init__.py +2 -2
- prospector-1.14.0/prospector/profiles/exceptions.py +31 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profile.py +184 -112
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/no_doc_warnings.yaml +3 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/no_test_warnings.yaml +1 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_high.yaml +7 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_medium.yaml +4 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_veryhigh.yaml +4 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/run.py +62 -75
- prospector-1.14.0/prospector/suppression.py +157 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/__init__.py +32 -12
- prospector-1.14.0/prospector/tools/bandit/__init__.py +81 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/base.py +13 -2
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/dodgy/__init__.py +14 -20
- prospector-1.14.0/prospector/tools/exceptions.py +3 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/mccabe/__init__.py +16 -18
- prospector-1.14.0/prospector/tools/mypy/__init__.py +107 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/profile_validator/__init__.py +87 -48
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pycodestyle/__init__.py +38 -48
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pydocstyle/__init__.py +18 -20
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pyflakes/__init__.py +36 -21
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pylint/__init__.py +97 -77
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pylint/collector.py +16 -17
- prospector-1.14.0/prospector/tools/pylint/linter.py +45 -0
- prospector-1.14.0/prospector/tools/pyright/__init__.py +99 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/pyroma/__init__.py +32 -21
- prospector-1.14.0/prospector/tools/ruff/__init__.py +86 -0
- prospector-1.14.0/prospector/tools/utils.py +59 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/tools/vulture/__init__.py +26 -16
- prospector-1.14.0/pyproject.toml +110 -0
- prospector-1.14.0/setup.py +81 -0
- prospector-1.7.1/prospector/blender_combinations.yaml +0 -254
- prospector-1.7.1/prospector/encoding.py +0 -33
- prospector-1.7.1/prospector/exceptions.py +0 -14
- prospector-1.7.1/prospector/finder.py +0 -212
- prospector-1.7.1/prospector/formatters/base.py +0 -14
- prospector-1.7.1/prospector/formatters/pylint.py +0 -45
- prospector-1.7.1/prospector/formatters/text.py +0 -101
- prospector-1.7.1/prospector/message.py +0 -113
- prospector-1.7.1/prospector/pathutils.py +0 -33
- prospector-1.7.1/prospector/suppression.py +0 -118
- prospector-1.7.1/prospector/tools/bandit/__init__.py +0 -62
- prospector-1.7.1/prospector/tools/frosted/__init__.py +0 -82
- prospector-1.7.1/prospector/tools/mypy/__init__.py +0 -97
- prospector-1.7.1/prospector/tools/pylint/linter.py +0 -26
- prospector-1.7.1/prospector/tools/utils.py +0 -45
- prospector-1.7.1/pyproject.toml +0 -97
- prospector-1.7.1/setup.py +0 -77
- {prospector-1.7.1 → prospector-1.14.0}/LICENSE +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/__init__.py +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/default.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/doc_warnings.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/flake8.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/full_pep8.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/member_warnings.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/no_member_warnings.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/no_pep8.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_low.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_none.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/strictness_verylow.yaml +0 -0
- {prospector-1.7.1 → prospector-1.14.0}/prospector/profiles/profiles/test_warnings.yaml +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: prospector
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.14.0
|
|
4
|
+
Summary: Prospector is a tool to analyse Python code by aggregating the result of other tools.
|
|
5
5
|
Home-page: http://prospector.readthedocs.io
|
|
6
|
-
License: GPLv2
|
|
6
|
+
License: GPLv2+
|
|
7
7
|
Keywords: pylint,prospector,static code analysis
|
|
8
8
|
Author: Carl Crowder
|
|
9
9
|
Author-email: git@carlcrowder.com
|
|
10
10
|
Maintainer: Carl Crowder
|
|
11
11
|
Maintainer-email: git@carlcrowder.com
|
|
12
|
-
Requires-Python: >=3.
|
|
12
|
+
Requires-Python: >=3.9,<4.0
|
|
13
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Environment :: Console
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
@@ -17,35 +17,40 @@ Classifier: License :: OSI Approved :: GNU General Public License v2 or later (G
|
|
|
17
17
|
Classifier: License :: Other/Proprietary License
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
22
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
26
|
Classifier: Programming Language :: Python :: 3.9
|
|
25
27
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
26
28
|
Provides-Extra: with_bandit
|
|
27
29
|
Provides-Extra: with_everything
|
|
28
|
-
Provides-Extra: with_frosted
|
|
29
30
|
Provides-Extra: with_mypy
|
|
31
|
+
Provides-Extra: with_pyright
|
|
30
32
|
Provides-Extra: with_pyroma
|
|
33
|
+
Provides-Extra: with_ruff
|
|
31
34
|
Provides-Extra: with_vulture
|
|
35
|
+
Requires-Dist: GitPython (>=3.1.27,<4.0.0)
|
|
32
36
|
Requires-Dist: PyYAML
|
|
33
37
|
Requires-Dist: bandit (>=1.5.1); extra == "with_bandit" or extra == "with_everything"
|
|
34
38
|
Requires-Dist: dodgy (>=0.2.1,<0.3.0)
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist: mccabe (>=0.6.0,<0.7.0)
|
|
39
|
+
Requires-Dist: mccabe (>=0.7.0,<0.8.0)
|
|
37
40
|
Requires-Dist: mypy (>=0.600); extra == "with_mypy" or extra == "with_everything"
|
|
41
|
+
Requires-Dist: packaging
|
|
38
42
|
Requires-Dist: pep8-naming (>=0.3.3,<=0.10.0)
|
|
39
|
-
Requires-Dist: pycodestyle (>=2.
|
|
43
|
+
Requires-Dist: pycodestyle (>=2.9.0)
|
|
40
44
|
Requires-Dist: pydocstyle (>=2.0.0)
|
|
41
|
-
Requires-Dist: pyflakes (>=2.2.0
|
|
42
|
-
Requires-Dist: pylint (>=
|
|
45
|
+
Requires-Dist: pyflakes (>=2.2.0)
|
|
46
|
+
Requires-Dist: pylint (>=3.0)
|
|
43
47
|
Requires-Dist: pylint-celery (==0.3)
|
|
44
|
-
Requires-Dist: pylint-django (>=2.
|
|
48
|
+
Requires-Dist: pylint-django (>=2.6.1)
|
|
45
49
|
Requires-Dist: pylint-flask (==0.6)
|
|
46
|
-
Requires-Dist:
|
|
50
|
+
Requires-Dist: pyright (>=1.1.3); extra == "with_pyright" or extra == "with_everything"
|
|
47
51
|
Requires-Dist: pyroma (>=2.4); extra == "with_pyroma" or extra == "with_everything"
|
|
48
|
-
Requires-Dist: requirements-detector (>=
|
|
52
|
+
Requires-Dist: requirements-detector (>=1.3.2)
|
|
53
|
+
Requires-Dist: ruff; extra == "with_ruff" or extra == "with_everything"
|
|
49
54
|
Requires-Dist: setoptconf-tmp (>=0.3.1,<0.4.0)
|
|
50
55
|
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
51
56
|
Requires-Dist: vulture (>=1.5); extra == "with_vulture" or extra == "with_everything"
|
|
@@ -58,17 +63,14 @@ prospector
|
|
|
58
63
|
.. image:: https://img.shields.io/pypi/v/prospector.svg
|
|
59
64
|
:target: https://pypi.python.org/pypi/prospector
|
|
60
65
|
:alt: Latest Version of Prospector
|
|
61
|
-
.. image:: https://
|
|
62
|
-
:target: https://
|
|
66
|
+
.. image:: https://github.com/PyCQA/prospector/actions/workflows/tests.yml/badge.svg
|
|
67
|
+
:target: https://github.com/PyCQA/prospector/actions/workflows/tests.yml
|
|
63
68
|
:alt: Build Status
|
|
64
|
-
.. image:: https://landscape.io/github/landscapeio/prospector/master/landscape.svg?style=flat
|
|
65
|
-
:target: https://landscape.io/github/landscapeio/prospector/master
|
|
66
|
-
:alt: Code Health
|
|
67
69
|
.. image:: https://img.shields.io/coveralls/PyCQA/prospector.svg?style=flat
|
|
68
70
|
:target: https://coveralls.io/r/PyCQA/prospector
|
|
69
71
|
:alt: Test Coverage
|
|
70
72
|
.. image:: https://readthedocs.org/projects/prospector/badge/?version=latest
|
|
71
|
-
:target:
|
|
73
|
+
:target: https://prospector.readthedocs.io/
|
|
72
74
|
:alt: Documentation
|
|
73
75
|
|
|
74
76
|
|
|
@@ -79,10 +81,10 @@ Prospector is a tool to analyse Python code and output information about
|
|
|
79
81
|
errors, potential problems, convention violations and complexity.
|
|
80
82
|
|
|
81
83
|
It brings together the functionality of other Python analysis tools such as
|
|
82
|
-
`Pylint <
|
|
83
|
-
`
|
|
84
|
+
`Pylint <https://docs.pylint.org/>`_,
|
|
85
|
+
`pycodestyle <https://pycodestyle.pycqa.org/>`_,
|
|
84
86
|
and `McCabe complexity <https://pypi.python.org/pypi/mccabe>`_.
|
|
85
|
-
See the `Supported Tools <
|
|
87
|
+
See the `Supported Tools <https://prospector.readthedocs.io/en/latest/supported_tools.html>`_
|
|
86
88
|
documentation section for a complete list.
|
|
87
89
|
|
|
88
90
|
The primary aim of Prospector is to be useful 'out of the box'. A common complaint of other
|
|
@@ -118,13 +120,13 @@ And for extras::
|
|
|
118
120
|
poetry install -E with_everything
|
|
119
121
|
|
|
120
122
|
For more detailed information on installing the tool, see the
|
|
121
|
-
`installation section <
|
|
123
|
+
`installation section <https://prospector.readthedocs.io/en/latest/#installation>`_ of the tool's main page
|
|
122
124
|
on ReadTheDocs.
|
|
123
125
|
|
|
124
126
|
Documentation
|
|
125
127
|
-------------
|
|
126
128
|
|
|
127
|
-
Full `documentation is available at ReadTheDocs <
|
|
129
|
+
Full `documentation is available at ReadTheDocs <https://prospector.readthedocs.io>`_.
|
|
128
130
|
|
|
129
131
|
Usage
|
|
130
132
|
-----
|
|
@@ -156,7 +158,7 @@ Profiles
|
|
|
156
158
|
|
|
157
159
|
Prospector is configurable using "profiles". These are composable YAML files with directives to
|
|
158
160
|
disable or enable tools or messages. For more information, read
|
|
159
|
-
`the documentation about profiles <
|
|
161
|
+
`the documentation about profiles <https://prospector.readthedocs.io/en/latest/profiles.html>`_.
|
|
160
162
|
|
|
161
163
|
If your code uses frameworks and libraries
|
|
162
164
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -205,9 +207,59 @@ text to your repositories' ``.pre-commit-config.yaml``::
|
|
|
205
207
|
|
|
206
208
|
repos:
|
|
207
209
|
- repo: https://github.com/PyCQA/prospector
|
|
208
|
-
rev: 1.
|
|
210
|
+
rev: 1.10.0 # The version of Prospector to use, if not 'master' for latest
|
|
211
|
+
hooks:
|
|
212
|
+
- id: prospector
|
|
213
|
+
|
|
214
|
+
This only installs base prospector - if you also use optional tools, for example bandit and/or mypy, then you can add
|
|
215
|
+
them to the hook configuration like so::
|
|
216
|
+
|
|
217
|
+
repos:
|
|
218
|
+
- repo: https://github.com/PyCQA/prospector
|
|
219
|
+
rev: 1.10.0
|
|
209
220
|
hooks:
|
|
210
221
|
- id: prospector
|
|
222
|
+
additional_dependencies:
|
|
223
|
+
- ".[with_mypy,with_bandit]"
|
|
224
|
+
- args: [
|
|
225
|
+
'--with-tool=mypy',
|
|
226
|
+
'--with-tool=bandit',
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
Additional dependencies can be `individually configured <https://prospector.landscape.io/en/master/profiles.html#individual-configuration-options>`_ in your `prospector.yml` file ::
|
|
230
|
+
|
|
231
|
+
# https://bandit.readthedocs.io/en/latest/config.html
|
|
232
|
+
bandit:
|
|
233
|
+
options:
|
|
234
|
+
skips:
|
|
235
|
+
- B201
|
|
236
|
+
- B601
|
|
237
|
+
- B610
|
|
238
|
+
- B611
|
|
239
|
+
- B703
|
|
240
|
+
|
|
241
|
+
# https://mypy.readthedocs.io/en/stable/command_line.html
|
|
242
|
+
mypy:
|
|
243
|
+
options:
|
|
244
|
+
ignore-missing-imports: true
|
|
245
|
+
|
|
246
|
+
For prospector options which affect display only - those which are not configurable using a profile - these can be
|
|
247
|
+
added as command line arguments to the hook. For example::
|
|
248
|
+
|
|
249
|
+
repos:
|
|
250
|
+
- repo: https://github.com/PyCQA/prospector
|
|
251
|
+
rev: 1.10.0
|
|
252
|
+
hooks:
|
|
253
|
+
- id: prospector
|
|
254
|
+
additional_dependencies:
|
|
255
|
+
- ".[with_mypy,with_bandit]"
|
|
256
|
+
args:
|
|
257
|
+
- --with-tool=mypy
|
|
258
|
+
- --with-tool=bandit
|
|
259
|
+
- --summary-only
|
|
260
|
+
- --zero-exit
|
|
261
|
+
|
|
262
|
+
|
|
211
263
|
|
|
212
264
|
License
|
|
213
265
|
-------
|
|
@@ -4,17 +4,14 @@ prospector
|
|
|
4
4
|
.. image:: https://img.shields.io/pypi/v/prospector.svg
|
|
5
5
|
:target: https://pypi.python.org/pypi/prospector
|
|
6
6
|
:alt: Latest Version of Prospector
|
|
7
|
-
.. image:: https://
|
|
8
|
-
:target: https://
|
|
7
|
+
.. image:: https://github.com/PyCQA/prospector/actions/workflows/tests.yml/badge.svg
|
|
8
|
+
:target: https://github.com/PyCQA/prospector/actions/workflows/tests.yml
|
|
9
9
|
:alt: Build Status
|
|
10
|
-
.. image:: https://landscape.io/github/landscapeio/prospector/master/landscape.svg?style=flat
|
|
11
|
-
:target: https://landscape.io/github/landscapeio/prospector/master
|
|
12
|
-
:alt: Code Health
|
|
13
10
|
.. image:: https://img.shields.io/coveralls/PyCQA/prospector.svg?style=flat
|
|
14
11
|
:target: https://coveralls.io/r/PyCQA/prospector
|
|
15
12
|
:alt: Test Coverage
|
|
16
13
|
.. image:: https://readthedocs.org/projects/prospector/badge/?version=latest
|
|
17
|
-
:target:
|
|
14
|
+
:target: https://prospector.readthedocs.io/
|
|
18
15
|
:alt: Documentation
|
|
19
16
|
|
|
20
17
|
|
|
@@ -25,10 +22,10 @@ Prospector is a tool to analyse Python code and output information about
|
|
|
25
22
|
errors, potential problems, convention violations and complexity.
|
|
26
23
|
|
|
27
24
|
It brings together the functionality of other Python analysis tools such as
|
|
28
|
-
`Pylint <
|
|
29
|
-
`
|
|
25
|
+
`Pylint <https://docs.pylint.org/>`_,
|
|
26
|
+
`pycodestyle <https://pycodestyle.pycqa.org/>`_,
|
|
30
27
|
and `McCabe complexity <https://pypi.python.org/pypi/mccabe>`_.
|
|
31
|
-
See the `Supported Tools <
|
|
28
|
+
See the `Supported Tools <https://prospector.readthedocs.io/en/latest/supported_tools.html>`_
|
|
32
29
|
documentation section for a complete list.
|
|
33
30
|
|
|
34
31
|
The primary aim of Prospector is to be useful 'out of the box'. A common complaint of other
|
|
@@ -64,13 +61,13 @@ And for extras::
|
|
|
64
61
|
poetry install -E with_everything
|
|
65
62
|
|
|
66
63
|
For more detailed information on installing the tool, see the
|
|
67
|
-
`installation section <
|
|
64
|
+
`installation section <https://prospector.readthedocs.io/en/latest/#installation>`_ of the tool's main page
|
|
68
65
|
on ReadTheDocs.
|
|
69
66
|
|
|
70
67
|
Documentation
|
|
71
68
|
-------------
|
|
72
69
|
|
|
73
|
-
Full `documentation is available at ReadTheDocs <
|
|
70
|
+
Full `documentation is available at ReadTheDocs <https://prospector.readthedocs.io>`_.
|
|
74
71
|
|
|
75
72
|
Usage
|
|
76
73
|
-----
|
|
@@ -102,7 +99,7 @@ Profiles
|
|
|
102
99
|
|
|
103
100
|
Prospector is configurable using "profiles". These are composable YAML files with directives to
|
|
104
101
|
disable or enable tools or messages. For more information, read
|
|
105
|
-
`the documentation about profiles <
|
|
102
|
+
`the documentation about profiles <https://prospector.readthedocs.io/en/latest/profiles.html>`_.
|
|
106
103
|
|
|
107
104
|
If your code uses frameworks and libraries
|
|
108
105
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -151,10 +148,60 @@ text to your repositories' ``.pre-commit-config.yaml``::
|
|
|
151
148
|
|
|
152
149
|
repos:
|
|
153
150
|
- repo: https://github.com/PyCQA/prospector
|
|
154
|
-
rev: 1.
|
|
151
|
+
rev: 1.10.0 # The version of Prospector to use, if not 'master' for latest
|
|
155
152
|
hooks:
|
|
156
153
|
- id: prospector
|
|
157
154
|
|
|
155
|
+
This only installs base prospector - if you also use optional tools, for example bandit and/or mypy, then you can add
|
|
156
|
+
them to the hook configuration like so::
|
|
157
|
+
|
|
158
|
+
repos:
|
|
159
|
+
- repo: https://github.com/PyCQA/prospector
|
|
160
|
+
rev: 1.10.0
|
|
161
|
+
hooks:
|
|
162
|
+
- id: prospector
|
|
163
|
+
additional_dependencies:
|
|
164
|
+
- ".[with_mypy,with_bandit]"
|
|
165
|
+
- args: [
|
|
166
|
+
'--with-tool=mypy',
|
|
167
|
+
'--with-tool=bandit',
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
Additional dependencies can be `individually configured <https://prospector.landscape.io/en/master/profiles.html#individual-configuration-options>`_ in your `prospector.yml` file ::
|
|
171
|
+
|
|
172
|
+
# https://bandit.readthedocs.io/en/latest/config.html
|
|
173
|
+
bandit:
|
|
174
|
+
options:
|
|
175
|
+
skips:
|
|
176
|
+
- B201
|
|
177
|
+
- B601
|
|
178
|
+
- B610
|
|
179
|
+
- B611
|
|
180
|
+
- B703
|
|
181
|
+
|
|
182
|
+
# https://mypy.readthedocs.io/en/stable/command_line.html
|
|
183
|
+
mypy:
|
|
184
|
+
options:
|
|
185
|
+
ignore-missing-imports: true
|
|
186
|
+
|
|
187
|
+
For prospector options which affect display only - those which are not configurable using a profile - these can be
|
|
188
|
+
added as command line arguments to the hook. For example::
|
|
189
|
+
|
|
190
|
+
repos:
|
|
191
|
+
- repo: https://github.com/PyCQA/prospector
|
|
192
|
+
rev: 1.10.0
|
|
193
|
+
hooks:
|
|
194
|
+
- id: prospector
|
|
195
|
+
additional_dependencies:
|
|
196
|
+
- ".[with_mypy,with_bandit]"
|
|
197
|
+
args:
|
|
198
|
+
- --with-tool=mypy
|
|
199
|
+
- --with-tool=bandit
|
|
200
|
+
- --summary-only
|
|
201
|
+
- --zero-exit
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
158
205
|
License
|
|
159
206
|
-------
|
|
160
207
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
3
|
import warnings
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Union
|
|
4
6
|
|
|
5
7
|
from requirements_detector import find_requirements
|
|
6
8
|
from requirements_detector.detect import RequirementsNotFound
|
|
7
9
|
|
|
8
10
|
from prospector import encoding
|
|
11
|
+
from prospector.exceptions import PermissionMissing
|
|
9
12
|
from prospector.pathutils import is_virtualenv
|
|
10
13
|
|
|
11
14
|
POSSIBLE_LIBRARIES = ("django", "celery", "flask")
|
|
@@ -17,7 +20,7 @@ _IMPORT_REGEX = re.compile(r"^\s*import ([\._a-zA-Z0-9]+)$")
|
|
|
17
20
|
_IMPORT_MULTIPLE_REGEX = re.compile(r"^\s*import ([\._a-zA-Z0-9]+(, ){1})+")
|
|
18
21
|
|
|
19
22
|
|
|
20
|
-
def find_from_imports(file_contents):
|
|
23
|
+
def find_from_imports(file_contents: str) -> set[str]:
|
|
21
24
|
names = set()
|
|
22
25
|
for line in file_contents.split("\n"):
|
|
23
26
|
match = _IMPORT_MULTIPLE_REGEX.match(line)
|
|
@@ -40,57 +43,55 @@ def find_from_imports(file_contents):
|
|
|
40
43
|
return names
|
|
41
44
|
|
|
42
45
|
|
|
43
|
-
def find_from_path(path):
|
|
46
|
+
def find_from_path(path: Path) -> set[str]:
|
|
44
47
|
names = set()
|
|
45
|
-
max_possible = len(POSSIBLE_LIBRARIES)
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
try:
|
|
50
|
+
for item in path.iterdir():
|
|
51
|
+
if item.is_dir():
|
|
52
|
+
if is_virtualenv(item):
|
|
53
|
+
continue
|
|
54
|
+
names |= find_from_path(item)
|
|
55
|
+
elif not item.is_symlink() and item.suffix == ".py":
|
|
56
|
+
try:
|
|
57
|
+
contents = encoding.read_py_file(item)
|
|
58
|
+
names |= find_from_imports(contents)
|
|
59
|
+
except encoding.CouldNotHandleEncoding as err:
|
|
60
|
+
# TODO: this output will break output formats such as JSON
|
|
61
|
+
warnings.warn(f"{err.path}: {err.__cause__}", ImportWarning, stacklevel=0)
|
|
62
|
+
|
|
63
|
+
if len(names) == len(POSSIBLE_LIBRARIES):
|
|
64
|
+
# don't continue on recursing, there's no point!
|
|
65
|
+
break
|
|
66
|
+
except PermissionError as err:
|
|
67
|
+
raise PermissionMissing(path) from err
|
|
64
68
|
|
|
65
69
|
return names
|
|
66
70
|
|
|
67
71
|
|
|
68
|
-
def find_from_requirements(path):
|
|
72
|
+
def find_from_requirements(path: Union[str, Path]) -> set[str]:
|
|
69
73
|
reqs = find_requirements(path)
|
|
70
|
-
names =
|
|
74
|
+
names: set[str] = set()
|
|
71
75
|
for requirement in reqs:
|
|
72
76
|
if requirement.name is not None and requirement.name.lower() in POSSIBLE_LIBRARIES:
|
|
73
|
-
names.
|
|
77
|
+
names.add(requirement.name.lower())
|
|
74
78
|
return names
|
|
75
79
|
|
|
76
80
|
|
|
77
|
-
def autodetect_libraries(path):
|
|
78
|
-
|
|
81
|
+
def autodetect_libraries(path: Union[str, Path]) -> set[str]:
|
|
79
82
|
if os.path.isfile(path):
|
|
80
83
|
path = os.path.dirname(path)
|
|
81
84
|
if path == "":
|
|
82
85
|
path = "."
|
|
83
86
|
|
|
84
|
-
libraries =
|
|
87
|
+
libraries: set[str] = set()
|
|
85
88
|
|
|
86
89
|
try:
|
|
87
90
|
libraries = find_from_requirements(path)
|
|
88
|
-
|
|
89
|
-
# pylint: disable=pointless-except
|
|
90
91
|
except RequirementsNotFound:
|
|
91
92
|
pass
|
|
92
93
|
|
|
93
94
|
if len(libraries) < len(POSSIBLE_LIBRARIES):
|
|
94
|
-
libraries = find_from_path(path)
|
|
95
|
+
libraries = find_from_path(Path(path))
|
|
95
96
|
|
|
96
97
|
return libraries
|
|
@@ -4,18 +4,22 @@
|
|
|
4
4
|
# the same line. For example, both pyflakes and pylint will generate an
|
|
5
5
|
# "Unused Import" warning on the same line. This is obviously redundant, so we
|
|
6
6
|
# remove duplicates.
|
|
7
|
+
import pkgutil
|
|
7
8
|
from collections import defaultdict
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional
|
|
8
11
|
|
|
9
|
-
import pkg_resources
|
|
10
12
|
import yaml
|
|
11
13
|
|
|
14
|
+
from prospector.message import Message
|
|
15
|
+
|
|
12
16
|
__all__ = (
|
|
13
17
|
"blend",
|
|
14
18
|
"BLEND_COMBOS",
|
|
15
19
|
)
|
|
16
20
|
|
|
17
21
|
|
|
18
|
-
def blend_line(messages, blend_combos=None):
|
|
22
|
+
def blend_line(messages: list[Message], blend_combos: Optional[list[list[tuple[str, str]]]] = None) -> list[Message]:
|
|
19
23
|
"""
|
|
20
24
|
Given a list of messages on the same line, blend them together so that we
|
|
21
25
|
end up with one message per actual problem. Note that we can still return
|
|
@@ -23,8 +27,8 @@ def blend_line(messages, blend_combos=None):
|
|
|
23
27
|
the line.
|
|
24
28
|
"""
|
|
25
29
|
blend_combos = blend_combos or BLEND_COMBOS
|
|
26
|
-
blend_lists = [[] for _ in range(len(blend_combos))]
|
|
27
|
-
blended = []
|
|
30
|
+
blend_lists: list[list[Message]] = [[] for _ in range(len(blend_combos))]
|
|
31
|
+
blended: list[Message] = []
|
|
28
32
|
|
|
29
33
|
# first we split messages into each of the possible blendable categories
|
|
30
34
|
# so that we have a list of lists of messages which can be blended together
|
|
@@ -52,6 +56,7 @@ def blend_line(messages, blend_combos=None):
|
|
|
52
56
|
for blend_combo_idx, blend_list in enumerate(blend_lists):
|
|
53
57
|
if len(blend_list) == 0:
|
|
54
58
|
continue
|
|
59
|
+
# pylint:disable=cell-var-from-loop
|
|
55
60
|
blend_list.sort(
|
|
56
61
|
key=lambda msg: blend_combos[blend_combo_idx].index(
|
|
57
62
|
(msg.source, msg.code),
|
|
@@ -71,16 +76,16 @@ def blend_line(messages, blend_combos=None):
|
|
|
71
76
|
# it will appear in two blend_lists. Therefore we mark anything not taken from the blend list
|
|
72
77
|
# as "consumed" and then filter later, to avoid such cases.
|
|
73
78
|
for now_used in blend_list[1:]:
|
|
74
|
-
now_used.used = True
|
|
79
|
+
now_used.used = True # type: ignore[attr-defined]
|
|
75
80
|
|
|
76
81
|
return [m for m in blended if not getattr(m, "used", False)]
|
|
77
82
|
|
|
78
83
|
|
|
79
|
-
def blend(messages, blend_combos=None):
|
|
84
|
+
def blend(messages: list[Message], blend_combos: Optional[list[list[tuple[str, str]]]] = None) -> list[Message]:
|
|
80
85
|
blend_combos = blend_combos or BLEND_COMBOS
|
|
81
86
|
|
|
82
87
|
# group messages by file and then line number
|
|
83
|
-
msgs_grouped = defaultdict(lambda: defaultdict(list))
|
|
88
|
+
msgs_grouped: dict[Optional[Path], dict[Optional[int], list[Message]]] = defaultdict(lambda: defaultdict(list))
|
|
84
89
|
|
|
85
90
|
for message in messages:
|
|
86
91
|
msgs_grouped[message.location.path][message.location.line].append(
|
|
@@ -96,18 +101,20 @@ def blend(messages, blend_combos=None):
|
|
|
96
101
|
return out
|
|
97
102
|
|
|
98
103
|
|
|
99
|
-
def get_default_blend_combinations():
|
|
100
|
-
|
|
104
|
+
def get_default_blend_combinations() -> list[list[tuple[str, str]]]:
|
|
105
|
+
blender_combinations = pkgutil.get_data(__name__, "blender_combinations.yaml")
|
|
106
|
+
assert blender_combinations is not None
|
|
107
|
+
combos = yaml.safe_load(blender_combinations)
|
|
101
108
|
combos = combos.get("combinations", [])
|
|
102
109
|
|
|
103
|
-
defaults = []
|
|
110
|
+
defaults: list[list[tuple[str, str]]] = []
|
|
104
111
|
for combo in combos:
|
|
105
112
|
toblend = []
|
|
106
113
|
for msg in combo:
|
|
107
114
|
toblend += msg.items()
|
|
108
|
-
defaults.append(
|
|
115
|
+
defaults.append(toblend)
|
|
109
116
|
|
|
110
|
-
return
|
|
117
|
+
return defaults
|
|
111
118
|
|
|
112
119
|
|
|
113
120
|
BLEND_COMBOS = get_default_blend_combinations()
|