dp_wizard_templates 0.1.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dp_wizard_templates might be problematic. Click here for more details.
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.coveragerc +1 -1
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.flake8 +4 -3
- dp_wizard_templates-0.3.0/.nojekyll +1 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.pre-commit-config.yaml +2 -1
- dp_wizard_templates-0.3.0/CHANGELOG.md +14 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/PKG-INFO +4 -8
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/README.md +1 -6
- dp_wizard_templates-0.3.0/dp_wizard_templates/VERSION +1 -0
- dp_wizard_templates-0.3.0/dp_wizard_templates/code_template.py +179 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/dp_wizard_templates/converters.py +23 -10
- dp_wizard_templates-0.3.0/dp_wizard_templates/py.typed +0 -0
- {dp_wizard_templates-0.1.0/README_examples → dp_wizard_templates-0.3.0/examples}/_block_demo.py +1 -0
- {dp_wizard_templates-0.1.0/README_examples → dp_wizard_templates-0.3.0/examples}/hello-world.html +7 -4
- {dp_wizard_templates-0.1.0/README_examples → dp_wizard_templates-0.3.0/examples}/hello-world.ipynb +10 -5
- dp_wizard_templates-0.3.0/index.html +7783 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/pyproject.toml +3 -2
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/test_code_template.py +58 -23
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/test_converters.py +1 -1
- dp_wizard_templates-0.3.0/tests/test_index_html.py +222 -0
- dp_wizard_templates-0.1.0/CHANGELOG.md +0 -5
- dp_wizard_templates-0.1.0/README_test.py +0 -139
- dp_wizard_templates-0.1.0/dp_wizard_templates/VERSION +0 -1
- dp_wizard_templates-0.1.0/dp_wizard_templates/code_template.py +0 -127
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.github/workflows/test.yml +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.gitignore +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/.pytest.ini +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/LICENSE +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/dp_wizard_templates/__init__.py +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/requirements-dev.in +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/requirements-dev.txt +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/requirements.in +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/requirements.txt +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/scripts/changelog.py +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/scripts/ci.sh +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/scripts/requirements.py +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/fixtures/fake-executed.ipynb +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/fixtures/fake.ipynb +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/fixtures/fake.py +0 -0
- {dp_wizard_templates-0.1.0 → dp_wizard_templates-0.3.0}/tests/test_misc.py +0 -0
|
@@ -9,6 +9,7 @@ extend-ignore = E203,E501,E701
|
|
|
9
9
|
|
|
10
10
|
per-file-ignores =
|
|
11
11
|
# Ignore undefined names in templates.
|
|
12
|
-
|
|
13
|
-
# Ignore mid-file imports: These
|
|
14
|
-
|
|
12
|
+
examples/*.py:F821,F401,E302
|
|
13
|
+
# Ignore mid-file imports: These make for a better exposition.
|
|
14
|
+
# Ignore lines that too long. Mostly URLs.
|
|
15
|
+
test_index_html.py:E402,B950
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Use index.html instead of Jekyll.
|
|
@@ -3,7 +3,8 @@ repos:
|
|
|
3
3
|
rev: v2.3.0
|
|
4
4
|
hooks:
|
|
5
5
|
- id: check-yaml
|
|
6
|
-
|
|
6
|
+
# This conflicts with generated notebooks:
|
|
7
|
+
# - id: end-of-file-fixer
|
|
7
8
|
- id: trailing-whitespace
|
|
8
9
|
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
|
9
10
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
- Show all errors, and support comment blocks [#12](https://github.com/opendp/dp-wizard-templates/pull/12)
|
|
6
|
+
|
|
7
|
+
## 0.2.0
|
|
8
|
+
|
|
9
|
+
- Link to ghpages [#7](https://github.com/opendp/dp-wizard-templates/pull/7)
|
|
10
|
+
- Add black, and a generated index.html [#6](https://github.com/opendp/dp-wizard-templates/pull/6)
|
|
11
|
+
|
|
12
|
+
## 0.1.0
|
|
13
|
+
|
|
14
|
+
Initial release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dp_wizard_templates
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Code templating tools
|
|
5
5
|
Author-email: The OpenDP Project <info@opendp.org>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -10,7 +10,8 @@ Requires-Dist: ipykernel
|
|
|
10
10
|
Requires-Dist: jupyter-client
|
|
11
11
|
Requires-Dist: jupytext
|
|
12
12
|
Requires-Dist: nbconvert
|
|
13
|
-
Project-URL:
|
|
13
|
+
Project-URL: GitHub, https://github.com/opendp/dp-wizard-templates
|
|
14
|
+
Project-URL: Homepage, https://opendp.github.io/dp-wizard-templates
|
|
14
15
|
|
|
15
16
|
# DP Wizard Templates
|
|
16
17
|
|
|
@@ -19,12 +20,7 @@ Project-URL: Home, https://github.com/opendp/dp-wizard-templates
|
|
|
19
20
|
DP Wizard Templates lets you use syntactically valid Python code as a template.
|
|
20
21
|
Templates can be filled and composed to generate entire notebooks.
|
|
21
22
|
|
|
22
|
-
[
|
|
23
|
-
and an example [output notebook](https://github.com/opendp/dp-wizard-templates/blob/main/README_examples/hello-world.ipynb)
|
|
24
|
-
is also available.
|
|
25
|
-
|
|
26
|
-
DP Wizard Templates was developed for [DP Wizard](https://github.com/opendp/dp-wizard),
|
|
27
|
-
and that codebase remains a good place to look for further examples.
|
|
23
|
+
See the [documentation](https://opendp.github.io/dp-wizard-templates) for more information.
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
## Development
|
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
DP Wizard Templates lets you use syntactically valid Python code as a template.
|
|
6
6
|
Templates can be filled and composed to generate entire notebooks.
|
|
7
7
|
|
|
8
|
-
[
|
|
9
|
-
and an example [output notebook](https://github.com/opendp/dp-wizard-templates/blob/main/README_examples/hello-world.ipynb)
|
|
10
|
-
is also available.
|
|
11
|
-
|
|
12
|
-
DP Wizard Templates was developed for [DP Wizard](https://github.com/opendp/dp-wizard),
|
|
13
|
-
and that codebase remains a good place to look for further examples.
|
|
8
|
+
See the [documentation](https://opendp.github.io/dp-wizard-templates) for more information.
|
|
14
9
|
|
|
15
10
|
|
|
16
11
|
## Development
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.3.0
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
from typing import Optional, Callable
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import inspect
|
|
4
|
+
import re
|
|
5
|
+
import black
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_body(func):
|
|
9
|
+
|
|
10
|
+
source_lines = inspect.getsource(func).splitlines()
|
|
11
|
+
first_line = source_lines[0]
|
|
12
|
+
if not re.match(r"def \w+\((\w+(, \w+)*)?\):", first_line.strip()):
|
|
13
|
+
# Parsing to AST and unparsing is a more robust option,
|
|
14
|
+
# but more complicated.
|
|
15
|
+
raise Exception(f"def and parameters should fit on one line: {first_line}")
|
|
16
|
+
|
|
17
|
+
# The "def" should not be in the output,
|
|
18
|
+
# and cleandoc handles the first line differently.
|
|
19
|
+
source_lines[0] = ""
|
|
20
|
+
body = inspect.cleandoc("\n".join(source_lines))
|
|
21
|
+
body = re.sub(
|
|
22
|
+
r"\s*#\s+type:\s+ignore\s*",
|
|
23
|
+
"\n",
|
|
24
|
+
body,
|
|
25
|
+
)
|
|
26
|
+
body = re.sub(
|
|
27
|
+
r"\s*#\s+noqa:.+",
|
|
28
|
+
"",
|
|
29
|
+
body,
|
|
30
|
+
)
|
|
31
|
+
return body
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Template:
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
template: str | Callable,
|
|
38
|
+
root: Optional[Path] = None,
|
|
39
|
+
):
|
|
40
|
+
if root is not None:
|
|
41
|
+
template_name = f"_{template}.py"
|
|
42
|
+
template_path = root / template_name
|
|
43
|
+
self._source = f"'{template_name}'"
|
|
44
|
+
self._template = template_path.read_text()
|
|
45
|
+
else:
|
|
46
|
+
if callable(template):
|
|
47
|
+
self._source = "function template"
|
|
48
|
+
self._template = _get_body(template)
|
|
49
|
+
else:
|
|
50
|
+
self._source = "string template"
|
|
51
|
+
self._template = template
|
|
52
|
+
# We want a list of the initial slots, because substitutions
|
|
53
|
+
# can produce sequences of upper case letters that could be mistaken for slots.
|
|
54
|
+
self._initial_slots = self._find_slots()
|
|
55
|
+
|
|
56
|
+
def _find_slots(self) -> set[str]:
|
|
57
|
+
# Slots:
|
|
58
|
+
# - are all caps or underscores
|
|
59
|
+
# - have word boundary on either side
|
|
60
|
+
# - are at least three characters
|
|
61
|
+
slot_re = r"\b[A-Z][A-Z_]{2,}\b"
|
|
62
|
+
return set(re.findall(slot_re, self._template))
|
|
63
|
+
|
|
64
|
+
def _make_message(self, errors: list[str]) -> str:
|
|
65
|
+
return (
|
|
66
|
+
f"In {self._source}, " + ", ".join(sorted(errors)) + f":\n{self._template}"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def _loop_kwargs(
|
|
70
|
+
self,
|
|
71
|
+
function: Callable[[str, str, list[str]], None],
|
|
72
|
+
**kwargs,
|
|
73
|
+
) -> None:
|
|
74
|
+
errors = []
|
|
75
|
+
for k, v in kwargs.items():
|
|
76
|
+
function(k, v, errors)
|
|
77
|
+
if errors:
|
|
78
|
+
raise Exception(self._make_message(errors))
|
|
79
|
+
|
|
80
|
+
def _fill_inline_slots(
|
|
81
|
+
self,
|
|
82
|
+
stringifier: Callable[[str], str],
|
|
83
|
+
**kwargs,
|
|
84
|
+
) -> None:
|
|
85
|
+
def function(k, v, errors):
|
|
86
|
+
k_re = re.escape(k)
|
|
87
|
+
self._template, count = re.subn(
|
|
88
|
+
rf"\b{k_re}\b", stringifier(v), self._template
|
|
89
|
+
)
|
|
90
|
+
if count == 0:
|
|
91
|
+
errors.append(f"no '{k}' slot to fill with '{v}'")
|
|
92
|
+
|
|
93
|
+
self._loop_kwargs(function, **kwargs)
|
|
94
|
+
|
|
95
|
+
def _fill_block_slots(
|
|
96
|
+
self,
|
|
97
|
+
prefix_re: str,
|
|
98
|
+
splitter: Callable[[str], list[str]],
|
|
99
|
+
**kwargs,
|
|
100
|
+
) -> None:
|
|
101
|
+
def function(k, v, errors):
|
|
102
|
+
if not isinstance(v, str):
|
|
103
|
+
errors.append(f"for '{k}' slot, expected string, not '{v}'")
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
def match_indent(match):
|
|
107
|
+
# This does what we want, but binding is confusing.
|
|
108
|
+
return "\n".join(
|
|
109
|
+
match.group(1) + line for line in splitter(v) # noqa: B023
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
k_re = re.escape(k)
|
|
113
|
+
self._template, count = re.subn(
|
|
114
|
+
rf"^([ \t]*{prefix_re}){k_re}$",
|
|
115
|
+
match_indent,
|
|
116
|
+
self._template,
|
|
117
|
+
flags=re.MULTILINE,
|
|
118
|
+
)
|
|
119
|
+
if count == 0:
|
|
120
|
+
base_message = f"no '{k}' slot to fill with '{v}'"
|
|
121
|
+
if k in self._template:
|
|
122
|
+
note = (
|
|
123
|
+
"comment slots must be prefixed with '#'"
|
|
124
|
+
if prefix_re
|
|
125
|
+
else "block slots must be alone on line"
|
|
126
|
+
)
|
|
127
|
+
errors.append(f"{base_message} ({note})")
|
|
128
|
+
else:
|
|
129
|
+
errors.append(base_message)
|
|
130
|
+
|
|
131
|
+
self._loop_kwargs(function, **kwargs)
|
|
132
|
+
|
|
133
|
+
def fill_expressions(self, **kwargs) -> "Template":
|
|
134
|
+
"""
|
|
135
|
+
Fill in variable names, or dicts or lists represented as strings.
|
|
136
|
+
"""
|
|
137
|
+
self._fill_inline_slots(stringifier=str, **kwargs)
|
|
138
|
+
return self
|
|
139
|
+
|
|
140
|
+
def fill_values(self, **kwargs) -> "Template":
|
|
141
|
+
"""
|
|
142
|
+
Fill in string or numeric values. `repr` is called before filling.
|
|
143
|
+
"""
|
|
144
|
+
self._fill_inline_slots(stringifier=repr, **kwargs)
|
|
145
|
+
return self
|
|
146
|
+
|
|
147
|
+
def fill_code_blocks(self, **kwargs) -> "Template":
|
|
148
|
+
"""
|
|
149
|
+
Fill in code blocks. Slot must be alone on line.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
def splitter(s):
|
|
153
|
+
return s.split("\n")
|
|
154
|
+
|
|
155
|
+
self._fill_block_slots(prefix_re=r"", splitter=splitter, **kwargs)
|
|
156
|
+
return self
|
|
157
|
+
|
|
158
|
+
def fill_comment_blocks(self, **kwargs) -> "Template":
|
|
159
|
+
"""
|
|
160
|
+
Fill in comment blocks. Slot must be commented.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def splitter(s):
|
|
164
|
+
stripped = [line.strip() for line in s.split("\n")]
|
|
165
|
+
return [line for line in stripped if line]
|
|
166
|
+
|
|
167
|
+
self._fill_block_slots(prefix_re=r"#\s+", splitter=splitter, **kwargs)
|
|
168
|
+
return self
|
|
169
|
+
|
|
170
|
+
def finish(self, reformat: bool = False) -> str:
|
|
171
|
+
unfilled_slots = self._initial_slots & self._find_slots()
|
|
172
|
+
if unfilled_slots:
|
|
173
|
+
errors = [f"'{slot}' slot not filled" for slot in unfilled_slots]
|
|
174
|
+
raise Exception(self._make_message(errors))
|
|
175
|
+
|
|
176
|
+
if reformat:
|
|
177
|
+
self._template = black.format_str(self._template, mode=black.Mode())
|
|
178
|
+
|
|
179
|
+
return self._template
|
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import nbformat
|
|
8
8
|
import nbconvert
|
|
9
9
|
import jupytext
|
|
10
|
+
import black
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def _is_kernel_installed() -> bool:
|
|
@@ -27,7 +28,9 @@ class ConversionException(Exception):
|
|
|
27
28
|
return f"Script to notebook conversion failed: {self.command}\n{self.stderr})"
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
def convert_py_to_nb(
|
|
31
|
+
def convert_py_to_nb(
|
|
32
|
+
python_str: str, title: str, execute: bool = False, reformat: bool = True
|
|
33
|
+
) -> str:
|
|
31
34
|
"""
|
|
32
35
|
Given Python code as a string, returns a notebook as a string.
|
|
33
36
|
Calls jupytext as a subprocess:
|
|
@@ -43,6 +46,9 @@ def convert_py_to_nb(python_str: str, title: str, execute: bool = False):
|
|
|
43
46
|
|
|
44
47
|
temp_dir_path = Path(temp_dir)
|
|
45
48
|
py_path = temp_dir_path / "input.py"
|
|
49
|
+
if reformat:
|
|
50
|
+
# Line length determined by PDF rendering.
|
|
51
|
+
python_str = black.format_str(python_str, mode=black.Mode(line_length=74))
|
|
46
52
|
py_path.write_text(python_str)
|
|
47
53
|
|
|
48
54
|
argv = [executable] + "-m jupytext --from .py --to .ipynb --output -".split(" ")
|
|
@@ -65,13 +71,13 @@ def convert_py_to_nb(python_str: str, title: str, execute: bool = False):
|
|
|
65
71
|
return _clean_nb(json.dumps(nb_dict))
|
|
66
72
|
|
|
67
73
|
|
|
68
|
-
def _stable_hash(lines: list[str]):
|
|
74
|
+
def _stable_hash(lines: list[str]) -> str:
|
|
69
75
|
import hashlib
|
|
70
76
|
|
|
71
77
|
return hashlib.sha1("\n".join(lines).encode()).hexdigest()[:8]
|
|
72
78
|
|
|
73
79
|
|
|
74
|
-
def _clean_nb(nb_json: str):
|
|
80
|
+
def _clean_nb(nb_json: str) -> str:
|
|
75
81
|
"""
|
|
76
82
|
Given a notebook as a string of JSON, remove the coda and pip output.
|
|
77
83
|
(The code may produce reports that we do need,
|
|
@@ -82,7 +88,9 @@ def _clean_nb(nb_json: str):
|
|
|
82
88
|
for cell in nb["cells"]:
|
|
83
89
|
if "pip install" in cell["source"][0]:
|
|
84
90
|
cell["outputs"] = []
|
|
85
|
-
|
|
91
|
+
# "Coda" may, or may not be followed by "\n".
|
|
92
|
+
# Be flexible!
|
|
93
|
+
if any(line.startswith("# Coda") for line in cell["source"]):
|
|
86
94
|
break
|
|
87
95
|
# Make ID stable:
|
|
88
96
|
cell["id"] = _stable_hash(cell["source"])
|
|
@@ -96,13 +104,9 @@ def _clean_nb(nb_json: str):
|
|
|
96
104
|
return json.dumps(nb, indent=1)
|
|
97
105
|
|
|
98
106
|
|
|
99
|
-
def convert_nb_to_html(python_nb: str):
|
|
100
|
-
return _convert_nb(python_nb, nbconvert.HTMLExporter)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def _convert_nb(python_nb: str, exporter_constructor):
|
|
107
|
+
def convert_nb_to_html(python_nb: str, numbered=True) -> str:
|
|
104
108
|
notebook = nbformat.reads(python_nb, as_version=4)
|
|
105
|
-
exporter =
|
|
109
|
+
exporter = nbconvert.HTMLExporter(
|
|
106
110
|
template_name="lab",
|
|
107
111
|
# The "classic" template's CSS forces large code cells on to
|
|
108
112
|
# the next page rather than breaking, so use "lab" instead.
|
|
@@ -116,4 +120,13 @@ def _convert_nb(python_nb: str, exporter_constructor):
|
|
|
116
120
|
# ],
|
|
117
121
|
)
|
|
118
122
|
(body, _resources) = exporter.from_notebook_node(notebook)
|
|
123
|
+
if not numbered:
|
|
124
|
+
body = body.replace(
|
|
125
|
+
"</head>",
|
|
126
|
+
"""
|
|
127
|
+
<style>
|
|
128
|
+
.jp-InputPrompt {display: none;}
|
|
129
|
+
</style>
|
|
130
|
+
</head>""",
|
|
131
|
+
)
|
|
119
132
|
return body
|
|
File without changes
|
{dp_wizard_templates-0.1.0/README_examples → dp_wizard_templates-0.3.0/examples}/hello-world.html
RENAMED
|
@@ -7511,19 +7511,19 @@ a.anchor-link {
|
|
|
7511
7511
|
<!-- End of mermaid configuration --></head>
|
|
7512
7512
|
<body class="jp-Notebook" data-jp-theme-light="true" data-jp-theme-name="JupyterLab Light">
|
|
7513
7513
|
<main>
|
|
7514
|
-
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=
|
|
7514
|
+
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6fc59e52">
|
|
7515
7515
|
<div class="jp-Cell-inputWrapper" tabindex="0">
|
|
7516
7516
|
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
|
7517
7517
|
</div>
|
|
7518
7518
|
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
|
7519
7519
|
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
|
7520
7520
|
<h1 id="Hello-World!">Hello World!<a class="anchor-link" href="#Hello-World!">¶</a></h1><p>Comments will be rendered as <em>Markdown</em>.
|
|
7521
|
-
The
|
|
7521
|
+
The <code>+</code> and <code>-</code> below ensure that only one code cell is produced,
|
|
7522
7522
|
even though the lines are not contiguous</p>
|
|
7523
7523
|
</div>
|
|
7524
7524
|
</div>
|
|
7525
7525
|
</div>
|
|
7526
|
-
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell" id="cell-id=
|
|
7526
|
+
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell" id="cell-id=d75dbbc1">
|
|
7527
7527
|
<div class="jp-Cell-inputWrapper" tabindex="0">
|
|
7528
7528
|
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
|
7529
7529
|
</div>
|
|
@@ -7535,8 +7535,11 @@ even though the lines are not contiguous</p>
|
|
|
7535
7535
|
<span class="w"> </span><span class="sd">"""</span>
|
|
7536
7536
|
<span class="sd"> This demonstrates how larger blocks of code can be built compositionally.</span>
|
|
7537
7537
|
<span class="sd"> """</span>
|
|
7538
|
+
<span class="c1"># Water freezes at:</span>
|
|
7539
|
+
<span class="c1"># 32 Fahrenheit</span>
|
|
7540
|
+
<span class="c1"># 0 Celsius</span>
|
|
7538
7541
|
<span class="k">if</span> <span class="n">temp_c</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
7539
|
-
<span class="nb">print</span><span class="p">(</span><span class="
|
|
7542
|
+
<span class="nb">print</span><span class="p">(</span><span class="s2">"It is freezing!"</span><span class="p">)</span>
|
|
7540
7543
|
|
|
7541
7544
|
|
|
7542
7545
|
<span class="n">freeze_warning</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">)</span>
|
{dp_wizard_templates-0.1.0/README_examples → dp_wizard_templates-0.3.0/examples}/hello-world.ipynb
RENAMED
|
@@ -2,20 +2,22 @@
|
|
|
2
2
|
"cells": [
|
|
3
3
|
{
|
|
4
4
|
"cell_type": "markdown",
|
|
5
|
-
"id": "
|
|
6
|
-
"metadata": {
|
|
5
|
+
"id": "6fc59e52",
|
|
6
|
+
"metadata": {
|
|
7
|
+
"lines_to_next_cell": 2
|
|
8
|
+
},
|
|
7
9
|
"source": [
|
|
8
10
|
"# Hello World!\n",
|
|
9
11
|
"\n",
|
|
10
12
|
"Comments will be rendered as *Markdown*.\n",
|
|
11
|
-
"The
|
|
13
|
+
"The `+` and `-` below ensure that only one code cell is produced,\n",
|
|
12
14
|
"even though the lines are not contiguous"
|
|
13
15
|
]
|
|
14
16
|
},
|
|
15
17
|
{
|
|
16
18
|
"cell_type": "code",
|
|
17
19
|
"execution_count": 1,
|
|
18
|
-
"id": "
|
|
20
|
+
"id": "d75dbbc1",
|
|
19
21
|
"metadata": {},
|
|
20
22
|
"outputs": [
|
|
21
23
|
{
|
|
@@ -31,8 +33,11 @@
|
|
|
31
33
|
" \"\"\"\n",
|
|
32
34
|
" This demonstrates how larger blocks of code can be built compositionally.\n",
|
|
33
35
|
" \"\"\"\n",
|
|
36
|
+
" # Water freezes at:\n",
|
|
37
|
+
" # 32 Fahrenheit\n",
|
|
38
|
+
" # 0 Celsius\n",
|
|
34
39
|
" if temp_c < 0:\n",
|
|
35
|
-
" print(
|
|
40
|
+
" print(\"It is freezing!\")\n",
|
|
36
41
|
"\n",
|
|
37
42
|
"\n",
|
|
38
43
|
"freeze_warning(-10)"
|