python-code-validator 0.2.1__tar.gz → 0.4.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 (36) hide show
  1. {python_code_validator-0.2.1/src/python_code_validator.egg-info → python_code_validator-0.4.0}/PKG-INFO +24 -2
  2. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/pyproject.toml +3 -3
  3. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/__init__.py +57 -57
  4. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/cli.py +26 -10
  5. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/components/definitions.py +91 -89
  6. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/components/factories.py +262 -262
  7. python_code_validator-0.4.0/src/code_validator/components/typo_detection/__init__.py +25 -0
  8. python_code_validator-0.4.0/src/code_validator/components/typo_detection/algorithms.py +117 -0
  9. python_code_validator-0.4.0/src/code_validator/components/typo_detection/detector.py +292 -0
  10. python_code_validator-0.4.0/src/code_validator/components/typo_detection/formatters.py +230 -0
  11. python_code_validator-0.4.0/src/code_validator/components/typo_detection/scope_analyzer.py +211 -0
  12. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/config.py +4 -2
  13. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/core.py +289 -223
  14. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/output.py +247 -236
  15. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/rules_library/basic_rules.py +201 -174
  16. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/rules_library/constraint_logic.py +81 -0
  17. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/rules_library/selector_nodes.py +473 -380
  18. {python_code_validator-0.2.1 → python_code_validator-0.4.0/src/python_code_validator.egg-info}/PKG-INFO +24 -2
  19. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/python_code_validator.egg-info/SOURCES.txt +6 -0
  20. python_code_validator-0.4.0/tests/test_scope_validation.py +196 -0
  21. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/tests/test_validator.py +11 -9
  22. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/LICENSE +0 -0
  23. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/README.md +0 -0
  24. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/setup.cfg +0 -0
  25. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/__main__.py +0 -0
  26. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/components/__init__.py +0 -0
  27. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/components/ast_utils.py +0 -0
  28. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/components/scope_handler.py +0 -0
  29. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/exceptions.py +0 -0
  30. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/code_validator/rules_library/__init__.py +0 -0
  31. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/python_code_validator.egg-info/dependency_links.txt +0 -0
  32. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/python_code_validator.egg-info/entry_points.txt +0 -0
  33. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/python_code_validator.egg-info/requires.txt +0 -0
  34. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/src/python_code_validator.egg-info/top_level.txt +0 -0
  35. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/tests/test_components.py +0 -0
  36. {python_code_validator-0.2.1 → python_code_validator-0.4.0}/tests/test_scope_handler.py +0 -0
@@ -1,9 +1,30 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-code-validator
3
- Version: 0.2.1
3
+ Version: 0.4.0
4
4
  Summary: A flexible, AST-based framework for static validation of Python code using declarative JSON rules.
5
5
  Author-email: Qu1nel <covach.qn@gmail.com>
6
- License-Expression: MIT
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Ivan Kovach
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
7
28
  Project-URL: Homepage, https://github.com/Qu1nel/PythonCodeValidator
8
29
  Project-URL: Documentation, https://pythoncodevalidator.readthedocs.io/en/latest/
9
30
  Project-URL: Bug Tracker, https://github.com/Qu1nel/PythonCodeValidator/issues
@@ -14,6 +35,7 @@ Classifier: Intended Audience :: Education
14
35
  Classifier: Programming Language :: Python :: 3
15
36
  Classifier: Programming Language :: Python :: 3.11
16
37
  Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: License :: OSI Approved :: MIT License
17
39
  Classifier: Operating System :: OS Independent
18
40
  Classifier: Topic :: Software Development :: Quality Assurance
19
41
  Classifier: Topic :: Software Development :: Testing
@@ -10,14 +10,13 @@ build-backend = "setuptools.build_meta"
10
10
  # ==============================================================================
11
11
  [project]
12
12
  name = "python-code-validator"
13
- version = "0.2.1"
13
+ version = "0.4.0"
14
14
  description = "A flexible, AST-based framework for static validation of Python code using declarative JSON rules."
15
15
  keywords = ["validation", "linter", "static analysis", "testing", "education", "ast"]
16
16
  authors = [{ name = "Qu1nel", email = "covach.qn@gmail.com" }]
17
17
  readme = "README.md"
18
18
  requires-python = ">=3.11"
