CLASPLint 0.4.4__tar.gz → 0.5.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.
Files changed (29) hide show
  1. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/__init__.py +8 -10
  2. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/__main__.py +44 -41
  3. CLASPLint-0.5.0/CLASPLint/checker_base.py +226 -0
  4. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/comment_checker.py +470 -289
  5. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/configuration.py +166 -86
  6. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/configuration.yaml +15 -18
  7. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/dict_key_checker.py +93 -69
  8. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/docstring_checker.py +441 -284
  9. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/function_checker.py +86 -115
  10. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/log_checker.py +155 -216
  11. CLASPLint-0.5.0/CLASPLint/naming_utils.py +759 -0
  12. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/reporter.py +75 -53
  13. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/runner.py +352 -285
  14. CLASPLint-0.5.0/CLASPLint/try_except_checker.py +328 -0
  15. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint/variable_checker.py +308 -217
  16. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/PKG-INFO +70 -60
  17. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/SOURCES.txt +2 -0
  18. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/LICENSE +1 -1
  19. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/PKG-INFO +70 -60
  20. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/README.md +68 -58
  21. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/pyproject.toml +2 -2
  22. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/setup.py +8 -10
  23. CLASPLint-0.4.4/CLASPLint/naming_utils.py +0 -464
  24. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/dependency_links.txt +0 -0
  25. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/entry_points.txt +0 -0
  26. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/not-zip-safe +0 -0
  27. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/CLASPLint.egg-info/top_level.txt +0 -0
  28. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/MANIFEST.in +0 -0
  29. {CLASPLint-0.4.4 → CLASPLint-0.5.0}/setup.cfg +0 -0
@@ -2,8 +2,7 @@
2
2
  """
3
3
  THIS FILE IS CORE PART OF CLASPLINT BY MATT BELFAST BROWN.
4
4
 
5
- ===============================================================================
6
-
5
+ ====================
7
6
  MODULE : CLASPLint.__init__
8
7
 
9
8
  TYPE : Python Script
@@ -11,7 +10,7 @@ TYPE : Python Script
11
10
  DESCRIPTION :
12
11
  Package entry point and public API surface. Exposes the runner and reporter
13
12
  modules as the primary public interface for programmatic use of the CLASP
14
- 3.2 / PEP 2606 static analysis engine.
13
+ Stage 3.3 / PEP 2606 static analysis engine.
15
14
 
16
15
  AUTHOR : Matt Belfast Brown
17
16
 
@@ -23,16 +22,16 @@ MAINTAINER :
23
22
 
24
23
  PROJECT CREATE DATE : 2026-06-17
25
24
 
26
- PROJECT VERSION DATE : 2026-07-06
25
+ PROJECT VERSION DATE : 2026-07-08
27
26
 
28
- PROJECT VERSION : 0.4.4
27
+ PROJECT VERSION : 0.5.0
29
28
 
30
29
 
31
30
  FILE CREATE DATE : 2026-06-17
32
31
 
33
- FILE VERSION DATE : 2026-07-06
32
+ FILE VERSION DATE : 2026-07-08
34
33
 
35
- FILE VERSION : 0.4.1
34
+ FILE VERSION : 0.5.0
36
35
 
37
36
 
38
37
  STATUS : Stable
@@ -50,8 +49,7 @@ USAGE :
50
49
  report = CLASPLint.runner.run(["path/to/code/"])
51
50
  print(report.summary())
52
51
 
53
- ===============================================================================
54
-
52
+ ====================
55
53
  THIS PROGRAM IS LICENSED UNDER GPL-3.0-only LICENSE.
56
54
  YOU SHOULD HAVE RECEIVED A COPY OF GPL-3.0-only LICENSE.
57
55
 
@@ -73,6 +71,6 @@ Sort License:
73
71
  """
74
72
 
75
73
  # Define the package version string.
76
- __version__ = "0.4.4"
74
+ __version__ = "0.5.0"
77
75
  # Expose the runner and reporter modules as the public API.
78
76
  __all__ = ["runner", "reporter"]
