diff --git a/CHANGELOG.md b/CHANGELOG.md index 88bdb1960cccb68c78b531924304bf86d4418af3..4ef346c32bb278bc91f0c5e65b13ce58b5f67a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +* Added support for passing callables as `find_func` to the `BaseTableExporter`. +* Added member `BaseTableExporter.all_keys` * Parsing from YAML now allows to give an existing model to which the YAML data model shall be added. diff --git a/src/caosadvancedtools/table_export.py b/src/caosadvancedtools/table_export.py index 056207a76fa01357e2269cd4cb8e9a09905d5d90..e82327198858de03e699d9e527b360782c10f71d 100644 --- a/src/caosadvancedtools/table_export.py +++ b/src/caosadvancedtools/table_export.py @@ -27,6 +27,7 @@ them for an export as a table, e.g., for the export to metadata repositories. """ +from inspect import signature import json import logging @@ -83,7 +84,7 @@ class BaseTableExporter(object): ``` {"entry_to_be_exported: { "optional": True/False - "find_func": name of member function + "find_func": callable or name of member function "query": query string "selector": selector for the query "error": error explanation @@ -97,8 +98,8 @@ class BaseTableExporter(object): - optional: True or False, if not present, the entry is assumed to be mandatory. - find_func: name of the member function that returns the - value for this entry. Must not exist together with - `query` + value for this entry or callable object. Must not exist + together with `query` - query: Query string for finding the value for this entry. If this is given, a record must be given to the constructor of this class. The query is then executed as @@ -132,6 +133,7 @@ class BaseTableExporter(object): self._check_sanity_of_export_dict() self.raise_error_if_missing = raise_error_if_missing self.info = {} + self.all_keys = [key for key in self.export_dict] def collect_information(self): """Use the items of `export_dict` to collect the information for the @@ -139,7 +141,8 @@ class BaseTableExporter(object): """ - for e, d in self.export_dict.items(): + for e in self.all_keys: + d = self.export_dict[e] if QUERY in d: # TODO: How do we make this more general? There might # be queries that don't need the record or work with @@ -163,12 +166,15 @@ class BaseTableExporter(object): else: self._append_missing(e, d) elif FIND_FUNCTION in d: - find_fun = getattr(self, d[FIND_FUNCTION]) try: - self.info[e] = find_fun() + val = self._call_find_function(d[FIND_FUNCTION], e) + if val is not None: + self.info[e] = val + else: + self._append_missing(e, d) except Exception as exc: self._append_missing(e, d) - logger.debug(exc) + logger.error(exc) # last resort: check if record has e as property: else: try: @@ -200,6 +206,22 @@ class BaseTableExporter(object): else: logger.error(errmssg) + def _call_find_function(self, find_function, e): + account_for_self = 0 + if callable(find_function): + find_fun = find_function + else: + find_fun = getattr(self, find_function) + account_for_self = 1 + + sig = signature(find_fun) + params = sig.parameters + if len(params) > (account_for_self + 1): + return find_fun(self.record, e) + elif len(params) > account_for_self: + return find_fun(self.record) + return find_fun() + def prepare_csv_export(self, delimiter=',', print_header=False, skip_empty_optionals=False): """Return the values in self.info as a single-line string, separated @@ -238,7 +260,8 @@ class BaseTableExporter(object): if print_header: header = "" - for e, d in self.export_dict.items(): + for e in self.all_keys: + d = self.export_dict[e] if e in self.info: body += str(self.info[e]) + delimiter @@ -287,7 +310,9 @@ class BaseTableExporter(object): # check find function if present if FIND_FUNCTION in d: - if not hasattr(self, d[FIND_FUNCTION]): + if callable(d[FIND_FUNCTION]): + pass + elif not hasattr(self, d[FIND_FUNCTION]): raise TableExportError( "Find function " + d[FIND_FUNCTION] + " was specified for entry " + e +