Package: abm
Allow loading non Python module formats as modules.InstallUsepipfor installing:$pipinstallabmUsageOnce installed, you can activateabmby importingabm.activate:fromabmimportactivateNow you can register new loaders by doing:fromabm.loadersimportIniLoaderIniLoader.register()Since now, you can load*.inifiles as if they were modules:# config.ini[section]option=valueimportconfigassert(config['example']isnotNone)assert(config['example']['option']is'value')Noteabm.loaderspackage is work in progress.
Theabm.loaderspackage is still work in progress and it will gather
a set of useful loaders for common extensions.Writing a loaderExtend the base loaderAbmLoaderprovided inabm.loadersand implementcreate_moduleandexecute_modulemethods. Provide theextensionclass member to allow automatic registration:fromconfigparserimportConfigParserfromtypesimportModuleTypefromabm.loadersimportAbmLoaderclassIniLoader(AbmLoader):extensions=('.ini',)def__init__(self,name,path):self.file_path=pathdefcreate_module(self,spec):module=ConfigModule(spec.name)self.init_module_attrs(spec,module)returnmoduledefexec_module(self,module):module.read(self.file_path)returnmoduleclassConfigModule(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.Implementingcreate_modulecreate_modulefunction should produce a module of the correct type. Nothing
more. This method is passed with the module specification object used to find
the module:defcreate_module(self,spec)module=ConfigModule(spec.name)self.init_module_attrs(spec,module)returnmoduleImplementingexecute_moduleexecute_modulefunction should contain the code for loading the contents
of the module:defexecute_module(self,module):module.read(self.file_path)returnmoduleA 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 extensionsOverriding builtin extensions such as.py,.pycor.sois possible
by passingoverride_builtins=Trueto theregister()method.fromabm.loadersimportAbmLoaderclassBreakPyModules(AbmLoader):extensions=('.py',)defcreate_module():raiseNotImplementedError('Can load .py modules no more.')BreakPythonModules.register(override_builtins=True)Use this with caution since you can break the import system.
Not passingoverride_builtinsresults in aValueErrorexception.How does it workExtension mechanism work by monkeypatching theFileFinderclass in charge
of reading Python several format modules from the local file system.Internally,FileFinderuses file loaders to read the several formats of
Python modules identified by their file extension. Although these classes are
public,FileFinderdoes not expose any extension mechanism to link new
extensions with new loaders.In the spirit ofsys.path_hooksand other extension hooks, activatingabmwill expose a dictionary insys.abm_hooksto register new loaders
dynamically. For instance:importsysfromabm.loadersimportIniLoaderfromabm.coreimportactivateactivate()sys.abm_hooks['.ini']=IniLoaderIt works by turning the internal instance attribute_loadersofFileFinderinstances 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 insys.abm_hooks.