Skip to content

Commit 079f79b

Browse files
committed
feat: add new parameter assets_path_ignore for dash.Dash()
1 parent 9566578 commit 079f79b

File tree

1 file changed

+37
-19
lines changed

1 file changed

+37
-19
lines changed

dash/dash.py

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ class Dash:
246246
to sensitive files.
247247
:type assets_ignore: string
248248
249+
:param assets_path_ignore: A list of regex, each regex as a string to pass to ``re.compile``, for
250+
assets path to omit from immediate loading. The files in these ignored paths will still be
251+
served if specifically requested. You cannot use this to prevent access
252+
to sensitive files.
253+
:type assets_path_ignore: list of strings
254+
249255
:param assets_external_path: an absolute URL from which to load assets.
250256
Use with ``serve_locally=False``. assets_external_path is joined
251257
with assets_url_path to determine the absolute url to the
@@ -391,6 +397,7 @@ def __init__( # pylint: disable=too-many-statements
391397
use_pages: Optional[bool] = None,
392398
assets_url_path: str = "assets",
393399
assets_ignore: str = "",
400+
assets_path_ignore: List[str] = None,
394401
assets_external_path: Optional[str] = None,
395402
eager_loading: bool = False,
396403
include_assets_files: bool = True,
@@ -451,6 +458,7 @@ def __init__( # pylint: disable=too-many-statements
451458
), # type: ignore
452459
assets_url_path=assets_url_path,
453460
assets_ignore=assets_ignore,
461+
assets_path_ignore=assets_path_ignore,
454462
assets_external_path=get_combined_config(
455463
"assets_external_path", assets_external_path, ""
456464
),
@@ -730,7 +738,6 @@ def layout(self, value):
730738
and not self.validation_layout
731739
and not self.config.suppress_callback_exceptions
732740
):
733-
734741
layout_value = self._layout_value()
735742
_validate.validate_layout(value, layout_value)
736743
self.validation_layout = layout_value
@@ -1348,9 +1355,7 @@ def dispatch(self):
13481355
outputs_grouping = map_grouping(
13491356
lambda ind: flat_outputs[ind], outputs_indices
13501357
)
1351-
g.outputs_grouping = (
1352-
outputs_grouping # pylint: disable=assigning-non-slot
1353-
)
1358+
g.outputs_grouping = outputs_grouping # pylint: disable=assigning-non-slot
13541359
g.using_outputs_grouping = ( # pylint: disable=assigning-non-slot
13551360
not isinstance(outputs_indices, int)
13561361
and outputs_indices != list(range(grouping_len(outputs_indices)))
@@ -1467,11 +1472,16 @@ def _walk_assets_directory(self):
14671472
walk_dir = self.config.assets_folder
14681473
slash_splitter = re.compile(r"[\\/]+")
14691474
ignore_str = self.config.assets_ignore
1475+
ignore_path_list = self.config.assets_path_ignore
14701476
ignore_filter = re.compile(ignore_str) if ignore_str else None
1477+
ignore_path_filters = [
1478+
re.compile(ignore_path) for ignore_path in ignore_path_list if ignore_path
1479+
]
14711480

14721481
for current, _, files in sorted(os.walk(walk_dir)):
14731482
if current == walk_dir:
14741483
base = ""
1484+
s = ""
14751485
else:
14761486
s = current.replace(walk_dir, "").lstrip("\\").lstrip("/")
14771487
splitted = slash_splitter.split(s)
@@ -1480,22 +1490,32 @@ def _walk_assets_directory(self):
14801490
else:
14811491
base = splitted[0]
14821492

1483-
if ignore_filter:
1484-
files_gen = (x for x in files if not ignore_filter.search(x))
1493+
# Check if any level of current path matches ignore path
1494+
if s and any(
1495+
ignore_path_filter.search(x)
1496+
for ignore_path_filter in ignore_path_filters
1497+
for x in s.split(os.path.sep)
1498+
):
1499+
pass
14851500
else:
1486-
files_gen = files
1501+
if ignore_filter:
1502+
files_gen = (x for x in files if not ignore_filter.search(x))
1503+
else:
1504+
files_gen = files
14871505

1488-
for f in sorted(files_gen):
1489-
path = "/".join([base, f]) if base else f
1506+
for f in sorted(files_gen):
1507+
path = "/".join([base, f]) if base else f
14901508

1491-
full = os.path.join(current, f)
1509+
full = os.path.join(current, f)
14921510

1493-
if f.endswith("js"):
1494-
self.scripts.append_script(self._add_assets_resource(path, full))
1495-
elif f.endswith("css"):
1496-
self.css.append_css(self._add_assets_resource(path, full))
1497-
elif f == "favicon.ico":
1498-
self._favicon = path
1511+
if f.endswith("js"):
1512+
self.scripts.append_script(
1513+
self._add_assets_resource(path, full)
1514+
)
1515+
elif f.endswith("css"):
1516+
self.css.append_css(self._add_assets_resource(path, full))
1517+
elif f == "favicon.ico":
1518+
self._favicon = path
14991519

15001520
@staticmethod
15011521
def _invalid_resources_handler(err):
@@ -2254,9 +2274,7 @@ def update(pathname_, search_, **states):
22542274
]
22552275
+ [
22562276
# pylint: disable=not-callable
2257-
self.layout()
2258-
if callable(self.layout)
2259-
else self.layout
2277+
self.layout() if callable(self.layout) else self.layout
22602278
]
22612279
)
22622280
if _ID_CONTENT not in self.validation_layout:

0 commit comments

Comments
 (0)