nti.site:

Contents:

nti.site API Reference

nti.site.interfaces module

Site interfaces.

interface nti.site.interfaces.IHostPolicyFolder[source]

Extends: zope.site.interfaces.IFolder

A folder that should always have a site manager, and thus is a site, representing a policy for the host name. Persistent configuration related to that host should reside in this folder.

interface nti.site.interfaces.IHostPolicySiteManager[source]

Extends: zope.site.interfaces.ILocalSiteManager

A persistent local site manager that is tied to a site name. It should always have two bases, a non-persistent global IComponents configured through z3c.baseregistry and the persistent main dataserver site manager, in that order. This should be the site manager for an IHostPolicyFolder

interface nti.site.interfaces.IHostSitesFolder[source]

Extends: zope.site.interfaces.IFolder

A container for the sites, each of which should be an IHostPolicyFolder

lastSynchronized

The timestamp at which this object was last synchronized .

Implementation:nti.schema.field.Number
Read Only:False
Required:True
Default Value:0.0
Allowed Type:numbers.Number
interface nti.site.interfaces.IMainApplicationFolder[source]

Extends: zope.site.interfaces.IFolder

The folder representing the application. The set of persistent components will be installed beneath this folder, and this folder will be an Site (with a site manager).

This may be the same thing as the root folder. As an implementation note, though, this is typically beneath the root folder and named something application specific (e.g., “dataserver2”).

interface nti.site.interfaces.ISiteMapping[source]

Maps a site name to an alternate site. Useful when we do not want full fledged persistent sites. Should only be used after checking for an existing site.

get_target_site(self)

Returns the target site as defined by this mapping.

:raises a SiteNotFoundError object if no site found

target_site_name

The target site name

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
source_site_name

The source site name

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
interface nti.site.interfaces.ISiteTransactionRunner[source]

Something that runs code within a transaction, properly setting up the ZODB, persistent site, and its environment.

__call__(func, retries=0, sleep=None, site_names=(), side_effect_free=False, root_folder_name=u'nti.dataserver')

Runs the function given in func in a transaction and application local site manager (defaulting to the current site manager).

Parameters:
  • func (function) – A function of zero parameters to run. If it has a docstring, that will be used as the transactions note. A transaction will be begun before this function executes, and committed after the function completes. This function may be rerun if retries are requested, so it should be prepared for that.
  • retries (int) – The number of times to retry the transaction and execution of func if transaction.interfaces.TransientError is raised when committing. Defaults to zero (so the job runs once). If you specify None, an implementation-specific number of retries will be used.
  • sleep (float) – If not none, then the greenlet running this function will sleep for this long between retry attempts.
  • site_names – DEPRECATED. Sequence of strings giving the virtual host names to use. If you do not provide this argument, then the currently installed site will be maintained when the transaction is run. NOTE: The implementation of this may maintain either the site names or the actual site object.
  • side_effect_free (bool) – If true (not the default), then the function is assummed to have no side effects that need to be committed; the transaction runner is free to abort/rollback or commit the transaction at its leisure.
  • root_folder_name (str) – This names the folder that can be found in the root of the ZODB that will serve as the starting point to look for the persistent named site.
Returns:

The value returned by the first successful invocation of func.

interface nti.site.interfaces.ITransactionSiteNames[source]

An interface for a utility that return a list of the possible site names needed whenever transaction is run.

__call__(*args, **kwargs)

Return the possible site names

exception nti.site.interfaces.InappropriateSiteError[source]

Bases: exceptions.LookupError

Raised if the installed site is not suitable to work with.

Currently no code in this package raises this exception.

exception nti.site.interfaces.SiteNotFoundError[source]

Bases: exceptions.LookupError

Raised if there is no valid site found.

exception nti.site.interfaces.SiteNotInstalledError[source]

Bases: exceptions.AssertionError

Raised when setting and getting a site do not work.

This is most often caused by not installing the zope.component hooks.

