Skip to content

Commit 1dfeceb

Browse files
template ext files (#49)
* change name of configuration files * make sure generator can handle both toml and json config files * change the default config test to be toml as it's the new default * add more tests * remove trailing space * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reuse check_project_manifest on tests that make sense * reuse check_project_manifest on tests that make sense * revert toml pretty version since new one is bugged * check whether html template is loading files externally instead of inline * add function to save app config file and add specific function to create project html file * change new project html template to use external files and not code inline * add default python main file to cli config * use config to filenames instead of variables * make sure config always have all keys * change path in template to point to local * add wrap template and fix wrap cmd issues * rename ambiguous template argument * change the way we check config dict because of non support python feature in 3.8 * reverd rev change on precommit hooks * add docstrings Co-authored-by: Fabio Pliger <fpliger@anaconda.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 36f1e59 commit 1dfeceb

File tree

6 files changed

+133
-10
lines changed

6 files changed

+133
-10
lines changed

src/pyscript/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
DEFAULT_CONFIG = {
1515
# Name of config file for PyScript projects.
1616
"project_config_filename": "pyscript.toml",
17+
"project_main_filename": "main.py",
1718
}
1819

1920

@@ -47,3 +48,9 @@
4748
app = typer.Typer(add_completion=False)
4849
with CONFIG_FILE.open() as config_file:
4950
config = json.load(config_file)
51+
52+
# Make sure all configuration keys are there. If any is missing,
53+
# we pick from the default config
54+
for (k, v) in DEFAULT_CONFIG.items():
55+
if k not in config:
56+
config[k] = v

src/pyscript/_generator.py

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,76 @@
99
from pyscript import config
1010

1111
_env = jinja2.Environment(loader=jinja2.PackageLoader("pyscript"))
12+
TEMPLATE_PYTHON_CODE = """# Replace the code below with your own
13+
print("Hello, world!")
14+
"""
1215

1316

14-
def string_to_html(input_str: str, title: str, output_path: Path) -> None:
17+
def create_project_html(
18+
title: str, python_file_path: str, config_file_path: str, output_file_path: Path
19+
) -> None:
1520
"""Write a Python script string to an HTML file template."""
1621
template = _env.get_template("basic.html")
22+
with output_file_path.open("w") as fp:
23+
fp.write(
24+
template.render(
25+
python_file_path=python_file_path,
26+
config_file_path=config_file_path,
27+
title=title,
28+
)
29+
)
30+
31+
32+
def save_config_file(config_file: Path, configuration: dict):
33+
"""Write an app configuration dict to `config_file`.
34+
35+
Params:
36+
37+
- config_file(Path): path configuration file. (I.e.: "pyscript.toml"). Supported
38+
formats: `toml` and `json`.
39+
- configuration(dict): app configuration to be saved
40+
41+
Return:
42+
(None)
43+
"""
44+
with config_file.open("w", encoding="utf-8") as fp:
45+
if str(config_file).endswith(".json"):
46+
json.dump(configuration, fp)
47+
else:
48+
toml.dump(configuration, fp)
49+
50+
51+
def string_to_html(
52+
code: str, title: str, output_path: Path, template_name: str = "basic.html"
53+
) -> None:
54+
"""Write a Python script string to an HTML file template.
55+
56+
Params:
57+
58+
- code(str): string containing the application code to be written to the
59+
PyScript app template
60+
- title(str): application title, that will be placed as title of the html
61+
app template
62+
- template_name(str): name of the template to be used
63+
64+
Output:
65+
(None)
66+
"""
67+
template = _env.get_template(template_name)
1768
with output_path.open("w") as fp:
18-
fp.write(template.render(code=input_str, title=title))
69+
fp.write(template.render(code=code, title=title))
1970

2071

21-
def file_to_html(input_path: Path, title: str, output_path: Optional[Path]) -> None:
72+
def file_to_html(
73+
input_path: Path,
74+
title: str,
75+
output_path: Optional[Path],
76+
template_name: str = "basic.html",
77+
) -> None:
2278
"""Write a Python script string to an HTML file template."""
2379
output_path = output_path or input_path.with_suffix(".html")
2480
with input_path.open("r") as fp:
25-
string_to_html(fp.read(), title, output_path)
81+
string_to_html(fp.read(), title, output_path, template_name)
2682

2783

2884
def create_project(
@@ -57,4 +113,15 @@ def create_project(
57113
toml.dump(context, fp)
58114

59115
index_file = app_dir / "index.html"
60-
string_to_html('print("Hello, world!")', app_name, index_file)
116+
117+
# Save the new python file
118+
python_filepath = app_dir / "main.py"
119+
with python_filepath.open("w", encoding="utf-8") as fp:
120+
fp.write(TEMPLATE_PYTHON_CODE)
121+
122+
create_project_html(
123+
app_name,
124+
config["project_main_filename"],
125+
config["project_config_filename"],
126+
index_file,
127+
)

src/pyscript/plugins/wrap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ def wrap(
5252
else:
5353
raise cli.Abort("Must provide an output file or use `--show` option")
5454
if input_file is not None:
55-
file_to_html(input_file, title, output)
55+
file_to_html(input_file, title, output, template_name="wrap.html")
5656
if command:
57-
string_to_html(command, title, output)
57+
string_to_html(command, title, output, template_name="wrap.html")
5858
if output:
5959
if show:
6060
console.print("Opening in web browser!")

src/pyscript/templates/basic.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
77
</head>
88
<body>
9-
<py-script>
10-
{{ code }}
11-
</py-script>
9+
<py-config src="./{{ config_file_path }}"></py-config>
10+
<py-script src="./{{ python_file_path }}"></py-script>
1211
</body>
1312
</html>

src/pyscript/templates/wrap.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>{{ title }}</title>
5+
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css"/>
6+
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
7+
</head>
8+
<body>
9+
<py-script>
10+
{{ code }}
11+
</py-script>
12+
</body>
13+
</html>

tests/test_generator.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def test_create_project(tmp_cwd: Path, is_not_none: Any) -> None:
2828
manifest_path = tmp_cwd / app_name / config["project_config_filename"]
2929

3030
check_project_manifest(manifest_path, toml, app_name, is_not_none)
31+
check_project_files(tmp_cwd / app_name)
3132

3233

3334
def test_create_project_twice_raises_error(tmp_cwd: Path) -> None:
@@ -131,3 +132,39 @@ def check_project_manifest(
131132
"author_email": author_email,
132133
"version": is_not_none,
133134
}
135+
136+
137+
def check_project_files(
138+
app_folder: Path,
139+
html_file: str = "index.html",
140+
config_file: str = config["project_config_filename"],
141+
python_file: str = "main.py",
142+
):
143+
"""
144+
Perform the following checks:
145+
146+
* checks that app_folder/html_file exists
147+
* checks that app_folder/config_file exists
148+
* checks that app_folder/python_file exists
149+
* checks that html_file actually loads both the python and the config files
150+
151+
Params:
152+
* config_path(Path): path to the app folder
153+
* html_file(str): name of the html file generated by the template
154+
(default: index.html)
155+
* config_file(str): name of the config file generated by the template
156+
(default: config["project_config_filename"])
157+
* python_file(str): name of the python file generated by the template
158+
(default: main.py)
159+
160+
"""
161+
# assert that the new project files exists
162+
html_file_path = app_folder / html_file
163+
assert html_file_path.exists(), f"{html_file} not found! :("
164+
assert (app_folder / config_file).exists(), f"{config_file} not found! :("
165+
assert (app_folder / python_file).exists(), f"{python_file} not found! :("
166+
167+
with html_file_path.open() as fp:
168+
contents = fp.read()
169+
assert f'<py-script src="./{python_file}">' in contents
170+
assert f'<py-config src="./{config_file}">' in contents

0 commit comments

Comments
 (0)