19
- license-files = ["LICEN[CS]E*"]
20
- license = "MIT"
19
+ license = { file = "LICENSE" }
21
20
  classifiers = [
22
21
  "Development Status :: 4 - Beta",
23
22
  "Intended Audience :: Developers",
@@ -25,6 +24,7 @@ classifiers = [
25
24
  "Programming Language :: Python :: 3",
26
25
  "Programming Language :: Python :: 3.11",
27
26
  "Programming Language :: Python :: 3.12",
27
+ "License :: OSI Approved :: MIT License",
28
28
  "Operating System :: OS Independent",
29
29
  "Topic :: Software Development :: Quality Assurance",
30
30
  "Topic :: Software Development :: Testing",
@@ -1,57 +1,57 @@
1
- """A flexible framework for static validation of Python code.
2
-
3
- This package provides a comprehensive toolkit for statically analyzing Python
4
- source code based on a declarative set of rules defined in a JSON format. It
5
- allows for checking syntax, style, structure, and constraints without
6
- executing the code.
7
-
8
- The primary entry point for using this package programmatically is the
9
- `StaticValidator` class.
10
-
11
- Example:
12
- A minimal example of using the validator as a library.
13
-
14
- .. code-block:: python
15
-
16
- from code_validator import StaticValidator, AppConfig, LogLevel
17
- from code_validator.output import Console, setup_logging
18
- from pathlib import Path
19
-
20
- # Basic setup
21
- logger = setup_logging(LogLevel.INFO)
22
- console = Console(logger)
23
- config = AppConfig(
24
- solution_path=Path("path/to/solution.py"),
25
- rules_path=Path("path/to/rules.json"),
26
- log_level=LogLevel.INFO,
27
- is_silent=False,
28
- stop_on_first_fail=False
29
- )
30
-
31
- # Run validation
32
- validator = StaticValidator(config, console)
33
- is_valid = validator.run()
34
-
35
- if is_valid:
36
- print("Validation Passed!")
37
-
38
- Attributes:
39
- __version__ (str): The current version of the package.
40
- __all__ (list[str]): The list of public objects exposed by the package.
41
-
42
- """
43
-
44
- from .config import AppConfig, ExitCode, LogLevel
45
- from .core import StaticValidator
46
- from .exceptions import RuleParsingError, ValidationFailedError
47
-
48
- __all__ = [
49
- "StaticValidator",
50
- "AppConfig",
51
- "ExitCode",
52
- "LogLevel",
53
- "ValidationFailedError",
54
- "RuleParsingError",
55
- ]
56
-
57
- __version__ = "0.2.1"
1
+ """A flexible framework for static validation of Python code.
2
+
3
+ This package provides a comprehensive toolkit for statically analyzing Python
4
+ source code based on a declarative set of rules defined in a JSON format. It
5
+ allows for checking syntax, style, structure, and constraints without
6
+ executing the code.
7
+
8
+ The primary entry point for using this package programmatically is the
9
+ `StaticValidator` class.
10
+
11
+ Example:
12
+ A minimal example of using the validator as a library.
13
+
14
+ .. code-block:: python
15
+
16
+ from code_validator import StaticValidator, AppConfig, LogLevel
17
+ from code_validator.output import Console, setup_logging
18
+ from pathlib import Path
19
+
20
+ # Basic setup
21
+ logger = setup_logging(LogLevel.INFO)
22
+ console = Console(logger)
23
+ config = AppConfig(
24
+ solution_path=Path("path/to/solution.py"),
25
+ rules_path=Path("path/to/rules.json"),
26
+ log_level=LogLevel.INFO,
27
+ is_silent=False,
28
+ stop_on_first_fail=False
29
+ )
30
+
31
+ # Run validation
32
+ validator = StaticValidator(config, console)
33
+ is_valid = validator.run()
34
+
35
+ if is_valid:
36
+ print("Validation Passed!")
37
+
38
+ Attributes:
39
+ __version__ (str): The current version of the package.
40
+ __all__ (list[str]): The list of public objects exposed by the package.
41
+
42
+ """
43
+
44
+ from .config import AppConfig, ExitCode, LogLevel
45
+ from .core import StaticValidator
46
+ from .exceptions import RuleParsingError, ValidationFailedError
47
+
48
+ __all__ = [
49
+ "StaticValidator",
50
+ "AppConfig",
51
+ "ExitCode",
52
+ "LogLevel",
53
+ "ValidationFailedError",
54
+ "RuleParsingError",
55
+ ]
56
+
57
+ __version__ = "0.4.0"
@@ -43,13 +43,22 @@ def setup_arg_parser() -> argparse.ArgumentParser:
43
43
  "--log",
44
44
  type=LogLevel,
45
45
  default=LogLevel.ERROR,
46
- help=("Set the logging level for stderr (TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL). Default: ERROR."),
46
+ help="Set the logging level for stderr (TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL). Default: ERROR.",
47
47
  )
48
48
  parser.add_argument(
49
49
  "--quiet", action="store_true", help="Suppress all stdout output (validation errors and final verdict)."
50
50
  )
51
51
  parser.add_argument("--no-verdict", action="store_true", help="Suppress stdout output verdict, show failed rules.")
52
- parser.add_argument("--stop-on-first-fail", action="store_true", help="Stop after the first failed rule.")
52
+ parser.add_argument(
53
+ "--max-messages",
54
+ type=int,
55
+ default=0,
56
+ metavar="N",
57
+ help="Maximum number of error messages to display. 0 for no limit. Default: 0.",
58
+ )
59
+ parser.add_argument(
60
+ "-x", "--exit-on-first-error", action="store_true", help="Exit instantly on the first error found."
61
+ )
53
62
  parser.add_argument("--version", "-v", action="version", version=f"%(prog)s {__version__}")
54
63
  return parser
55
64
 
@@ -79,7 +88,8 @@ def run_from_cli() -> None:
79
88
  rules_path=args.rules_path,
80
89
  log_level=args.log,
81
90
  is_quiet=args.quiet,
82
- stop_on_first_fail=args.stop_on_first_fail,
91
+ exit_on_first_error=args.exit_on_first_error,
92
+ max_messages=args.max_messages,
83
93
  )
