Skip to content

Commit 74252a8

Browse files
committed
Fix imports of modules by Dash Pages feature
1 parent 1b3b6a4 commit 74252a8

File tree

4 files changed

+47
-35
lines changed

4 files changed

+47
-35
lines changed

dash/_pages.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import os
2-
from os import listdir
3-
from os.path import isfile, join
41
import collections
5-
from urllib.parse import parse_qs
6-
from fnmatch import fnmatch
2+
import os
73
import re
4+
import sys
5+
from fnmatch import fnmatch
86
from pathlib import Path
7+
from os.path import isfile, join
8+
from urllib.parse import parse_qs
99

1010
import flask
1111

@@ -34,7 +34,7 @@ def _infer_image(module):
3434

3535
if os.path.exists(assets_folder):
3636
files_in_assets = [
37-
f for f in listdir(assets_folder) if isfile(join(assets_folder, f))
37+
f for f in os.listdir(assets_folder) if isfile(join(assets_folder, f))
3838
]
3939
app_file = None
4040
logo_file = None
@@ -66,9 +66,9 @@ def _module_name_to_page_name(module_name):
6666
def _infer_path(module_name, template):
6767
if template is None:
6868
if CONFIG.pages_folder:
69-
pages_folder = str(Path(CONFIG.pages_folder).name)
69+
pages_module = str(Path(CONFIG.pages_folder).name)
7070
path = (
71-
module_name.split(pages_folder)[-1]
71+
module_name.split(pages_module)[-1]
7272
.replace("_", "-")
7373
.replace(".", "/")
7474
.lower()
@@ -83,6 +83,29 @@ def _infer_path(module_name, template):
8383
return path
8484

8585

86+
def _module_name_is_package(module_name):
87+
return (
88+
module_name in sys.modules
89+
and Path(sys.modules[module_name].__file__).name == "__init__.py"
90+
)
91+
92+
93+
def _infer_module_name(page_path):
94+
page_path = page_path.replace("\\", "/")
95+
_, _, filename = page_path.partition(CONFIG.pages_folder.replace("\\", "/") + "/")
96+
module = filename.replace(".py", "").replace("/", ".")
97+
proj_root = flask.helpers.get_root_path(CONFIG.name)
98+
parent_module = CONFIG.pages_folder
99+
if CONFIG.pages_folder.startswith(proj_root):
100+
parent_module = parent_module[len(proj_root) :]
101+
parent_module = parent_module.lstrip("/").replace("/", ".")
102+
module_name = f"{parent_module}.{module}"
103+
if _module_name_is_package(CONFIG.name):
104+
# Only prefix with CONFIG.name when its an imported package name
105+
module_name = f"{CONFIG.name}.{module_name}"
106+
return module_name
107+
108+
86109
def _parse_query_string(search):
87110
if search and len(search) > 0 and search[0] == "?":
88111
search = search[1:]

dash/dash.py

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464

6565
from . import _pages
6666
from ._pages import (
67+
_infer_module_name,
6768
_parse_path_variables,
6869
_parse_query_string,
6970
)
@@ -1987,9 +1988,7 @@ def verify_url_part(served_part, url_part, part_name):
19871988
self.server.run(host=host, port=port, debug=debug, **flask_run_options)
19881989

19891990
def _import_layouts_from_pages(self):
1990-
walk_dir = self.config.pages_folder
1991-
1992-
for (root, dirs, files) in os.walk(walk_dir):
1991+
for root, dirs, files in os.walk(self.config.pages_folder):
19931992
dirs[:] = [
19941993
d for d in dirs if not d.startswith(".") and not d.startswith("_")
19951994
]
@@ -2000,29 +1999,17 @@ def _import_layouts_from_pages(self):
20001999
or not file.endswith(".py")
20012000
):
20022001
continue
2003-
with open(os.path.join(root, file), encoding="utf-8") as f:
2002+
page_path = os.path.join(root, file)
2003+
with open(page_path, encoding="utf-8") as f:
20042004
content = f.read()
20052005
if "register_page" not in content:
20062006
continue
20072007

2008-
page_filename = os.path.join(root, file).replace("\\", "/")
2009-
_, _, page_filename = page_filename.partition(
2010-
walk_dir.replace("\\", "/") + "/"
2011-
)
2012-
page_filename = page_filename.replace(".py", "").replace("/", ".")
2013-
2014-
proj_root = flask.helpers.get_root_path(self.config.name)
2015-
parent_module = self.config.pages_folder
2016-
if self.config.pages_folder.startswith(proj_root):
2017-
parent_module = parent_module[len(proj_root) :]
2018-
parent_module = parent_module.lstrip("/").replace("/", ".")
2019-
module_name = f"{parent_module}.{page_filename}"
2020-
2021-
spec = importlib.util.spec_from_file_location(
2022-
module_name, os.path.join(root, file)
2023-
)
2008+
module_name = _infer_module_name(page_path)
2009+
spec = importlib.util.spec_from_file_location(module_name, page_path)
20242010
page_module = importlib.util.module_from_spec(spec)
20252011
spec.loader.exec_module(page_module)
2012+
sys.modules[module_name] = page_module
20262013

20272014
if (
20282015
module_name in _pages.PAGE_REGISTRY

tests/unit/pages/__init__.py

Whitespace-only changes.

tests/unit/pages/test_pages.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import sys
12
from pathlib import Path
23

34
import pytest
45
import dash
56
from dash import Dash, _pages
6-
from mock import patch
7+
from mock import patch, Mock
78

89

910
THIS_DIR = Path(__file__).parent
@@ -36,17 +37,18 @@ def test_infer_path(clear_pages_state, module_name, template, pages_folder, expe
3637

3738

3839
@pytest.mark.parametrize(
39-
"pages_folder, expected_module_name",
40+
"name, pages_folder, expected_module_name",
4041
[
41-
("custom_pages", "custom_pages.page"),
42-
("sub_dir/custom_pages", "sub_dir.custom_pages.page"),
43-
(str(THIS_DIR / "custom_pages"), "custom_pages.page"),
42+
(__name__, "custom_pages", "custom_pages.page"),
43+
(__name__, "sub_dir/custom_pages", "sub_dir.custom_pages.page"),
44+
(__name__, str(THIS_DIR / "custom_pages"), "custom_pages.page"),
45+
(__package__, "custom_pages", "pages.custom_pages.page"),
4446
],
4547
)
4648
def test_import_layouts_from_pages(
47-
clear_pages_state, pages_folder, expected_module_name
49+
clear_pages_state, name, pages_folder, expected_module_name
4850
):
49-
_ = Dash(__name__, use_pages=True, pages_folder=pages_folder)
51+
_ = Dash(name, use_pages=True, pages_folder=pages_folder)
5052
assert len(dash.page_registry) == 1
5153

5254
page_entry = list(dash.page_registry.values())[0]

0 commit comments

Comments
 (0)