prospector 1.13.3__py3-none-any.whl → 1.14.0__py3-none-any.whl

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.
@@ -277,6 +277,11 @@ combinations:
277
277
  - - pep257: D103
278
278
  - pydocstyle: D103
279
279
  - pylint: missing-docstring
280
+
280
281
  - - pylint: singleton-comparison
281
282
  - pep8: E711
282
283
  - pycodestyle: E711
284
+
285
+ - - pylint: subprocess-run-check
286
+ - bandit: B603
287
+ - ruff: S603
prospector/finder.py CHANGED
@@ -56,8 +56,8 @@ class FileFinder:
56
56
  def is_excluded(self, path: Path) -> bool:
57
57
  return any(filt(path) for filt in self._exclusion_filters)
58
58
 
59
- def _filter(self, paths: Iterable[Path]) -> list[Path]:
60
- return [path for path in paths if not self.is_excluded(path)]
59
+ def _filter(self, paths: Iterable[Path]) -> set[Path]:
60
+ return {path for path in paths if not self.is_excluded(path)}
61
61
 
62
62
  def _walk(self, directory: Path) -> Iterator[Path]:
63
63
  if not self.is_excluded(directory):
@@ -72,22 +72,25 @@ class FileFinder:
72
72
  yield path
73
73
 
74
74
  @property
75
- def files(self) -> list[Path]:
75
+ def files(self) -> set[Path]:
76
76
  """
77
77
  List every individual file found from the given configuration.
78
78
 
79
79
  This method is useful for tools which require an explicit list of files to check.
80
80
  """
81
81
  files = set()
82
- for path in self._provided_files:
83
- files.add(path)
84
82
 
85
83
  for directory in self.directories:
86
84
  for path in self._walk(directory):
87
85
  if path.is_file():
88
86
  files.add(path)
89
87
 
90
- return self._filter(files)
88
+ files = self._filter(files)
89
+
90
+ for path in self._provided_files:
91
+ files.add(path)
92
+
93
+ return files
91
94
 
92
95
  @property
93
96
  def python_packages(self) -> list[Path]:
@@ -97,7 +100,7 @@ class FileFinder:
97
100
 
98
101
  This method is useful for passing to tools which will do their own discovery of python files.
99
102
  """
100
- return self._filter(d for d in self.directories if is_python_package(d))
103
+ return [d for d in self.directories if is_python_package(d)]
101
104
 
102
105
  @property
103
106
  def python_modules(self) -> list[Path]:
@@ -107,10 +110,10 @@ class FileFinder:
107
110
 
108
111
  This method is useful for passing to tools which will do their own discovery of python files.
109
112
  """
110
- return self._filter(f for f in self.files if is_python_module(f))
113
+ return [f for f in self.files if is_python_module(f)]
111
114
 
112
115
  @property
