Piggyback

What’s Piggyback?

Piggyback is a tiny module which allows you to properly import other modules easily, and in an extensible manner. The design of Piggyback is inherently simple enough, so anyone unfamiliar with the codebase can read and understand the code. This project aims to be used in other codebases where they need to import modules/plugins:

from piggyback.finder import Finder
from piggyback.loader import Loader

loader = Loader(Finder('path/to/modules'))
modules = loader.import_all()
modules['module'].function()

Installing

The package is available on PyPI. To install it, use either pip or easy_install:

$ pip install Piggyback

Usage

To load modules, you first have to create a Loader and Finder object. The task of the Loader object is simply to load the modules (import them), while the task of the Finder object is to find the modules, and pass them to the loader. To create a loader:

from piggyback.finder import Finder
from piggyback.loader import Loader

loader = Loader(Finder('path'))

Then when you want to load modules, you can simply call the load function. For example if you want to load the module named examples that is a submodule of the module that the Finder object was created with, you should do:

loader.load('path.examples')

Alternatively you can discover all modules by calling the import_all function:

modules = loader.import_all()
modules['path.examples']

Note that if you use a path to a script (file) when creating the Finder object, Piggyback will also handle that correctly and import the file only. Also, all files starting with double underscores will not be imported, i.e. to prevent some side effects when __main__ is called. To find out if the path points to a script or package, you have two options:

is_package = loader.root is not None
is_package = loader.finder.is_package

API

class piggyback.loader.Loader(finder)

Create a loader object with the given finder class and options.

Parameters:finder – The Finder class.
import_all()

Import all of the modules under the given path and stores them (according to their name) in a dictionary. All names are provided with the root of the path intact, i.e. if you look for modules under test you will get test.mod1, test.mod2, etc.

load(module)

Load a desired module from the search path, and return the module object. You will raise an ImportError if the module is not found.

Parameters:module – The desired module.
search()

List the modules found by a given finder. Does not actually import anything.

class piggyback.finder.Finder(path, prefix='', suffix='.py')

Create a finder object for the given path.

Parameters:
  • path – The path.
  • prefix – Only load files with this prefix.
  • suffix – Only load files with this suffix (can be combined with the prefix option).
find_modules()

Search for the modules under path of the finder object. Returns either the root path or the found modules depending on whether the finder object is a package.

find_nested_modules()

Look for nested modules. To be called only when the finder object is a package (dictated by the is_package property).

hint_function

Returns the hint function for the finder object. The hint function basically checks if the path conforms to all of the hints in the hints attribute.

Advanced Usage

You can easily customize the finder object so that it loads only certain types of files, for example if you want it to load only files that start with test_, you can configure it using the prefix attribute:

finder.prefix = 'test_'

Alternatively (and a better method) is using a function that will check if the filename doesn’t start with test_, by appending a function into the ignored attribute. What this means is that all files that do not start with test_ are ignored. Every function that is within the ignored list will be passed the filename of every traversed Python module:

finder.ignored.append(lambda x: not x.startswith('test_'))

Also, you can also configure the finder to only traverse directories that contain certain files/do not contain certain files with the hints attribute. How this works is that each traversed directory will be called with each function in the hints attribute, and it will only be yielded/taken into account if all the hints return True:

finder.hints.append(lambda files: '.notests' not in files)

Table Of Contents

This Page