7272)
7373from .id_manager import IdManager
7474
75+ if get_robot_version () >= (5 , 0 ):
76+ from robot .running .model import Try
77+ from robot .utils import Matcher as RobotMatcher
78+
7579if get_robot_version () >= (7 , 0 ):
7680 from robot .running import UserKeyword as UserKeywordHandler
7781else :
@@ -1202,12 +1206,8 @@ def _get_matcher(self, pattern_type: str) -> Optional[Callable[[str, str], bool]
12021206
12031207 def _glob_matcher (self , message : str , pattern : str ) -> bool :
12041208 """Optimized glob matcher with cached Robot Matcher."""
1205- if self .__robot_matcher is None :
1206- from robot .utils import Matcher
1207-
1208- self .__robot_matcher = Matcher
12091209
1210- return bool (self . __robot_matcher (pattern , spaceless = False , caseless = False ).match (message ))
1210+ return bool (RobotMatcher (pattern , spaceless = False , caseless = False ).match (message ))
12111211
12121212 def _regexp_matcher (self , message : str , pattern : str ) -> bool :
12131213 """Optimized regex matcher with LRU caching (max 25 entries)."""
@@ -1259,14 +1259,21 @@ def _get_step_data(self, step: Any) -> Any:
12591259 def _get_step_data (self , step : Any ) -> Any :
12601260 return step .data
12611261
1262- def is_not_caugthed_by_except (self , message : Optional [str ]) -> bool :
1263- if not message :
1264- return True
1262+ if get_robot_version () < (5 , 0 ):
1263+
1264+ def is_not_caugthed_by_except (self , message : Optional [str ]) -> bool :
1265+ if not message :
1266+ return True
1267+ return False
1268+ else :
12651269
1266- if self . debug_logger :
1267- if get_robot_version () >= ( 5 , 0 ) :
1268- from robot . running . model import Try
1270+ def is_not_caugthed_by_except ( self , message : Optional [ str ]) -> bool :
1271+ if not message :
1272+ return True
12691273
1274+ # TODO resolve variables in exception message
1275+
1276+ if self .debug_logger :
12701277 if self .debug_logger .steps :
12711278 for branch in [
12721279 self ._get_step_data (f )
@@ -1276,7 +1283,7 @@ def is_not_caugthed_by_except(self, message: Optional[str]) -> bool:
12761283 for except_branch in branch .except_branches :
12771284 if self ._should_run_except (except_branch , message ):
12781285 return False
1279- return True
1286+ return True
12801287
12811288 def end_keyword (self , name : str , attributes : AttributeDict ) -> None :
12821289 if self .state == State .CallKeyword :
@@ -1610,131 +1617,143 @@ def get_variables(
16101617 count : Optional [int ] = None ,
16111618 format : Optional [ValueFormat ] = None ,
16121619 ) -> List [Variable ]:
1613- result : MutableMapping [str , Any ] = {}
1614-
16151620 if filter is None :
1616- entry = next (
1617- (
1618- v
1619- for v in self .stack_frames
1620- if variables_reference in [v .global_id , v .suite_id , v .test_id , v .local_id ]
1621- ),
1622- None ,
1623- )
1624- if entry is not None :
1625- context = entry .context ()
1626- if context is not None :
1627- if entry .global_id == variables_reference :
1628- result .update (
1629- {k : self ._create_variable (k , v ) for k , v in context .variables ._global .as_dict ().items ()}
1630- )
1631- elif entry .suite_id == variables_reference :
1632- globals = context .variables ._global .as_dict ()
1633- vars = entry .get_first_or_self ().variables ()
1634- vars_dict = vars .as_dict () if vars is not None else {}
1635- result .update (
1636- {
1637- k : self ._create_variable (k , v )
1638- for k , v in context .variables ._suite .as_dict ().items ()
1639- if (k not in globals or globals [k ] != v ) and (k in vars_dict )
1640- }
1641- )
1642- elif entry .test_id == variables_reference :
1643- globals = context .variables ._suite .as_dict ()
1644- vars = entry .get_first_or_self ().variables ()
1645- vars_dict = vars .as_dict () if vars is not None else {}
1646- result .update (
1647- {
1648- k : self ._create_variable (k , v )
1649- for k , v in context .variables ._test .as_dict ().items ()
1650- if (k not in globals or globals [k ] != v ) and (k in vars_dict )
1651- }
1652- )
1653- elif entry .local_id == variables_reference :
1654- vars = entry .get_first_or_self ().variables ()
1655-
1656- if self ._current_exception is not None :
1657- result ["${EXCEPTION}" ] = self ._create_variable (
1658- "${EXCEPTION}" ,
1659- self ._current_exception ,
1660- VariablePresentationHint (kind = "virtual" ),
1661- )
1662-
1663- if vars is not None :
1664- p = entry .parent () if entry .parent else None
1665-
1666- globals = (
1667- (p .get_first_or_self ().variables () if p is not None else None )
1668- or context .variables ._test
1669- or context .variables ._suite
1670- or context .variables ._global
1671- ).as_dict ()
1672-
1673- suite_vars = (context .variables ._suite or context .variables ._global ).as_dict ()
1674-
1675- result .update (
1676- {
1677- k : self ._create_variable (k , v )
1678- for k , v in vars .as_dict ().items ()
1679- if (k not in globals or globals [k ] != v )
1680- and (entry .handler is None or k not in suite_vars or suite_vars [k ] != v )
1681- }
1682- )
1683-
1684- if entry .handler is not None and self .get_handler_args (entry .handler ):
1685- for argument in self .get_handler_args (entry .handler ).argument_names :
1686- name = f"${{{ argument } }}"
1687- try :
1688- value = vars [name ]
1689- except (SystemExit , KeyboardInterrupt ):
1690- raise
1691- except BaseException as e :
1692- value = str (e )
1693-
1694- result [name ] = self ._create_variable (name , value )
1695- else :
1696- value = self ._variables_cache .get (variables_reference , None )
1621+ return self ._get_variables_no_filter (variables_reference )
1622+ if filter == "indexed" :
1623+ return self ._get_variables_indexed (variables_reference , start , count )
1624+ if filter == "named" :
1625+ return self ._get_variables_named (variables_reference , start , count )
16971626
1698- if value is not None and isinstance (value , Mapping ):
1699- result .update ({"len()" : self ._create_variable ("len()" , len (value ))})
1627+ raise ValueError (f"Unknown filter: { filter } " )
17001628
1701- for i , (k , v ) in enumerate (value .items (), start or 0 ):
1702- result [repr (i )] = self ._create_variable (repr (k ), v )
1703- if i >= MAX_VARIABLE_ITEMS_DISPLAY :
1704- result ["Unable to handle" ] = self ._create_variable (
1705- "Unable to handle" ,
1706- f"Maximum number of items ({ MAX_VARIABLE_ITEMS_DISPLAY } ) reached." ,
1707- )
1708- break
1709-
1710- elif value is not None and isinstance (value , Sequence ) and not isinstance (value , str ):
1711- result .update ({"len()" : self ._create_variable ("len()" , len (value ))})
1712-
1713- elif filter == "indexed" :
1629+ def _get_variables_no_filter (self , variables_reference : int ) -> List [Variable ]:
1630+ result : MutableMapping [str , Any ] = {}
1631+ entry = next (
1632+ (v for v in self .stack_frames if variables_reference in [v .global_id , v .suite_id , v .test_id , v .local_id ]),
1633+ None ,
1634+ )
1635+ if entry is not None :
1636+ context = entry .context ()
1637+ if context is not None :
1638+ if entry .global_id == variables_reference :
1639+ result .update (
1640+ {k : self ._create_variable (k , v ) for k , v in context .variables ._global .as_dict ().items ()}
1641+ )
1642+ elif entry .suite_id == variables_reference :
1643+ result .update (self ._get_suite_variables (context , entry ))
1644+ elif entry .test_id == variables_reference :
1645+ result .update (self ._get_test_variables (context , entry ))
1646+ elif entry .local_id == variables_reference :
1647+ result .update (self ._get_local_variables (context , entry ))
1648+ else :
17141649 value = self ._variables_cache .get (variables_reference , None )
1650+ result .update (self ._get_cached_variables (value ))
1651+ return list (result .values ())
17151652
1716- if value is not None :
1717- c = 0
1653+ def _get_suite_variables (self , context : Any , entry : Any ) -> MutableMapping [str , Variable ]:
1654+ result : MutableMapping [str , Variable ] = {}
1655+ globals = context .variables ._global .as_dict ()
1656+ vars = entry .get_first_or_self ().variables ()
1657+ vars_dict = vars .as_dict () if vars is not None else {}
1658+ for k , v in context .variables ._suite .as_dict ().items ():
1659+ if (k not in globals or globals [k ] != v ) and (k in vars_dict ):
1660+ result [k ] = self ._create_variable (k , v )
1661+ return result
17181662
1719- padding = len (str (len (value )))
1663+ def _get_test_variables (self , context : Any , entry : Any ) -> MutableMapping [str , Variable ]:
1664+ result : MutableMapping [str , Variable ] = {}
1665+ globals = context .variables ._suite .as_dict ()
1666+ vars = entry .get_first_or_self ().variables ()
1667+ vars_dict = vars .as_dict () if vars is not None else {}
1668+ for k , v in context .variables ._test .as_dict ().items ():
1669+ if (k not in globals or globals [k ] != v ) and (k in vars_dict ):
1670+ result [k ] = self ._create_variable (k , v )
1671+ return result
17201672
1721- for i , v in enumerate (value [start :], start or 0 ):
1722- result [str (i )] = self ._create_variable (str (i ).zfill (padding ), v )
1723- c += 1
1724- if count is not None and c >= count :
1725- break
1673+ def _get_local_variables (self , context : Any , entry : Any ) -> MutableMapping [str , Variable ]:
1674+ result : MutableMapping [str , Variable ] = {}
1675+ vars = entry .get_first_or_self ().variables ()
1676+ if self ._current_exception is not None :
1677+ result ["${EXCEPTION}" ] = self ._create_variable (
1678+ "${EXCEPTION}" ,
1679+ self ._current_exception ,
1680+ VariablePresentationHint (kind = "virtual" ),
1681+ )
1682+ if vars is not None :
1683+ p = entry .parent () if entry .parent else None
1684+ globals = (
1685+ (p .get_first_or_self ().variables () if p is not None else None )
1686+ or context .variables ._test
1687+ or context .variables ._suite
1688+ or context .variables ._global
1689+ ).as_dict ()
1690+ suite_vars = (context .variables ._suite or context .variables ._global ).as_dict ()
1691+ for k , v in vars .as_dict ().items ():
1692+ if (k not in globals or globals [k ] != v ) and (
1693+ entry .handler is None or k not in suite_vars or suite_vars [k ] != v
1694+ ):
1695+ result [k ] = self ._create_variable (k , v )
1696+ if entry .handler is not None and self .get_handler_args (entry .handler ):
1697+ for argument in self .get_handler_args (entry .handler ).argument_names :
1698+ name = f"${{{ argument } }}"
1699+ try :
1700+ value = vars [name ]
1701+ except (SystemExit , KeyboardInterrupt ):
1702+ raise
1703+ except BaseException as e :
1704+ value = str (e )
1705+ result [name ] = self ._create_variable (name , value )
1706+ return result
17261707
1727- elif filter == "named" :
1728- value = self ._variables_cache .get (variables_reference , None )
1708+ def _get_cached_variables (self , value : Any ) -> MutableMapping [str , Variable ]:
1709+ result : MutableMapping [str , Variable ] = {}
1710+ if value is not None and isinstance (value , Mapping ):
1711+ result ["len()" ] = self ._create_variable ("len()" , len (value ))
1712+ for i , (k , v ) in enumerate (value .items ()):
1713+ result [repr (i )] = self ._create_variable (repr (k ), v )
1714+ if i >= MAX_VARIABLE_ITEMS_DISPLAY :
1715+ result ["Unable to handle" ] = self ._create_variable (
1716+ "Unable to handle" ,
1717+ f"Maximum number of items ({ MAX_VARIABLE_ITEMS_DISPLAY } ) reached." ,
1718+ )
1719+ break
1720+ elif value is not None and isinstance (value , Sequence ) and not isinstance (value , str ):
1721+ result ["len()" ] = self ._create_variable ("len()" , len (value ))
1722+ return result
17291723
1730- if value is not None and isinstance (value , Mapping ):
1731- for i , (k , v ) in enumerate (value .items (), start or 0 ):
1732- result [repr (i )] = self ._create_variable (repr (k ), v )
1733- if count is not None and i >= count :
1734- break
1735- elif value is not None and isinstance (value , Sequence ) and not isinstance (value , str ):
1736- result .update ({"len()" : self ._create_variable ("len()" , len (value ))})
1724+ def _get_variables_indexed (
1725+ self ,
1726+ variables_reference : int ,
1727+ start : Optional [int ],
1728+ count : Optional [int ],
1729+ ) -> List [Variable ]:
1730+ result : MutableMapping [str , Any ] = {}
1731+ value = self ._variables_cache .get (variables_reference , None )
1732+ if value is not None :
1733+ c = 0
1734+ padding = len (str (len (value )))
1735+ for i , v in enumerate (value [start :], start or 0 ):
1736+ result [str (i )] = self ._create_variable (str (i ).zfill (padding ), v )
1737+ c += 1
1738+ if count is not None and c >= count :
1739+ break
1740+ return list (result .values ())
17371741
1742+ def _get_variables_named (
1743+ self ,
1744+ variables_reference : int ,
1745+ start : Optional [int ],
1746+ count : Optional [int ],
1747+ ) -> List [Variable ]:
1748+ result : MutableMapping [str , Any ] = {}
1749+ value = self ._variables_cache .get (variables_reference , None )
1750+ if value is not None and isinstance (value , Mapping ):
1751+ for i , (k , v ) in enumerate (value .items (), start or 0 ):
1752+ result [repr (i )] = self ._create_variable (repr (k ), v )
1753+ if count is not None and i >= count :
1754+ break
1755+ elif value is not None and isinstance (value , Sequence ) and not isinstance (value , str ):
1756+ result ["len()" ] = self ._create_variable ("len()" , len (value ))
17381757 return list (result .values ())
17391758
17401759 IS_VARIABLE_RE : ClassVar = re .compile (r"^[$@&]\{.*\}(\[[^\]]*\])?$" )
0 commit comments