nti.site.hostpolicy module

Support for host policies.

This contains the main unique functionality for this package.

nti.site.hostpolicy.get_all_host_sites()[source]

The order in which sites are accessed is top-down breadth-first, that is, the shallowest to the deepest nested sites. This allows you to assume that your parent sites have already been updated.

Returns:A list of sites
Return type:list
nti.site.hostpolicy.get_host_site(site_name, safe=False)[source]

Find the persistent site named site_name and return it.

Parameters:safe (bool) – If True, silently ignore any errors. DO NOT use this param. Deprecated and dangerous.
nti.site.hostpolicy.get_site(site_name, safe=False)

Find the persistent site named site_name and return it.

Parameters:safe (bool) – If True, silently ignore any errors. DO NOT use this param. Deprecated and dangerous.
nti.site.hostpolicy.install_main_application_and_sites(conn, root_name=<u'Application' is the default root folder>, root_alias=<u'nti.dataserver_root' is the default alias of root folder>, main_name=<u'dataserver2' is the default main application folder>, main_alias=<u'nti.dataserver' is the default alias of main application folder>, main_factory=<class 'zope.site.folder.Folder'>, main_setup=None)[source]

Install the main application and site folder structure into ZODB.

When this completes, the ZODB root object will have a IRootFolder object at root_name (and optionally at root_alias), created by zope.site.folder.rootFolder(). This will have a site manager. Note that this object does not have a __name__ and will serve as the base (root, or “/”) for object path traversal.

The root folder in turn will have a IMainApplicationFolder child named main_name (and optionally at main_alias). It will have a site manager, and in this site manager will be the “++etc++hostsites” object used to contain host site folders.

The tree will look like this:

<Connection Root Dictionary>
   <ISite,IRootFolder>: root_name rootFolder()
       <ISite,IMainApplicationFolder>: main_name  <main_factory>
           ++etc++hostsites <class 'nti.site.folder.HostSitesFolder'>
   main_name  -> /root_name/main_name
   main_alias -> /root_name/main_name
   root_alias -> /root_name

Using the default names, that would be:

<Connection Root Dictionary>
   <ISite,IRootFolder>: Application
       <ISite,IMainApplicationFolder>: dataserver2
           ++etc++hostsites
   dataserver2         -> /Application/dataserver2
   nti.dataserver      -> /Application/dataserver2
   nti.dataserver_root -> /Application

Caution

Passing in duplicate names for any of the parameters may result in unexpected results.

Note

The aliases are only installed if the alias parameters are true. In the future, the alias parameters will default to false.

Note

The root folder

Changed in version 2.1: The root_alias now points to the root_name. Previously it pointed to main_name (e.g., /Application/dataserver2). This made no sense because main_alias already pointed there.

Parameters:
  • conn – The open ZODB connection.
  • root_name (str) – The main name of the root folder. This generally should be left as “Application” as that’s what many Zope 3 components expect.
  • main_factory – The factory that will be used for the IMainApplicationFolder. If it produces an object that doesn’t implement this interface, it will still be marked as doing so.
  • main_setup (callable) – If given, a callable that will accept the main application folder object and perform further setup on it. This will be called before any lifecycle events are generated. This is a good time to install additional utilities, such as IIntId utilities.

After main_setup has been called, and the lifecycle events for the root folder and main folder have been generated, this calls install_sites_folder().

nti.site.hostpolicy.install_sites_folder(server_folder)[source]

Given a IMainApplicationFolder that has a site manager, install a host sites folder.

The folder will be installed at “++etc++hostsites”, and registered to provide IEtcNamespace with the name “hostsites” so it can be found by traversal.

See also

zope.traversing.namespace.etc.

nti.site.hostpolicy.run_job_in_all_host_sites(func)[source]

While already operating inside of a transaction and the application environment, execute the callable given by func once for each persistent, registered host (see synchronize_host_policies()). The callable is run with that site current.