113
- def directories(self) -> list[Path]:
116
+ def directories(self) -> set[Path]:
114
117
  """
115
118
  Lists every directory found from the given configuration, regardless of its contents.
116
119
 
@@ -1,4 +1,4 @@
1
- from . import emacs, grouped, json, pylint, text, vscode, xunit, yaml
1
+ from . import emacs, grouped, json, pylint, pylint_parseable, text, vscode, xunit, yaml
2
2
  from .base import Formatter
3
3
 
4
4
  __all__ = ("FORMATTERS", "Formatter")
@@ -11,6 +11,7 @@ FORMATTERS: dict[str, type[Formatter]] = {
11
11
  "emacs": emacs.EmacsFormatter,
12
12
  "yaml": yaml.YamlFormatter,
13
13
  "pylint": pylint.PylintFormatter,
14
+ "pylint_parseable": pylint_parseable.PylintParseableFormatter,
14
15
  "xunit": xunit.XunitFormatter,
15
16
  "vscode": vscode.VSCodeFormatter,
16
17
  }
@@ -39,9 +39,18 @@ class Formatter(ABC):
39
39
  "line": message.location.line,
40
40
  "character": message.location.character,
41
41
  }
42
- return {
42
+ if message.location.line_end is not None and message.location.line_end != -1:
43
+ loc["lineEnd"] = message.location.line_end
44
+ if message.location.character_end is not None and message.location.character_end != -1:
45
+ loc["characterEnd"] = message.location.character_end
46
+ result = {
43
47
  "source": message.source,
44
48
  "code": message.code,
45
49
  "location": loc,
46
50
  "message": message.message,
51
+ "isFixable": message.is_fixable,
47
52
  }
53
+ if message.doc_url:
54
+ result["docUrl"] = message.doc_url
55
+
56
+ return result
@@ -7,12 +7,7 @@ __all__ = ("EmacsFormatter",)
7
7
  class EmacsFormatter(TextFormatter):
8
8
  def render_message(self, message: Message) -> str:
9
9
  output = [
10
- "%s:%s:%d:"
11
- % (
12
- self._make_path(message.location),
13
- message.location.line,
14
- (message.location.character or 0) + 1,
15
- ),
10
+ f"{self._make_path(message.location)}:{message.location.line}:{(message.location.character or 0) + 1}:",
16
11
  " L{}:{} {}: {} - {}".format(
17
12
  message.location.line or "-",
18
13
  message.location.character if message.location.line else "-",
@@ -23,8 +23,8 @@ class PylintFormatter(SummaryFormatter):
23
23
  header = f"************* Module {module_name}"
24
24
  output.append(header)
25
25
 
26
- # ={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
27
- # prospector/configuration.py:65: [missing-docstring(missing-docstring), build_default_sources] \
26
+ # ={path}:{line}:{character}: [{msg_id}({symbol}), {obj}] {msg}
27
+ # prospector/configuration.py:65:1: [missing-docstring(missing-docstring), build_default_sources] \
28
28
  # Missing function docstring
29
29
 
30
30
  template_location = (
@@ -49,6 +49,9 @@ class PylintFormatter(SummaryFormatter):
49
49
  else f"{template_code}: %(message)s"
50
50
  )
51
51
 
52
+ message_str = message.message.strip()
53
+ if message.doc_url:
54
+ message_str += f" (See: {message.doc_url})"
52
55
  output.append(
53
56
  template
54
57
  % {
@@ -0,0 +1,74 @@
1
+ import os
2
+ import re
3
+
4
+ from prospector.formatters.base_summary import SummaryFormatter
5
+
6
+
7
+ class PylintParseableFormatter(SummaryFormatter):
8
+ """
9
+ This formatter outputs messages in the same way as `pylint --output-format=parseable`, which is used by several
10
+ tools to parse pylint output. This formatter is therefore a compatibility shim between tools built
11
+ on top of pylint and prospector itself.
12
+ """
13
+
14
+ def render_messages(self) -> list[str]:
15
+ cur_loc = None
16
+ output = []
17
+ for message in sorted(self.messages):
18
+ if cur_loc != message.location.path:
19
+ cur_loc = message.location.path
20
+ module_name = str(self._make_path(message.location)).replace(os.path.sep, ".")
21
+ module_name = re.sub(r"(\.__init__)?\.py$", "", module_name)
22
+
23
+ header = f"************* Module {module_name}"
24
+ output.append(header)
25
+
26
+ # ={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
27
+ # prospector/configuration.py:65: [missing-docstring(missing-docstring), build_default_sources] \
28
+ # Missing function docstring
29
+
30
+ template_location = (
31
+ ""
32
+ if message.location.path is None
33
+ else "%(path)s"
34
+ if message.location.line is None
35
+ else "%(path)s:%(line)s"
36
+ )
37
+ template_code = (
38
+ "(%(source)s)"
39
+ if message.code is None
40
+ else "%(code)s(%(source)s)"
41
+ if message.location.function is None
42
+ else "[%(code)s(%(source)s), %(function)s]"
43
+ )
44
+ template = (
45
+ f"{template_location}: {template_code}: %(message)s"
46
+ if template_location
47
+ else f"{template_code}: %(message)s"
48
+ )
49
+
50
+ output.append(
51
+ template
52
+ % {
53
+ "path": self._make_path(message.location),
54
+ "line": message.location.line,
55
+ "source": message.source,
56
+ "code": message.code,
57
+ "function": message.location.function,
58
+ "message": message.message.strip(),
59
+ }
60
+ )
61
+ return output
62
+
63
+ def render(self, summary: bool = True, messages: bool = True, profile: bool = False) -> str:
64
+ output: list[str] = []
65
+ if messages:
66
+ output.extend(self.render_messages())
67
+ if profile:
68
+ output.append("")
69
+ output.append(self.render_profile())
70
+ if summary:
71
+ output.append("")
72
+ output.append(self.render_summary())
73
+
74
+ return "\n".join(output)
prospector/message.py CHANGED
@@ -12,6 +12,8 @@ class Location:
12
12
  function: Optional[str],
13
13
  line: Optional[int],
14
14
  character: Optional[int],
15
+ line_end: Optional[int] = None,
16
+ character_end: Optional[int] = None,
15
17
  ):
16
18
  if isinstance(path, Path):
17
19
  self._path = path.absolute()
@@ -25,6 +27,8 @@ class Location:
25
27
  self.function = function or None
26
28
  self.line = None if line == -1 else line
27
29
  self.character = None if character == -1 else character
30
+ self.line_end = line_end
31
+ self.character_end = character_end
28
32
 
29
33
  @property
30
34
  def path(self) -> Optional[Path]:
@@ -36,7 +40,9 @@ class Location:
36
40
  def relative_path(self, root: Optional[Path]) -> Optional[Path]:
37
41
  if self._path is None:
38
42
  return None
39
- return self._path.relative_to(root) if root else self._path
43
+ if root is None:
44
+ return self._path
45
+ return self._path.relative_to(root) if self._path.is_relative_to(root) else self._path
40
46
 
41
47
  def __repr__(self) -> str:
42
48
  return f"{self._path}:L{self.line}:{self.character}"
@@ -67,11 +73,21 @@ class Location:
67
73
 
68
74
 
69
75
  class Message:
70
- def __init__(self, source: str, code: str, location: Location, message: str):
76
+ def __init__(
77
+ self,
78
+ source: str,
79
+ code: str,
80
+ location: Location,
81
+ message: str,
82
+ doc_url: Optional[str] = None,
83
+ is_fixable: bool = False,
84
+ ):
71
85
  self.source = source
72
86
  self.code = code
73
87
  self.location = location
74
88
  self.message = message
89
+ self.doc_url = doc_url
90
+ self.is_fixable = is_fixable
75
91
 
76
92
  def __repr__(self) -> str:
77
93
  return f"{self.source}-{self.code}"
prospector/postfilter.py CHANGED
@@ -48,9 +48,14 @@ def filter_messages(filepaths: list[Path], messages: list[Message]) -> list[Mess
48
48
  if (
49
49
  relative_message_path in messages_to_ignore
50
50
  and message.location.line in messages_to_ignore[relative_message_path]
51
- and message.code in messages_to_ignore[relative_message_path][message.location.line]
52
51
  ):
53
- continue
52
+ matched = False
53
+ for ignore in messages_to_ignore[relative_message_path][message.location.line]:
54
+ if (ignore.source is None or message.source == ignore.source) and message.code in ignore.code:
55
+ matched = True
56
+ continue
57
+ if matched:
58
+ continue
54
59
 
55
60
  # otherwise this message was not filtered
56
61
  filtered.append(message)
@@ -54,3 +54,10 @@ pydocstyle:
54
54
  disable:
55
55
  - D400
56
56
  - D401
57
+
58
+ mypy:
59
+ options:
60
+ ignore-missing-imports: true
61
+ follow-imports: skip
62
+ disallow-untyped-defs: true
63
+ strict: false
@@ -125,3 +125,7 @@ pydocstyle:
125
125
  - D101
126
126
  - D102
127
127
  - D103
128
+
129
+ mypy:
130
+ options:
131
+ disallow-untyped-defs: false
@@ -38,3 +38,7 @@ pyroma:
38
38
  pydocstyle:
39
39
  disable:
40
40
  - D000
41
+
42
+ mypy:
43
+ options:
44
+ strict: true
prospector/suppression.py CHANGED
@@ -31,11 +31,28 @@ from prospector.exceptions import FatalProspectorException
31
31
  from prospector.message import Message
32
32
 
33
33
  _FLAKE8_IGNORE_FILE = re.compile(r"flake8[:=]\s*noqa", re.IGNORECASE)
34
- _PEP8_IGNORE_LINE = re.compile(r"#\s+noqa", re.IGNORECASE)
34
+ _PEP8_IGNORE_LINE = re.compile(r"#\s*noqa(\s*#.*)?$", re.IGNORECASE)
35
+ _PEP8_IGNORE_LINE_CODE = re.compile(r"#\s*noqa:([^#]*[^# ])(\s*#.*)?$", re.IGNORECASE)
35
36
  _PYLINT_SUPPRESSED_MESSAGE = re.compile(r"^Suppressed \'([a-z0-9-]+)\' \(from line \d+\)$")
36
37
 
37
38
 
38
- def get_noqa_suppressions(file_contents: list[str]) -> tuple[bool, set[int]]:
39
+ class Ignore:
40
+ source: Optional[str]
41
+ code: str
42
+
43
+ def __init__(
44
+ self,
45
+ source: Optional[str],
46
+ code: str,
47
+ ) -> None:
48
+ self.source = source
49
+ self.code = code
50
+
51
+ def __str__(self) -> str:
52
+ return self.code if self.source is None else f"{self.source}.{self.code}"
53
+
54
+
55
+ def get_noqa_suppressions(file_contents: list[str]) -> tuple[bool, set[int], dict[int, set[Ignore]]]:
39
56
  """
