Skip to content

Commit 91474b3

Browse files
committed
add modifiable config options
1 parent 5697a2d commit 91474b3

File tree

11 files changed

+100
-66
lines changed

11 files changed

+100
-66
lines changed

.pre-commit-config.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ repos:
77
rev: 3.7.9
88
hooks:
99
- id: flake8
10-
- repo: https://github.com/kynan/nbstripout
11-
rev: 0.3.9
12-
hooks:
13-
- id: nbstripout
14-
files: ".ipynb"
1510
- repo: https://github.com/pycqa/isort
1611
rev: 5.6.3
1712
hooks:

docs/source/package-api.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,10 @@ Useful Tools
100100

101101
.. automodule:: idom.utils
102102
:members:
103+
104+
105+
Configuration Options
106+
---------------------
107+
108+
.. automodule:: idom.config
109+
:members:

src/idom/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# package is not installed
88
__version__ = "0.0.0"
99

10-
from . import log
10+
from . import config, log
1111
from .client.module import Import, Module, install
1212
from .core import hooks
1313
from .core.component import Component, component
@@ -58,4 +58,5 @@
5858
"client",
5959
"install",
6060
"log",
61+
"config",
6162
]

src/idom/_option.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import os
2+
from typing import Callable, Generic, TypeVar
3+
4+
_O = TypeVar("_O")
5+
6+
7+
class Option(Generic[_O]):
8+
"""An option that can be set using an environment variable of the same name"""
9+
10+
def __init__(
11+
self,
12+
name: str,
13+
default: _O,
14+
allow_changes: bool = True,
15+
from_string: Callable[[str], _O] = lambda x: x,
16+
) -> None:
17+
self.name = name
18+
self._default = default
19+
self._allow_changes = allow_changes
20+
assert name == name.upper()
21+
if name not in os.environ:
22+
self._value = default
23+
else:
24+
self._value = from_string(os.environ[name])
25+
26+
def get(self) -> _O:
27+
return self._value
28+
29+
def set(self, new: _O) -> _O:
30+
if not self._allow_changes:
31+
raise ValueError(f"{self.name} cannot be modified.")
32+
old = self._value
33+
self._value = new
34+
return old
35+
36+
def reset(self) -> _O:
37+
return self.set(self._default)

src/idom/_options.py

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/idom/client/app/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
node_modules
22
web_modules
33
build
4-
src/user-packages.js

src/idom/client/manage.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,36 @@
66
from tempfile import TemporaryDirectory
77
from typing import List, Sequence, Set, Union
88

9+
from idom.config import IDOM_CLIENT_BUILD_DIR
10+
911
from .utils import find_js_module_exports_in_source, get_package_name
1012

1113
logger = getLogger(__name__)
1214

1315

14-
THIS_DIR = Path(__file__).parent
15-
# these directories are never modified
16-
APP_DIR = THIS_DIR / "app"
17-
BACKUP_BUILD_DIR = APP_DIR / "build"
16+
_THIS_DIR = Path(__file__).parent
17+
_APP_DIR = _THIS_DIR / "app"
18+
_BACKUP_BUILD_DIR = _APP_DIR / "build"
1819
# these directory are modified when users install packages
19-
BUILD_DIR = THIS_DIR / "build"
20-
WEB_MODULES_DIR = BUILD_DIR / "_snowpack" / "pkg"
20+
21+
22+
def _build_dir() -> Path:
23+
return IDOM_CLIENT_BUILD_DIR.get()
24+
25+
26+
def _web_modules_dir() -> Path:
27+
return _build_dir() / "_snowpack" / "pkg"
2128

2229

2330
def _copy_to_build_dir(source: Path) -> None:
24-
if BUILD_DIR.exists():
25-
shutil.rmtree(BUILD_DIR)
26-
shutil.copytree(source, BUILD_DIR, symlinks=True)
31+
target = _build_dir()
32+
if target.exists():
33+
shutil.rmtree(target)
34+
shutil.copytree(source, target, symlinks=True)
2735

2836

29-
if not BUILD_DIR.exists(): # coverage: skip
30-
_copy_to_build_dir(BACKUP_BUILD_DIR)
37+
if not _build_dir().exists(): # coverage: skip
38+
_copy_to_build_dir(_BACKUP_BUILD_DIR)
3139

3240

3341
def web_module_exports(package_name: str) -> List[str]:
@@ -48,8 +56,9 @@ def web_module_exists(package_name: str) -> bool:
4856

4957
def web_module_names() -> Set[str]:
5058
names = []
51-
for pth in WEB_MODULES_DIR.glob("**/*.js"):
52-
rel_pth = pth.relative_to(WEB_MODULES_DIR)
59+
web_mod_dir = _web_modules_dir()
60+
for pth in web_mod_dir.glob("**/*.js"):
61+
rel_pth = pth.relative_to(web_mod_dir)
5362
if Path("common") in rel_pth.parents:
5463
continue
5564
module_path = str(rel_pth.as_posix())
@@ -70,7 +79,7 @@ def add_web_module(package_name: str, source: Union[Path, str]) -> str:
7079