This is typically used to make configuration changes/adjustments to utilities local within each site, while the appropriate event listeners for the site also fire.

You are responsible for transaction management.

Raises:Whatever the callable raises.
Returns:A list of pairs (site, result) containing each site and the result of running the function in that site.
Return type:list
nti.site.hostpolicy.run_job_in_host_site(site, func)[source]

Helper function to run the func with the given site as the current site.

Parameters:site – Either the site object itself, or its unique name.
nti.site.hostpolicy.synchronize_host_policies()[source]

Called within a transaction with a site being the current application site, find any z3c.baseregistry components that should be persistent sites, and register them in the database.

As a prerequisite, install_sites_folder() must have been done, and we must be in that site.

nti.site.folder module

Implementations of folders for site policies.

class nti.site.folder.HostPolicyFolder[source]

Bases: zope.site.folder.Folder

Simple container implementation for the named host site.

class nti.site.folder.HostPolicySiteManager(site, default_folder=True)[source]

Bases: nti.site.site.BTreeLocalSiteManager

class nti.site.folder.HostSitesFolder[source]

Bases: zope.site.folder.Folder

Simple container implementation for named host sites.

lastSynchronized = 0

nti.site.localutility module

Helpers for working with local utilities.

A local utility is a (persistent) utility registered in a local (persistent) site manager. Local utilities need to be traversable and thus are usually children of the local site manager itself.

nti.site.localutility.install_utility(utility, utility_name, provided, local_site_manager)[source]

Call this to install a local utility. Often you will do this from inside a handler for the registration of another dependent utility (IRegistration).

The utility should be IContained because it will be held inside the site manager.

Parameters:utility_name (str) – The traversal name of the utility, not the component registration name. This currently only handles the default, unnamed registration.
nti.site.localutility.install_utility_on_registration(utility, utility_name, provided, event)[source]

Call this to install a local utility in response to the registration of another object.

The utility should be IContained because it will be held inside the site manager.

Parameters:event – The IRegistered event
nti.site.localutility.queryNextUtility(context, interface, default=None)[source]

Our persistent sites are a mix of persistent and non-persistent bases, with many of them having multiple bases. For example (using the notation: name (bases,) [type]):

example.com (GlobalSiteManager) [global]
Application (GlobalSiteManager) [persistent]
site-root.example.com (Application, example.com) [persistent]
child.example.com (example.com) [global]
site-child.example.com (child.example.com, site-root.example.com) [persistent]

This gives site-child.example.com this (correct) resolution order:

site-child.example.com, child.example.com, site-root.example,com Application, example.com, GSM

However, zope.component.queryNextUtility() only looks in the first base to find a next utility. Therefore, when site-janux.ou.edu asks for a next utility, instead of getting something persistent from site-platform.ou.edu, it instead gets the global non-persistent version from platform.ou.edu.

We don’t generally want to change the resolution order, but we do need to tweak it here for getting next utilities so that we consider persistent things first. Note that this breaks down if we have utilities registered both persistently and non-persistently at the same level.

nti.site.localutility.uninstall_utility_on_unregistration(utility_name, provided, event)[source]

When a dependent object is unregistered, this undoes the work done by install_utility().

Parameters:utility_name (str) – The traversal name of the utility, not the component registration name. This currently only handles the default, unnamed registration.

nti.site.runner module

Helpers for running jobs in specific sites.

nti.site.runner.get_possible_site_names(*args, **kwargs)[source]

Helper to find the most applicable site names.

This uses the ITransactionSiteNames utility.

nti.site.runner.run_job_in_site(func, retries=0, sleep=None, site_names=<object object>, job_name=None, side_effect_free=False, root_folder_name=u'nti.dataserver')[source]

Runs the function given in func in a transaction and application local site manager (defaulting to the current site manager).

