python-code-validator 0.1.2__py3-none-any.whl → 0.2.1__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.
@@ -3,7 +3,8 @@
3
3
  Each class in this module implements the `Selector` protocol and is responsible
4
4
  for finding and returning specific types of nodes from an Abstract Syntax Tree.
5
5
  They use `ast.walk` to traverse the tree and can be constrained to specific
6
- scopes using the ScopedSelector base class.
6
+ scopes via the `ScopedSelector` base class, which uses the `scope_handler`.
7
+ These classes are instantiated by the `SelectorFactory`.
7
8
  """
8
9
 
9
10
  import ast
@@ -12,6 +13,7 @@ from typing import Any
12
13
  from ..components.ast_utils import get_full_name
13
14
  from ..components.definitions import Selector
14
15
  from ..components.scope_handler import find_scope_node
16
+ from ..output import LogLevel, log_initialization
15
17
 
16
18
 
17
19
  class ScopedSelector(Selector):
@@ -27,11 +29,11 @@ class ScopedSelector(Selector):
27
29
  """
28
30
 
29
31
  def __init__(self, **kwargs: Any):
30
- """Initializes the ScopedSelector.
32
+ """Initializes the ScopedSelector base class.
31
33
 
32
34
  Args:
33
- **kwargs: Keyword arguments containing the scope configuration.
34
- Expects `in_scope` key.
35
+ **kwargs: Keyword arguments passed from a subclass constructor.
36
+ It extracts the `in_scope` configuration.
35
37
  """
36
38
  self.in_scope_config = kwargs.get("in_scope")
37
39
 
@@ -66,7 +68,14 @@ class FunctionDefSelector(ScopedSelector):
66
68
  name (str): The name of the function to find. Use "*" to find all.
67
69
  """
68
70
 
71
+ @log_initialization(level=LogLevel.TRACE)
69
72
  def __init__(self, **kwargs: Any):
73
+ """Initializes the FunctionDefSelector.
74
+
75
+ Args:
76
+ **kwargs: Keyword arguments from the JSON rule's selector config.
77
+ Expects `name` (str) and optionally `in_scope` (dict).
78
+ """
70
79
  super().__init__(**kwargs)
71
80
  self.name_to_find = kwargs.get("name")
72
81
 
@@ -91,6 +100,7 @@ class ClassDefSelector(ScopedSelector):
91
100
  name (str): The name of the class to find. Use "*" to find all.
92
101
  """
93
102
 
103
+ @log_initialization(level=LogLevel.TRACE)
94
104
  def __init__(self, **kwargs: Any):
95
105
  """Initializes the selector."""
96
106
  super().__init__(**kwargs)
@@ -117,7 +127,14 @@ class ImportStatementSelector(ScopedSelector):
117
127
  name (str): The name of the module to find (e.g., "os", "requests").
118
128
  """
119
129
 
130
+ @log_initialization(level=LogLevel.TRACE)
120
131
  def __init__(self, **kwargs: Any):
132
+ """Initializes the ImportStatementSelector.
133
+
134
+ Args:
135
+ **kwargs: Keyword arguments from the JSON rule's selector config.
136
+ Expects `name` (str) for the module name and optionally `in_scope`.
137
+ """
121
138
  super().__init__(**kwargs)
122
139
  self.module_name_to_find = kwargs.get("name")
123
140
 
@@ -156,6 +173,7 @@ class FunctionCallSelector(ScopedSelector):
156
173
  name (str): The full name of the function being called.
157
174
  """
158
175
 
176
+ @log_initialization(level=LogLevel.TRACE)
159
177
  def __init__(self, **kwargs: Any):
160
178
  """Initializes the selector."""
161
179
  super().__init__(**kwargs)
@@ -187,7 +205,14 @@ class AssignmentSelector(ScopedSelector):
187
205
  name (str): The full name of the variable or attribute being assigned to.
188
206
  """
189
207
 
208
+ @log_initialization(level=LogLevel.TRACE)
190
209
  def __init__(self, **kwargs: Any):
