From d14b005fd284abc631f3aa8d8702ae499706981b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 5 Dec 2024 22:15:38 -0600 Subject: [PATCH] fix: add `--fields` and `--exclude` params for import/export cli --- src/wuttasync/cli/base.py | 23 ++++++++++------------- src/wuttasync/importing/base.py | 20 ++++++++++++++++++++ tests/importing/test_base.py | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/wuttasync/cli/base.py b/src/wuttasync/cli/base.py index c1fbd55..008dd5b 100644 --- a/src/wuttasync/cli/base.py +++ b/src/wuttasync/cli/base.py @@ -56,25 +56,22 @@ def importer_command_template( bool, typer.Option(help="Allow existing target records to be deleted.")] = False, + # fields + fields: Annotated[ + str, + typer.Option('--fields', + help="List of fields to process. See also --exclude.")] = None, + excluded_fields: Annotated[ + str, + typer.Option('--exclude', + help="List of fields *not* to process. See also --fields.")] = None, + # dry run? dry_run: Annotated[ bool, typer.Option('--dry-run', help="Go through the motions, but rollback the transaction.")] = False, - # # fields - # fields: Annotated[ - # str, - # typer.Option('--fields', - # help="List of fields to process. If specified, " - # "any field not listed is excluded regardless " - # "of --exclude.")] = None, - # exclude_fields: Annotated[ - # str, - # typer.Option('--exclude', - # help="List of fields not to process. If " - # "specified, any field not listed is (not?) included " - # "based on app logic and/or --fields.")] = None, ): """ Stub function which provides a common param signature; used with diff --git a/src/wuttasync/importing/base.py b/src/wuttasync/importing/base.py index 164c04f..d46ae67 100644 --- a/src/wuttasync/importing/base.py +++ b/src/wuttasync/importing/base.py @@ -82,6 +82,14 @@ class Importer: overwrite this attribute directly, for dynamic fields. If so then ``get_fields()`` will return the new value. And really, it's probably just as safe to read this attribute directly too. + + .. attribute:: excluded_fields + + This attribute will often not exist, but is mentioned here for + reference. + + It may be specified via constructor param in which case each + field listed therein will be removed from :attr:`fields`. """ allow_create = True @@ -183,6 +191,18 @@ class Importer: self.supported_fields = self.get_supported_fields() self.fields = self.get_fields() + # fields could be comma-delimited string from cli param + if isinstance(self.fields, str): + self.fields = self.config.parse_list(self.fields) + + # discard any fields caller asked to exclude + excluded = getattr(self, 'excluded_fields', None) + if excluded: + if isinstance(excluded, str): + excluded = self.config.parse_list(excluded) + self.fields = [f for f in self.fields + if f not in excluded] + @property def orientation(self): """ diff --git a/tests/importing/test_base.py b/tests/importing/test_base.py index abe121b..0648dc9 100644 --- a/tests/importing/test_base.py +++ b/tests/importing/test_base.py @@ -36,6 +36,20 @@ class TestImporter(DataTestCase): self.assertTrue(imp.delete) self.assertFalse(imp.dry_run) + def test_constructor_fields(self): + model = self.app.model + + # basic importer + imp = self.make_importer(model_class=model.Setting, fields='name') + self.assertEqual(imp.fields, ['name']) + + def test_constructor_excluded_fields(self): + model = self.app.model + + # basic importer + imp = self.make_importer(model_class=model.Setting, excluded_fields='value') + self.assertEqual(imp.fields, ['name']) + def test_get_model_title(self): model = self.app.model imp = self.make_importer(model_class=model.Setting)