@@ -37,6 +37,21 @@ def __eq__(self, other):
37
37
and self .value == other .value
38
38
)
39
39
40
+ def get_parameter_cell (nb , tag = 'parameters' ):
41
+ cell = find_first_tagged_cell (nb , tag )
42
+ if cell is None :
43
+ cell = first_code_cell (nb )
44
+ return cell
45
+
46
+ def find_first_tagged_cell (nb , tag ):
47
+ tag = tag .lower ()
48
+ for cell in nb .cells :
49
+ if cell .cell_type == 'code' :
50
+ tags = cell .get ('metadata' , {}).get ('tags' , [])
51
+ if any ([i .lower () == tag for i in tags ]):
52
+ return cell
53
+
54
+
40
55
def first_code_cell (nb ):
41
56
for cell in nb .cells :
42
57
if cell .cell_type == 'code' :
@@ -52,31 +67,41 @@ def get_driver_module(nb, override=None):
52
67
assert kernel_name_re .match (module_name )
53
68
return importlib .import_module ('nbparameterise.code_drivers.%s' % module_name )
54
69
55
- def extract_parameter_dict (nb , lang = None ):
70
+ def extract_parameter_dict (nb , lang = None , tag = 'Parameters' ):
56
71
"""Returns a dictionary of Parameter objects derived from the notebook.
57
72
58
73
This looks for assignments (like 'n = 50') in the first code cell of the
59
- notebook. The parameters may also have some metadata stored in the notebook
60
- metadata; this will be attached as the .metadata instance on each one.
74
+ notebook, or the first cell with a 'parameters' tag. The parameters may also
75
+ have some metadata stored in the notebook metadata; this will be attached as
76
+ the .metadata instance on each one.
61
77
62
- lang may be used to override the kernel name embedded in the notebook. For
78
+ * lang* may be used to override the kernel name embedded in the notebook. For
63
79
now, nbparameterise only handles 'python'.
80
+
81
+ *tag* specifies the cell tag which it will look for, with case-insensitive
82
+ matching. If no code cell has the tag, it will take the first code cell.
64
83
"""
65
- params = extract_parameters (nb , lang )
84
+ params = extract_parameters (nb , lang , tag = tag )
66
85
return {p .name : p for p in params }
67
86
68
- def extract_parameters (nb , lang = None ):
87
+ def extract_parameters (nb , lang = None , tag = 'Parameters' ):
69
88
"""Returns a list of Parameter instances derived from the notebook.
70
89
71
90
This looks for assignments (like 'n = 50') in the first code cell of the
72
- notebook. The parameters may also have some metadata stored in the notebook
73
- metadata; this will be attached as the .metadata instance on each one.
91
+ notebook, or the first cell with a 'parameters' tag. The parameters may also
92
+ have some metadata stored in the notebook metadata; this will be attached as
93
+ the .metadata instance on each one.
74
94
75
- lang may be used to override the kernel name embedded in the notebook. For
95
+ * lang* may be used to override the kernel name embedded in the notebook. For
76
96
now, nbparameterise only handles 'python'.
97
+
98
+ *tag* specifies the cell tag which it will look for, with case-insensitive
99
+ matching. If no code cell has the tag, it will take the first code cell.
77
100
"""
78
101
drv = get_driver_module (nb , override = lang )
79
- params = list (drv .extract_definitions (first_code_cell (nb ).source ))
102
+ cell = get_parameter_cell (nb ,tag )
103
+
104
+ params = list (drv .extract_definitions (cell .source ))
80
105
81
106
# Add extra info from notebook metadata
82
107
for param in params :
@@ -126,8 +151,8 @@ def parameter_values(params, new_values=None, new='ignore', **kwargs):
126
151
return res
127
152
128
153
def replace_definitions (nb , values , execute = False , execute_resources = None ,
129
- lang = None , * , comments = True ):
130
- """Return a copy of nb with the first code cell defining the given parameters.
154
+ lang = None , * , comments = True , tag = 'Parameters' ):
155
+ """Return a copy of nb with the parameter cell defining the given parameters.
131
156
132
157
values should be a dict (from :func:`extract_parameter_dict`) or a list
133
158
(from :func:`extract_parameters`) of :class:`Parameter` objects,
@@ -138,8 +163,12 @@ def replace_definitions(nb, values, execute=False, execute_resources=None,
138
163
and if possible should contain a 'path' key for the working directory in
139
164
which to run the notebook.
140
165
141
- lang may be used to override the kernel name embedded in the notebook. For
166
+ * lang* may be used to override the kernel name embedded in the notebook. For
142
167
now, nbparameterise only handles 'python3' and 'python2'.
168
+
169
+ *tag* specifies the cell tag which the parameter cell should have, with
170
+ case-insensitive matching. If no code cell has the tag, it will replace the
171
+ first code cell.
143
172
"""
144
173
if isinstance (values , list ):
145
174
values = {p .name : p for p in values }
@@ -148,12 +177,10 @@ def replace_definitions(nb, values, execute=False, execute_resources=None,
148
177
warn ("comments=False is now ignored" , stacklevel = 2 )
149
178
150
179
nb = copy .deepcopy (nb )
151
- params_cell = first_code_cell (nb )
152
180
153
181
drv = get_driver_module (nb , override = lang )
154
- params_cell .source = drv .build_definitions (
155
- values , prev_code = params_cell .source
156
- )
182
+ cell = get_parameter_cell (nb , tag )
183
+ cell .source = drv .build_definitions (values , prev_code = cell .source )
157
184
if execute :
158
185
resources = execute_resources or {}
159
186
nb , resources = ExecutePreprocessor ().preprocess (nb , resources )
0 commit comments