@@ -2,14 +2,13 @@
2
2
  """
3
3
  THIS FILE IS CORE PART OF CLASPLINT BY MATT BELFAST BROWN.
4
4
 
5
- ===============================================================================
6
-
5
+ ====================
7
6
  MODULE : CLASPLint.__main__
8
7
 
9
8
  TYPE : Python Script
10
9
 
11
10
  DESCRIPTION :
12
- Command-line entry point for the CLASP 3.2 / PEP 2606 static analysis tool.
11
+ Command-line entry point for the CLASP Stage 3.3 / PEP 2606 static analysis tool.
13
12
 
14
13
  AUTHOR : Matt Belfast Brown
15
14
 
@@ -21,16 +20,16 @@ MAINTAINER :
21
20
 
22
21
  PROJECT CREATE DATE : 2026-06-17
23
22
 
24
- PROJECT VERSION DATE : 2026-07-06
23
+ PROJECT VERSION DATE : 2026-07-08
25
24
 
26
- PROJECT VERSION : 0.4.4
25
+ PROJECT VERSION : 0.5.0
27
26
 
28
27
 
29
28
  FILE CREATE DATE : 2026-06-17
30
29
 
31
- FILE VERSION DATE : 2026-07-06
30
+ FILE VERSION DATE : 2026-07-08
32
31
 
33
- FILE VERSION : 0.4.1
32
+ FILE VERSION : 1.0.0
34
33
 
35
34
 
36
35
  STATUS : Stable
@@ -49,8 +48,7 @@ USAGE :
49
48
 
50
49
  CLASPLint --category variable src/
51
50
 
52
- ===============================================================================
53
-
51
+ ====================
54
52
  THIS PROGRAM IS LICENSED UNDER GPL-3.0-only LICENSE.
55
53
  YOU SHOULD HAVE RECEIVED A COPY OF GPL-3.0-only LICENSE.
56
54
 
@@ -70,36 +68,39 @@ Sort License:
70
68
  You should have received a copy of the GNU General Public License
71
69
  along with CLASPLint. If not, see <https://www.gnu.org/licenses/>.
72
70
  """
73
-
74
71
  import argparse
75
- import sys
76
72
  import os
73
+ import sys
77
74
  from typing import Optional, Sequence
78
75
 
79
- from .runner import run
80
76
  from . import __version__
77
+ from .runner import run
81
78
 
82
79
 
83
80
  def _init_build_parser_function_() -> argparse.ArgumentParser:
84
- """Construct the argument parser for the CLASPLint command-line interface.
81
+ """
82
+ Construct the argument parser for the CLASPLint command-line interface.
85
83
 
86
- Registers positional paths, --version, --no-recursive, --quiet,
87
- and --category arguments on a new ArgumentParser instance.
84
+ Defines the complete CLI surface with five argument groups: positional
85
+ paths for file and directory scanning, a version flag, a recursive-mode
86
+ toggle, a quiet-mode switch for summary-only output, and a category
87
+ filter to restrict violation reporting to a single checker type.
88
88
 
89
89
  :return: A configured ArgumentParser ready for parse_args.
90
90
  :rtype: argparse.ArgumentParser
