Skip to content

Commit

Permalink
Fix path_template variable parsing containing dots
Browse files Browse the repository at this point in the history
see #2437
  • Loading branch information
jowlo committed Mar 2, 2023
1 parent 8aec8d4 commit 4811dd2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
28 changes: 11 additions & 17 deletions dash/_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from os.path import isfile, join
import collections
from urllib.parse import parse_qs
from fnmatch import fnmatch
import re
import flask

Expand Down Expand Up @@ -101,23 +100,18 @@ def _parse_path_variables(pathname, path_template):
returns **{"asset_id": "a100"}
"""

# parse variable definitions e.g. <var_name> from template
# and create pattern to match
wildcard_pattern = re.sub("<.*?>", "*", path_template)
var_pattern = re.sub("<.*?>", "(.*)", path_template)
# Copy of re._special_chars_map from Python >= 3.7 for backwards compatibility with 3.6
_special_chars_map = {i: '\\' + chr(i) for i in b'()[]{}?*+-|^$\\.&~# \t\n\r\v\f'}
escaped_template = path_template.translate(_special_chars_map)

# check that static sections of the pathname match the template
if not fnmatch(pathname, wildcard_pattern):
return None

# parse variable names e.g. var_name from template
var_names = re.findall("<(.*?)>", path_template)

# parse variables from path
variables = re.findall(var_pattern, pathname)
variables = variables[0] if isinstance(variables[0], tuple) else variables

return dict(zip(var_names, variables))
pattern = re.compile(
re.sub(
"<(?P<var>.*?)>", r"(?P<\g<var>>.*)",
escaped_template
)
)
match = pattern.match(pathname)
return match.groupdict() if match else None


def _create_redirect_function(redirect_to):
Expand Down
21 changes: 21 additions & 0 deletions tests/unit/test_path_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from dash._pages import _parse_path_variables


def test_path_template_general():
path_template = "some/<var>/static"
assert _parse_path_variables("some/value/static", path_template) == {'var': 'value'}


def test_path_template():
path_template = "<foo>/<bar>"
assert _parse_path_variables("one/two", path_template) == {'foo': 'one', 'bar': 'two'}


def test_path_template_dots():
path_template = "<foo>.<bar>"
assert _parse_path_variables("one.two", path_template) == {'foo': 'one', 'bar': 'two'}


def test_path_template_none():
path_template = "novars"
assert _parse_path_variables("one/two", path_template) is None

0 comments on commit 4811dd2

Please sign in to comment.