From 0d83b0ab6470d98d620144ba8cfea5e9a6826852 Mon Sep 17 00:00:00 2001 From: Avi Zurel Date: Fri, 18 Oct 2019 19:42:14 -0700 Subject: [PATCH 1/4] Generating build files through globality-build --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 18878ce..f6f42c7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ defaults: &defaults working_directory: ~/repo docker: - - image: ${AWS_ECR_DOMAIN}/globality-build:2019.23.2 + - image: ${AWS_ECR_DOMAIN}/globality-build:2019.41.70 aws_auth: aws_access_key_id: ${AWS_ACCESS_KEY_ID} aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY} @@ -28,7 +28,7 @@ defaults: &defaults deploy_defaults: &deploy_defaults working_directory: ~/repo docker: - - image: ${AWS_ECR_DOMAIN}/globality-build:2019.23.2 + - image: ${AWS_ECR_DOMAIN}/globality-build:2019.41.70 aws_auth: aws_access_key_id: ${AWS_ACCESS_KEY_ID} aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY} @@ -70,8 +70,8 @@ jobs: # install dependencies for loading ecs task definitions command: | eval $(aws ecr get-login --no-include-email) - globality-build docker-base --repo python-library - globality-build docker --repo python-library + globality-build build-gen local + globality-build docker-build-push --repo python-library test: <<: *defaults From 73b423ffd2ffd76a69f6a11b4daf1dfc0e16dc8b Mon Sep 17 00:00:00 2001 From: Avi Zurel Date: Fri, 18 Oct 2019 19:42:18 -0700 Subject: [PATCH 2/4] Generating build files through globality-build [skip ci] --- .globality/build.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.globality/build.json b/.globality/build.json index 32dde24..6b1595c 100644 --- a/.globality/build.json +++ b/.globality/build.json @@ -6,5 +6,5 @@ } }, "type": "python-library", - "version": "2019.23.2" + "version": "2019.41.70" } From e42f0d6a0bfee98e4d1e938d5554a0251801ad88 Mon Sep 17 00:00:00 2001 From: Adrien Fallou Date: Mon, 21 Oct 2019 23:46:12 +0200 Subject: [PATCH 3/4] Isolate hooks between class and subclass (#67) **Why?** Component hooks are registered on the class that will be instantiated for the component, through a class attribute. This means that if component `a` is an instance of `class A`, and component `b` an instance of `class B(A)` then the hooks defined on those two components will get mixed. **What?** Ensure separation of hooks in cases like the one above by using the class name in the class attribute used to hold hooks. --- microcosm/hooks.py | 18 ++++++++++++------ microcosm/tests/test_hooks.py | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/microcosm/hooks.py b/microcosm/hooks.py index eaac015..8a9a1a1 100644 --- a/microcosm/hooks.py +++ b/microcosm/hooks.py @@ -42,15 +42,20 @@ class Bar: ON_RESOLVE = "_microcosm_on_resolve_" -def _invoke_hook(hook_name, target): +def _get_hook_name(hook_prefix, target_cls): + return f"{hook_prefix}_{target_cls.__name__}" + + +def _invoke_hook(hook_prefix, target_component): """ Generic hook invocation. """ + hook_name = _get_hook_name(hook_prefix, target_component.__class__) try: - for value in getattr(target, hook_name): + for value in getattr(target_component, hook_name): func, args, kwargs = value - func(target, *args, **kwargs) + func(target_component, *args, **kwargs) except AttributeError: # no hook defined pass @@ -59,16 +64,17 @@ def _invoke_hook(hook_name, target): pass -def _register_hook(hook_name, target, func, *args, **kwargs): +def _register_hook(hook_prefix, target_cls, func, *args, **kwargs): """ Generic hook registration. """ + hook_name = _get_hook_name(hook_prefix, target_cls) call = (func, args, kwargs) try: - getattr(target, hook_name).append(call) + getattr(target_cls, hook_name).append(call) except AttributeError: - setattr(target, hook_name, [call]) + setattr(target_cls, hook_name, [call]) def invoke_resolve_hook(target): diff --git a/microcosm/tests/test_hooks.py b/microcosm/tests/test_hooks.py index f4f5cd6..495d0fd 100644 --- a/microcosm/tests/test_hooks.py +++ b/microcosm/tests/test_hooks.py @@ -19,12 +19,18 @@ def __init__(self, graph): self.callbacks = [] +@binding("subfoo") +class SubFoo(Foo): + pass + + @binding("bar") def new_foo(graph): return Foo(graph) on_resolve(Foo, foo_hook, "baz") +on_resolve(SubFoo, foo_hook, "qux") class TestHooks: @@ -54,6 +60,20 @@ def test_on_resolve_foo_again(self): assert_that(graph.foo.callbacks, contains("baz")) + def test_on_resolve_foo_subfoo(self): + """ + If we have two components, and one is a subclass of the other's class, we should + still have isolation of the hooks between them + + """ + graph = create_object_graph("test") + graph.use("foo") + graph.use("subfoo") + graph.lock() + + assert_that(graph.foo.callbacks, contains("baz")) + assert_that(graph.subfoo.callbacks, contains("qux")) + def test_on_resolve_bar_once(self): """ Resolving Foo through a separate factory calls the hook. From 37d11492f3ab3908dbf3932c171bff8379cb33a6 Mon Sep 17 00:00:00 2001 From: Adrien Fallou Date: Mon, 21 Oct 2019 22:50:52 +0100 Subject: [PATCH 4/4] Bump version to 2.13.1 --- .bumpversion.cfg | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0d8e99d..603243a 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.13.0 +current_version = 2.13.1 commit = False tag = False diff --git a/setup.py b/setup.py index d48de25..975c85a 100755 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ project = "microcosm" -version = "2.13.0" +version = "2.13.1" setup( name=project,