routes icon indicating copy to clipboard operation
routes copied to clipboard

repeating a variable in a path/pattern fails

Open commonism opened this issue 1 year ago • 1 comments

Using the same variable name in a path mutiple times fails:

import routes
m = routes.Mapper()
m.connect("/redfish/v1/Systems/{ComputerSystemId}/Memory/{MemoryId}/Oem/Dell/DellMemory/{MemoryId}")
m.routematch("/redfish/v1/Systems/1/Memory/0/Oem/Dell/DellMemory/0")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/venv//lib/python3.10/site-packages/routes/mapper.py", line 761, in routematch
    result = self._match(url, environ)
  File "~/venv//lib/python3.10/site-packages/routes/mapper.py", line 672, in _match
    self.create_regs()
  File "~/venv//lib/python3.10/site-packages/routes/mapper.py", line 612, in create_regs
    self._create_regs(*args, **kwargs)
  File "~/venv//lib/python3.10/site-packages/routes/mapper.py", line 630, in _create_regs
    route.makeregexp(clist)
  File "~/venv//lib/python3.10/site-packages/routes/route.py", line 315, in makeregexp
    self.regmatch = re.compile(reg)
  File "/usr/lib/python3.10/re.py", line 251, in compile
    return _compile(pattern, flags)
  File "/usr/lib/python3.10/re.py", line 303, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python3.10/sre_compile.py", line 788, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/lib/python3.10/sre_parse.py", line 955, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
  File "/usr/lib/python3.10/sre_parse.py", line 444, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
  File "/usr/lib/python3.10/sre_parse.py", line 838, in _parse
    raise source.error(err.msg, len(name) + 1) from None
re.error: redefinition of group name 'MemoryId' as group 3; was group 2 at position 102

commonism avatar Dec 15 '23 15:12 commonism

possible via backrefs e.g. \1

diff --git a/routes/route.py b/routes/route.py
index 719636a..3a29077 100644
--- a/routes/route.py
+++ b/routes/route.py
@@ -318,6 +318,7 @@ class Route(object):
         """Build the regexp by iterating through the routelist and
         replacing dicts with the appropriate regexp match"""
         regparts = []
+        offsets = list()
         for part in self.routelist:
             if isinstance(part, dict):
                 var = part['name']
@@ -330,7 +331,12 @@ class Route(object):
                 else:
                     partmatch = self.reqs.get(var) or '.+?'
                 if include_names:
-                    regpart = '(?P<%s>%s)' % (var, partmatch)
+                    if var not in offsets:
+                        offsets.append(var)
+                        regpart = '(?P<%s>%s)' % (var, partmatch)
+                    else:
+                        offset = offsets.index(var)
+                        regpart = f'\\{offset+1}'
                 else:
                     regpart = '(?:%s)' % partmatch
                 if part['type'] == '.':

commonism avatar Dec 15 '23 15:12 commonism