Parameters:
  • func (function) – A function of zero parameters to run. If it has a docstring, that will be used as the transactions note. A transaction will be begun before this function executes, and committed after the function completes. This function may be rerun if retries are requested, so it should be prepared for that.
  • retries (int) – The number of times to retry the transaction and execution of func if transaction.interfaces.TransientError is raised when committing. Defaults to zero (so the job runs once). If you specify None, an implementation-specific number of retries will be used.
  • sleep (float) – If not none, then the greenlet running this function will sleep for this long between retry attempts.
  • site_names – DEPRECATED. Sequence of strings giving the virtual host names to use. If you do not provide this argument, then the currently installed site will be maintained when the transaction is run. NOTE: The implementation of this may maintain either the site names or the actual site object.
  • side_effect_free (bool) – If true (not the default), then the function is assummed to have no side effects that need to be committed; the transaction runner is free to abort/rollback or commit the transaction at its leisure.
  • root_folder_name (str) – This names the folder that can be found in the root of the ZODB that will serve as the starting point to look for the persistent named site.
Returns:

The value returned by the first successful invocation of func.

nti.site.site module

Implementations of sites and helpers for working with sites.

class nti.site.site.BTreeLocalAdapterRegistry(bases=())[source]

Bases: zope.site.site._LocalAdapterRegistry

A persistent adapter registry that can switch its internal data structures to be more persistent friendly when they get large.

Caution

This registry doesn’t support registrations on bare classes. This is because the Implements and Provides objects returned on bare classes do not support comparison or equality and hence cannot be used in BTrees. (They only hash and compare equal to themselves; within the same process this works out because of aggressive caching on class objects.) Registering a utility to provide a bare class is quite hard to do, in any case. Registering adapters to require bare classes is easier but generally not a best practice.

Changed in version 3.0.0: No longer converts any data structures as part of mutating this object. Instead, uses the support from zope.interface 5.3 and zope.component 5.0 to specify the data types to use as they are created on demand.

Existing persistent registries must have the rebuild() method called on them as part of a migration. The best way to do that would be through the rebuild() method on their containing BTreeLocalSiteManager.

btree_family = <BTree family using 64 bits. Supports signed integer values from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 and maximum unsigned integer value 18,446,744,073,709,551,615.>

The family for the provided map. Defaults to 64-bit maps. I.e., long.

class nti.site.site.BTreeLocalSiteManager(site, default_folder=True)[source]

Bases: nti.site.site.BTreePersistentComponents, zope.site.site.LocalSiteManager

Persistent local site manager that will be friendly to ZODB when they get large.

Caution

This registry doesn’t support bare class registrations. See BTreeLocalAdapterRegistry for details.

Changed in version 3.0.0: No longer attempts to change the class of the adapters and utilities objects when reading old pickles.

Instead, you must call this object’s rebuild() method as part of a migration. This method will call rebuild() on the adapters and utilities objects, and also reset the __bases__ of this object (to its current bases). The order (leaves first or roots first) shouldn’t matter, as long as all registries in an inheritance hierarchy are committed in a single transaction.

If we detect old versions of the class that haven’t been migrated, we log an error.

rebuild()[source]
class nti.site.site.BTreePersistentComponents(name='', bases=())[source]

Bases: zope.component.persistentregistry.PersistentComponents

Persistent components that will be friendly to ZODB when they get large.

Note that despite the name, this class is not Persistent, only its internal components are.

Caution

This registry doesn’t support bare class registrations. See BTreeLocalAdapterRegistry for details.

btree_family = <BTree family using 64 bits. Supports signed integer values from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 and maximum unsigned integer value 18,446,744,073,709,551,615.>
btree_threshold = 30

The size at which we will switch from maps to BTrees for registered adapters and registered utilities (individually). This defaults to the maximum size of a BTree bucket before it splits. Thus, when we do this, we will wind up with at least two persistent objects.

registerAdapter(*args, **kwargs)[source]
registerUtility(*args, **kwargs)[source]
class nti.site.site.SiteMapping(**kw)[source]