7180

7281
def web_module_path(package_name: str, must_exist: bool = False) -> Path:
73-
path = WEB_MODULES_DIR.joinpath(*(package_name + ".js").split("/"))
82+
path = _web_modules_dir().joinpath(*(package_name + ".js").split("/"))
7483
if must_exist and not path.exists():
7584
raise ValueError(
7685
f"Web module {package_name!r} does not exist at path {str(path)!r}"
@@ -79,7 +88,7 @@ def web_module_path(package_name: str, must_exist: bool = False) -> Path:
7988

8089

8190
def restore() -> None:
82-
_copy_to_build_dir(BACKUP_BUILD_DIR)
91+
_copy_to_build_dir(_BACKUP_BUILD_DIR)
8392

8493

8594
def build(packages_to_install: Sequence[str], clean_build: bool = False) -> None:
@@ -92,7 +101,7 @@ def build(packages_to_install: Sequence[str], clean_build: bool = False) -> None
92101
package_json_path = temp_app_dir / "package.json"
93102

94103
# copy over the whole APP_DIR directory into the temp one
95-
shutil.copytree(APP_DIR, temp_app_dir, symlinks=True)
104+
shutil.copytree(_APP_DIR, temp_app_dir, symlinks=True)
96105

97106
package_names_to_install = {get_package_name(p) for p in packages_to_install}
98107

src/idom/client/utils.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import json
21
import re
3-
from contextlib import contextmanager
4-
from pathlib import Path
5-
from typing import Any, Iterator, List, Tuple
2+
from typing import List, Tuple
63

74

85
def get_package_name(pkg: str) -> str:
@@ -24,17 +21,6 @@ def split_package_name_and_version(pkg: str) -> Tuple[str, str]:
2421
return pkg, ""
2522

2623

27-
@contextmanager
28-
def open_modifiable_json(path: Path) -> Iterator[Any]:
29-
with path.open() as f:
30-
data = json.loads(f.read().strip() or "{}")
31-
32-
yield data
33-
34-
with path.open("w") as f:
35-
json.dump(data, f)
36-
37-
3824
_JS_MODULE_EXPORT_PATTERN = re.compile(
3925
r";?\s*export\s*{([0-9a-zA-Z_$\s,]*)}\s*;", re.MULTILINE
4026
)

src/idom/config.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from pathlib import Path
2+
3+
from ._option import Option
4+
5+
IDOM_DEBUG_MODE = Option(
6+
"IDOM_DEBUG_MODE",
7+
default=False,
8+
allow_changes=False,
9+
from_string=lambda x: bool(int(x)),
10+
)
11+
"""Turn on/off debug mode"""
12+
13+
IDOM_CLIENT_BUILD_DIR = Option(
14+
"IDOM_CLIENT_BUILD_DIR",
15+
default=Path(__file__).parent / "client" / "build",
16+
from_string=Path,
17+
)
18+
"""The location IDOM will use for its client application"""
19+
20+
IDOM_CLIENT_WEB_MODULE_BASE_URL = Option(
21+
"IDOM_CLIENT_WEB_MODULE_BASE_URL",
22+
default="./_snowpack/pkg",
23+
)
24+
"""The base URL where all user-installed web modules reside"""

src/idom/core/layout.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from jsonpatch import apply_patch, make_patch
2020

21-
from idom._options import IDOM_DEBUG_MODE
21+
from idom.config import IDOM_DEBUG_MODE
2222

2323
from .component import AbstractComponent
2424
from .events import EventHandler, EventTarget
@@ -102,7 +102,7 @@ async def render(self) -> LayoutUpdate:
102102
if self._has_component_state(component):
103103
return self._create_layout_update(component)
104104

105-
if IDOM_DEBUG_MODE:
105+
if IDOM_DEBUG_MODE.get():
106106
_debug_render = render
107107

108108
@wraps(_debug_render)

src/idom/log.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
from logging.config import dictConfig
44

5-
from ._options import IDOM_DEBUG_MODE
5+
from .config import IDOM_DEBUG_MODE
66

77
root_logger = logging.getLogger("idom")
88

@@ -12,7 +12,7 @@
1212
"disable_existing_loggers": False,
1313
"loggers": {
1414
"idom": {
15-
"level": "DEBUG" if IDOM_DEBUG_MODE else "INFO",
15+
"level": "DEBUG" if IDOM_DEBUG_MODE.get() else "INFO",
1616
"handlers": ["console"],
1717
},
1818
},

0 commit comments

Comments
 (0)