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 details)

Uploaded Source

File details

Details for the file abm-0.3.0.tar.gz.

File metadata

  • Download URL: abm-0.3.0.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.2

File hashes

Hashes for abm-0.3.0.tar.gz
Algorithm Hash digest
SHA256 57dca3bcc24649f0b58eebd7e0decfdc473bb15a9dc586e2af8c6c7d79090759
MD5 e38de4261f65bd08179ea6088fcb964f
BLAKE2b-256 2074227e679e53b204e58ade7998dc304f5aa5a7b8b09f7adcb64df555229224

See more details on using hashes here.

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