Bases: nti.schema.schema.SchemaConfigured

Maps one site to another.

:raises a SiteNotFoundError object if no site found

get_target_site()[source]

Returns the target site as defined by this mapping.

source_site_name

Computed attributes based on schema fields

Field properties provide default values, data validation and error messages based on data found in field meta-data.

Note that FieldProperties cannot be used with slots. They can only be used for attributes stored in instance dictionaries.

target_site_name

Computed attributes based on schema fields

Field properties provide default values, data validation and error messages based on data found in field meta-data.

Note that FieldProperties cannot be used with slots. They can only be used for attributes stored in instance dictionaries.

exception nti.site.site.WrongRegistrationTypeError[source]

Bases: exceptions.TypeError

Raised if an adapter registration is of the wrong type.

Changed in version 1.0.1: This is no longer raised by this package.

nti.site.site.find_site_components(site_names, check_alternate=False)[source]

Return an (global, registered) IComponents implementation named for the first virtual site found in the sequence of site_names. If no such components can be found, returns none.

nti.site.site.get_alternate_site_name(site_name)[source]

Check for a configured ISiteMapping

nti.site.site.get_component_hierarchy(site=None)[source]
nti.site.site.get_component_hierarchy_names(site=None, reverse=False)[source]
nti.site.site.get_site_for_site_names(site_names, site=None)[source]

Return an ISite implementation named for the first virtual site found in the sequence of site_names.

First, we’ll attempt to find the registered persistent site; either given by the site name or redirected by a registered ISiteMapping pointing to a persistent site. Otherwise, we’ll look for a site without the ISiteMapping lookup.

We’ll then look a registered persistent site having the same name as the registered global components found for site_names, then that site will be used. Otherwise, if there is only a registered global components, a non-persistent site that incorporates those components in the lookup order while still incorporating the current (or provided) site will be returned.

If no such site or components can be found, returns the fallback site (the current or provided site).

Parameters:
  • site_names – Sequence of strings giving the virtual host names to use.
  • site – If given, this will be the fallback site (and site manager). If not given, then the currently installed site will be used.

Changed in version 1.2.0: Look for a ISiteMapping registration to map a non-persistent site to a persistent site.

Changed in version 1.3.0: Prioritize ISiteMapping so that persistent sites can be mapped to other persistent sites.

nti.site.subscribers module

Subscribers for traversal events to ensure that the the proper site is installed, including respecting global registered components.

Caution

zope.site.site.threadSiteSubscriber() also exists and is configured by some packages like zope.app.publication. Care must be used to ensure that it is not configured in place of our own threadSiteSubscriber().

nti.site.subscribers.new_local_site_dispatcher(event)[source]

Dispatches just like an object event, that way we can do things based on the type of the site manager.

Note that if the containing ISite is (re)moved, an ObjectEvent will be fired for (sitemanager, site-event); that is, you subscribe to the site manager and the object moved event, but the event will have the ISite as the object property.

nti.site.subscribers.threadSiteSubscriber(new_site, _event)[source]

Set the current zope.component.hooks site to the new_site object found during traversal, being careful to maintain any previously installed host (site-name) configurations as lower priority than the new site.

Sites encountered during traversal are expected to have the main application site (e.g., nti.dataserver) in their base chain so we have access to its configuration and persistent utilities. This implies that sites encountered during traversal are either synthetic (generated by a traversal adapter to use some particular IComponents) or themselves persistent.

Because of this, when we encounter the root or dataserver folders as sites, we take no action (unless there is no site presently installed; in that case we install them).

We expect that something else takes care of clearing the site.

Important

Clearing the site is important, especially if the site was persistent. You can use a subscriber to “end request” style events or otherwise make it part of request lifecycle. When that’s not possible, please do so manually.

Changed in version 2.3.0: Always install the new_site if there is no current site. Previously, if new_site provided IMainApplicationFolder or zope.site.interfaces.IRootFolder, it was always ignored.

