@@ -121,12 +121,12 @@ class Variable:
121121 explode : bool = False
122122
123123
124- @dataclass ( frozen = True )
124+ @dataclass
125125class _Expression :
126126 """A parsed ``{...}`` expression: one operator, one or more variables."""
127127
128128 operator : Operator
129- variables : tuple [Variable , ... ]
129+ variables : list [Variable ]
130130
131131
132132_Part = str | _Expression
@@ -236,11 +236,11 @@ class UriTemplate:
236236 """
237237
238238 template : str
239- _parts : tuple [_Part , ... ] = field (repr = False , compare = False )
240- _variables : tuple [Variable , ... ] = field (repr = False , compare = False )
239+ _parts : list [_Part ] = field (repr = False , compare = False )
240+ _variables : list [Variable ] = field (repr = False , compare = False )
241241 _pattern : re .Pattern [str ] = field (repr = False , compare = False )
242- _path_variables : tuple [Variable , ... ] = field (repr = False , compare = False )
243- _query_variables : tuple [Variable , ... ] = field (repr = False , compare = False )
242+ _path_variables : list [Variable ] = field (repr = False , compare = False )
243+ _query_variables : list [Variable ] = field (repr = False , compare = False )
244244
245245 @staticmethod
246246 def is_template (value : str ) -> bool :
@@ -311,14 +311,14 @@ def parse(
311311 )
312312
313313 @property
314- def variables (self ) -> tuple [Variable , ... ]:
314+ def variables (self ) -> list [Variable ]:
315315 """All variables in the template, in order of appearance."""
316- return self ._variables
316+ return list ( self ._variables )
317317
318318 @property
319- def variable_names (self ) -> tuple [str , ... ]:
319+ def variable_names (self ) -> list [str ]:
320320 """All variable names in the template, in order of appearance."""
321- return tuple ( v .name for v in self ._variables )
321+ return [ v .name for v in self ._variables ]
322322
323323 def expand (self , variables : Mapping [str , str | Sequence [str ]]) -> str :
324324 """Expand the template by substituting variable values.
@@ -465,7 +465,7 @@ def __str__(self) -> str:
465465 return self .template
466466
467467
468- def _extract_path (m : re .Match [str ], variables : tuple [Variable , ... ]) -> dict [str , str | list [str ]] | None :
468+ def _extract_path (m : re .Match [str ], variables : Sequence [Variable ]) -> dict [str , str | list [str ]] | None :
469469 """Decode regex capture groups into a variable-name mapping.
470470
471471 Handles scalar and explode variables. Named explode (``;``) strips
@@ -506,9 +506,7 @@ def _extract_path(m: re.Match[str], variables: tuple[Variable, ...]) -> dict[str
506506 return result
507507
508508
509- def _split_query_tail (
510- parts : tuple [_Part , ...],
511- ) -> tuple [tuple [_Part , ...], tuple [Variable , ...]]:
509+ def _split_query_tail (parts : list [_Part ]) -> tuple [list [_Part ], list [Variable ]]:
512510 """Separate trailing ``?``/``&`` expressions from the path portion.
513511
514512 Lenient query matching (order-agnostic, partial, ignores extras)
@@ -532,23 +530,23 @@ def _split_query_tail(
532530 break
533531
534532 if split == len (parts ):
535- return parts , ()
533+ return parts , []
536534
537535 # If the path portion contains a literal ?, the URI's ? won't align
538536 # with our template split. Fall back to strict regex.
539537 for part in parts [:split ]:
540538 if isinstance (part , str ) and "?" in part :
541- return parts , ()
539+ return parts , []
542540
543541 query_vars : list [Variable ] = []
544542 for part in parts [split :]:
545543 assert isinstance (part , _Expression )
546544 query_vars .extend (part .variables )
547545
548- return parts [:split ], tuple ( query_vars )
546+ return parts [:split ], query_vars
549547
550548
551- def _build_pattern (parts : tuple [_Part , ... ]) -> re .Pattern [str ]:
549+ def _build_pattern (parts : Sequence [_Part ]) -> re .Pattern [str ]:
552550 """Compile a regex that matches URIs produced by this template.
553551
554552 Walks parts in order: literals are ``re.escape``'d, expressions
@@ -606,7 +604,7 @@ def _expression_pattern(expr: _Expression) -> str:
606604 return "" .join (pieces )
607605
608606
609- def _parse (template : str , * , max_expressions : int ) -> tuple [tuple [_Part , ... ], tuple [Variable , ... ]]:
607+ def _parse (template : str , * , max_expressions : int ) -> tuple [list [_Part ], list [Variable ]]:
610608 """Split a template into an ordered sequence of literals and expressions.
611609
612610 Walks the string, alternating between collecting literal runs and
@@ -663,7 +661,7 @@ def _parse(template: str, *, max_expressions: int) -> tuple[tuple[_Part, ...], t
663661
664662 _check_adjacent_explodes (template , parts )
665663 _check_duplicate_variables (template , variables )
666- return tuple ( parts ), tuple ( variables )
664+ return parts , variables
667665
668666
669667def _parse_expression (template : str , body : str , pos : int ) -> _Expression :
@@ -730,7 +728,7 @@ def _parse_expression(template: str, body: str, pos: int) -> _Expression:
730728
731729 variables .append (Variable (name = name , operator = operator , explode = explode ))
732730
733- return _Expression (operator = operator , variables = tuple ( variables ) )
731+ return _Expression (operator = operator , variables = variables )
734732
735733
736734def _check_duplicate_variables (template : str , variables : list [Variable ]) -> None :
0 commit comments