Skip to main content

Persistent Python modules allow us to develop and store Python modules in the ZODB in contrast to storing them on the filesystem. You might want to look at the zodbcode package for the details of the implementation. In Zope 3 we implemented persistent modules as utilities. These utilities are known as module managers that manage the source code, compiled module and name of the module. We then provide a special module registry that looks up the utilities to find modules.

Detailed Documentation

Persistent Python Modules

Persistent Python modules allow us to develop and store Python modules in the ZODB in contrast to storing them on the filesystem. You might want to look at the zodbcode package for the details of the implementation. In Zope 3 we implemented persistent modules as utilities. These utilities are known as module managers that manage the source code, compiled module and name of the module. We then provide a special module registry that looks up the utilities to find modules.

The Module Manager

One can simply create a new module manager by instantiating it:

>>> from zope.app.module.manager import ModuleManager
>>> manager = ModuleManager()

If I create the manager without an argument, there is no source code:

>>> manager.source
''

When we add some code

>>> manager.source = """\n
... foo = 1
... def bar(): return foo
... class Blah(object):
...     def __init__(self, id): self.id = id
...     def __repr__(self): return 'Blah(id=%s)' % self.id
... """

we can get the compiled module and use the created objects:

>>> module = manager.getModule()
>>> module.foo
1
>>> module.bar()
1
>>> module.Blah('blah')
Blah(id=blah)

We can also ask for the name of the module:

>>> manager.name
>>> module.__name__

But why is it None? Because we have no registered it yet. Once we register and activate the registration a name will be set:

>>> from zope.app.testing import setup
>>> root = setup.buildSampleFolderTree()
>>> root_sm = setup.createSiteManager(root)
>>> from zope.app.module import interfaces
>>> manager = setup.addUtility(root_sm, 'mymodule',
...                            interfaces.IModuleManager, manager)
>>> manager.name
'mymodule'
>>> manager.getModule().__name__
'mymodule'

Next, let’s ensure that the module’s persistence works correctly. To do that let’s create a database and add the root folder to it:

>>> from ZODB.tests.util import DB
>>> db = DB()
>>> conn = db.open()
>>> conn.root()['Application'] = root
>>> import transaction
>>> transaction.commit()

Let’s now reopen the database to test that the module can be seen from a different connection.

>>> conn2 = db.open()
>>> root2 = conn2.root()['Application']
>>> module2 = root2.getSiteManager().queryUtility(
...     interfaces.IModuleManager, 'mymodule').getModule()
>>> module2.foo
1
>>> module2.bar()
1
>>> module2.Blah('blah')
Blah(id=blah)

Module Lookup API

The way the persistent module framework hooks into Python is via module registires that behave pretty much like sys.modules. Zope 3 provides its own module registry that uses the registered utilities to look up modules:

>>> from zope.app.module import ZopeModuleRegistry
>>> ZopeModuleRegistry.findModule('mymodule')

But why did we not get the module back? Because we have not set the site yet:

>>> from zope.app.component import hooks
>>> hooks.setSite(root)

Now it will find the module and we can retrieve a list of all persistent module names:

>>> ZopeModuleRegistry.findModule('mymodule') is module
True
>>> ZopeModuleRegistry.modules()
[u'mymodule']

Additionally, the package provides two API functions that look up a module in the registry and then in sys.modules:

>>> import zope.app.module
>>> zope.app.module.findModule('mymodule') is module
True
>>> zope.app.module.findModule('zope.app.module') is zope.app.module
True

The second function can be used to lookup objects inside any module:

>>> zope.app.module.resolve('mymodule.foo')
1
>>> zope.app.module.resolve('zope.app.module.foo.resolve')

In order to use this framework in real Python code import statements, we need to install the importer hook, which is commonly done with an event subscriber:

>>> import __builtin__
>>> event = object()
>>> zope.app.module.installPersistentModuleImporter(event)
>>> __builtin__.__import__ # doctest: +ELLIPSIS
<bound method ZopePersistentModuleImporter.__import__ of ...>

Now we can simply import the persistent module:

>>> import mymodule
>>> mymodule.Blah('my id')
Blah(id=my id)

Finally, we unregister the hook again:

>>> zope.app.module.uninstallPersistentModuleImporter(event)
>>> __builtin__.__import__
<built-in function __import__>

Persistent Interfaces

zope.app.module’s ModuleManagers behave a little differently when interfaces are involved:

>>> from zope.app.module.manager import ModuleManager
>>> manager = ModuleManager()
>>> source = """\n
... from zope.interface import Interface
... class IFoo(Interface): pass
... class IBar(IFoo): pass
... """
>>> manager.source = source

A ModuleManager doesn’t get a name until it’s registered and the zodbcode wrappers break without a name, so we can’t retrieve our module until our manager is registered:

>>> from zope.app.testing import setup
>>> from zope.app.module import interfaces
>>> root = setup.buildSampleFolderTree()
>>> root_sm = setup.createSiteManager(root)
>>> manager = setup.addUtility(root_sm, u'foo',
...                            interfaces.IModuleManager, manager)

Now we can compile a module with interfaces and access everything appropriately:

>>> module = manager.getModule()
>>> module
<PersistentModule foo>
>>> module.IFoo
<PersistentInterfaceClass foo.IFoo>
>>> module.IBar
<PersistentInterfaceClass foo.IBar>

CHANGES

3.5.0 (2009-02-01)

  • Use zope.container instead of zope.app.container.

3.4.0 (2007-10-25)

  • Initial release independent of the main Zope tree.

Release files for zope.app.module 3.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zope.app.module 3.5.0
File Size Uploaded
zope.app.module-3.5.0.tar.gz 10.1 kB Details

Release files / zope.app.module-3.5.0.tar.gz

Download URL zope.app.module-3.5.0.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ef3c1ec5de3b2f86d8fc250e9b7b28faaed3482d699e27915eec68aac2dd944b
BLAKE2b-256 checksum
How to use checksums
1ed2270fcc50bd8922ffd62d569e4f804f5523929e97cc63f0f3a1769a9d7130
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

3.5.0 This release

1 release file

3.4.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page