1- from typing import Optional , List
1+ from typing import Optional
22
33from cucumber_expressions .argument import Argument
44from cucumber_expressions .ast import Node , NodeType
55from cucumber_expressions .expression_parser import CucumberExpressionParser
66from cucumber_expressions .parameter_type import ParameterType
7+ from cucumber_expressions .parameter_type_registry import ParameterTypeRegistry
78from cucumber_expressions .tree_regexp import TreeRegexp
89from cucumber_expressions .errors import (
9- UndefinedParameterTypeError ,
1010 ParameterIsNotAllowedInOptional ,
1111 OptionalIsNotAllowedInOptional ,
1212 OptionalMayNotBeEmpty ,
1313 AlternativeMayNotBeEmpty ,
14- AlternativeMayNotExclusivelyContainOptionals ,
14+ AlternativeMayNotExclusivelyContainOptionals , UndefinedParameterTypeError ,
1515)
1616
1717ESCAPE_PATTERN = rb"([\\^\[({$.|?*+})\]])"
1818
1919
2020class CucumberExpression :
21- def __init__ (self , expression , parameter_type_registry ):
21+ def __init__ (self , expression : str , parameter_type_registry : ParameterTypeRegistry ):
2222 self .expression = expression
2323 self .parameter_type_registry = parameter_type_registry
24- self .parameter_types : List [ ParameterType ] = []
24+ self .parameter_types_and_names : list [ tuple [ ParameterType , Optional [ str ]] ] = []
2525 self .tree_regexp = TreeRegexp (
2626 self .rewrite_to_regex (CucumberExpressionParser ().parse (self .expression ))
2727 )
2828
29- def match (self , text : str ) -> Optional [List [Argument ]]:
30- return Argument .build (self .tree_regexp , text , self .parameter_types )
29+ def match (self , text : str ) -> Optional [list [Argument ]]:
30+ return Argument .build (self .tree_regexp , text , self .parameter_types_and_names )
3131
3232 @property
3333 def source (self ):
@@ -57,23 +57,17 @@ def rewrite_to_regex(self, node: Node):
5757 def escape_regex (expression ) -> str :
5858 return expression .translate ({i : "\\ " + chr (i ) for i in ESCAPE_PATTERN })
5959
60- def rewrite_optional (self , node : Node ):
61- _possible_node_with_params = self .get_possible_node_with_parameters (node )
62- if _possible_node_with_params :
63- raise ParameterIsNotAllowedInOptional (
64- _possible_node_with_params , self .expression
65- )
66- _possible_node_with_optionals = self .get_possible_node_with_optionals (node )
67- if _possible_node_with_optionals :
68- raise OptionalIsNotAllowedInOptional (
69- _possible_node_with_optionals , self .expression
70- )
60+ def rewrite_optional (self , node : Node ) -> str :
61+ if self .get_possible_node_with_parameters (node ):
62+ raise ParameterIsNotAllowedInOptional (self .get_possible_node_with_parameters (node ), self .expression )
63+ if self .get_possible_node_with_optionals (node ):
64+ raise OptionalIsNotAllowedInOptional (self .get_possible_node_with_optionals (node ), self .expression )
7165 if self .are_nodes_empty (node ):
7266 raise OptionalMayNotBeEmpty (node , self .expression )
7367 regex = "" .join ([self .rewrite_to_regex (_node ) for _node in node .nodes ])
7468 return rf"(?:{ regex } )?"
7569
76- def rewrite_alternation (self , node : Node ):
70+ def rewrite_alternation (self , node : Node ) -> str :
7771 for alternative in node .nodes :
7872 if not alternative .nodes :
7973 raise AlternativeMayNotBeEmpty (alternative , self .expression )
@@ -87,20 +81,30 @@ def rewrite_alternation(self, node: Node):
8781 def rewrite_alternative (self , node : Node ):
8882 return "" .join ([self .rewrite_to_regex (_node ) for _node in node .nodes ])
8983
90- def rewrite_parameter (self , node : Node ):
84+ def rewrite_parameter (self , node : Node ) -> str :
9185 name = node .text
92- parameter_type = self .parameter_type_registry . lookup_by_type_name (name )
86+ group_name , parameter_type = self .parse_parameter_name (name )
9387
9488 if not parameter_type :
9589 raise UndefinedParameterTypeError (node , self .expression , name )
9690
97- self .parameter_types .append (parameter_type )
91+ self .parameter_types_and_names .append (( parameter_type , group_name ) )
9892
9993 regexps = parameter_type .regexps
10094 if len (regexps ) == 1 :
10195 return rf"({ regexps [0 ]} )"
10296 return rf"((?:{ ')|(?:' .join (regexps )} ))"
10397
98+ def parse_parameter_name (self , name : str ) -> tuple [Optional [str ], Optional [ParameterType ]]:
99+ """Helper function to parse the parameter name and return group_name and parameter_type."""
100+ if ":" in name :
101+ group_name , parameter_type_name = name .split (":" )
102+ parameter_type = self .parameter_type_registry .lookup_by_type_name (parameter_type_name )
103+ else :
104+ group_name = None
105+ parameter_type = self .parameter_type_registry .lookup_by_type_name (name )
106+ return group_name , parameter_type
107+
104108 def rewrite_expression (self , node : Node ):
105109 regex = "" .join ([self .rewrite_to_regex (_node ) for _node in node .nodes ])
106110 return rf"^{ regex } $"
@@ -117,5 +121,5 @@ def get_possible_node_with_optionals(self, node: Node) -> Optional[Node]:
117121 return results [0 ] if results else None
118122
119123 @staticmethod
120- def get_nodes_with_ast_type (node : Node , ast_type : NodeType ) -> List [Node ]:
124+ def get_nodes_with_ast_type (node : Node , ast_type : NodeType ) -> list [Node ]:
121125 return [ast_node for ast_node in node .nodes if ast_node .ast_type == ast_type ]
0 commit comments