PyTapable provides a set of utility to help you implement hookable interfaces in your classes. This opens up the posibility for solving a number of usecases such as
- Providing plugable interfaces for your libraries and frameworks
- Code seperation by functional and service domains
This project can be used in python 2.7, 3.5 and greater
$ pip install pytapable
We first create our hook called my_hook
from pytapable import Hook
my_hook = Hook()
As a consumer, we can tap into this hook by passing a name for our tap and a callback function
def my_callback(context, fn_kwargs):
print(f"Hook says: {fn_kwargs['greeting']}")
my_hook.tap('My Tap Name', my_callback)
Our callback is executed when the hook.call(...)
is executed. The callback receives whatever args were passed in the
hook.call
method in addition to a context dict
my_hook.call(greeting="Hi Callback")
Functional hooks are different from inline hooks in that the callback args are predefined.
from pytapable import CreateHook, HookableMixin, create_hook_name
class Car(HookableMixin):
HOOK_ON_MOVE = create_hook_name('on_move')
@CreateHook(name=HOOK_ON_MOVE)
def move(self, speed=10):
return f"Moving at {speed} Mph"
- Start adding the
HookableMixin
to the Car Class. This is necessary to install hooks on class methods. - Decorate the
Car.move
method using the@CreateHook
decorator. In the decorator, give it a name. As best practice we define the name as a Class Constant so consumers can easily refer to it. - The value of the hook can be anything. We use the
create_hook_name(str)
utility to generate a unique name. Generating a unique name is not required but becomes important when inheriting hooks from other Classes.
def callback(context, fn_kwargs, fn_output, is_before):
kmph_speed = fn_kwargs['speed'] * 1.61
print(f"The car is moving {kmph_speed} kmph")
c = Car()
c.hooks[Car.HOOK_ON_MOVE].tap('log_metric_speed', callback, before=False)
c.move(10)
- Here we tap into the
on_move
hook which fires our callback after thec.move
method has executed - The
c.move()
arguments are passed asfn_kargs
to the callback and return value, if any, is passed asfn_output
- All positional arguments are converted to named arguments
- The context holds a
is_before
andis_after
flag it signify if the callback was executed before or afterc.move()
Full documentation is available here https://pytapable.readthedocs.io/en/latest
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
To tests on your changes locally, run:
$ pip install -r test_requirements.txt
$ tox .
This will run your changes on python-2 and python-3
Documentation for any new changes are a must. We use Sphinx and to build the documentation locally, run:
$ cd docs/
$ make html
# or on windows
$ make.bat html
Distributed under the Apache License
Logo made by Smashicons