diff --git a/conservancy_beancount/reports/query.py b/conservancy_beancount/reports/query.py index ad8e04f..ebdabde 100644 --- a/conservancy_beancount/reports/query.py +++ b/conservancy_beancount/reports/query.py @@ -548,8 +548,7 @@ class BQLShell(bc_query_shell.BQLShell): self.last_line_parsed = line super().run_parser(line, default_close_date) - @functools.wraps(bc_query_shell.BQLShell.on_Select, ('__doc__',)) - def on_Select(self, statement: QueryStatement) -> None: + def _select(self, statement: QueryStatement) -> None: output_format: str = self.vars['format'] try: render_func = getattr(self, f'_render_{output_format}') @@ -587,6 +586,16 @@ class BQLShell(bc_query_shell.BQLShell): logger.debug("rendering query as %s", output_format) render_func(statement, row_types, rows) + @functools.wraps(bc_query_shell.BQLShell.on_Select, ('__doc__',)) + def on_Select(self, statement: QueryStatement) -> None: + try: + self._select(statement) + except KeyboardInterrupt: + if self.is_interactive: + logger.info("interrupted") + else: + raise + def _hint_TypeError(self, error: TypeError, statement: QueryStatement) -> None: try: errmsg = str(error.args[0]) @@ -653,7 +662,7 @@ class QueryODS(core.BaseODS[NamedTuple, None]): ]) def is_empty(self) -> bool: - return not self.sheet.childNodes + return not self.document.spreadsheet.firstChild.getAttribute('name').startswith('Query ') def section_key(self, row: NamedTuple) -> None: return None @@ -760,9 +769,12 @@ class QueryODS(core.BaseODS[NamedTuple, None]): query_string: Optional[str]=None, ) -> None: if self.is_empty(): - self.sheet.setAttribute('name', "Query 1") + query_count = 1 else: - self.use_sheet(f"Query {len(self.document.spreadsheet.childNodes) + 1}") + query_count = len(self.document.spreadsheet.childNodes) + 1 + # We avoid using self.use_sheet() because fully building the sheet + # before adding it to the doc makes the query safer to interrupt. + self.sheet = odf.table.Table(name=f"Query {query_count}") for name, row_type in row_types: if issubclass(row_type, datetime.date): col_width = 1.0 @@ -785,6 +797,10 @@ class QueryODS(core.BaseODS[NamedTuple, None]): cell_func(value) for cell_func, value in zip(cell_funcs, row) )) + if query_count == 1: + self.document.spreadsheet.childNodes[-1] = self.sheet + else: + self.document.spreadsheet.appendChild(self.sheet) class ReportFormat(enum.Enum): diff --git a/setup.cfg b/setup.cfg index 425499f..ce4f230 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = conservancy_beancount -version = 1.19.7 +version = 1.19.8 author = Software Freedom Conservancy author_email = info@sfconservancy.org description = Plugin, library, and reports for reading Conservancy’s books