diff --git a/parsers/common/cellparser.py b/parsers/common/cellparser.py index 0d01bb7..3c9a776 100644 --- a/parsers/common/cellparser.py +++ b/parsers/common/cellparser.py @@ -68,16 +68,18 @@ def parse(self, value, context={}): return self.split_into_lists(value) def parse_as_string(self, value, context={}, is_object=None): + # If context is None, template parsing is omitted entirely. # is_object is a pass-by-reference boolean, realised via # the class BooleanWrapper, to indicate to the caller # whether the parsing result represents an object that # is not to be processed any further. if value is None: return '' - if not context and '{' not in value: + if context is None or (not context and '{' not in value): # This is a hacky optimization. return value stripped_value = value.strip() + env = self.env if stripped_value.startswith('{@') and stripped_value.endswith('@}'): # Special case: Return a python object rather than a string, # if possible. @@ -85,8 +87,10 @@ def parse_as_string(self, value, context={}, is_object=None): assert stripped_value[2:].find('{@') == -1 if is_object is not None: is_object.boolean = True - template = self.native_env.from_string(stripped_value) - return template.render(context) - else: - template = self.env.from_string(stripped_value) + env = self.native_env + + try: + template = env.from_string(stripped_value) return template.render(context) + except Exception as e: + raise ValueError(str(e), stripped_value, context) diff --git a/parsers/common/sheetparser.py b/parsers/common/sheetparser.py index 0e20b7e..9317146 100644 --- a/parsers/common/sheetparser.py +++ b/parsers/common/sheetparser.py @@ -35,12 +35,13 @@ def go_to_bookmark(self, name): def remove_bookmark(self, name): self.bookmarks.pop(name) - def parse_next_row(self): + def parse_next_row(self, omit_templating=False): try: input_row = next(self.iterator) except StopIteration: return None - row = self.row_parser.parse_row(input_row, self.context) + context = self.context if not omit_templating else None + row = self.row_parser.parse_row(input_row, context) return row def parse_all(self): diff --git a/parsers/common/tests/mock_sheetparser.py b/parsers/common/tests/mock_sheetparser.py index b35d979..af7686e 100644 --- a/parsers/common/tests/mock_sheetparser.py +++ b/parsers/common/tests/mock_sheetparser.py @@ -17,7 +17,7 @@ def __init__(self, row_parser, rows, context={}): self.iterator = iter(self.input_rows) self.context = copy.deepcopy(context) - def parse_next_row(self): + def parse_next_row(self, omit_templating=False): # Simply return the input. try: input_row = next(self.iterator) diff --git a/parsers/creation/contentindexparser.py b/parsers/creation/contentindexparser.py index 11f2cc6..6a0d7e9 100644 --- a/parsers/creation/contentindexparser.py +++ b/parsers/creation/contentindexparser.py @@ -142,8 +142,8 @@ def map_template_arguments_to_context(self, arg_defs, args, context): for arg_def, arg in zip(arg_defs, args + args_padding): if arg_def.name in context: raise ValueError(f'Template argument "{arg_def.name}" doubly defined in context') - arg_value = arg or arg_def.default_value - if not arg_value: + arg_value = arg if arg != '' else arg_def.default_value + if arg_value == '': raise ValueError(f'Required template argument "{arg_def.name}" not provided') if arg_def.type == 'sheet': context[arg_def.name] = self.data_sheets[arg_value] diff --git a/parsers/creation/flowparser.py b/parsers/creation/flowparser.py index 3e5a41e..588154d 100644 --- a/parsers/creation/flowparser.py +++ b/parsers/creation/flowparser.py @@ -304,7 +304,7 @@ def parse(self): return flow_container def _parse_block(self, depth=0, block_type='root_block', omit_content=False): - row = self.sheet_parser.parse_next_row() + row = self.sheet_parser.parse_next_row(omit_templating=omit_content) while not self._is_end_of_block(block_type, row): if omit_content or not row.include_if: if row.type == 'begin_for': @@ -349,7 +349,7 @@ def _parse_block(self, depth=0, block_type='root_block', omit_content=False): self.append_node_group(new_node_group, row.row_id) else: self._parse_row(row) - row = self.sheet_parser.parse_next_row() + row = self.sheet_parser.parse_next_row(omit_templating=omit_content) def _is_end_of_block(self, block_type, row): block_end_map = {