84
94
  console.print(f"Config is: {config}", level=LogLevel.TRACE)
85
95
 
@@ -95,18 +105,24 @@ def run_from_cli() -> None:
95
105
  console.print("Validation successful.", level=LogLevel.INFO, is_verdict=True)
96
106
  sys.exit(ExitCode.SUCCESS)
97
107
  else:
98
- console.print("Validation failed.", level=LogLevel.INFO, is_verdict=True)
108
+ console.print("Validation failed.", level=LogLevel.WARNING, is_verdict=True)
99
109
  sys.exit(ExitCode.VALIDATION_FAILED)
100
110
 
101
111
  except CodeValidatorError as e:
102
- console.print("Error: Internal Error of validator!", level=LogLevel.CRITICAL)
103
- logger.exception(f"Traceback for CodeValidatorError: {e}")
112
+ console.print(
113
+ f"Error: An internal validator error occurred: {e}", level=LogLevel.CRITICAL, show_user=True, exc_info=True
114
+ )
104
115
  sys.exit(ExitCode.VALIDATION_FAILED)
105
116
  except FileNotFoundError as e:
106
- console.print(f"Error: File not found - {e.filename}!", level=LogLevel.CRITICAL)
107
- logger.exception(f"Traceback for FileNotFoundError: {e}")
117
+ console.print(
118
+ f"Error: Input file not found: {e.filename}", level=LogLevel.CRITICAL, show_user=True, exc_info=True
119
+ )
108
120
  sys.exit(ExitCode.FILE_NOT_FOUND)
109
121
  except Exception as e:
110
- console.print(f"An unexpected error occurred: {e.__class__.__name__}!", level=LogLevel.CRITICAL)
111
- logger.exception(f"Traceback for unexpected error: {e}")
122
+ console.print(
123
+ f"Error: An unexpected error occurred: {e.__class__.__name__}. See logs for detailed traceback.",
124
+ level=LogLevel.CRITICAL,
125
+ show_user=True,
126
+ exc_info=True,
127
+ )
112
128
  sys.exit(ExitCode.UNEXPECTED_ERROR)
