From c8886ea3fa4cb77f4df7022faf6560e6581874d7 Mon Sep 17 00:00:00 2001 From: davidlatwe Date: Tue, 10 Mar 2020 11:55:22 +0800 Subject: [PATCH 1/8] Make `api.create` able to run with one specific creator plugin --- avalon/pipeline.py | 11 ++++++----- avalon/tools/creator/app.py | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/avalon/pipeline.py b/avalon/pipeline.py index 735a518c2..935b5728b 100644 --- a/avalon/pipeline.py +++ b/avalon/pipeline.py @@ -878,12 +878,13 @@ def create(name, asset, family, options=None, data=None): host = registered_host() - plugins = list() - for Plugin in discover(Creator): - has_family = family == Plugin.family + if isinstance(family, str): + Plugins = [P for P in discover(Creator) if family == P.family] + else: + Plugins = [family] - if not has_family: - continue + plugins = list() + for Plugin in Plugins: Plugin.log.info( "Creating '%s' with '%s'" % (name, Plugin.__name__) diff --git a/avalon/tools/creator/app.py b/avalon/tools/creator/app.py index 1bfdaef2d..b7001aa39 100644 --- a/avalon/tools/creator/app.py +++ b/avalon/tools/creator/app.py @@ -436,13 +436,13 @@ def on_create(self): subset_name = result.text() asset = asset.text() - family = item.data(FamilyRole) + Plugin = item.data(PluginRole) use_selection = self.data["Use Selection Checkbox"].isChecked() try: api.create(subset_name, asset, - family, + Plugin, options={"useSelection": use_selection}) except NameError as e: From ebcb78c407b2a72f85024c24d1daf69da90d269a Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 13:33:18 +0800 Subject: [PATCH 2/8] Reverse if-statement for better readability --- avalon/pipeline.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/avalon/pipeline.py b/avalon/pipeline.py index 935b5728b..0db58a53f 100644 --- a/avalon/pipeline.py +++ b/avalon/pipeline.py @@ -862,7 +862,7 @@ def create(name, asset, family, options=None, data=None): Arguments: name (str): Name of subset asset (str): Name of asset - family (str): Name of family + family (str, Creator): Name of family, or a Creator plugin class options (dict, optional): Additional options from GUI data (dict, optional): Additional data from GUI @@ -878,10 +878,11 @@ def create(name, asset, family, options=None, data=None): host = registered_host() - if isinstance(family, str): - Plugins = [P for P in discover(Creator) if family == P.family] - else: + if issubclass(family, Creator): + # Allow passing in a specific Creator to run only that plug-in Plugins = [family] + else: + Plugins = [P for P in discover(Creator) if family == P.family] plugins = list() for Plugin in Plugins: From 11a319ac4687fb34ea5d0ae92fc8da643f647a46 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 19:16:33 +0800 Subject: [PATCH 3/8] Fix non-class family input --- avalon/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avalon/pipeline.py b/avalon/pipeline.py index 0db58a53f..17fe13e53 100644 --- a/avalon/pipeline.py +++ b/avalon/pipeline.py @@ -878,7 +878,7 @@ def create(name, asset, family, options=None, data=None): host = registered_host() - if issubclass(family, Creator): + if inspect.isclass(family) and issubclass(family, Creator): # Allow passing in a specific Creator to run only that plug-in Plugins = [family] else: From 69d99b20095397a0432af14befcf2bacf6f1b650 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 19:16:42 +0800 Subject: [PATCH 4/8] Add test --- avalon/tests/test_pipeline.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/avalon/tests/test_pipeline.py b/avalon/tests/test_pipeline.py index fffb74b46..4ffcfaca9 100644 --- a/avalon/tests/test_pipeline.py +++ b/avalon/tests/test_pipeline.py @@ -76,6 +76,23 @@ def process(self, name, namespace, context): shutil.rmtree(tempdir) +@with_setup(clear) +def test_creators(): + """Register a Creator and create instance by different family input""" + + class BarCreator(pipeline.Creator): + def process(self): + return True + family = "bar" + + pipeline.register_plugin(pipeline.Creator, BarCreator) + + # Create with regular string type family + assert pipeline.create("foo", "my_asset", family="bar") + # Create with plugin class, see getavalon/core#531 + assert pipeline.create("foo", "my_asset", family=BarCreator) + + @with_setup(clear) def test_on(): """api.on() works as advertised""" From 83b72ab71c4619722d1f74ccda6968ca6e9732d6 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 19:34:55 +0800 Subject: [PATCH 5/8] Fix test --- avalon/tests/test_pipeline.py | 38 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/avalon/tests/test_pipeline.py b/avalon/tests/test_pipeline.py index 4ffcfaca9..e3ed69587 100644 --- a/avalon/tests/test_pipeline.py +++ b/avalon/tests/test_pipeline.py @@ -80,17 +80,37 @@ def process(self, name, namespace, context): def test_creators(): """Register a Creator and create instance by different family input""" - class BarCreator(pipeline.Creator): - def process(self): - return True - family = "bar" + tempdir = tempfile.mkdtemp() + + creator = """ +from avalon import api - pipeline.register_plugin(pipeline.Creator, BarCreator) +class BarCreator(api.Creator): + def process(self): + return True + family = "bar" +""" + + with open(os.path.join(tempdir, "my_creator.py"), "w") as f: + f.write(creator) - # Create with regular string type family - assert pipeline.create("foo", "my_asset", family="bar") - # Create with plugin class, see getavalon/core#531 - assert pipeline.create("foo", "my_asset", family=BarCreator) + try: + pipeline.register_plugin_path(pipeline.Creator, tempdir) + + # Create with regular string type family + # + instance = pipeline.create("foo", "my_asset", family="bar") + assert_equals(instance, True) + + # Create with plugin class, see getavalon/core#531 + # + creators = pipeline.discover(pipeline.Creator) + BarCreator = next(c for c in creators if c.__name__ == "BarCreator") + instance = pipeline.create("foo", "my_asset", family=BarCreator) + assert_equals(instance, True) + + finally: + shutil.rmtree(tempdir) @with_setup(clear) From 301ec73cfafe2d77bc223d64cef49849cf0c3c58 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 20:35:13 +0800 Subject: [PATCH 6/8] Skip testing vendorized avalon/style module --- run_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_tests.py b/run_tests.py index 7dfa8f247..b0d1e5f2e 100644 --- a/run_tests.py +++ b/run_tests.py @@ -27,6 +27,7 @@ # We can expect any vendors to # be well tested beforehand. "--exclude-dir=avalon/vendor", + "--exclude-dir=avalon/style", ]) nose.main(argv=argv, From ce8a24e5bc0660a51fda277edb913745d6d93bbe Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 20:35:58 +0800 Subject: [PATCH 7/8] Fix mock host --- avalon/tests/test_pipeline.py | 44 ++++++++++++----------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/avalon/tests/test_pipeline.py b/avalon/tests/test_pipeline.py index e3ed69587..20e0be43d 100644 --- a/avalon/tests/test_pipeline.py +++ b/avalon/tests/test_pipeline.py @@ -33,9 +33,15 @@ def setup(): pipeline.register_root(self.tempdir) # Mock host + dummy_maintained_selection = type( + "empty_ctx", (object,), + {"__enter__": lambda s: s, "__exit__": lambda *a, **k: None} + ) + host = types.ModuleType("Test") host.__dict__.update({ "ls": lambda: [], + "maintained_selection": dummy_maintained_selection, }) pipeline.register_host(host) @@ -80,37 +86,17 @@ def process(self, name, namespace, context): def test_creators(): """Register a Creator and create instance by different family input""" - tempdir = tempfile.mkdtemp() - - creator = """ -from avalon import api - -class BarCreator(api.Creator): - def process(self): - return True - family = "bar" -""" - - with open(os.path.join(tempdir, "my_creator.py"), "w") as f: - f.write(creator) - - try: - pipeline.register_plugin_path(pipeline.Creator, tempdir) - - # Create with regular string type family - # - instance = pipeline.create("foo", "my_asset", family="bar") - assert_equals(instance, True) + class BarCreator(pipeline.Creator): + def process(self): + return True + family = "bar" - # Create with plugin class, see getavalon/core#531 - # - creators = pipeline.discover(pipeline.Creator) - BarCreator = next(c for c in creators if c.__name__ == "BarCreator") - instance = pipeline.create("foo", "my_asset", family=BarCreator) - assert_equals(instance, True) + pipeline.register_plugin(pipeline.Creator, BarCreator) - finally: - shutil.rmtree(tempdir) + # Create with regular string type family + assert pipeline.create("foo", "my_asset", family="bar") + # Create with plugin class, see getavalon/core#531 + assert pipeline.create("foo", "my_asset", family=BarCreator) @with_setup(clear) From ccb393c098f2149d1c9be32cf829bf4d608fafcb Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 30 Sep 2020 22:39:55 +0800 Subject: [PATCH 8/8] Improve test to reflect exact result of #531 --- avalon/tests/test_pipeline.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/avalon/tests/test_pipeline.py b/avalon/tests/test_pipeline.py index 20e0be43d..64522f7c5 100644 --- a/avalon/tests/test_pipeline.py +++ b/avalon/tests/test_pipeline.py @@ -86,17 +86,28 @@ def process(self, name, namespace, context): def test_creators(): """Register a Creator and create instance by different family input""" - class BarCreator(pipeline.Creator): + data = {"value": 0} + + class CreateA(pipeline.Creator): + def process(self): + data["value"] += 1 + family = "foobar" + + class CreateB(pipeline.Creator): def process(self): - return True - family = "bar" + data["value"] += 10 + family = "foobar" - pipeline.register_plugin(pipeline.Creator, BarCreator) + pipeline.register_plugin(pipeline.Creator, CreateA) + pipeline.register_plugin(pipeline.Creator, CreateB) # Create with regular string type family - assert pipeline.create("foo", "my_asset", family="bar") + pipeline.create("foo", "my_asset", family="foobar") + assert data["value"] == 11, "Must run both Creator Plugins" + # Create with plugin class, see getavalon/core#531 - assert pipeline.create("foo", "my_asset", family=BarCreator) + pipeline.create("foo", "my_asset", family=CreateA) + assert data["value"] == 12, "Must run only CreatorA Plugin" @with_setup(clear)