Skip to content

Commit ea19a07

Browse files
committed
cleaner way to specify import sources
this gives the server more authority over where resources are located and makes it easier for downstream applications to configure
1 parent bf089e6 commit ea19a07

File tree

6 files changed

+44
-15
lines changed

6 files changed

+44
-15
lines changed

src/idom/_option.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,19 @@ def mutable(self) -> bool:
2828
"""Whether this option can be modified after being loaded"""
2929
return self._mutable
3030

31+
@property
32+
def default(self) -> _O:
33+
"""This option's default value"""
34+
return self._default
35+
3136
def get(self) -> _O:
3237
"""Get the current value of this option."""
3338
return self._value
3439

3540
def set(self, new: _O) -> _O:
3641
"""Set the value of this configuration option
3742
38-
Raises a ``TypeError`` if this option is immutable.
43+
Raises a ``TypeError`` if this option is not :attr:`Option.mutable`.
3944
"""
4045
if not self._mutable:
4146
raise TypeError(f"{self} cannot be modified after initial load")

src/idom/client/_private.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
APP_DIR = HERE / "app"
1212
BACKUP_BUILD_DIR = APP_DIR / "build"
1313

14+
# the path relative to the build that contains import sources
15+
IDOM_CLIENT_IMPORT_SOURCE_URL_INFIX = "/_snowpack/pkg"
16+
17+
18+
def web_modules_dir() -> Path:
19+
return IDOM_CLIENT_BUILD_DIR.get().joinpath(
20+
*IDOM_CLIENT_IMPORT_SOURCE_URL_INFIX[1:].split("/")
21+
)
22+
1423

1524
if not IDOM_CLIENT_BUILD_DIR.get().exists(): # pragma: no cover
1625
shutil.copytree(BACKUP_BUILD_DIR, IDOM_CLIENT_BUILD_DIR.get(), symlinks=True)

src/idom/client/manage.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,16 @@
55
from tempfile import TemporaryDirectory
66
from typing import Dict, Iterable, List, Sequence, Set, Union
77

8-
from idom.config import IDOM_CLIENT_BUILD_DIR, IDOM_CLIENT_WEB_MODULE_BASE_URL
8+
from idom.config import IDOM_CLIENT_IMPORT_SOURCE_URL
99

1010
from . import _private
1111

1212

1313
logger = getLogger(__name__)
1414

1515

16-
def web_modules_dir() -> Path:
17-
return IDOM_CLIENT_BUILD_DIR.get() / "_snowpack" / "pkg"
18-
19-
2016
def web_module_path(package_name: str, must_exist: bool = False) -> Path:
21-
path = web_modules_dir().joinpath(*(package_name + ".js").split("/"))
17+
path = _private.web_modules_dir().joinpath(*(package_name + ".js").split("/"))
2218
if must_exist and not path.exists():
2319
raise ValueError(
2420
f"Web module {package_name!r} does not exist at path {str(path)!r}"
@@ -35,7 +31,10 @@ def web_module_exports(package_name: str) -> List[str]:
3531

3632
def web_module_url(package_name: str) -> str:
3733
web_module_path(package_name, must_exist=True)
38-
return IDOM_CLIENT_WEB_MODULE_BASE_URL.get() + f"/{package_name}.js"
34+
return (
35+
IDOM_CLIENT_IMPORT_SOURCE_URL.get()
36+
+ f"{_private.IDOM_CLIENT_IMPORT_SOURCE_URL_INFIX}/{package_name}.js"
37+
)
3938

4039

4140
def web_module_exists(package_name: str) -> bool:
@@ -44,7 +43,7 @@ def web_module_exists(package_name: str) -> bool:
4443

4544
def web_module_names() -> Set[str]:
4645
names = []
47-
web_mod_dir = web_modules_dir()
46+
web_mod_dir = _private.web_modules_dir()
4847
for pth in web_mod_dir.glob("**/*.js"):
4948
rel_pth = pth.relative_to(web_mod_dir)
5049
if Path("common") in rel_pth.parents:

src/idom/config.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,24 @@
3131
a set of publically available APIs for working with the client.
3232
"""
3333

34-
IDOM_CLIENT_WEB_MODULE_BASE_URL = _option.Option(
35-
"IDOM_CLIENT_WEB_MODULE_BASE_URL",
36-
default=".",
34+
35+
IDOM_CLIENT_IMPORT_SOURCE_URL = _option.Option(
36+
"IDOM_CLIENT_IMPORT_SOURCE_URL",
37+
default="/client",
3738
validator=lambda x: cast(str, x[:-1] if x.endswith("/") else x),
3839
)
39-
"""The base URL where all user-installed web modules reside"""
40+
"""The URL to importable modules containing Javascript components
41+
42+
Setting this to an empty string will given the client control over the location of
43+
import sources. Using a relative path (e.g. one starting with ``./``) with locate import
44+
sources relative to a base URL specified by the client. Lastly, an absolute URL
45+
specifies exactly where import sources are located and ignores are client configuration.
46+
47+
Examples:
48+
Empty String:
49+
``CLIENT_SPECIFIED_BASE_URL/my-module.js``
50+
Relative Path:
51+
``CLIENT_SPECIFIED_BASE_URL/RELATIVE_PATH/my-module.js``
52+
Absolute URL
53+
``ABSOLUTE_PATH/my-module.js``
54+
"""

tests/test__option.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def test_option_from_os_environ():
2020
def test_option_from_default():
2121
opt = Option("A_FAKE_OPTION", "default-value")
2222
assert opt.get() == "default-value"
23+
assert opt.get() is opt.default
2324

2425

2526
@mock.patch.dict(os.environ, {"A_FAKE_OPTION": "1"})
@@ -47,7 +48,7 @@ def test_option_reset():
4748
opt.set("a-new-value")
4849
assert opt.get() == "a-new-value"
4950
opt.reset()
50-
assert opt.get() == "default-value"
51+
assert opt.get() is opt.default
5152

5253

5354
def test_option_set_returns_last_value():

tests/test_client/test_manage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def test_web_module_path_must_exist():
3333

3434
def test_web_module_url(victory):
3535
assert web_module_exists("victory")
36-
assert web_module_url("victory") == "./victory.js"
36+
assert web_module_url("victory") == "/client/_snowpack/pkg/victory.js"
3737

3838

3939
def test_web_module_exports(victory):

0 commit comments

Comments
 (0)