@@ -1,89 +1,91 @@
1
- """Defines the core component interfaces for the validator using Protocols.
2
-
3
- This module establishes the fundamental "contracts" for the main architectural
4
- components: Rules, Selectors, and Constraints. By using `typing.Protocol`, we
5
- ensure that any class conforming to these interfaces can be used interchangeably
6
- by the system's factories and core engine. This enables a flexible and
7
- decoupled plugin-style architecture, where new components can be added without
8
- modifying the core logic.
9
- """
10
-
11
- import ast
12
- from typing import Protocol, runtime_checkable
13
-
14
- from ..config import FullRuleConfig, ShortRuleConfig
15
-
16
-
17
- @runtime_checkable
18
- class Selector(Protocol):
19
- """An interface for objects that find and select specific nodes from an AST.
20
-
21
- A Selector's main responsibility is to traverse the Abstract Syntax Tree (AST)
22
- of a Python source file and return a list of nodes that match a specific
23
- criterion (e.g., all function definitions, all import statements).
24
- """
25
-
26
- def select(self, tree: ast.Module) -> list[ast.AST]:
27
- """Selects and returns a list of relevant AST nodes from the tree.
28
-
29
- Args:
30
- tree: The full, parsed AST of the source code to be searched.
31
-
32
- Returns:
33
- A list of ast.AST nodes that match the selector's criteria.
34
- An empty list should be returned if no matching nodes are found.
35
- """
36
- ...
37
-
38
-
39
- @runtime_checkable
40
- class Constraint(Protocol):
41
- """An interface for objects that apply a condition to a set of AST nodes.
42
-
43
- A Constraint takes the list of nodes found by a Selector and checks if they
44
- satisfy a specific condition (e.g., the list must not be empty, the node
45
- must inherit from a specific class).
46
- """
47
-
48
- def check(self, nodes: list[ast.AST]) -> bool:
49
- """Checks if the given list of nodes satisfies the constraint.
50
-
51
- Args:
52
- nodes: A list of AST nodes provided by a Selector.
53
-
54
- Returns:
55
- True if the constraint is satisfied, False otherwise.
56
- """
57
- ...
58
-
59
-
60
- @runtime_checkable
61
- class Rule(Protocol):
62
- """An interface for any complete, executable validation rule.
63
-
64
- A Rule represents a single, self-contained validation check. It can be a
65
- "short" rule (like a linter check) or a "full" rule that internally uses
66
- a Selector and a Constraint. The core validator engine interacts with
67
- objects conforming to this protocol.
68
-
69
- Attributes:
70
- config: The dataclass object holding the configuration for this rule,
71
- parsed from the JSON file.
72
- """
73
-
74
- config: FullRuleConfig | ShortRuleConfig
75
-
76
- def execute(self, tree: ast.Module | None, source_code: str | None = None) -> bool:
77
- """Executes the validation rule.
78
-
79
- Depending on the rule type, this method might operate on the AST, the
80
- raw source code, or both.
81
-
82
- Args:
83
- tree: The full AST of the source code (for structural checks).
84
- source_code: The raw source code string (e.g., for linter checks).
85
-
86
- Returns:
87
- True if the validation check passes, False otherwise.
88
- """
89
- ...
1
+ """Defines the core component interfaces for the validator using Protocols.
2
+
3
+ This module establishes the fundamental "contracts" for the main architectural
4
+ components: Rules, Selectors, and Constraints. By using `typing.Protocol`, we
5
+ ensure that any class conforming to these interfaces can be used interchangeably
6
+ by the system's factories and core engine. This enables a flexible and
7
+ decoupled plugin-style architecture, where new components can be added without
8
+ modifying the core logic.
9
+ """
10
+
11
+ import ast
12
+ from typing import Protocol, runtime_checkable
13
+
14
+ from ..config import FullRuleConfig, ShortRuleConfig
15
+
16
+
17
+ @runtime_checkable
18
+ class Selector(Protocol):
19
+ """An interface for objects that find and select specific nodes from an AST.
20
+
21
+ A Selector's main responsibility is to traverse the Abstract Syntax Tree (AST)
22
+ of a Python source file and return a list of nodes that match a specific
23
+ criterion (e.g., all function definitions, all import statements).
24
+ """
25
+
26
+ def select(self, tree: ast.Module) -> list[ast.AST]:
27
+ """Selects and returns a list of relevant AST nodes from the tree.
28
+
29
+ Args:
30
+ tree: The full, parsed AST of the source code to be searched.
31
+
32
+ Returns:
33
+ A list of ast.AST nodes that match the selector's criteria.
34
+ An empty list should be returned if no matching nodes are found.
35
+ """
36
+ ...
37
+
38
+
39
+ @runtime_checkable
40
+ class Constraint(Protocol):
41
+ """An interface for objects that apply a condition to a set of AST nodes.
42
+
43
+ A Constraint takes the list of nodes found by a Selector and checks if they
44
+ satisfy a specific condition (e.g., the list must not be empty, the node
45
+ must inherit from a specific class).
46
+ """
47
+
48
+ def check(self, nodes: list[ast.AST]) -> bool:
49
+ """Checks if the given list of nodes satisfies the constraint.
50
+
51
+ Args:
52
+ nodes: A list of AST nodes provided by a Selector.
53
+
54
+ Returns:
55
+ True if the constraint is satisfied, False otherwise.
56
+ """
57
+ ...
58
+
59
+
60
+ @runtime_checkable
61
+ class Rule(Protocol):
62
+ """An interface for any complete, executable validation rule.
63
+
64
+ A Rule represents a single, self-contained validation check. It can be a
65
+ "short" rule (like a linter check) or a "full" rule that internally uses
66
+ a Selector and a Constraint. The core validator engine interacts with
67
+ objects conforming to this protocol.
68
+
69
+ Attributes:
70
+ config: The dataclass object holding the configuration for this rule,
71
+ parsed from the JSON file.
72
+ typo_suggestion: Optional typo suggestion message for user display.
73
+ """
74
+
75
+ config: FullRuleConfig | ShortRuleConfig
76
+ typo_suggestion: str | None
77
+
78
+ def execute(self, tree: ast.Module | None, source_code: str | None = None) -> bool:
79
+ """Executes the validation rule.
80
+
81
+ Depending on the rule type, this method might operate on the AST, the
82
+ raw source code, or both.
83
+
84
+ Args:
85
+ tree: The full AST of the source code (for structural checks).
86
+ source_code: The raw source code string (e.g., for linter checks).
87
+
88
+ Returns:
89
+ True if the validation check passes, False otherwise.
90
+ """
91
+ ...