| @ -1,10 +1,23 @@ | |||||
| Importhook Changelog | Importhook Changelog | ||||
| =================== | =================== | ||||
| Version 1.0.1 | |||||
| ------------- | |||||
| :Released: 09-24-2018 | |||||
| :Changes: | |||||
| Expand on documentation. | |||||
| Fix `setup.py` long description content type. | |||||
| Cleanup code for finder and meta paths. | |||||
| Version 1.0.0 | Version 1.0.0 | ||||
| ------------- | ------------- | ||||
| :Released: 09-22-2018 | |||||
| :Released: 09-24-2018 | |||||
| :Changes: | :Changes: | ||||
| Initial release | |||||
| Initial release | |||||
| @ -0,0 +1,86 @@ | |||||
| Importhook | |||||
| ========= | |||||
| [](https://badge.fury.io/py/importhook) | |||||
| `importhook` is a Python package that lets you configure functions to call whenever a specific module is imported. | |||||
| ## Installation | |||||
| ```bash | |||||
| pip install importhook | |||||
| ``` | |||||
| ## Usage | |||||
| Configure a hook to be called when `socket` module is imported. | |||||
| ```python | |||||
| import importhook | |||||
| # Setup hook to be called any time the `socket` module is imported and loaded into module cache | |||||
| @importhook.on_import('socket') | |||||
| def on_socket_import(socket): | |||||
| print('"socket" module has been imported') | |||||
| # Import module | |||||
| import socket | |||||
| ``` | |||||
| You can also use `importhook` to intercept and modify a module on import by returning a Python module from your hook function. | |||||
| ```python | |||||
| import importhook | |||||
| # Setup hook to be called any time the `socket` module is imported and loaded into module cache | |||||
| @importhook.on_import('socket') | |||||
| def on_socket_import(socket): | |||||
| new_socket = importhook.copy_module(socket) | |||||
| setattr(new_socket, 'gethostname', lambda: 'patched-hostname') | |||||
| return new_socket | |||||
| # Import module | |||||
| import socket | |||||
| # Prints: 'patched-hostname' | |||||
| print(socket.gethostname()) | |||||
| ``` | |||||
| `importhook` also comes with helpers to reload modules that have already been imported. | |||||
| ```python | |||||
| import socket | |||||
| import importhook | |||||
| # Setup hook to be called any time the `socket` module is imported and loaded into module cache | |||||
| @ DEV: `on_socket_import` will be called immediately because the `socket` module is already loaded | |||||
| @importhook.on_import('socket') | |||||
| def on_socket_import(socket): | |||||
| print('"socket" module has been imported') | |||||
| # Reload the socket module | |||||
| # DEV: Reassign to `socket` in case one of our hooks modifies the module | |||||
| socket = importhook.reload_module(socket) | |||||
| ``` | |||||
| ## Design decisions | |||||
| ### Overwriting sys.meta_paths | |||||
| If a Python developer wants to modify the import behavior they can do so by adding a new `importlib.abc.Finder` | |||||
| class into `sys.meta_path`. | |||||
| ```python | |||||
| import sys | |||||
| # Add our custom `importlib.abc.Finder` to `sys.meta_path` | |||||
| sys.meta_path.append(MyCustomFinder) | |||||
| ``` | |||||
| One of the major design decisions we have taken with `importhook` is to wrap/overwrite `sys.meta_path`. | |||||
| What it means is that `importhook` will continue to work as expected regardless of any other modifications of `sys.meta_path`. | |||||
| There is however one caveat, if you were to do `sys.meta_path = [MyCustomFinder] + sys.meta_path` then `sys.meta_path` will get | |||||
| converted back into a `list`. Existing modifications to the finders in `sys.meta_path` will still work as expected, but any | |||||
| new finders added will not get hooked. | |||||
| @ -1,29 +0,0 @@ | |||||
| Importhook | |||||
| ========= | |||||
| .. image:: https://badge.fury.io/py/importhook.svg | |||||
| :target: https://badge.fury.io/py/importhook | |||||
| Installation | |||||
| ~~~~~~~~~~~~ | |||||
| .. code:: bash | |||||
| pip install importhook | |||||
| Usage | |||||
| ~~~~~ | |||||
| .. code:: python | |||||
| import importhook | |||||
| # Setup hook to be called any time the `socket` module is imported and loaded into module cache | |||||
| @importhook.on_import('socket') | |||||
| def on_socket_import(socket): | |||||
| print('"socket" module has been imported') | |||||
| # Import module | |||||
| import socket | |||||