210
+ """Initializes the AssignmentSelector.
211
+
212
+ Args:
213
+ **kwargs: Keyword arguments from the JSON rule's selector config.
214
+ Expects `name` (str) for the assignment target and optionally `in_scope`.
215
+ """
191
216
  super().__init__(**kwargs)
192
217
  self.target_name_to_find = kwargs.get("name")
193
218
 
@@ -220,7 +245,15 @@ class UsageSelector(ScopedSelector):
220
245
  name (str): The name of the variable or attribute being used.
221
246
  """
222
247
 
248
+ @log_initialization(level=LogLevel.TRACE)
223
249
  def __init__(self, **kwargs: Any):
250
+ """Initializes the UsageSelector.
251
+
252
+ Args:
253
+ **kwargs: Keyword arguments from the JSON rule's selector config.
254
+ Expects `name` (str) for the variable/attribute being used and
255
+ optionally `in_scope`.
256
+ """
224
257
  super().__init__(**kwargs)
225
258
  self.variable_name_to_find = kwargs.get("name")
226
259
 
@@ -247,11 +280,32 @@ class LiteralSelector(ScopedSelector):
247
280
  name (str): The type of literal to find. Supported: "number", "string".
248
281
  """
249
282
 
283
+ @log_initialization(level=LogLevel.TRACE)
250
284
  def __init__(self, **kwargs: Any):
285
+ """Initializes the LiteralSelector.
286
+
287
+ Args:
288
+ **kwargs: Keyword arguments from the JSON rule's selector config.
289
+ Expects `name` (str) to be "string" or "number" and optionally
290
+ `in_scope`.
291
+ """
251
292
  super().__init__(**kwargs)
252
- self.literal_type = kwargs.get("name") # 'name' - это наш унифицированный ключ
293
+ self.literal_type = kwargs.get("name")
253
294
 
254
295
  def select(self, tree: ast.Module) -> list[ast.AST]:
296
+ """Finds all ast.Constant nodes that match the type criteria.
297
+
298
+ This method traverses the given AST (or a sub-tree defined by `in_scope`)
299
+ and collects all number or string literals. It contains special logic
300
+ to intelligently ignore nodes that are likely to be docstrings or parts
301
+ of f-strings to avoid false positives.
302
+
303
+ Args:
304
+ tree: The root of the AST (the module object) to be searched.
305
+
306
+ Returns:
307
+ A list of `ast.Constant` nodes matching the criteria.
308
+ """
255
309
  search_tree = self._get_search_tree(tree)
256
310
  if not search_tree:
257
311
  return []
@@ -294,7 +348,14 @@ class AstNodeSelector(ScopedSelector):
294
348
  as defined in the `ast` module (e.g., "For", "While", "Try").
