]> crepu.dev Git - config.git/blame - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/flake8/statistics.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / flake8 / statistics.py
CommitLineData
53e6db90
DC
1"""Statistic collection logic for Flake8."""
2from __future__ import annotations
3
4from typing import Generator
5from typing import NamedTuple
6
7from flake8.violation import Violation
8
9
10class Statistics:
11 """Manager of aggregated statistics for a run of Flake8."""
12
13 def __init__(self) -> None:
14 """Initialize the underlying dictionary for our statistics."""
15 self._store: dict[Key, Statistic] = {}
16
17 def error_codes(self) -> list[str]:
18 """Return all unique error codes stored.
19
20 :returns:
21 Sorted list of error codes.
22 """
23 return sorted({key.code for key in self._store})
24
25 def record(self, error: Violation) -> None:
26 """Add the fact that the error was seen in the file.
27
28 :param error:
29 The Violation instance containing the information about the
30 violation.
31 """
32 key = Key.create_from(error)
33 if key not in self._store:
34 self._store[key] = Statistic.create_from(error)
35 self._store[key].increment()
36
37 def statistics_for(
38 self, prefix: str, filename: str | None = None
39 ) -> Generator[Statistic, None, None]:
40 """Generate statistics for the prefix and filename.
41
42 If you have a :class:`Statistics` object that has recorded errors,
43 you can generate the statistics for a prefix (e.g., ``E``, ``E1``,
44 ``W50``, ``W503``) with the optional filter of a filename as well.
45
46 .. code-block:: python
47
48 >>> stats = Statistics()
49 >>> stats.statistics_for('E12',
50 filename='src/flake8/statistics.py')
51 <generator ...>
52 >>> stats.statistics_for('W')
53 <generator ...>
54
55 :param prefix:
56 The error class or specific error code to find statistics for.
57 :param filename:
58 (Optional) The filename to further filter results by.
59 :returns:
60 Generator of instances of :class:`Statistic`
61 """
62 matching_errors = sorted(
63 key for key in self._store if key.matches(prefix, filename)
64 )
65 for error_code in matching_errors:
66 yield self._store[error_code]
67
68
69class Key(NamedTuple):
70 """Simple key structure for the Statistics dictionary.
71
72 To make things clearer, easier to read, and more understandable, we use a
73 namedtuple here for all Keys in the underlying dictionary for the
74 Statistics object.
75 """
76
77 filename: str
78 code: str
79
80 @classmethod
81 def create_from(cls, error: Violation) -> Key:
82 """Create a Key from :class:`flake8.violation.Violation`."""
83 return cls(filename=error.filename, code=error.code)
84
85 def matches(self, prefix: str, filename: str | None) -> bool:
86 """Determine if this key matches some constraints.
87
88 :param prefix:
89 The error code prefix that this key's error code should start with.
90 :param filename:
91 The filename that we potentially want to match on. This can be
92 None to only match on error prefix.
93 :returns:
94 True if the Key's code starts with the prefix and either filename
95 is None, or the Key's filename matches the value passed in.
96 """
97 return self.code.startswith(prefix) and (
98 filename is None or self.filename == filename
99 )
100
101
102class Statistic:
103 """Simple wrapper around the logic of each statistic.
104
105 Instead of maintaining a simple but potentially hard to reason about
106 tuple, we create a class which has attributes and a couple
107 convenience methods on it.
108 """
109
110 def __init__(
111 self, error_code: str, filename: str, message: str, count: int
112 ) -> None:
113 """Initialize our Statistic."""
114 self.error_code = error_code
115 self.filename = filename
116 self.message = message
117 self.count = count
118
119 @classmethod
120 def create_from(cls, error: Violation) -> Statistic:
121 """Create a Statistic from a :class:`flake8.violation.Violation`."""
122 return cls(
123 error_code=error.code,
124 filename=error.filename,
125 message=error.text,
126 count=0,
127 )
128
129 def increment(self) -> None:
130 """Increment the number of times we've seen this error in this file."""
131 self.count += 1