Rule & Component Library

This section documents the concrete implementations of all rules, selectors, and constraints.

Rule Handlers

Contains concrete implementations of executable validation rules.

This module defines the handler classes for both “short” (pre-defined) and “full” (custom selector/constraint) rules. Each class in this module implements the Rule protocol from definitions.py and encapsulates the logic for a specific type of validation check. The RuleFactory uses these classes to instantiate the correct handler for each rule defined in a JSON file.

class code_validator.rules_library.basic_rules.CheckLinterRule(config: ShortRuleConfig, console: Console)

Handles the ‘check_linter_pep8’ short rule by running flake8.

This rule executes the flake8 linter as an external subprocess on the source code to check for style and common programming errors. It is configurable via the ‘params’ field in the JSON rule.

execute(tree: Module | None, source_code: str | None = None) bool

Executes the flake8 linter on the source code via a subprocess.

It constructs a command-line call to flake8, passing the source code via stdin. This approach ensures isolation and uses flake8’s stable CLI interface.

Parameters:
  • tree – Not used by this rule.

  • source_code – The raw source code string to be linted.

Returns:

True if no PEP8 violations are found, False otherwise.

class code_validator.rules_library.basic_rules.CheckSyntaxRule(config: ShortRuleConfig, console: Console)

Handles the ‘check_syntax’ short rule.

Note

The actual syntax validation is performed preemptively in the core validator engine when it calls ast.parse(). Therefore, this rule’s execute method will only be called if the syntax is already valid. Its primary purpose is to exist so that a check_syntax rule can be formally defined in the JSON configuration.

execute(tree: Module | None, source_code: str | None = None) bool

Confirms that syntax is valid.

This method is guaranteed to be called only after a successful AST parsing.

Returns:

Always returns True.

class code_validator.rules_library.basic_rules.FullRuleHandler(config: FullRuleConfig, selector: Selector, constraint: Constraint, console: Console)

Handles a full, custom rule composed of a selector and a constraint.

This class acts as a generic executor for complex rules. It does not contain any specific validation logic itself but instead orchestrates the interaction between a Selector and a Constraint object.

config

The dataclass object holding the rule’s config.

Type:

FullRuleConfig

_selector

The selector object responsible for finding nodes.

Type:

Selector

_constraint

The constraint object for checking the nodes.

Type:

Constraint

_console

The console handler for logging.

Type:

Console

execute(tree: Module | None, source_code: str | None = None) bool

Executes the rule by running the selector and applying the constraint.

Parameters:
  • tree – The enriched AST of the source code.

  • source_code – Not used by this rule.

Returns:

The boolean result of applying the constraint to the selected nodes.

Selectors

Contains concrete implementations of all Selector components.

Each class in this module implements the Selector protocol and is responsible for finding and returning specific types of nodes from an Abstract Syntax Tree. They use ast.walk to traverse the tree and can be constrained to specific scopes via the ScopedSelector base class, which uses the scope_handler. These classes are instantiated by the SelectorFactory.

class code_validator.rules_library.selector_nodes.AssignmentSelector(**kwargs: Any)

Selects assignment nodes (= or := or type-annotated).

This can find assignments to simple variables (x = 5) and attributes (self.player = …).

JSON Params:

name (str): The full name of the variable or attribute being assigned to.

select(tree: Module) list[AST]

Finds all ast.Assign or ast.AnnAssign nodes matching the target name.

class code_validator.rules_library.selector_nodes.AstNodeSelector(**kwargs: Any)

A generic selector for finding any AST node by its class name.

This is a powerful, low-level selector for advanced use cases.

JSON Params:
node_type (str | list[str]): The name(s) of the AST node types to find,

as defined in the ast module (e.g., “For”, “While”, “Try”).

select(tree: Module) list[AST]

Finds all AST nodes that are instances of the specified types.

class code_validator.rules_library.selector_nodes.ClassDefSelector(**kwargs: Any)

Selects class definition (class) nodes from an AST.

JSON Params:

name (str): The name of the class to find. Use “*” to find all.

select(tree: Module) list[AST]

Finds all ast.ClassDef nodes that match the name criteria.

class code_validator.rules_library.selector_nodes.FunctionCallSelector(**kwargs: Any)

Selects function call nodes from an AST.

This can find simple function calls (my_func()) and method calls (requests.get()).

JSON Params:

name (str): The full name of the function being called.

select(tree: Module) list[AST]

Finds all ast.Call nodes that match the name criteria.

class code_validator.rules_library.selector_nodes.FunctionDefSelector(**kwargs: Any)

Selects function definition (def) nodes from an AST.

JSON Params:

name (str): The name of the function to find. Use “*” to find all.

select(tree: Module) list[AST]

Finds all ast.FunctionDef nodes that match the name criteria.

class code_validator.rules_library.selector_nodes.ImportStatementSelector(**kwargs: Any)

Selects import nodes (import or from…import) from an AST.

JSON Params:

name (str): The name of the module to find (e.g., “os”, “requests”).

select(tree: Module) list[AST]

Finds all import-related nodes that match the name criteria.

class code_validator.rules_library.selector_nodes.LiteralSelector(**kwargs: Any)

Selects literal nodes (e.g., numbers, strings), ignoring docstrings.

JSON Params:

name (str): The type of literal to find. Supported: “number”, “string”.

