@@ -246,6 +246,12 @@ class Dash:
246
246
to sensitive files.
247
247
:type assets_ignore: string
248
248
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
+
249
255
:param assets_external_path: an absolute URL from which to load assets.
250
256
Use with ``serve_locally=False``. assets_external_path is joined
251
257
with assets_url_path to determine the absolute url to the
@@ -391,6 +397,7 @@ def __init__( # pylint: disable=too-many-statements
391
397
use_pages : Optional [bool ] = None ,
392
398
assets_url_path : str = "assets" ,
393
399
assets_ignore : str = "" ,
400
+ assets_path_ignore : List [str ] = None ,
394
401
assets_external_path : Optional [str ] = None ,
395
402
eager_loading : bool = False ,
396
403
include_assets_files : bool = True ,
@@ -451,6 +458,7 @@ def __init__( # pylint: disable=too-many-statements
451
458
), # type: ignore
452
459
assets_url_path = assets_url_path ,
453
460
assets_ignore = assets_ignore ,
461
+ assets_path_ignore = assets_path_ignore ,
454
462
assets_external_path = get_combined_config (
455
463
"assets_external_path" , assets_external_path , ""
456
464
),
@@ -730,7 +738,6 @@ def layout(self, value):
730
738
and not self .validation_layout
731
739
and not self .config .suppress_callback_exceptions
732
740
):
733
-
734
741
layout_value = self ._layout_value ()
735
742
_validate .validate_layout (value , layout_value )
736
743
self .validation_layout = layout_value
@@ -1348,9 +1355,7 @@ def dispatch(self):
1348
1355
outputs_grouping = map_grouping (
1349
1356
lambda ind : flat_outputs [ind ], outputs_indices
1350
1357
)
1351
- g .outputs_grouping = (
1352
- outputs_grouping # pylint: disable=assigning-non-slot
1353
- )
1358
+ g .outputs_grouping = outputs_grouping # pylint: disable=assigning-non-slot
1354
1359
g .using_outputs_grouping = ( # pylint: disable=assigning-non-slot
1355
1360
not isinstance (outputs_indices , int )
1356
1361
and outputs_indices != list (range (grouping_len (outputs_indices )))
@@ -1467,11 +1472,16 @@ def _walk_assets_directory(self):
1467
1472
walk_dir = self .config .assets_folder
1468
1473
slash_splitter = re .compile (r"[\\/]+" )
1469
1474
ignore_str = self .config .assets_ignore
1475
+ ignore_path_list = self .config .assets_path_ignore
1470
1476
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
+ ]
1471
1480
1472
1481
for current , _ , files in sorted (os .walk (walk_dir )):
1473
1482
if current == walk_dir :
1474
1483
base = ""
1484
+ s = ""
1475
1485
else :
1476
1486
s = current .replace (walk_dir , "" ).lstrip ("\\ " ).lstrip ("/" )
1477
1487
splitted = slash_splitter .split (s )
@@ -1480,22 +1490,32 @@ def _walk_assets_directory(self):
1480
1490
else :
1481
1491
base = splitted [0 ]
1482
1492
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
1485
1500
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
1487
1505
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
1490
1508
1491
- full = os .path .join (current , f )
1509
+ full = os .path .join (current , f )
1492
1510
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
1499
1519
1500
1520
@staticmethod
1501
1521
def _invalid_resources_handler (err ):
@@ -2254,9 +2274,7 @@ def update(pathname_, search_, **states):
2254
2274
]
2255
2275
+ [
2256
2276
# 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
2260
2278
]
2261
2279
)
2262
2280
if _ID_CONTENT not in self .validation_layout :
0 commit comments