python-hookman 0.8.0
HookMan is a python package that provides a plugin management system to applications, specially those who are written (in totally or partially) in C++.
License: MIT license
Requires Python: >=3.10
Keywords: hookman

=======
Hookman
=======

.. image:: https://img.shields.io/pypi/v/python-hookman.svg
    :target: https://pypi.python.org/pypi/python-hookman

.. image:: https://img.shields.io/conda/vn/conda-forge/python-hookman.svg
    :target: https://anaconda.org/conda-forge/python-hookman

.. image:: https://img.shields.io/pypi/pyversions/python-hookman.svg
    :target: https://pypi.org/project/python-hookman

.. image:: https://codecov.io/gh/ESSS/hookman/branch/master/graph/badge.svg
    :target: https://codecov.io/gh/ESSS/hookman

.. image:: https://github.com/ESSS/hookman/workflows/Hookman%20-%20CI/badge.svg
    :target: https://github.com/ESSS/hookman/actions

.. image:: https://readthedocs.org/projects/hookman/badge/?version=latest
    :target: https://hookman.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation Status


This documentation covers HookMan usage & API.

For information about HookMan,  read the section above. For public changelog and how the project is maintained, please check the `GitHub page`_

What is HookMan?
================

``HookMan`` is a python package that provides a plugin management system to applications,
specially those who are written (in totally or partially) in C++.

It enables external contributors to implement plugins which act as extensions written in C/C++
that interact with the application through well-defined *hooks*.

This system was largely inspired by `pluggy`_,
the plugin system which powers `pytest`_, `tox`_, and `devpi`_, but with the intent to be called
from a C++ application rather than from Python.

It was conceived to facilitate the application development, allowing hooks to be exposed in a
clear way and allowing plugins to be developed without access to classes or data from the application.

With ``HookMan`` your application can have access to the hooks implemented on plugins as simple as the example below.

.. code-block:: python

    # Initializing a class
    hm = HookMan(specs=acme_specs, plugin_dirs=['path1','path2'])

    hook_caller = hm.get_hook_caller()

    # Getting access to the hook implementation
    friction_factor = hook_caller.friction_factor()
    env_temperature = hook_caller.env_temperature()

    # Checking if the hook was implemented
    assert friction_factor is not None
    assert env_temperature is None

    # Executing the hook, wherever it is implemented either in plugin A or B.
    ff_result = friction_factor(1, 2.5)
    env_tmp_result = env_temperature(35.5, 45.5)

How does it work?
-----------------

In order to use ``HookMan`` in your application, it is necessary to inform which ``Hooks``
are available to be implemented through a configuration object.


With this configuration defined, users can create plugins that implement available ``Hooks`` extending the behavior of your application.


All plugins informed to your application will be validated by HookMan (to check which hooks are implemented),
and an object holding a reference to the ``Hooks`` will be passed to the application.


The ``HookMan`` project uses the library pybind11_ to interact between Python and C/C++,
allowing a straightforward usage for who is calling the function (either in Python or in C++).


Defining some terminologies:

- ``Application`` ⇨  The program that offers the extensions.
- ``Hook``        ⇨  An extension of the Application.
- ``Plugin``      ⇨  The program that implements the ``Hooks``.
- ``User``        ⇨  The person who installed the application.




`Read the docs to learn more!`_

* Documentation: https://hookman.readthedocs.io.
* Free software: MIT license


Credits
-------
Thanks for pluggy_,  which is a similar project (plugin system) and source for many ideas.

This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.


.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
.. _`GitHub page` :                   https://github.com/ESSS/hookman
.. _`read the docs to learn more!` :  https://hookman.readthedocs.io
.. _Cookiecutter:                     https://github.com/audreyr/cookiecutter
.. _devpi:                            https://github.com/devpi/devpi
.. _pluggy:                           https://github.com/pytest-dev/pluggy
.. _pybind11:                         https://github.com/pybind/pybind11
.. _pytest:                           https://github.com/pytest-dev/pytest
.. _tox:                              https://github.com/tox-dev/tox


=======
History
=======
0.8.0 (2025-08-18)
==================
- Allow install multiple versions of the same plugin.

0.7.0 (2025-06-10)
==================

- Add a new ``requirements`` property which allows specifying any additional requirements for plugins.
- Add support for packaging Linux libraries with version suffixes (e.g. `libhookman.so.1.0.0`).

0.6.0 (2025-02-28)
==================

- Dropped support for old Python versions, requiring Python 3.10+.
- Add CHANGELOG.rst to plugin generator

0.5.0 (2023-02-10)
==================

- Allow to add some extra text to created hmplugin file.


0.4.0 (2020-10-23)
==================

- When removing plugins they are first moved to a ``.trash`` dir and not directly deleted.
- Allow HookManager to call hooks of a specific plugin.


0.3.0 (2019-12-16)
==================

- Rename the parameter ``dst_path`` to ``dest_path`` on ``install_plugin`` method.
- ``install_plugin`` now returns the name of the plugin when the installation is successful.
- Now the library path dir is added to ``PATH`` environment variable before load the library (Only on Windows).
- Added an optional "extras" entry to plugin definition yaml:

  - "extras" is a dictionary for adding (key, value) customized options, accessible in ``PluginInfo.extras``;
  - Plugin generation accepts a dict of default (key, value) pairs to be added to ``extras``;


0.2.0 (2019-02-08)
==================

- Moved load hook function code to ``HookCaller.load_impls_from_library`` function implemented in C++. This
  enables using hook functionality in projects which don't use Python as their entry point.

- ``HookSpecs`` now accepts an ``extra_includes`` argument, which can be used to add custom ``#include`` directives
  to the generated ``HookCaller.hpp`` file.

- ``HookCaller`` now contains a ``std::vector`` of functions bound to plugin implementations. This allows multiple
  plugins to implement the same hook; how the results of each call is to behave is responsibility of the caller.

  Because of this, the following classes/methods have been removed because they are no longer relevant:

  * ``ConflictBetweenPluginsError``
  * ``ConflictStatus``
  * ``HookMan.ensure_is_valid``
  * ``HookMan.get_status``


- Generated files now sport a "do not modify" comment header.

- Generation of the bindings code for ``HookCaller`` is skipped if ``specs.pyd_name`` is not defined.

- Code generation is now available directly in the command-line through the commands:

  * ``python -m hookman generate-plugin-template``
  * ``python -m hookman generate-project-files``
  * ``python -m hookman generate-hook-specs-h``
  * ``python -m hookman package-plugin``

- Explicitly declare ``extern "C"`` calling convention in the ``hook_specs.h`` file.

- The ``INIT_HOOKS`` macro has been removed as it didn't have any useful function.

0.1.7 (2018-08-23)
==================

- First Release on PyPI.

0.1.6 (2018-08-23)
==================

- Never released, deployment error.

0.1.5 (2018-08-23)
==================

- Never released, deployment error.


0.1.4 (2018-08-23)
==================

- Never released, deployment error.

0.1.3 (2018-08-23)
==================

- Never released, deployment error.


0.1.2 (2018-08-23)
==================

- Never released, deployment error.


0.1.1 (2018-08-23)
==================

- Never released, deployment error.
- Dropping bumperversion and using setuptool_scm

0.1.0 (2018-08-23)
==================

- Never released, deployment error.