40
57
  Finds all pep8/flake8 suppression messages
41
58
 
@@ -47,12 +64,21 @@ def get_noqa_suppressions(file_contents: list[str]) -> tuple[bool, set[int]]:
47
64
  """
48
65
  ignore_whole_file = False
49
66
  ignore_lines = set()
67
+ messages_to_ignore: dict[int, set[Ignore]] = defaultdict(set)
50
68
  for line_number, line in enumerate(file_contents):
51
69
  if _FLAKE8_IGNORE_FILE.search(line):
52
70
  ignore_whole_file = True
53
71
  if _PEP8_IGNORE_LINE.search(line):
54
72
  ignore_lines.add(line_number + 1)
55
- return ignore_whole_file, ignore_lines
73
+ else:
74
+ noqa_match = _PEP8_IGNORE_LINE_CODE.search(line)
75
+ if noqa_match:
76
+ prospector_ignore = noqa_match.group(1).strip().split(",")
77
+ prospector_ignore = [elem.strip() for elem in prospector_ignore]
78
+ for code in prospector_ignore:
79
+ messages_to_ignore[line_number + 1].add(Ignore(None, code))
80
+
81
+ return ignore_whole_file, ignore_lines, messages_to_ignore
56
82
 
57
83
 
58
84
  _PYLINT_EQUIVALENTS = {
@@ -89,7 +115,7 @@ def _parse_pylint_informational(
89
115
 
90
116
  def get_suppressions(
91
117
  filepaths: list[Path], messages: list[Message]
92
- ) -> tuple[set[Optional[Path]], dict[Path, set[int]], dict[Optional[Path], dict[int, set[tuple[str, str]]]]]:
118
+ ) -> tuple[set[Optional[Path]], dict[Path, set[int]], dict[Optional[Path], dict[int, set[Ignore]]]]:
93
119
  """
