From ebe0760f5463604613a18034ae501c8d4fc157f2 Mon Sep 17 00:00:00 2001 From: Lucy Liu Date: Wed, 13 Dec 2023 17:01:10 +1100 Subject: [PATCH 1/4] expand processor/provider doc --- docs/getting_started.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 755f8bc..3d6447e 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -14,7 +14,7 @@ in `in-n-out` are *providers* and *processors*. A [`Store`][in_n_out.Store] is a collection of providers and processors. You will usually begin by creating a `Store` instance to manage your providers and -processors. +processors. More than one provider/processor can be registered per type. ```python from in_n_out import Store @@ -38,7 +38,7 @@ store = Store.get_store('my-store') ## Registering Providers Dependency inject works by providing an instance of a type to a function -or method that requires it. Let's being by declaring some type that will be +or method that requires it. Let's begin by declaring some type that will be important to our application: ```python @@ -97,7 +97,13 @@ get_things_name() # TypeError: get_things_name() missing 1 required positional argument: 'thing' ``` -We can use the [`Store.inject`][in_n_out.Store.inject] method to inject a `Thing` into the function: +We can use the [`Store.inject`][in_n_out.Store.inject] method to inject a `Thing` into the function. +More than one provider per type can be registered. The store will iterate through all +providers registered for the required type, stopping at the first one that returns an +object that is not `None`. + +Providers should return `None` if it is not able to provide the requested object as +this allows `in-n-out` to continue iterating through any other registered providers: ```python get_things_name = store.inject(get_things_name) @@ -110,7 +116,9 @@ print(get_things_name()) # prints "Thing" ```python @store.inject def get_things_name(thing: Thing) -> str: - return thing.name + if hasattr(thing, name): + return thing.name + return None print(get_things_name()) # prints "Thing" ``` @@ -130,8 +138,8 @@ give_me_a_string() ### Weights and provider priority -You may register multiple providers for the same type. In this case, the -store will use the provider with the highest *weight*. +When you are registering multiple providers for the same type, you can use the +`weight` parameter to specify which providers should be tried first. ```python def give_me_another_thing() -> Thing: @@ -171,8 +179,18 @@ print(get_things_name()) # prints "Another Thing" ## Processors Processors are functions that take an instance of a type and do something -with it, usually for the purpose of side effects. Processors are registered -using the [`Store.register_processor`][in_n_out.Store.register_processor] method. +with it, usually for the purpose of side effects. Like providers, you can register +multiple processors per return type and the Store will iterate through all of +them. [`Store.register_processor`][in_n_out.Store.register_processor] will also +take a `weight` parameter that enables you to specify the order in which to +'process' the return objects. + +If an error is raised when executing a processor, it will be passed as a warning +after the final processor has been run. + +[`Store.inject_processors`][in_n_out.Store.inject_processors] will also take a +`first_processor_only` parameter that can be used to specify that only the +first processor should be used. ```python @store.inject_processors From ff0f9de5b4bb071252ebb7db758e695cac43106d Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 16 Dec 2023 15:38:15 -0500 Subject: [PATCH 2/4] update wording --- docs/getting_started.md | 55 +++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 3d6447e..161d1d3 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -97,19 +97,21 @@ get_things_name() # TypeError: get_things_name() missing 1 required positional argument: 'thing' ``` -We can use the [`Store.inject`][in_n_out.Store.inject] method to inject a `Thing` into the function. -More than one provider per type can be registered. The store will iterate through all -providers registered for the required type, stopping at the first one that returns an -object that is not `None`. - -Providers should return `None` if it is not able to provide the requested object as -this allows `in-n-out` to continue iterating through any other registered providers: +We can use the [`Store.inject`][in_n_out.Store.inject] method to inject a `Thing` into the function: ```python get_things_name = store.inject(get_things_name) print(get_things_name()) # prints "Thing" ``` +!!!note "multiple providers" + In the case that more one provider has been registered for a given type. The store will + iterate through all providers registered for the required type (ordered by [weight](#weights-and-provider-priority)), stopping at the first one that returns an object that + is not `None` . + + Providers should return `None` if it is not able to provide the requested object as + this allows `in-n-out` to continue iterating through any other registered providers. + !!!tip "decorators" As with registration functions, we can use `Store.inject` as a decorator: @@ -138,8 +140,9 @@ give_me_a_string() ### Weights and provider priority -When you are registering multiple providers for the same type, you can use the -`weight` parameter to specify which providers should be tried first. +When registering multiple providers for the same type, you can use the +`weight` parameter to specify the order in which providers should be tried. +(Providers with a higher weight will be tried first.) ```python def give_me_another_thing() -> Thing: @@ -179,18 +182,8 @@ print(get_things_name()) # prints "Another Thing" ## Processors Processors are functions that take an instance of a type and do something -with it, usually for the purpose of side effects. Like providers, you can register -multiple processors per return type and the Store will iterate through all of -them. [`Store.register_processor`][in_n_out.Store.register_processor] will also -take a `weight` parameter that enables you to specify the order in which to -'process' the return objects. - -If an error is raised when executing a processor, it will be passed as a warning -after the final processor has been run. - -[`Store.inject_processors`][in_n_out.Store.inject_processors] will also take a -`first_processor_only` parameter that can be used to specify that only the -first processor should be used. +with it, usually for the purpose of side effects. Processors are registered +using the [`Store.register_processor`][in_n_out.Store.register_processor] method. ```python @store.inject_processors @@ -211,6 +204,26 @@ get_things_name(Thing('Bob')) # prints "Hello, Bob!" (and still returns "Bob") did above. Or, at the very least, we wouldn't inject processors into a function that returned `str`. +### Multiple processors + +As with providers, you may register multiple processors per return type, and the +`weight` parameter will be used to specify the order in which they should be run. +(higher weights running first). + +The default behavior is to call all processors that have been registered for a +given type. However, you can use the `first_processor_only` parameter when +injecting processors with [`Store.inject_processors`][in_n_out.Store.inject_processors] +to specify that only the first processor should be used. + +Note that all processors recieve the same object (the return value of the +function being injected into). They are *not* chained, and any value returned +by a processor will be ignored. + +If an unhandled exception is raised while executing a processor, it will be caught +and a warning will be emitted, by default. If you would prefer to handle raised +exceptions yourself, you can pass `raise_exception=True` to +[`Store.inject_processors`][in_n_out.Store.inject_processors]. + ## Real world example Let's look at a more realistic example. From e8daa8c08cb7e764aab1f2cc91a01fb1814babe5 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 16 Dec 2023 15:40:41 -0500 Subject: [PATCH 3/4] grammar --- docs/getting_started.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 161d1d3..0567ad8 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -207,12 +207,13 @@ get_things_name(Thing('Bob')) # prints "Hello, Bob!" (and still returns "Bob") ### Multiple processors As with providers, you may register multiple processors per return type, and the -`weight` parameter will be used to specify the order in which they should be run. -(higher weights running first). +`weight` parameter will be used to specify the order in which they should be run, +with higher weights running first. The default behavior is to call all processors that have been registered for a -given type. However, you can use the `first_processor_only` parameter when +given type. However, you can use `first_processor_only=True` when injecting processors with [`Store.inject_processors`][in_n_out.Store.inject_processors] +or when manually calling [`Store.process`][in_n_out.Store.process] to specify that only the first processor should be used. Note that all processors recieve the same object (the return value of the @@ -220,7 +221,7 @@ function being injected into). They are *not* chained, and any value returned by a processor will be ignored. If an unhandled exception is raised while executing a processor, it will be caught -and a warning will be emitted, by default. If you would prefer to handle raised +and a warning will be emitted. If you would prefer to handle raised exceptions yourself, you can pass `raise_exception=True` to [`Store.inject_processors`][in_n_out.Store.inject_processors]. From ad192d725b95cf74ffbfe068d63f031b471f1d85 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 17 Dec 2023 09:31:29 -0500 Subject: [PATCH 4/4] Update docs/getting_started.md --- docs/getting_started.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 0567ad8..bbe589a 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -118,9 +118,7 @@ print(get_things_name()) # prints "Thing" ```python @store.inject def get_things_name(thing: Thing) -> str: - if hasattr(thing, name): - return thing.name - return None + return thing.name print(get_things_name()) # prints "Thing" ```