No longer raises a LocationError if an unknown type of site is encountered. Instead, simply installs it, replacing the current site.

nti.site.transient module

Transient, in-memory, non-persistent site and site manager implementations. These are used to get non-persistent host-based global IComponents into the base resolution order.

class nti.site.transient.BasedSiteManager(site, name, bases)[source]

Bases: zope.site.site.LocalSiteManager

A site manager that exists simply to have bases, but not to record itself as children of those bases (since that’s unnecessary for our purposes and leads to ZODB conflicts).

class nti.site.transient.HostSiteManager(site, name, host_components, persistent_components)[source]

Bases: nti.site.transient.BasedSiteManager

A site manager that is intended to be used with globally registered IComponents plus the application persistent components.

host_components
persistent_components
class nti.site.transient.TrivialSite(site_manager)[source]

Bases: zope.container.contained.Contained

Trivial non-persistent implementation of ISite

getSiteManager()[source]

nti.site.utils module

This module currently has no non-deprecated functions.

nti.site.utils.registerUtility(registry, *args, **kwargs)[source]
nti.site.utils.unregisterUtility(registry, *args, **kwargs)[source]

nti.site.testing module

Support for testing code that uses nti.site.

Most of the functionality exposed through this module uses ZODB to test persistence and transaction handling and is based on the support code from nti.testing.zodb.

New in version 2.1.0.

nti.site.testing.setHooks()[source]

Make zope.component.getSiteManager and interface adaptation respect the current site.

Most applications will want to be sure te call this early in their startup sequence. Test code that uses these APIs should also arrange to call this.

nti.site.testing.resetHooks()[source]

Reset zope.component.getSiteManager and interface adaptation to their original implementations that are unaware of the current site.

Use caution when calling this; most code will not need to call this. If code using the global API executes following this, it will most likely use the base global component registry instead of a site-specific registry it was expected. This can lead to failures in adaptation and utility lookup.

nti.site.testing.print_tree(folder, file=sys.stdout, show_unknown=repr, basic_indent=' ', details=('id', 'type', 'len', 'siteManager')) → None[source]

Print a descriptive tree of the contents of the dict-like folder to file.

Pass a subset of details to disable printing certain information when it isn’t relavent.

Changed in version 2.2.0: Add several arguments including show_unknown, details. Print the contents of site managers by default. Fix a bug not passing the basic_indent to recursive calls.

class nti.site.testing.persistent_site_trans(db=None, site_name=None)[source]

Bases: nti.testing.zodb.mock_db_trans

Context manager for a ZODB database connection and active zope.component site (usually) persisted in the database.

Changed in version 2.1.0: While there was no previous public version of this class, there was a private version in nti.site.tests. That version called install_main_application_and_sites() setting the root_alias to the main_application_folder_name. Since older versions of that function installed the root_alias to point to the main_name, this used result in no alias for the root folder in the root. Now, there will be an alias (at DEFAULT_ROOT_ALIAS).

Parameters:
main_application_folder_name = <u'nti.dataserver' is the default alias of main application folder>

The site to make active by default and when looking up a site_name. This must identify an object in the root of the database that provides IMainApplicationFolder.

on_application_and_sites_installed(folder)[source]

Called when the main application and sites have been installed. This may not be called every time an instance of this class is used, as the database may be persistent.

on_connection_opened(conn)[source]

Called when the connection to the DB has been opened.

Subclasses may override to perform initialization. The DB may have been used before, so check its state and don’t assume a complete initialization must happen.

on_main_application_folder_missing(conn)[source]

Called from on_connection_opened() when the main_application_folder_name is not found in the root of the conn.

This method calls install_main_application_and_sites(), passing main_application_folder_name as the main_alias.

class nti.site.testing.SharedConfiguringTestLayer[source]

Bases: nti.testing.zodb.ZODBLayer, nti.testing.layers.GCLayerMixin, nti.testing.layers.ConfiguringLayerMixin