94
120
  Given every message which was emitted by the tools, and the
95
121
  list of files to inspect, create a list of files to ignore,
@@ -97,9 +123,9 @@ def get_suppressions(
97
123
  """
98
124
  paths_to_ignore: set[Optional[Path]] = set()
99
125
  lines_to_ignore: dict[Path, set[int]] = defaultdict(set)
100
- messages_to_ignore: dict[Optional[Path], dict[int, set[tuple[str, str]]]] = defaultdict(lambda: defaultdict(set))
126
+ messages_to_ignore: dict[Optional[Path], dict[int, set[Ignore]]] = defaultdict(lambda: defaultdict(set))
101
127
 
102
- # first deal with 'noqa' style messages
128
+ # First deal with 'noqa' style messages
103
129
  for filepath in filepaths:
104
130
  try:
105
131
  file_contents = encoding.read_py_file(filepath).split("\n")
@@ -108,20 +134,24 @@ def get_suppressions(
108
134
  warnings.warn(f"{err.path}: {err.__cause__}", ImportWarning, stacklevel=2)
109
135
  continue
110
136
 
111
- ignore_file, ignore_lines = get_noqa_suppressions(file_contents)
137
+ ignore_file, ignore_lines, file_messages_to_ignore = get_noqa_suppressions(file_contents)
112
138
  if ignore_file:
113
139
  paths_to_ignore.add(filepath)
114
140
  lines_to_ignore[filepath] |= ignore_lines
141
+ for line, codes_ignore in file_messages_to_ignore.items():
142
+ messages_to_ignore[filepath][line] |= codes_ignore
115
143
 
116
- # now figure out which messages were suppressed by pylint
144
+ # Now figure out which messages were suppressed by pylint
117
145
  pylint_ignore_files, pylint_ignore_messages = _parse_pylint_informational(messages)
118
146
  paths_to_ignore |= pylint_ignore_files
119
- for pylint_filepath, line in pylint_ignore_messages.items():
120
- for line_number, codes in line.items():
147
+ for pylint_filepath, line_codes in pylint_ignore_messages.items():
148
+ for line_number, codes in line_codes.items():
121
149
  for code in codes:
122
- messages_to_ignore[pylint_filepath][line_number].add(("pylint", code))
150
+ ignore = Ignore("pylint", code)
151
+ messages_to_ignore[pylint_filepath][line_number].add(ignore)
123
152
  if code in _PYLINT_EQUIVALENTS:
124
- for equivalent in _PYLINT_EQUIVALENTS[code]:
125
- messages_to_ignore[pylint_filepath][line_number].add(equivalent)
153
+ for ignore_source, ignore_code in _PYLINT_EQUIVALENTS[code]:
154
+ ignore = Ignore(ignore_source, ignore_code)
155
+ messages_to_ignore[pylint_filepath][line_number].add(ignore)
126
156
 
127
157
  return paths_to_ignore, lines_to_ignore, messages_to_ignore
@@ -1,6 +1,7 @@
1
1
  from typing import TYPE_CHECKING, Any, Optional
2
2
 
3
3
  from bandit.cli.main import _get_profile, _init_extensions
4
+ from bandit.core import docs_utils
4
5
  from bandit.core.config import BanditConfig
5
6
  from bandit.core.constants import RANKING
6
7
  from bandit.core.manager import BanditManager
@@ -66,7 +67,15 @@ class BanditTool(ToolBase):
66
67
  results = self.manager.get_issue_list(sev_level=RANKING[self.severity], conf_level=RANKING[self.confidence])
67
68
  messages = []
68
69
  for result in results:
69
- loc = Location(result.fname, None, "", int(result.lineno), 0)
70
- msg = Message("bandit", result.test_id, loc, result.text)
70
+ loc = Location(
71
+ result.fname,
72
+ None,
73
+ "",
74
+ result.lineno,
75
+ result.col_offset,
76
+ line_end=result.linerange[-1] if result.linerange else result.lineno,
77
+ character_end=result.end_col_offset,
78
+ )
79
+ msg = Message("bandit", result.test_id, loc, result.text, doc_url=docs_utils.get_url(result.test_id))
71
80
  messages.append(msg)
72
81
  return messages
@@ -87,7 +87,7 @@ class MypyTool(ToolBase):
87
87
  self.options.append(f"--{name}-{v}")
88
88
  continue
89
89
 
90
- raise BadToolConfig("mypy", f"The option {name} has an unsupported balue type: {type(value)}")
90
+ raise BadToolConfig("mypy", f"The option {name} has an unsupported value type: {type(value)}")
91
91
 
92
92
  def run(self, found_files: FileFinder) -> list[Message]:
93
93
  paths = [str(path) for path in found_files.python_modules]
@@ -17,7 +17,7 @@ class Collector(BaseReporter):
17
17
  self._messages: list[Message] = []
18
18
 
19
19
  def handle_message(self, msg: PylintMessage) -> None:
20
- loc = Location(msg.abspath, msg.module, msg.obj, msg.line, msg.column)
20
+ loc = Location(msg.abspath, msg.module, msg.obj, msg.line, msg.column, msg.end_line, msg.end_column)
21
21
 
22
22
  # At this point pylint will give us the code but we want the
23
23
  # more user-friendly symbol
@@ -31,7 +31,13 @@ class Collector(BaseReporter):
31
31
  else:
32
32
  msg_symbol = msg_data[0].symbol
33
33
 
34
- message = Message("pylint", msg_symbol, loc, msg.msg)
34
+ message = Message(
35
+ "pylint",
36
+ msg_symbol,
37
+ loc,
38
+ msg.msg,
39
+ doc_url=f"https://pylint.readthedocs.io/en/latest/user_guide/messages/{msg.category}/{msg.symbol}.html",
40
+ )
35
41
  self._messages.append(message)
36
42
 
37
43
  def get_messages(self) -> list[Message]:
@@ -44,7 +44,7 @@ class RuffTool(ToolBase):
44
44
 
45
45
  def run(self, found_files: FileFinder) -> list[Message]:
46
46
  messages = []
47
- completed_process = subprocess.run( # noqa: S603
47
+ completed_process = subprocess.run( # noqa
48
48
  [self.ruff_bin, *self.ruff_args, *found_files.python_modules], capture_output=True
49
49
  )
50
50
  if not completed_process.stdout:
@@ -59,8 +59,6 @@ class RuffTool(ToolBase):
59
59
  return messages
60
60
  for message in json.loads(completed_process.stdout):
61
61
  sub_message = {}
62
- if message.get("url"):
63
- sub_message["See"] = message["url"]
64
62
  if message.get("fix") and message["fix"].get("applicability"):
65
63
  sub_message["Fix applicability"] = message["fix"]["applicability"]
66
64
  message_str = message.get("message", "")
@@ -77,8 +75,12 @@ class RuffTool(ToolBase):
77
75
  None,
78
76
  line=message.get("location", {}).get("row"),
79
77
  character=message.get("location", {}).get("column"),
78
+ line_end=message.get("end_location", {}).get("row"),
79
+ character_end=message.get("end_location", {}).get("column"),
80
80
  ),
81
81
  message_str,
82
+ doc_url=message.get("url"),
83
+ is_fixable=bool((message.get("fix") or {}).get("applicability") in ("safe", "unsafe")),
82
84
  )
83
85
  )
84
86
  return messages
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prospector
3
- Version: 1.13.3
3
+ Version: 1.14.0
4
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
6
  License: GPLv2+
@@ -2,28 +2,29 @@ prospector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  prospector/__main__.py,sha256=-gdHYZxwq_P8er7HuZEBImY0pwaFq8uIa78dQdJsTTQ,71
3
3
  prospector/autodetect.py,sha256=Ok8S6jpDiGyhQlnRCMWpsLpSAIXWxA-NQphQuPaOm6o,3112
4
4
  prospector/blender.py,sha256=ldQSkfoEKv6pd72B9YCYdapeGUzgfhGzieAu7To3l6Y,4926
5
- prospector/blender_combinations.yaml,sha256=yN7BOUCDomDZVRZzYxsRdxQPLpzxm9TDhv18B_GdLPU,6551
5
+ prospector/blender_combinations.yaml,sha256=38M1G3mjnYXULhSOuwWYbeJncnaK6w1zqwr2W52bjyw,6624
6
6
  prospector/compat.py,sha256=p_2BOebzUcKbUAd7mW8rn6tIc10R96gJuZS71QI0XY4,360
7
7
  prospector/config/__init__.py,sha256=4nYshBncKUvZrwNKmp2bQ2mQ8uRS7GU20xPbiC-nJ9g,14793
8
8
  prospector/config/configuration.py,sha256=sNYR5Jc3P7tfIDXQoDMrOX4i2Yde0o9bc21ZXZNn6rw,14046
9
9
  prospector/config/datatype.py,sha256=u2i3YxtFKXkeGKzrYnc8koI-Xq-Owl74e_XveNhFY8Y,658
10
10
  prospector/encoding.py,sha256=67sbqzcUoQqi3PRm_P3GNGwcL1N56RZ3T_YHmSrICEE,1549
11
11
  prospector/exceptions.py,sha256=3P58RNF7j1n4CUIZ8VM5BVhB4Q6UtVs-dQRG8TRCZ7o,1248
12
- prospector/finder.py,sha256=-gqGVEv6c6FEyKWZIcQ7FquSlVKvpVWsJK9-HkTeg3c,4778
13
- prospector/formatters/__init__.py,sha256=ixMDeM27mmaLBxHmcRYoC1tPPi17SBXS91Rc2dMv30s,467
14
- prospector/formatters/base.py,sha256=SMRvrX1xAQ1aaM8S-wPSH7cbs-x8QEXmLW0PeSf6PIg,1436
12
+ prospector/finder.py,sha256=pmGuxf9Jq5SX1ANHHdnFKLDfFwTk4fKakxnFHuwzpvs,4775
13
+ prospector/formatters/__init__.py,sha256=Ko96rZA7C0vjWdsU80DHdHoCk8PNjfDEQI-AACs3_CI,552
14
+ prospector/formatters/base.py,sha256=f3ku_wbFDk_woCPS15FvLDFQBSw8Bxf9Wytuz8vdplc,1883
15
15
  prospector/formatters/base_summary.py,sha256=C2O6XAU4l-rOHL1q4rA56jO9sU7Sf0sHRvqgiY6PQgw,1410
16
- prospector/formatters/emacs.py,sha256=FwMqdDxCKA51B76ORuSJE1E2xy-glNpORIzAQaw7LUM,807
16
+ prospector/formatters/emacs.py,sha256=lDOxDJSYYLV1gzevO_z7NlM4AUH6JC9EwoEZu6knnqs,724
17
17
  prospector/formatters/grouped.py,sha256=-vD8I3unoO0FBISoUPHZPCa0p-btWMvt1D_UxzmcGDA,1357
18
18
  prospector/formatters/json.py,sha256=_DbZ_Eb0fmZf6qZMXCU__QRXv_awkBisZ-jvGfOr4aw,1000
19
- prospector/formatters/pylint.py,sha256=WAdD9tMYkk4BWfhoqJJBRc2d3xxQ0bJdQXOZU0ZzYTE,2871
19
+ prospector/formatters/pylint.py,sha256=uotSwdXb0eSey4cltbvGVfOVi6bZcb4c7XebfkcexLU,3027
20
+ prospector/formatters/pylint_parseable.py,sha256=o80NQZjPqKIHVfywJTci4ky_FzP4XlPa6ZSXoVPPxnY,2724
20
21
  prospector/formatters/text.py,sha256=5czha8YfdJ9SD6vWLHE85LgB3-d0lHOsxpYhtokRmTU,1611
21
22
  prospector/formatters/vscode.py,sha256=ffP-JmrgZhhdirTj1ldV5fG10hdDiHjRfekSqQpQmx0,1643
22
23
  prospector/formatters/xunit.py,sha256=e5ObAWSLm-ekvWs8xsi-OaIL2yoYedlxuJdUhLZ8gkk,2464
23
24
  prospector/formatters/yaml.py,sha256=0RAL5BaaL9A0DfWZ-bdpK1mwgr8zJ_ULVwlnSXVPlDU,684
24
- prospector/message.py,sha256=ty_e5T7fpZcZb69sAUIgvV-9qHuAx6-Nkq3bP6IVAqw,3279
25
+ prospector/message.py,sha256=HKXdO8bOezRKSnTtjqu0k04Cb7JgL0oPUWakuSBE9s4,3710
25
26
  prospector/pathutils.py,sha256=CyZIj4WXGill8OfnqRvcVqZYX0lzL3QcIxpkxCz-dkE,1219
26
- prospector/postfilter.py,sha256=sbUv8P8XE1-7mXh12iZ539FVBK1JSoC-VmnsQyr6EOk,2201
27
+ prospector/postfilter.py,sha256=3sZXhgyWy1Zs3qlqSchvd8a34j59150_nI1V8-ct-ls,2427
27
28
  prospector/profiles/__init__.py,sha256=q9zPLVEwo7qoouYFrmENsmByFrKKkr27Dd_Wo9btTJI,683
28
29
  prospector/profiles/exceptions.py,sha256=MDky4KXVwfOlW1yCbyp8Y07D8Kfz76jL3z-8T3WQIFI,1062
29
30
  prospector/profiles/profile.py,sha256=U8vDdyfka0_Ht9cYT2i_c-xbMcktSpS1h53cU7tGerk,17828
@@ -36,36 +37,36 @@ prospector/profiles/profiles/no_doc_warnings.yaml,sha256=6Q_g5xNKJlEhM6PvtE1Wb6J
36
37
  prospector/profiles/profiles/no_member_warnings.yaml,sha256=1ImTwpubSHXEwq76aO3jVSE7VvjzZG6BGudAv9reccw,83
37
38
  prospector/profiles/profiles/no_pep8.yaml,sha256=cnjvmO-0kcul-URYJv-kJsaob2Zc4bCUJLiYiIVzN84,348
38
39
  prospector/profiles/profiles/no_test_warnings.yaml,sha256=vDlRgnOr1YhEAwGW2fmTydHYq10k9nrMyQdM-K6H9EA,175
39
- prospector/profiles/profiles/strictness_high.yaml,sha256=4IHE07_JMjZdAz5w_mRFt-kP1sTbQuz5rrPJ3InGm2I,818
40
+ prospector/profiles/profiles/strictness_high.yaml,sha256=o-StUkt9IWs3p1Empt2LTowv3E5jVK6mFl5gAcLGlOo,944
40
41
  prospector/profiles/profiles/strictness_low.yaml,sha256=QONar05NOI_cidCoRASmDFzd7CSk_JC-KVjwDzcPU_8,1066
41
- prospector/profiles/profiles/strictness_medium.yaml,sha256=z8LNJTbACa2L24TCNVfkGA-PUvnZgzJk7yDiDFRj8eo,1836
42
+ prospector/profiles/profiles/strictness_medium.yaml,sha256=ycM66O_oX2nAmq36isxR1pBX4T6ykEIWIo8bJZuS6vg,1887
42
43
  prospector/profiles/profiles/strictness_none.yaml,sha256=_Yf-eEl4cVXw6ePqx3V4mvG80JksH9ggkUqbuAdR5iI,151
43
- prospector/profiles/profiles/strictness_veryhigh.yaml,sha256=m93J1OzGCRVTWrIQbzhYJux9BCC7amdp5e9ePxIkbDY,594
44
+ prospector/profiles/profiles/strictness_veryhigh.yaml,sha256=whQFEUtkySSEIriEwYOjSr-0SxICOWalNA9Y7FmXopQ,628
44
45
  prospector/profiles/profiles/strictness_verylow.yaml,sha256=YxZowcBtA3tAaHJGz2htTdAJ-AXmlHB-o4zEYKPRfJg,833
45
46
  prospector/profiles/profiles/test_warnings.yaml,sha256=arUcV9MnqiZJEHURH9bVRSYDhYUegNc-ltFYe_yQW44,23
46
47
  prospector/run.py,sha256=hjNyzY-wyedGwJspT80jCz4usk-HqL6FmqDcinASJZA,8403
47
- prospector/suppression.py,sha256=5VPSvw1ECIR1_4spf0Q2jUx04GygEoptA4LDFaErYVU,4954
48
+ prospector/suppression.py,sha256=ecRCLcFNl-XygRnV6m2lqc4vLa0Kusb0mLkkYd6YMxw,6135
48
49
  prospector/tools/__init__.py,sha256=9tDmxL_kn5jmAACeSi1jtSvT-9tI468Ccn1Up2wUFi0,2956
49
- prospector/tools/bandit/__init__.py,sha256=oQZANkiQh3MI2HjtLNXbW-yWrtzlbdq2oaGl2_7B4dM,2711
50
+ prospector/tools/bandit/__init__.py,sha256=iU39U28_YP5QUm8sgU21Ps96czIIl6tSV7qtCxbFvms,3035
50
51
  prospector/tools/base.py,sha256=T1F-vq4rNcaToA4fXjZmcozkABpeiz0odFAMVMEJM1w,1838
51
52
  prospector/tools/dodgy/__init__.py,sha256=howLCjFEheW_6ZoyQ15gLbiNNNUr0Pm2qNpLg3kleFY,1648
52
53
  prospector/tools/exceptions.py,sha256=Q-u4n6YzZuoMu17XkeKac1o1gBY36JK4MnvWaYrVYL0,170
53
54
  prospector/tools/mccabe/__init__.py,sha256=80-aYPqKCREeBqxiIUgsDvxc_GqYxHb5R0JduKHPRaE,3277
54
- prospector/tools/mypy/__init__.py,sha256=rv4FVOT0ry7E3DlInjKO1_fa01T7IyrxxC3-weL4RuQ,3504
55
+ prospector/tools/mypy/__init__.py,sha256=edd7hg7Cj1jP_Aoy7J3CzkjIqCrK1wu-lm5ygUQHV3g,3504
55
56
  prospector/tools/profile_validator/__init__.py,sha256=bAkVG-fKtm3WaEv-We36wqzvtqWv4s06Z7YnRVG7UQ4,8326
56
57
  prospector/tools/pycodestyle/__init__.py,sha256=uMpUxqsPsryEsfyfGxpLzwoWUjIvfxIQke4Xvkfbi9A,5970
57
58
  prospector/tools/pydocstyle/__init__.py,sha256=WB-AT-c1FeUUUWATUzJbBLeREtu-lxT03bChh4nablo,2776
58
59
  prospector/tools/pyflakes/__init__.py,sha256=53NQFODU416KO991NxW14gChjagbSAhhfErx1ll7VUQ,5631
59
60
  prospector/tools/pylint/__init__.py,sha256=WoI23QXmGlumgZMRg1-tQJ8Tpzl9_KpLUQIKlb7vEkE,11108
60
- prospector/tools/pylint/collector.py,sha256=OSDV_58EE5C-fykXxDykIji88N1e-GLfHB849HrjefA,1353
61
+ prospector/tools/pylint/collector.py,sha256=7FHgO6OOLGD15_U4DERiXyEbSFnMjGUBeCwdmUlhO8I,1559
61
62
  prospector/tools/pylint/linter.py,sha256=YQ9SOna4WjbbauqSgUio6Ss8zN08PCr3aKdK9rMi7Ag,2143
62
63
  prospector/tools/pyright/__init__.py,sha256=USqauZofh-8ZSKGwXRXoaM2ItzfSFo2nGwPtLGEWICU,3346
63
64
  prospector/tools/pyroma/__init__.py,sha256=GPQRJZfbs_SI0RBTyySz-4SIuM__YoLfXAm7uYVXAS8,3151
64
- prospector/tools/ruff/__init__.py,sha256=HRj2S-I45DCg3y4T6035PvHyRutTPU9Boeh3IWU9_pw,3300
65
+ prospector/tools/ruff/__init__.py,sha256=4ieK1lWmJMW27LvLNcnkufZFexU46N2Cu5Qv_y-BIfk,3525
65
66
  prospector/tools/utils.py,sha256=cRCogsMCH0lPBhdujPsIY0ovNAL6TAxBMohZRES02-4,1770
66
67
  prospector/tools/vulture/__init__.py,sha256=eaTh4X5onNlBMuz1x0rmcRn7x5XDVDgqftjIEd47eWI,3583
67
- prospector-1.13.3.dist-info/entry_points.txt,sha256=SxvCGt8MJTEZefHAvwnUc6jDetgCaaYY1Zpifuk8tqU,50
68
- prospector-1.13.3.dist-info/LICENSE,sha256=WoTRadDy8VbcIKoVzl5Q1QipuD_cexAf3ul4MaVLttc,18044
69
- prospector-1.13.3.dist-info/WHEEL,sha256=gSF7fibx4crkLz_A-IKR6kcuq0jJ64KNCkG8_bcaEao,88
70
- prospector-1.13.3.dist-info/METADATA,sha256=Ds5fPmZfhk-Lnx4mXweNkbi5w6Pwa8g8CP_1LknAMJ0,9962
71
- prospector-1.13.3.dist-info/RECORD,,
68
+ prospector-1.14.0.dist-info/entry_points.txt,sha256=SxvCGt8MJTEZefHAvwnUc6jDetgCaaYY1Zpifuk8tqU,50
69
+ prospector-1.14.0.dist-info/LICENSE,sha256=WoTRadDy8VbcIKoVzl5Q1QipuD_cexAf3ul4MaVLttc,18044
70
+ prospector-1.14.0.dist-info/WHEEL,sha256=gSF7fibx4crkLz_A-IKR6kcuq0jJ64KNCkG8_bcaEao,88
71
+ prospector-1.14.0.dist-info/METADATA,sha256=BnLIKymjwtohSKYyDAoaWKTQHWNoMA9RTVN4ka7v_As,9962
72
+ prospector-1.14.0.dist-info/RECORD,,