select(tree: Module) list[AST]

Finds all ast.Constant nodes that match the type criteria.

This method traverses the given AST (or a sub-tree defined by in_scope) and collects all number or string literals. It contains special logic to intelligently ignore nodes that are likely to be docstrings or parts of f-strings to avoid false positives.

Parameters:

tree – The root of the AST (the module object) to be searched.

Returns:

A list of ast.Constant nodes matching the criteria.

class code_validator.rules_library.selector_nodes.ScopedSelector(**kwargs: Any)

An abstract base class for selectors that support scoping.

This class provides a common mechanism for subclasses to narrow their search to a specific part of the AST (e.g., a single function or class) before performing their selection logic.

in_scope_config

The configuration dictionary or string that defines the desired scope.

Type:

dict | str | None

select(tree: Module) list[AST]

Abstract select method to be implemented by subclasses.

class code_validator.rules_library.selector_nodes.UsageSelector(**kwargs: Any)

Selects nodes where a variable or attribute is used (read).

This finds nodes in a “load” context, meaning the value of the variable is being accessed, not assigned.

JSON Params:

name (str): The name of the variable or attribute being used.

select(tree: Module) list[AST]

Finds all ast.Name nodes (in load context) matching the name.

Constraints

Contains concrete implementations of all Constraint components.

Each class in this module implements the Constraint protocol and encapsulates the logic for a specific condition that can be checked against a list of AST nodes. These classes are instantiated by the ConstraintFactory based on the “constraint” block in a JSON rule.

The module also includes helper functions for processing AST nodes, which are used internally by the constraint classes.

class code_validator.rules_library.constraint_logic.IsForbiddenConstraint(**kwargs: Any)

Checks that no nodes were found by the selector.

This is the inverse of IsRequiredConstraint and is used to forbid certain constructs, such as specific function calls or imports.

check(nodes: list[AST]) bool

Checks if the list of nodes is empty.

class code_validator.rules_library.constraint_logic.IsRequiredConstraint(**kwargs: Any)

Checks that at least one node was found by the selector.

This constraint is used to enforce the presence of a required language construct. It can also check for an exact number of occurrences.

Supports smart typo detection when no nodes are found - analyzes similar names in the same scope and provides helpful suggestions.

JSON Params:
count (int, optional): If provided, checks if the number of found

nodes is exactly equal to this value.

check(nodes: list[AST]) bool

Checks if the list of nodes is not empty or matches expected count.

check_with_context(nodes: list[AST], target_name: str, scope_config: dict[str, Any] | str, ast_tree: Module, file_path: str, console) tuple[bool, str | None]

Enhanced check with typo detection support.

Performs the standard constraint check, and if it fails due to no nodes being found, analyzes potential typos and provides helpful suggestions.

Parameters:
  • nodes – List of AST nodes found by the selector

  • target_name – The name that was being searched for

  • scope_config – Scope configuration for the search

  • ast_tree – The complete AST tree for analysis

  • file_path – Path to the source file

  • console – Console instance for output

Returns:

Tuple of (constraint_result, typo_suggestion_message)

class code_validator.rules_library.constraint_logic.MustBeTypeConstraint(**kwargs: Any)

Checks the type of the value in an assignment statement.

It works for simple literals (numbers, strings, lists, etc.) and for calls to built-in type constructors (e.g., list(), dict()).

JSON Params:

expected_type (str): The name of the type, e.g., “str”, “int”, “list”.

check(nodes: list[AST]) bool

Checks if the assigned value has the expected Python type.

class code_validator.rules_library.constraint_logic.MustHaveArgsConstraint(**kwargs: Any)

Checks that a FunctionDef node has a specific signature.

This constraint can check for an exact number of arguments or for an exact sequence of argument names, ignoring self or cls in methods.

JSON Params:

count (int, optional): The exact number of arguments required. names (list[str], optional): The exact list of argument names in order. exact_match (bool, optional): Used with names. If False, only checks

for presence, not for exact list match. Defaults to True.

check(nodes: list[AST]) bool

Checks if the function signature matches the criteria.

class code_validator.rules_library.constraint_logic.MustInheritFromConstraint(**kwargs: Any)

Checks that a ClassDef node inherits from a specific parent class.

This constraint is designed to work with a selector that returns a single ast.ClassDef node. It can resolve both simple names (e.g., Exception) and attribute-based names (e.g., arcade.Window).

JSON Params:

parent_name (str): The expected name of the parent class.

check(nodes: list[AST]) bool

Checks if the found class node inherits from the specified parent.

class code_validator.rules_library.constraint_logic.NameMustBeInConstraint(**kwargs: Any)

Checks if the name of a found node is in an allowed list of names.

This is useful for rules like restricting global variables to a pre-defined set of constants.

JSON Params:

allowed_names (list[str]): A list of strings containing the allowed names.

check(nodes: list[AST]) bool

Checks if all found node names are in the allowed set.

class code_validator.rules_library.constraint_logic.ValueMustBeInConstraint(**kwargs: Any)

Checks if the value of a found literal node is in an allowed list.

This is primarily used to check for “magic numbers” or “magic strings”, allowing only a specific set of literal values to be present.

JSON Params:

allowed_values (list): A list of allowed literal values (e.g., [0, 1]).

check(nodes: list[AST]) bool

Checks if all found literal values are in the allowed set.