A test layer that configures this package, and sets other useful test settings.

Note that the details of the test settings may change. In this version, this configures the BTreeLocalAdapterRegistry to immediately switch to BTrees instead of dicts.

current_test = None

The test (a unittest.TestCase subclass) currently executing in this layer. If there is no such test, this is None.

classmethod testSetUp(test=None)[source]

Tests that run in this layer have their db property set to the current db of this layer.

classmethod testTearDown()[source]

When a test in this layer is torn down, its db property is set to None, as is this layer’s current_test.

class nti.site.testing.SiteTestCase(methodName='runTest')[source]

Bases: unittest.case.TestCase

A test case that runs in the SharedConfiguringTestLayer.

Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.

layer

alias of SharedConfiguringTestLayer

nti.site.testing.uses_independent_db_site(db_factory=None, installer_factory=persistent_site_trans, installer_kwargs={}) → function[source]

A decorator or decorator factory. Creates a new database using db_factory, initializes it using installer_factory, and then runs the body of the function in a site and site manager that are disconnected from the database.

If the function is a unittest method, the unittest object’s db attribute will be set to the created db during executing. Likewise, the nti.testing.zodb.ZODBLayer db attribute (and layers that extend from it like SharedConfiguringTestLayer) will be set to this object and returned to the previous value on exit.

This can be called as given in the signature, or can be called with no arguments:

class MyTest(TestCase):

    @uses_independent_db_site
    def test_something(self):
        pass

    @uses_independent_db_site(installer_factory=MyCustomFactory)
    def test_something_else(self):
        pass

The body of the function is free to use persistent_site_trans statements. They will default to using the database established here instead of a database established by a test layer (which should be the same in most cases).

Parameters:
  • db_factory (callable) – The 0-argument factory used to create a DB to pass to the installer.
  • installer_factory (type) – The factory used to create the installer. The installer executes before the body of the wrapped function. This defaults to persistent_site_trans, but can be set to any custom subclass that accepts the db as its first argument and is a context manager that does whatever installation is needed and commits the transaction.
  • installer_kwargs (dict) – Keyword arguments to pass to the installer_factory

Changes

3.0.1 (unreleased)

  • Nothing changed yet.

3.0.0 (2021-03-23)

  • Update to zope.interface 5.3. and zope.component 5.0. This lets the BTreeAdapterRegistry and BTreeLocalSiteManager work much more smoothly and scale better.

    Important

    The automatic conversion from dicts to BTrees has been removed. You must explicitly migrate by calling BTreeLocalSiteManager.rebuild().

2.4.2 (2021-03-01)

  • Fix BTreePersistentComponents attempting BTree conversion during _p_activate(). Only actual mutations via registering or unregistering utilities, adapters or subscribers should trigger conversion. See issue #38.

2.4.1 (2021-03-01)

  • Fix a TypeError in logging during the conversion performed by BTreePersistentComponents.

2.4.0 (2021-02-25)

  • Substantially reduce the thresholds at which the BTreePersistentComponents will convert internal data structures from plain dict objects into BTree objects. This is intended to reduce the pickle size of, and number of ghost objects created by, components containing many utilities. Previously, the thresholds were set very high and mostly worked for sites with many adapters.
  • Add support for Python 3.9.
  • Move to Github Actions from Travis CI.

2.3.0 (2020-09-11)

  • Make threadSiteSubscriber (the traversal subscriber for ISite objects) will install a traversed site that is a root if there is no current site.

    Previously, it never installed root sites.

  • Make threadSiteSubscriber install sites when their configuration is not recognized.

    Previously, it would raise LocationError.

  • Fix tests with, and require, zope.site 4.4.0 or above. See issue #34.

  • Fix deprecation warning from nti.transactions. Requires nti.transactions 4.0. See issue #33.

2.2.0 (2020-07-30)

  • Improvements and bug fixes to nti.testing.print_tree.