91
91
  """
92
- # Create the top-level argument parser with a description.
92
+ # Build the description string in progressive segments for readability.
93
+ string_about = f"CLASP Stage 3.3 / PEP 2606 static analysis tool v{__version__}. "
94
+ # Append the first fragment describing what the tool checks.
95
+ string_about += "Checks variable, dict key, function, class naming "
96
+ # Append the final fragment covering remaining convention categories.
97
+ string_about += "and comment/log conventions."
98
+ # Instantiate the parser with the assembled description and program name.
93
99
  parser_result = argparse.ArgumentParser(
94
100
  # Set the program name displayed in help text.
95
101
  prog="CLASPLint",
96
- # Provide a description of what the tool does.
97
- description="CLASP 3.2 / PEP 2606 static analysis tool. "
98
- # Continue the description across multiple lines for readability.
99
- "Checks variable, dict key, function, class naming "
100
- # Complete the tool description with comment and log conventions.
101
- "and comment/log conventions.",
102
- # Close the ArgumentParser constructor call.
102
+ # Supply the pre-built description string to the parser.
103
+ description=string_about,
103
104
  )
104
105
  # Accept one or more file or directory paths as positional arguments.
105
106
  parser_result.add_argument(
@@ -107,7 +108,6 @@ def _init_build_parser_function_() -> argparse.ArgumentParser:
107
108
  "paths", nargs="*", default=["."],
108
109
  # Provide the help text for the paths' argument.
109
110
  help="Python files or directories to check (default: current directory).",
110
- # Close the first add_argument call.
111
111
  )
112
112
  # Provide a --version flag to display the tool version.
113
113
  parser_result.add_argument(
@@ -115,7 +115,6 @@ def _init_build_parser_function_() -> argparse.ArgumentParser:
115
115
  "--version", action="version",
116
116
  # Construct the version message from the package version.
117
117
  version=f"CLASPLint {__version__}",
118
- # Close the second add_argument call.
119
118
  )
120
119
  # Provide a flag to disable recursive directory traversal.
121
120
  parser_result.add_argument(
@@ -123,7 +122,6 @@ def _init_build_parser_function_() -> argparse.ArgumentParser:
123
122
  "--no-recursive", action="store_true",
124
123
  # Provide the help text for the no-recursive flag.
125
124
  help="Do not recursively check subdirectories.",
126
- # Close the third add_argument call.
127
125
  )
128
126
  # Provide a quiet mode that suppresses per-violation output.
129
127
  parser_result.add_argument(
@@ -131,27 +129,30 @@ def _init_build_parser_function_() -> argparse.ArgumentParser:
131
129
  "--quiet", "-q", action="store_true",
132
130
  # Provide the help text for the quiet flag.
133
131
  help="Suppress individual violation output; show only summary.",
134
- # Close the fourth add_argument call.
135
132
  )
136
133
  # Provide a category filter to report only specific violation types.
137
134
  parser_result.add_argument(
138
135
  # Accept --category or -c with a choice of violation types.
139
136
  "--category", "-c",
140
137
  # Restrict the value to the five supported violation categories.
141
- choices=["variable", "dict_key", "function", "comment", "log", "docstring"],
138
+ choices=["variable", "dict_key", "function", "comment", "log", "docstring", "tryexcept"],
142
139
  # Provide the help text for the category filter.
143
140
  help="Only report violations of a specific category.",
144
- # Close the fifth add_argument call.
145
141
  )
146
142
  # Return the fully configured argument parser.
147
143
  return parser_result
148
144
 
149
145
 
150
146
  def main(argv: Optional[Sequence[str]] = None) -> int:
151
- """Execute the CLASPLint analysis and return an exit code.
147
+ """
148
+ Execute the CLASPLint analysis and return an exit code.
149
+
150
+ Interprets command-line arguments to discover Python source files,
151
+ dispatches each file through the full checker pipeline, narrows
152
+ results by an optional category filter, and prints a formatted
153
+ summary followed by individual violation details when requested.
152
154
 
153
- Parses command-line arguments, resolves input paths, dispatches
154
- to the runner, applies category filters, and prints the report.
155
+ The parameters are as follows:
155
156
 
156
157
  :param argv: Optional list of command-line argument strings.
157
158
  :type argv: Optional[Sequence[str]]
@@ -182,16 +183,18 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
182
183
  bool_recursive = not parsed_options.no_recursive
183
184
  # Run all checkers on the resolved paths.
184
185
  report_result = run(list_resolved, bool_recursive=bool_recursive)
185
- # Apply category filter if one was specified.
186
+ # Filter violations to only the requested category.
186
187
  if parsed_options.category:
187
- # Filter violations to only the requested category.
188
- report_result.list_violations = [
189
- # Iterate over each violation to check against the filter.
190
- violation_item for violation_item in report_result.list_violations
191
- # Keep only violations matching the requested category filter.
192
- if violation_item.string_category == parsed_options.category
193
- # Close the filtered list comprehension.
194
- ]
188
+ # Build a filtered list excluding non-matching categories.
189
+ list_filtered = []
190
+ # Iterate through each violation for category comparison.
191
+ for violation_item in report_result.list_violations:
192
+ # Include violations whose category matches the filter.
193
+ if violation_item.string_category == parsed_options.category:
194
+ # Add the matching violation to the filtered list.
195
+ list_filtered.append(violation_item)
196
+ # Replace the violations with the filtered subset.
197
+ report_result.list_violations = list_filtered
195
198
  # Print the summary line to stdout.
196
199
  print(report_result.summary())
197
200
  # Print individual violations unless quiet mode is active.
@@ -0,0 +1,226 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ THIS FILE IS CORE PART OF CLASPLINT BY MATT BELFAST BROWN.
4
+
5
+ ====================
6
+ MODULE : CLASPLint.checker_base
7
+
8
+ TYPE : Python Script
9
+
10
+ DESCRIPTION :
11
+ Base class providing shared infrastructure for CLASP Stage 3.3 AST checkers.
12
+ Supports source line extraction, violation recording, and previous line
13
+ retrieval for both log and try-except validation visitors.
14
+
15
+ AUTHOR : Matt Belfast Brown
16
+
17
+ CONTACT : thedayofthedo@gmail.com
18
+
19
+ MAINTAINER :
20
+ Matt Belfast Brown (thedayofthedo@gmail.com)
21
+
22
+
23
+ PROJECT CREATE DATE : 2026-06-17
24
+
25
+ PROJECT VERSION DATE : 2026-07-08
26
+
27
+ PROJECT VERSION : 0.5.0
28
+
29
+
30
+ FILE CREATE DATE : 2026-07-08
31
+
32
+ FILE VERSION DATE : 2026-07-08
33
+
34
+ FILE VERSION : 1.0.0
35
+
36
+
37
+ STATUS : Stable
38
+
39
+ PYTHON : >=3.8
40
+
41
+ LICENSE : GPL-3.0-only
42
+
43
+ SPDX ID : GPL-3.0-only
44
+
45
+
46
+ USAGE :
47
+ from CLASPLint.checker_base import CheckerBase
48
+
49
+ class MyChecker(CheckerBase):
50
+ def visit_SomeNode(self, node):
51
+ source = self.extract_source_line(node)
52
+ self.record_violation(node, "Violation message.", "mycategory")
53
+ previous = self.extract_previous_line(node.lineno)
54
+
55
+ ====================
56
+ THIS PROGRAM IS LICENSED UNDER GPL-3.0-only LICENSE.
57
+ YOU SHOULD HAVE RECEIVED A COPY OF GPL-3.0-only LICENSE.
58
+
59
+ Copyright (C) 2026 Matt Belfast Brown.
60
+
61
+ Sort License:
62
+
63
+ CLASPLint is free software: you can redistribute it and/or modify
64
+ it under the terms of the GNU General Public License as published by
65
+ the Free Software Foundation, version 3 of the License.
66
+
67
+ CLASPLint is distributed in the hope that it will be useful,
68
+ but WITHOUT ANY WARRANTY; without even the implied warranty
69
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70
+ GNU General Public License for more details.
71
+
72
+ You should have received a copy of the GNU General Public License
73
+ along with CLASPLint. If not, see <https://www.gnu.org/licenses/>.
74
+ """
75
+
76
+ import ast
77
+ from typing import List
78
+
79
+ from .reporter import Violation
80
+
81
+
82
+ class CheckerBase(ast.NodeVisitor):
83
+ """
84
+ CheckerBase CLASS IS CORE PART OF CLASPLINT CHECKER_BASE.
85
+
86
+ CLASPLint.checker_base.CheckerBase:
87
+ Base AST visitor class providing shared infrastructure for CLASP
88
+ Stage 3.3 checkers. Handles source line extraction, violation
89
+ recording, and previous line retrieval for derived checker classes.
90
+
91
+ ATTRIBUTES :
92
+ file_path (str): Path to the file being checked.
93
+ source_lines (list): Source lines for contextual messages.
94
+ list_violations (list): Collected violations from derived checkers.
95
+
96
+ PUBLIC METHODS :
97
+ extract_source_line(code_node: ast.AST) -> str:
98
+ Retrieve the source line text for a given AST node.
99
+ record_violation(code_node: ast.AST, string_message: str, string_category: str) -> None:
100
+ Record a violation with the specified category and source context.
101
+ extract_previous_line(int_lineno: int) -> str:
102
+ Get the source line immediately before the given line number.
103
+
104
+ PRIVATE METHODS :
105
+ None.
106
+
107
+ USAGE :
108
+ class MyChecker(CheckerBase):
109
+ def visit_SomeNode(self, node):
110
+ source = self.extract_source_line(node)
111
+ self.record_violation(node, "Message.", "mycategory")
112
+
113
+ WARNING :
114
+ Private methods should not be called from outside the class.
115
+ """
116
+
117
+ def __init__(self, file_path: str, source_lines: List[str]):
118
+ """
119
+ Initialize the checker base with file path and source lines.
120
+
121
+ Stores the file path and source lines for later use during AST traversal
122
+ and initializes an empty violations list for derived checkers.
123
+
124
+ The parameters are as follows:
125
+
126
+ :param file_path: Path to the file being checked.
127
+ :type file_path: str
128
+ :param source_lines: Source lines of the file for contextual messages.
129
+ :type source_lines: List[str]
130
+ """
131
+ # Store the file path for violation reporting.
132
+ self.file_path = file_path
133
+ # Store source lines for contextual violation messages.
134
+ self.source_lines = source_lines
135
+ # Collect violations found during AST traversal.
136
+ self.list_violations: List[Violation] = []
137
+
138
+ def extract_source_line(self, code_node: ast.AST) -> str:
139
+ """
140
+ Retrieve the source line text for a given AST node.
141
+
142
+ Uses the node line number to index into the stored source lines list
143
+ and returns the full source line text for violation context messages.
144
+
145
+ The parameters are as follows:
146
+
147
+ :param code_node: The AST node whose source line text is needed.
148
+ :type code_node: ast.AST
149
+ :return: The source line corresponding to the node, or an empty string.
150
+ :rtype: str
151
+ """
152
+ # Retrieve the line number from the node attributes.
153
+ int_lineno = getattr(code_node, 'lineno', 0)
154
+ # Guard against nodes without line numbers or out-of-range indices.
155
+ if int_lineno and int_lineno <= len(self.source_lines):
156
+ # Return the corresponding source line string.
157
+ return self.source_lines[int_lineno - 1]
158
+ # Return an empty string for unavailable line numbers.
159
+ return ""
160
+
161
+ def record_violation(
162
+ # Accept the self-reference for this instance method invocation.
163
+ self,
164
+ # Define the AST node where the violation was detected.
165
+ code_node: ast.AST,
166
+ # Define the message identifier for the violation.
167
+ string_message: str,
168
+ # Define the category identifier for violation classification.
169
+ string_category: str
170
+ # Return nothing after recording the violation in the internal list.
171
+ ) -> None:
172
+ """
173
+ Record a violation with the specified category and source context.
174
+
175
+ Constructs a Violation instance with file path, node line number,
176
+ the given category string, the message, and the source line. Appends
177
+ the violation to the internal list for later collection.
178
+
179
+ The parameters are as follows:
180
+
181
+ :param code_node: The AST node where the violation was detected.
182
+ :type code_node: ast.AST
183
+ :param string_message: The human-readable violation message.
184
+ :type string_message: str
185
+ :param string_category: The violation category identifier.
186
+ :type string_category: str
187
+ """
188
+ # Append a new Violation to the internal list with full context.
189
+ self.list_violations.append(
190
+ # Create a Violation data class instance.
191
+ Violation(
192
+ # Supply the file path for the violation location.
193
+ file_path=self.file_path,
194
+ # Extract the line number from the AST node.
195
+ int_linenumber=getattr(code_node, 'lineno', 0),
196
+ # Assign the caller-provided violation category identifier.
197
+ string_category=string_category,
198
+ # Assign the human-readable violation message.
199
+ string_message=string_message,
200
+ # Extract the source line for contextual display.
201
+ source_line=self.extract_source_line(code_node),
202
+ )
203
+ )
204
+
205
+ def extract_previous_line(self, int_lineno: int) -> str:
206
+ """
207
+ Get the source line immediately before the given line number.
208
+
209
+ Used by derived checkers to verify comment presence before statements
210
+ such as raise or return.
211
+
212
+ The parameters are as follows:
213
+
214
+ :param int_lineno: The line number to look before (1-based).
215
+ :type int_lineno: int
216
+ :return: The previous source line string, or an empty string.
217
+ :rtype: str
218
+ """
219
+ # Calculate the zero-based index of the previous line.
220
+ int_index = int_lineno - 2
221
+ # Guard against negative indices when checking line 1.
222
+ if 0 <= int_index < len(self.source_lines):
223
+ # Return the source line immediately before the target line.
224
+ return self.source_lines[int_index]
225
+ # Return an empty string when no previous line exists.
226
+ return ""