diff --git a/regex_humanizer/converter/converter.py b/regex_humanizer/converter/converter.py index dccabdb..e20b9da 100644 --- a/regex_humanizer/converter/converter.py +++ b/regex_humanizer/converter/converter.py @@ -1,4 +1,6 @@ -from typing import List, Optional +"""Implementation of regex to English conversion.""" + +from typing import Any, List from ..parser import ( Alternation, @@ -15,6 +17,7 @@ from ..parser import ( def quantifier_description(quantifier: Quantifier, child_desc: str) -> str: + """Generate description for a quantifier.""" if quantifier.min == 0 and quantifier.max == 1: base = "optionally" elif quantifier.min == 0 and quantifier.max == Quantifier.MAX_UNBOUNDED: @@ -37,6 +40,7 @@ def quantifier_description(quantifier: Quantifier, child_desc: str) -> str: def literal_description(node: Literal) -> str: + """Generate description for a literal character.""" if node.value == " ": return "a space" elif node.value == "\t": @@ -52,6 +56,7 @@ def literal_description(node: Literal) -> str: def character_class_description(node: CharacterClass) -> str: + """Generate description for a character class.""" parts = [] if node.inverted: @@ -90,6 +95,7 @@ def character_class_description(node: CharacterClass) -> str: def special_sequence_description(node: SpecialSequence) -> str: + """Generate description for a special sequence.""" sequences = { ".": "any single character", r"\d": "a digit (0-9)", @@ -111,6 +117,7 @@ def special_sequence_description(node: SpecialSequence) -> str: def anchor_description(node: Anchor) -> str: + """Generate description for an anchor.""" anchors = { "^": "the start of the string", "$": "the end of the string", @@ -121,6 +128,7 @@ def anchor_description(node: Anchor) -> str: def group_description(node: Group) -> str: + """Generate description for a group.""" if node.name: name_desc = f"named '{node.name}'" elif not node.capturing: @@ -136,6 +144,7 @@ def group_description(node: Group) -> str: def alternation_description(node: Alternation) -> str: + """Generate description for an alternation.""" option_descs = [] for option in node.options: if option: @@ -150,6 +159,7 @@ def alternation_description(node: Alternation) -> str: def backreference_description(node: Backreference) -> str: + """Generate description for a backreference.""" if isinstance(node.reference, int): return f"whatever was matched by capture group {node.reference}" else: @@ -157,6 +167,7 @@ def backreference_description(node: Backreference) -> str: def generate_description(nodes: List[ASTNode]) -> str: + """Generate a human-readable description for a list of AST nodes.""" if not nodes: return "an empty pattern" @@ -201,6 +212,15 @@ def generate_description(nodes: List[ASTNode]) -> str: def convert_to_english(pattern: str, flavor: str = "pcre") -> str: + """Convert a regex pattern to human-readable English. + + Args: + pattern: The regex pattern to convert. + flavor: The regex flavor (pcre, javascript, python, go). + + Returns: + A human-readable English description of the pattern. + """ try: ast = parse_regex(pattern) return generate_description(ast) @@ -209,10 +229,19 @@ def convert_to_english(pattern: str, flavor: str = "pcre") -> str: def convert_to_english_verbose(pattern: str, flavor: str = "pcre") -> dict: + """Convert a regex pattern to detailed structure. + + Args: + pattern: The regex pattern to convert. + flavor: The regex flavor. + + Returns: + A dictionary with pattern analysis. + """ try: ast = parse_regex(pattern) - result = { + result: dict[str, Any] = { "pattern": pattern, "flavor": flavor, "description": generate_description(ast), @@ -234,8 +263,9 @@ def convert_to_english_verbose(pattern: str, flavor: str = "pcre") -> dict: } -def node_to_dict(node: ASTNode) -> dict: - result = {"type": type(node).__name__} +def node_to_dict(node: ASTNode) -> dict[str, Any]: + """Convert an AST node to a dictionary.""" + result: dict[str, Any] = {"type": type(node).__name__} if hasattr(node, 'position'): result["position"] = node.position