diff --git a/conservancy_beancount/reports/core.py b/conservancy_beancount/reports/core.py index ca83943d4895f295cbcad62b51d85149071463a9..300e404764921533a6d180f03f3b071bb15c1cb1 100644 --- a/conservancy_beancount/reports/core.py +++ b/conservancy_beancount/reports/core.py @@ -23,9 +23,11 @@ import babel.numbers # type:ignore[import] import git # type:ignore[import] import odf.config # type:ignore[import] +import odf.dc # type:ignore[import] import odf.element # type:ignore[import] import odf.meta # type:ignore[import] import odf.number # type:ignore[import] +import odf.office # type:ignore[import] import odf.opendocument # type:ignore[import] import odf.style # type:ignore[import] import odf.table # type:ignore[import] @@ -1335,6 +1337,22 @@ class BaseODS(BaseSpreadsheet[RT, ST], metaclass=abc.ABCMeta): ### Rows and cells + def add_annotation( + self, + text: Optional[str]=None, + when: Optional[datetime.datetime]=None, + parent: Optional[odf.table.TableCell]=None, + ) -> odf.office.Annotation: + if when is None: + when = datetime.datetime.now() + retval = odf.office.Annotation() + retval.appendChild(odf.dc.Date(text=when.isoformat(timespec='seconds'))) + if text is not None: + retval.appendChild(odf.text.P(text=text)) + if parent is not None: + parent.appendChild(retval) + return retval + def add_row(self, *cells: odf.table.TableCell, **attrs: Any) -> odf.table.TableRow: row = odf.table.TableRow(**attrs) for cell in cells: diff --git a/conservancy_beancount/reports/query.py b/conservancy_beancount/reports/query.py index 69822b92110f074fe3bb7d4c3d1961ec09634f33..24eab377a8dc7286a67f078308ae23d44c7a98ac 100644 --- a/conservancy_beancount/reports/query.py +++ b/conservancy_beancount/reports/query.py @@ -213,6 +213,15 @@ class BQLShell(bc_query_shell.BQLShell): self.env_postings = FilterPostingsEnvironment() self.env_targets = TargetsEnvironment() self.ods = QueryODS(rt_wrapper) + self.last_line_parsed = '' + + def run_parser( + self, + line: str, + default_close_date: Optional[datetime.datetime]=None, + ) -> None: + self.last_line_parsed = line + super().run_parser(line, default_close_date) def on_Select(self, statement: QueryStatement) -> None: output_format: str = self.vars['format'] @@ -265,7 +274,7 @@ class BQLShell(bc_query_shell.BQLShell): ) def _render_ods(self, statement: QueryStatement, row_types: RowTypes, rows: Rows) -> None: - self.ods.write_query(statement, row_types, rows) + self.ods.write_query(statement, row_types, rows, self.last_line_parsed) logger.info( "%s rows of results saved in sheet %s", len(rows), @@ -400,7 +409,13 @@ class QueryODS(core.BaseODS[NamedTuple, None]): else: yield self._metadata_cell - def write_query(self, statement: QueryStatement, row_types: RowTypes, rows: Rows) -> None: + def write_query( + self, + statement: QueryStatement, + row_types: RowTypes, + rows: Rows, + query_string: Optional[str]=None, + ) -> None: if self.is_empty(): self.sheet.setAttribute('name', "Query 1") else: @@ -419,6 +434,8 @@ class QueryODS(core.BaseODS[NamedTuple, None]): for name, _ in row_types )) self.lock_first_row() + if query_string: + self.add_annotation(query_string, parent=self.sheet.lastChild.firstChild) cell_funcs = list(self._cell_types(statement, row_types)) for row in rows: self.add_row(*( @@ -576,7 +593,6 @@ def main(arglist: Optional[Sequence[str]]=None, if not shell.ods.is_empty(): shell.ods.set_common_properties(config.books_repo()) - shell.ods.set_custom_property('BeanQuery', query or '') if args.output_file is None: out_dir_path = config.repository_path() or Path() args.output_file = out_dir_path / 'QueryResults_{}.ods'.format( diff --git a/setup.py b/setup.py index 940b34c916a96f1bdf1ef480037364fca0f6936c..ee681bb0d517cb71312304c05ef823efaaf85b4b 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup setup( name='conservancy_beancount', description="Plugin, library, and reports for reading Conservancy's books", - version='1.18.4', + version='1.19.0', author='Software Freedom Conservancy', author_email='info@sfconservancy.org', license='GNU AGPLv3+',