Skip to main content

Allow loading non Python module formats as modules

Project description

Allow loading non Python module formats as modules.

Install

Use pip for installing:

$ pip install abm

Usage

Once installed, you can activate abm by importing abm.activate:

from abm import activate

Now you can register new loaders by doing:

from abm.loaders import IniLoader
IniLoader.register()

Since now, you can load *.ini files as if they were modules:

# config.ini
[section]
option = value
import config
assert(config['example'] is not None)
assert(config['example']['option'] is 'value')

Writing a loader

Extend the base loader AbmLoader provided in abm.loaders and implement create_module and execute_module methods. Provide the extension class member to allow automatic registration:

from configparser import ConfigParser
from types import ModuleType
from abm.loaders import AbmLoader


class IniLoader(AbmLoader):

    extensions = ('.ini', )

    def __init__(self, name, path):
        self.file_path = path

    def create_module(self, spec):
        module = ConfigModule(spec.name)
        self.init_module_attrs(spec, module)
        return module

    def exec_module(self, module):
        module.read(self.file_path)
        return module


class ConfigModule(ModuleType, ConfigParser):

    def __init__(self, specname):
        ModuleType.__init__(self, specname)
        ConfigParser.__init__(self)

Loaders are initialized passing the name of the module in the form:

'path.to.the.module'

And its absolute path.

Implementing create_module

create_module function should produce a module of the correct type. Nothing more. This method is passed with the module specification object used to find the module:

def create_module(self, spec)
    module = ConfigModule(spec.name)
    self.init_module_attrs(spec, module)
    return module

Implementing execute_module

execute_module function should contain the code for loading the contents of the module:

def execute_module(self, module):
    module.read(self.file_path)
    return module

A good tip for determining how to implement this method is imagining you trigger a reload of the module: the code syncing the module contents with the file is what you should put here.

Overriding builtin extensions

Overriding builtin extensions such as .py, .pyc or .so is possible by passing override_builtins=True to the register() method.

from abm.loaders import AbmLoader

class BreakPyModules(AbmLoader):

    extensions = ('.py', )

    def create_module():
        raise NotImplementedError('Can load .py modules no more.')

BreakPythonModules.register(override_builtins=True)

Use this with caution since you can break the import system. Not passing override_builtins results in a ValueError exception.

How does it work

Extension mechanism work by monkeypatching the FileFinder class in charge of reading Python several format modules from the local file system.

Internally, FileFinder uses file loaders to read the several formats of Python modules identified by their file extension. Although these classes are public, FileFinder does not expose any extension mechanism to link new extensions with new loaders.

In the spirit of sys.path_hooks and other extension hooks, activating abm will expose a dictionary in sys.abm_hooks to register new loaders dynamically. For instance:

import sys
from abm.loaders import IniLoader
from abm.core import activate

activate()
sys.abm_hooks['.ini'] = IniLoader

It works by turning the internal instance attribute _loaders of FileFinder instances into a class property. Setting the property will diverge the new value to a different attribute while reading the value will combine the original one with the extensions in sys.abm_hooks.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

abm-0.3.0.tar.gz (6.7 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page