2.1.0 (2020-06-17)

  • Test changes: Depend on nti.testing 3.0 and refactor certain internal test methods for improved isolation. The dependency on ZODB is now >= 5.6.0.

    Some internal, undocumented test attributes (current_mock_db, a ZODB.DB, and current_transaction which was actually a ZODB Connection) have been removed. The former is replaced with nti.testing.zodb.ZODBLayer.db, and there is no replacement for the later.

  • Add the module nti.site.testing. This contains extensible, documnted versions of the functions that were previously in nti.site.tests as private helpers.

  • Add support for Python 3.8.

  • Make hostpolicy.install_main_application_and_sites() set the root_alias correctly. Previously, instead of setting it to the root_name, it set it to the main_name.

2.0.0 (2019-09-10)

  • Update run_job_in_site to work with nti.transactions 3.0 and enable the optimizations of an explicit transaction manager.
  • Test support for Python 3.7.
  • Stop claiming support for Python 3.4 or 3.5; those aren’t tested.
  • Test support for PyPy3.

1.4.0 (2019-05-06)

  • Add subscriber to unregister IBaseComponents on host policy folder removal.

1.3.0 (2017-11-16)

  • Allow ISiteMapping to map between persistent sites.

1.2.0 (2017-09-18)

  • Add the ability to map one (non-persistent) site to another via configuration. If get_site_for_site_names does not find persistent site components for a site, it will fall back to looking for a configured ISiteMapping pointing to another target site.

1.1.0 (2017-06-14)

  • Require zope.interface 4.4.2 or greater; 4.4.1 has regressions.
  • Require transaction >= 2.1.2 for its more relaxed handling of text or byte meta data.
  • Require BTrees >= 4.3.2 for its relaxed handling of objects with default comparison.

1.0.3 (2016-11-21)

1.0.2 (2016-11-21)

  • Support for transaction 2.0, and fix a lurking UnicodeError under Python 3. See issue #14.

1.0.1 (2016-09-08)

  • If you are using zope.interface 4.3.0 or greater, you can register utilities and adapters using implementedBy (so bare classes) in a BTreeLocalSiteManager. Otherwise, using an older version, you’ll get a TypeError and may be unable to complete the registration or transition to BTrees, and the map data may be inconsistent.

1.0.0 (2016-08-02)

  • First PyPI release.
  • Add support for Python 3.
  • Remove HostPolicySiteManager.subscribedRegisterUtility and subscribeUnregisterUtility. See issue #5. This may be a small performance regression in large sites. If so we’ll find a different way to deal with it.
  • Remove HostSitesFolder._delitemf. It was unused and buggy.
  • Add BTreesLocalSiteManager to automatically switch internal registration data to BTrees when possible and necessary. See issue #4.
  • Add nti.site.hostpolicy.install_main_application_and_sites() for setting up a database. See issue #9.

Addons and additions to the Zope site concept.

Integration between the ZCA site system, configured site policies, and the persistent database.

In the Zope world, sites are objects that can express configuration by holding onto an instance of IComponents known as its site manager. Typically they are arranged in a tree, with the global site at the root of the tree. Site managers inherit configuration from their parents (bases, which may or may not be their __parent__). Often, they are persistent and part of the traversal tree. One site is the current site and the ZCA functions (e.g., IComponentArchitecture.queryUtility()) apply to that site.

Our application has one main persistent site, the application site, containing persistent utilities (such as the application object). This site, or a descendent of it, must always be the current site when executing application code.

In our application, we also have the concept of site policies, something that is applied based on virtual hosting. A site policy is also an IComponents, registered in the global site as a utility named for the hostname to which it should apply (e.g., domain.example.com). Historically, these are not necessarily persistent and part of the traversal tree. Now, we expect them to be persistent, though they are still not part of the traversal tree.

Thus there are two things to accomplish: make the application site the current site, and also construct a site that descends from that site and contains any applicable policies that are globally configured.

Indices and tables