Skip to content

Commit e84fdfa

Browse files
committed
fix bug in example and some more improvements/clarfications.
* fix bug introduced when "fixing" the example * reorder code: give the big picture first (main()) * split out function to get plugin manager * use the two functions to demonstrate returning a result vs modifying an argument * avoid too lont sentences. * use pip --editable instead of -e for clarity
1 parent 653a1e9 commit e84fdfa

File tree

5 files changed

+58
-39
lines changed

5 files changed

+58
-39
lines changed

docs/examples/eggsample-spam/eggsample_spam.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@
22

33
@eggsample.hookimpl
44
def eggsample_add_ingredients(ingredients):
5-
if len([e for e in ingredients if e == "egg"]) > 2:
6-
ingredients.remove("egg")
7-
spam = ["lovely spam", "wonderous spam", "splendiferous spam"]
5+
"""Here we get an immutable object, so we return something to the caller."""
6+
if "egg" in ingredients:
7+
spam = ["lovely spam", "wonderous spam"]
8+
else:
9+
spam = ["splendiferous spam", "magnificent spam"]
810
print(f"Add {spam}")
911
return spam
1012

1113
@eggsample.hookimpl
1214
def eggsample_prep_condiments(condiments):
15+
"""Here we get a mutable object, so we just mess with it directly."""
1316
try:
1417
del condiments["steak sauce"]
1518
except KeyError:
1619
pass
20+
condiments['spam sauce'] = 42
21+
print(f"Now. this is what I call a condiments tray!")

docs/examples/eggsample/eggsample/hookspecs.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
hookspec = pluggy.HookspecMarker("eggsample")
44

55
@hookspec
6-
def eggsample_add_ingredients(ingredients):
7-
"""Change the used ingredients.
6+
def eggsample_add_ingredients(ingredients: tuple):
7+
"""Have a look at the ingredients and offer your own.
88
9-
:param list ingredients: the ingredients to be modified
9+
:param ingredients: the ingredients, don't touch them!
10+
:return: a list of ingredients
1011
"""
1112

1213
@hookspec
13-
def eggsample_prep_condiments(condiments):
14-
"""Reorganize the condiments tray.
14+
def eggsample_prep_condiments(condiments: dict):
15+
"""Reorganize the condiments tray to your heart's content.
1516
16-
:param dict condiments: some sauces and stuff
17+
:param condiments: some sauces and stuff
18+
:return: will be ignored by caller
1719
"""
Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import itertools
12
import random
23

34
import pluggy
@@ -6,16 +7,34 @@
67

78
condiments_tray = {"pickled walnuts": 13, "steak sauce": 4, "mushy peas": 2}
89

10+
def main():
11+
pm = get_plugin_manager()
12+
cook = EggsellentCook(pm.hook)
13+
cook.add_ingredients()
14+
cook.prepare_the_food()
15+
cook.serve_the_food()
16+
17+
def get_plugin_manager():
18+
pm = pluggy.PluginManager("eggsample")
19+
pm.add_hookspecs(hookspecs)
20+
pm.load_setuptools_entrypoints("eggsample")
21+
pm.register(lib)
22+
return pm
23+
924
class EggsellentCook:
25+
FAVORITE_INGREDIENTS = ("egg", "egg", "egg")
26+
1027
def __init__(self, hook):
1128
self.hook = hook
12-
self.ingredients = []
29+
self.ingredients = None
1330

1431
def add_ingredients(self):
15-
more_ingredients = self.hook.eggsample_add_ingredients(
16-
ingredients=self.ingredients)
17-
# each hook implementation returned a list of ingredients
18-
self.ingredients.extend(more_ingredients)
32+
results = self.hook.eggsample_add_ingredients(
33+
ingredients=self.FAVORITE_INGREDIENTS)
34+
my_ingredients = list(self.FAVORITE_INGREDIENTS)
35+
# Each hook returns a list - so we chain this list of lists
36+
other_ingredients = list(itertools.chain(*results))
37+
self.ingredients = my_ingredients + other_ingredients
1938