295
349
  """
296
350
 
351
+ @log_initialization(level=LogLevel.TRACE)
297
352
  def __init__(self, **kwargs: Any):
353
+ """Initializes the AstNodeSelector.
354
+
355
+ Args:
356
+ **kwargs: Keyword arguments from the JSON rule's selector config.
357
+ Expects `node_type` (str or list[str]) and optionally `in_scope`.
358
+ """
298
359
  super().__init__(**kwargs)
299
360
  node_type_arg = kwargs.get("node_type")
300
361
 
@@ -1,49 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-code-validator
3
- Version: 0.1.2
4
- Summary: A flexible framework for static validation of Python code based on JSON rules.
3
+ Version: 0.2.1
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: 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
-
6
+ License-Expression: MIT
28
7
  Project-URL: Homepage, https://github.com/Qu1nel/PythonCodeValidator
29
8
  Project-URL: Documentation, https://pythoncodevalidator.readthedocs.io/en/latest/
30
9
  Project-URL: Bug Tracker, https://github.com/Qu1nel/PythonCodeValidator/issues
31
- Keywords: validation,linter,static analysis,testing,education
32
- Classifier: Development Status :: 3 - Alpha
10
+ Keywords: validation,linter,static analysis,testing,education,ast
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Education
33
14
  Classifier: Programming Language :: Python :: 3
34
15
  Classifier: Programming Language :: Python :: 3.11
35
16
  Classifier: Programming Language :: Python :: 3.12
36
- Classifier: License :: OSI Approved :: MIT License
37
17
  Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Classifier: Topic :: Software Development :: Testing
20
+ Classifier: Topic :: Education
38
21
  Requires-Python: >=3.11
39
22
  Description-Content-Type: text/markdown
40
23
  License-File: LICENSE
24
+ Requires-Dist: flake8>=7.0.0
41
25
  Provides-Extra: dev
42
26
  Requires-Dist: ruff>=0.4.0; extra == "dev"
43
- Requires-Dist: flake8>=7.0.0; extra == "dev"
44
27
  Requires-Dist: build; extra == "dev"
45
28
  Requires-Dist: twine; extra == "dev"
46
- Requires-Dist: coverage>=7.5.0; extra == "dev"
29
+ Requires-Dist: coverage[toml]>=7.5.0; extra == "dev"
47
30
  Provides-Extra: docs
48
31
  Requires-Dist: sphinx>=7.0.0; extra == "docs"
49
32
  Requires-Dist: furo; extra == "docs"
@@ -282,7 +265,7 @@ Validation failed.
282
265
  **[Read the Docs](https://[your-project].readthedocs.io)**.
283
266
  - **Developer's Guide**: For a deep dive into the architecture, see the
284
267
  **[How It Works guide](./docs/how_it_works/index.md)**.
285
- - **Interactive AI-Powered Docs**: *(Coming Soon)* An interactive documentation experience.
268
+ - **Interactive AI-Powered Docs**: **[DeepWiki](https://deepwiki.com/Qu1nel/PythonCodeValidator)**.
286
269
 
287
270
  ## 🤝 Contributing
288
271
 
@@ -0,0 +1,22 @@
1
+ code_validator/__init__.py,sha256=uag-AMj0a1I953aW7JLcxS6q0f_rueJWvO3AmGOWgUI,1721
2
+ code_validator/__main__.py,sha256=Z41EoJqX03AI11gnku_Iwt6rP8SPUkYuxwN7P51qgLc,600
3
+ code_validator/cli.py,sha256=-8pl9iv1ufRWiRKrY0vtk3ncZu6tFj6ZrKa0F-ruuZ4,4826
4
+ code_validator/config.py,sha256=ELi19GC1YeLEZZbm49FO8a1URLBrZxAuOGkrHTK8FvE,5071
5
+ code_validator/core.py,sha256=HyXXxECxsAgiXOl9tMZVqg0Xptx7nA-64IDVv_W4Svo,10117
6
+ code_validator/exceptions.py,sha256=XkiRNQ25FWJkjS2wBaUaKQcEL5WF9tN_HSV3tqJwDcE,1627
7
+ code_validator/output.py,sha256=Saydp1D6JRIzHroK12K38lnoMZCJaIEDyPD1ZXgJFGA,9137
8
+ code_validator/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ code_validator/components/ast_utils.py,sha256=v0N3F58oxNMg7bUY6-8x0AeoLsxrzrp_bLTGNVr5EMU,1589
10
+ code_validator/components/definitions.py,sha256=9WEXQ_i-S4Vega6HqOdjreZE_1cgJPC7guZodTKtzhc,3208
11
+ code_validator/components/factories.py,sha256=XvsSXbTHHmPrOvAseSYc9Xl8z-Zu5K5Eb8aWAvIgkuQ,11327
12
+ code_validator/components/scope_handler.py,sha256=q4cFK_YzoYvAqPkw9wPPxgPe-aO0kgy6gk0ETWduj-U,2593
13
+ code_validator/rules_library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ code_validator/rules_library/basic_rules.py,sha256=RGlHEDnd0Cn72ofbE8Y7wAl9h7iZR8reR80v2oiICTo,7118
15
+ code_validator/rules_library/constraint_logic.py,sha256=-gN6GaIZvPfHqiLCzH5Jwuz6DcPaQKlepbMo2r5V2Yc,11026
16
+ code_validator/rules_library/selector_nodes.py,sha256=wCAnQRSdEB8HM8avTy1wkJzyb6v2EQgHIPASXruiqbc,14733
17
+ python_code_validator-0.2.1.dist-info/licenses/LICENSE,sha256=Lq69RwIO4Dge7OsjgAamJfYSDq2DWI2yzVYI1VX1s6c,1089
18
+ python_code_validator-0.2.1.dist-info/METADATA,sha256=EKuyRnPMen6M3C5YgSWHXmI1BjOyTP_-ttXgIfZDGKc,10794
19
+ python_code_validator-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ python_code_validator-0.2.1.dist-info/entry_points.txt,sha256=pw_HijiZyPxokVJHStTkGCwheTjukDomdk81JyHzv74,66
21
+ python_code_validator-0.2.1.dist-info/top_level.txt,sha256=yowMDfABI5oqgW3hhTdec_7UHGeprkvc2BnqRzNbI5w,15
22
+ python_code_validator-0.2.1.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- code_validator/__init__.py,sha256=etZcfEkc_LFR8gqYPeH6hitwZ5-HS2WKSjl6LW9M8PY,961
2
- code_validator/__main__.py,sha256=c7P8Lz3EuwYRHarTEp_DExMUauod9X42p6aTZkpvi10,330
3
- code_validator/cli.py,sha256=fLbSP_4ABZGZTH6-L4oAXKVRTW-OVMdpcZgT9F4ibtY,3466
4
- code_validator/config.py,sha256=kTqD8-SFbtUQ9oif-TylqNFPadTq5JSGBv84cI0R8dY,2657
5
- code_validator/core.py,sha256=4sPdlunmODfNpDrP9QH2jIrGFVLFlo_r8MAoB4_63vo,4560
6
- code_validator/exceptions.py,sha256=XkiRNQ25FWJkjS2wBaUaKQcEL5WF9tN_HSV3tqJwDcE,1627
7
- code_validator/output.py,sha256=VRJLGwm6X9i8SnovosNrHu96ueZXz9GIvUQXy4xDtHw,3304
8
- code_validator/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- code_validator/components/ast_utils.py,sha256=7DzyKmLekj_qtuZcS8BrcWXqQXVEPPQ_rwh3BmpIk9o,1412
10
- code_validator/components/definitions.py,sha256=cFbKL7UZYHqWjz2gJCmZ6fU_ZdQ5L_h1tlQBYkxSO7Q,3126
11
- code_validator/components/factories.py,sha256=qrQotS7lyqIGhoNGRvSNQKy6p9YJKQC7YaPi4eCtpww,10436
12
- code_validator/components/scope_handler.py,sha256=vb4pCE-4DyxGkRYGeW2JWxP2IiZH3uRRfReo0IBgM5Y,2459
13
- code_validator/rules_library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- code_validator/rules_library/basic_rules.py,sha256=0K45Ed8yjy-pXDZpI1Xvgj94zvaFz-PucFRz__X4uRI,6652
15
- code_validator/rules_library/constraint_logic.py,sha256=X95g0673hoZey3LGCBH6AscbIuHYq_aY9WRKIkJhOnk,9525
16
- code_validator/rules_library/selector_nodes.py,sha256=JxhUBXS95Dad_60Ut-8XkW2MFM-7bkeRb_yk7vXlNPE,12200
17
- python_code_validator-0.1.2.dist-info/licenses/LICENSE,sha256=Lq69RwIO4Dge7OsjgAamJfYSDq2DWI2yzVYI1VX1s6c,1089
18
- python_code_validator-0.1.2.dist-info/METADATA,sha256=lYCstaPpPsj2KDOze-aYZFkr_NDi3Cy8UAgUCJHB2Mo,11829
19
- python_code_validator-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- python_code_validator-0.1.2.dist-info/entry_points.txt,sha256=pw_HijiZyPxokVJHStTkGCwheTjukDomdk81JyHzv74,66
21
- python_code_validator-0.1.2.dist-info/top_level.txt,sha256=yowMDfABI5oqgW3hhTdec_7UHGeprkvc2BnqRzNbI5w,15
22
- python_code_validator-0.1.2.dist-info/RECORD,,