2039
def prepare_the_food(self):
2140
random.shuffle(self.ingredients)
@@ -25,15 +44,5 @@ def serve_the_food(self):
2544
print(f"Your food: {', '.join(self.ingredients)}")
2645
print(f"Some condiments: {', '.join(condiments_tray.keys())}")
2746

28-
def main():
29-
pluginmanager = pluggy.PluginManager("eggsample")
30-
pluginmanager.add_hookspecs(hookspecs)
31-
pluginmanager.load_setuptools_entrypoints("eggsample")
32-
pluginmanager.register(lib)
33-
cook = EggsellentCook(pluginmanager.hook)
34-
cook.add_ingredients()
35-
cook.prepare_the_food()
36-
cook.serve_the_food()
37-
3847
if __name__ == '__main__':
3948
main()

docs/examples/eggsample/eggsample/lib.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import eggsample
22

33
@eggsample.hookimpl
4-
def eggsample_add_ingredients(ingredients):
5-
basics = ["egg", "egg", "salt", "pepper"]
6-
print(f"Add {basics}")
7-
return basics
4+
def eggsample_add_ingredients():
5+
spices = ["salt", "pepper"]
6+
you_can_never_have_enough_eggs = ["egg", "egg"]
7+
ingredients = spices + you_can_never_have_enough_eggs
8+
print(f"Add {ingredients}")
9+
return ingredients
810

911
@eggsample.hookimpl
1012
def eggsample_prep_condiments(condiments):

docs/index.rst

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ between ``host`` and ``plugins``.
3535

3636
The ``pluggy`` approach puts the burden on the designer of the
3737
``host program`` to think carefully about which objects are really
38-
needed in a hook implementation, which gives `plugin` creators a clear
38+
needed in a hook implementation. This gives `plugin` creators a clear
3939
framework for how to extend the ``host`` via a well defined set of functions
4040
and objects to work with.
4141

@@ -91,8 +91,8 @@ Now let us demonstrate how this plays together in a vaguely real world scenario.
9191
Let's assume our ``host program`` is called **eggsample** where some eggs will
9292
be prepared and served with a tray containing condiments. As everybody knows:
9393
the more cooks are involved the better the food, so let us make the process
94-
pluggable and write a plugin that improves the meal with some spam and removes
95-
the steak sauce from the condiments tray (nobody likes that anyway).
94+
pluggable and write a plugin that improves the meal with some spam and replaces
95+
the steak sauce (nobody likes that anyway) with spam sauce (it's a thing - trust me).
9696

9797
.. note::
9898

@@ -124,11 +124,11 @@ The host
124124

125125
Let's get cooking - we install the host and see what a program run looks like::
126126

127-
$ pip install -e pluggy/docs/examples/eggsample
127+
$ pip install --editable pluggy/docs/examples/eggsample
128128
$ eggsample
129129

130-
Add ['egg', 'egg', 'salt', 'pepper']
131-
Your food: egg, salt, pepper, egg
130+
Add ['salt', 'pepper', 'egg', 'egg']
131+
Your food: pepper, egg, egg, egg, egg, salt, egg
132132
Some condiments: pickled walnuts, steak sauce, mushy peas, mint sauce
133133

134134
The plugin
@@ -144,13 +144,14 @@ The plugin
144144
Let's get cooking with more cooks - we install the plugin and and see what
145145
we get::
146146

147-
$ pip install -e pluggy/docs/examples/eggsample-spam
147+
$ pip install --editable pluggy/docs/examples/eggsample-spam
148148
$ eggsample
149149

150-
Add ['egg', 'egg', 'salt', 'pepper']
151-
add ['lovely spam', 'wonderous spam', 'splendiferous spam']
152-
Your food: egg, lovely spam, egg, pepper, salt, wonderous spam, splendiferous spam
153-
Some condiments: pickled walnuts, mushy peas, mint sauce
150+
Add ['salt', 'pepper', 'egg', 'egg']
151+
Add ['lovely spam', 'wonderous spam']
152+
Now, this is what I call a condiments tray!
153+
Your food: wonderous spam, pepper, egg, egg, egg, egg, lovely spam, egg, salt
154+
Some condiments: pickled walnuts, mushy peas, mint sauce, spam sauce
154155

155156
More real world examples
156157
------------------------

0 commit comments

Comments
 (0)