zope.site-3.9.2/000755 000766 000024 00000000000 11447354567 013371 5ustar00macstaff000000 000000 zope.site-3.9.2/CHANGES.txt000644 000766 000024 00000006533 11447354561 015203 0ustar00macstaff000000 000000 ======= CHANGES ======= 3.9.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.testing`. 3.9.1 (2010-04-30) ------------------ - Removed use of 'zope.testing.doctest' in favor of stdlib's 'doctest. - Removed use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.9.0 (2009-12-29) ------------------ - Avoid a test dependency on zope.copypastemove by testing the correct persistent behavior of a site manager using the normal pickle module. 3.8.0 (2009-12-15) ------------------ - Removed functional testing setup and dependency on zope.app.testing. 3.7.1 (2009-11-18) ------------------ - Moved the zope.site.hooks functionality to zope.component.hooks as it isn't actually dealing with zope.site's concept of a site. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.7.0 (2009-09-29) ------------------ - Cleaned up the undeclared dependency on zope.app.publication by moving the two relevant subscriber registrations and their tests to that package. - Dropped the dependency on zope.traversing which was only used to access zope.location functionality. Configure zope.location for some tests. - Demoted zope.configuration to a testing dependency. 3.6.4 (2009-09-01) ------------------ - Set __parent__ and __name__ in the LocalSiteManager's constructor after calling constructor of its superclasses, so __name__ doesn't get overwritten with empty string by the Components constructor. - Don't set __parent__ and __name__ attributes of site manager in SiteManagerContainer's ``setSiteManager`` method, as they're already set for LocalSiteManager. Other site manager implementations are not required to have those attributes at all, so we're not adding them anymore. 3.6.3 (2009-07-27) ------------------ - Propagate an ObjectRemovedEvent to the SiteManager upon removal of a SiteManagerContainer. 3.6.2 (2009-07-24) ------------------ - Fixed tests to pass with latest packages. - Removed failing test of persistent interfaces, since it did not test anything in this package and used the deprecated ``zodbcode`` module. - Fix NameError when calling ``zope.site.testing.siteSetUp(site=True)``. - The ``getNextUtility`` and ``queryNextUtility`` functions was moved to ``zope.component``. While backward-compatibility imports are provided, it's strongly recommended to update your imports. 3.6.1 (2009-02-28) ------------------ - Import symbols moved from zope.traversing to zope.location from the new location. - Don't fail when changing component registry bases while moving ISite object to non-ISite object. - Allow specify whether to create 'default' SiteManagementFolder on initializing LocalSiteManager. Use the ``default_folder`` argument. - Add a containment constraint to the SiteManagementFolder that makes it only available to be contained in ILocalSiteManagers and other ISiteManagementFolders. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old unused code. Update package description. 3.6.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. 3.5.1 (2009-01-27) ------------------ - Extracted from zope.app.component (trunk, 3.5.1 under development) as part of an effort to clean up dependencies between Zope packages. zope.site-3.9.2/COPYRIGHT.txt000644 000766 000024 00000000040 11447354561 015466 0ustar00macstaff000000 000000 Zope Foundation and Contributorszope.site-3.9.2/LICENSE.txt000644 000766 000024 00000004026 11447354561 015210 0ustar00macstaff000000 000000 Zope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zope.site-3.9.2/PKG-INFO000644 000766 000024 00000044034 11447354567 014473 0ustar00macstaff000000 000000 Metadata-Version: 1.0 Name: zope.site Version: 3.9.2 Summary: Local registries for zope component architecture Home-page: http://pypi.python.org/pypi/zope.site Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ===================================== Zope 3's Local Component Architecture ===================================== This package provides a local and persistent site manager implementation, so that one can register local utilities and adapters. It uses local adapter registries for its adapter and utility registry. The module also provides some facilities to organize the local software and ensures the correct behavior inside the ZODB. .. contents:: ============================= Sites and Local Site Managers ============================= This is an introduction of location-based component architecture. Creating and Accessing Sites ---------------------------- *Sites* are used to provide custom component setups for parts of your application or web site. Every folder: >>> from zope.site import folder >>> myfolder = folder.rootFolder() has the potential to become a site: >>> from zope.component.interfaces import ISite, IPossibleSite >>> IPossibleSite.providedBy(myfolder) True but is not yet one: >>> ISite.providedBy(myfolder) False If you would like your custom content component to be able to become a site, you can use the `SiteManagerContainer` mix-in class: >>> from zope import site >>> class MyContentComponent(site.SiteManagerContainer): ... pass >>> myContent = MyContentComponent() >>> IPossibleSite.providedBy(myContent) True >>> ISite.providedBy(myContent) False To convert a possible site to a real site, we have to provide a site manager: >>> sm = site.LocalSiteManager(myfolder) >>> myfolder.setSiteManager(sm) >>> ISite.providedBy(myfolder) True >>> myfolder.getSiteManager() is sm True Note that an event is generated when a local site manager is created: >>> from zope.component.eventtesting import getEvents >>> from zope.site.interfaces import INewLocalSite >>> [event] = getEvents(INewLocalSite) >>> event.manager is sm True If one tries to set a bogus site manager, a `ValueError` will be raised: >>> myfolder2 = folder.Folder() >>> myfolder2.setSiteManager(object) Traceback (most recent call last): ... ValueError: setSiteManager requires an IComponentLookup If the possible site has been changed to a site already, a `TypeError` is raised when one attempts to add a new site manager: >>> myfolder.setSiteManager(site.LocalSiteManager(myfolder)) Traceback (most recent call last): ... TypeError: Already a site There is also an adapter you can use to get the next site manager from any location: >>> myfolder['mysubfolder'] = folder.Folder() >>> import zope.component >>> zope.component.interfaces.IComponentLookup(myfolder['mysubfolder']) is sm True If the location passed is a site, the site manager of that site is returned: >>> zope.component.interfaces.IComponentLookup(myfolder) is sm True Using the Site Manager ---------------------- A site manager contains several *site management folders*, which are used to logically organize the software. When a site manager is initialized, a default site management folder is created: >>> sm = myfolder.getSiteManager() >>> default = sm['default'] >>> default.__class__ However, you can tell not to create the default site manager folder on LocalSiteManager creation: >>> nodefault = site.LocalSiteManager(myfolder, default_folder=False) >>> 'default' in nodefault False Also, note that when creating LocalSiteManager, its __parent__ is set to site that was passed to constructor and the __name__ is set to ++etc++site. >>> nodefault.__parent__ is myfolder True >>> nodefault.__name__ == '++etc++site' True You can easily create a new site management folder: >>> sm['mySMF'] = site.SiteManagementFolder() >>> sm['mySMF'].__class__ Once you have your site management folder -- let's use the default one -- we can register some components. Let's start with a utility: >>> import zope.interface >>> class IMyUtility(zope.interface.Interface): ... pass >>> import persistent >>> from zope.container.contained import Contained >>> class MyUtility(persistent.Persistent, Contained): ... zope.interface.implements(IMyUtility) ... def __init__(self, title): ... self.title = title ... def __repr__(self): ... return "%s('%s')" %(self.__class__.__name__, self.title) Now we can create an instance of our utility and put it in the site management folder and register it: >>> myutil = MyUtility('My custom utility') >>> default['myutil'] = myutil >>> sm.registerUtility(myutil, IMyUtility, 'u1') Now we can ask the site manager for the utility: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') Of course, the local site manager has also access to the global component registrations: >>> gutil = MyUtility('Global Utility') >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.registerUtility(gutil, IMyUtility, 'gutil') >>> sm.queryUtility(IMyUtility, 'gutil') MyUtility('Global Utility') Next let's see whether we can also successfully register an adapter as well. Here the adapter will provide the size of a file: >>> class IFile(zope.interface.Interface): ... pass >>> class ISized(zope.interface.Interface): ... pass >>> class File(object): ... zope.interface.implements(IFile) >>> class FileSize(object): ... zope.interface.implements(ISized) ... def __init__(self, context): ... self.context = context Now that we have the adapter we need to register it: >>> sm.registerAdapter(FileSize, [IFile]) Finally, we can get the adapter for a file: >>> file = File() >>> size = sm.queryAdapter(file, ISized, name='') >>> size.__class__ >>> size.context is file True By the way, once you set a site >>> from zope.component import hooks >>> hooks.setSite(myfolder) you can simply use the zope.component's `getSiteManager()` method to get the nearest site manager: >>> from zope.component import getSiteManager >>> getSiteManager() is sm True This also means that you can simply use zope.component to look up your utility >>> from zope.component import getUtility >>> getUtility(IMyUtility, 'gutil') MyUtility('Global Utility') or the adapter via the interface's `__call__` method: >>> size = ISized(file) >>> size.__class__ >>> size.context is file True Multiple Sites -------------- Until now we have only dealt with one local and the global site. But things really become interesting, once we have multiple sites. We can override other local configuration. This behaviour uses the notion of location, therefore we need to configure the zope.location package first: >>> import zope.configuration.xmlconfig >>> _ = zope.configuration.xmlconfig.string(""" ... ... ... ... ... """) Let's now create a new folder called `folder11`, add it to `myfolder` and make it a site: >>> myfolder11 = folder.Folder() >>> myfolder['myfolder11'] = myfolder11 >>> myfolder11.setSiteManager(site.LocalSiteManager(myfolder11)) >>> sm11 = myfolder11.getSiteManager() If we ask the second site manager for its next, we get >>> sm11.__bases__ == (sm, ) True and the first site manager should have the folling sub manager: >>> sm.subs == (sm11,) True If we now register a second utility with the same name and interface with the new site manager folder, >>> default11 = sm11['default'] >>> myutil11 = MyUtility('Utility, uno & uno') >>> default11['myutil'] = myutil11 >>> sm11.registerUtility(myutil11, IMyUtility, 'u1') then it will will be available in the second site manager >>> sm11.queryUtility(IMyUtility, 'u1') MyUtility('Utility, uno & uno') but not in the first one: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') It is also interesting to look at the use cases of moving and copying a site. To do that we create a second root folder and make it a site, so that site hierarchy is as follows: :: _____ global site _____ / \ myfolder1 myfolder2 | myfolder11 >>> myfolder2 = folder.rootFolder() >>> myfolder2.setSiteManager(site.LocalSiteManager(myfolder2)) Before we can move or copy sites, we need to register two event subscribers that manage the wiring of site managers after moving or copying: >>> from zope import container >>> gsm.registerHandler( ... site.changeSiteConfigurationAfterMove, ... (ISite, container.interfaces.IObjectMovedEvent), ... ) We only have to register one event listener, since the copy action causes an `IObjectAddedEvent` to be created, which is just a special type of `IObjectMovedEvent`. First, make sure that everything is setup correctly in the first place: >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs () Let's now move `myfolder11` from `myfolder` to `myfolder2`: >>> myfolder2['myfolder21'] = myfolder11 >>> del myfolder['myfolder11'] Now the next site manager for `myfolder11`'s site manager should have changed: >>> myfolder21 = myfolder11 >>> myfolder21.getSiteManager().__bases__ == (myfolder2.getSiteManager(), ) True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True >>> myfolder.getSiteManager().subs () Make sure that our interfaces and classes are picklable: >>> import sys >>> sys.modules['zope.site.tests'].IMyUtility = IMyUtility >>> IMyUtility.__module__ = 'zope.site.tests' >>> sys.modules['zope.site.tests'].MyUtility = MyUtility >>> MyUtility.__module__ = 'zope.site.tests' >>> from pickle import dumps, loads >>> data = dumps(myfolder2['myfolder21']) >>> myfolder['myfolder11'] = loads(data) >>> myfolder11 = myfolder['myfolder11'] >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True Finally, let's check that everything works fine when our folder is moved to the folder that doesn't contain any site manager. Our folder's sitemanager's bases should be set to global site manager. >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> nosm = folder.Folder() >>> nosm['root'] = myfolder11 >>> myfolder11.getSiteManager().__bases__ == (gsm, ) True ======= CHANGES ======= 3.9.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.testing`. 3.9.1 (2010-04-30) ------------------ - Removed use of 'zope.testing.doctest' in favor of stdlib's 'doctest. - Removed use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.9.0 (2009-12-29) ------------------ - Avoid a test dependency on zope.copypastemove by testing the correct persistent behavior of a site manager using the normal pickle module. 3.8.0 (2009-12-15) ------------------ - Removed functional testing setup and dependency on zope.app.testing. 3.7.1 (2009-11-18) ------------------ - Moved the zope.site.hooks functionality to zope.component.hooks as it isn't actually dealing with zope.site's concept of a site. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.7.0 (2009-09-29) ------------------ - Cleaned up the undeclared dependency on zope.app.publication by moving the two relevant subscriber registrations and their tests to that package. - Dropped the dependency on zope.traversing which was only used to access zope.location functionality. Configure zope.location for some tests. - Demoted zope.configuration to a testing dependency. 3.6.4 (2009-09-01) ------------------ - Set __parent__ and __name__ in the LocalSiteManager's constructor after calling constructor of its superclasses, so __name__ doesn't get overwritten with empty string by the Components constructor. - Don't set __parent__ and __name__ attributes of site manager in SiteManagerContainer's ``setSiteManager`` method, as they're already set for LocalSiteManager. Other site manager implementations are not required to have those attributes at all, so we're not adding them anymore. 3.6.3 (2009-07-27) ------------------ - Propagate an ObjectRemovedEvent to the SiteManager upon removal of a SiteManagerContainer. 3.6.2 (2009-07-24) ------------------ - Fixed tests to pass with latest packages. - Removed failing test of persistent interfaces, since it did not test anything in this package and used the deprecated ``zodbcode`` module. - Fix NameError when calling ``zope.site.testing.siteSetUp(site=True)``. - The ``getNextUtility`` and ``queryNextUtility`` functions was moved to ``zope.component``. While backward-compatibility imports are provided, it's strongly recommended to update your imports. 3.6.1 (2009-02-28) ------------------ - Import symbols moved from zope.traversing to zope.location from the new location. - Don't fail when changing component registry bases while moving ISite object to non-ISite object. - Allow specify whether to create 'default' SiteManagementFolder on initializing LocalSiteManager. Use the ``default_folder`` argument. - Add a containment constraint to the SiteManagementFolder that makes it only available to be contained in ILocalSiteManagers and other ISiteManagementFolders. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old unused code. Update package description. 3.6.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. 3.5.1 (2009-01-27) ------------------ - Extracted from zope.app.component (trunk, 3.5.1 under development) as part of an effort to clean up dependencies between Zope packages. Keywords: zope component architecture local Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.site-3.9.2/README.txt000644 000766 000024 00000000665 11447354561 015070 0ustar00macstaff000000 000000 ===================================== Zope 3's Local Component Architecture ===================================== This package provides a local and persistent site manager implementation, so that one can register local utilities and adapters. It uses local adapter registries for its adapter and utility registry. The module also provides some facilities to organize the local software and ensures the correct behavior inside the ZODB. zope.site-3.9.2/bootstrap.py000644 000766 000024 00000007330 11447354561 015755 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os, shutil, sys, tempfile, urllib2 from optparse import OptionParser tmpeggs = tempfile.mkdtemp() is_jython = sys.platform.startswith('java') # parsing arguments parser = OptionParser() parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="distribute", default=False, help="Use Disribute rather than Setuptools.") parser.add_option("-c", None, action="store", dest="config_file", help=("Specify the path to the buildout configuration " "file to be used.")) options, args = parser.parse_args() # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args += ['-c', options.config_file] if options.version is not None: VERSION = '==%s' % options.version else: VERSION = '' USE_DISTRIBUTE = options.distribute args = args + ['bootstrap'] to_reload = False try: import pkg_resources if not hasattr(pkg_resources, '_distribute'): to_reload = True raise ImportError except ImportError: ez = {} if USE_DISTRIBUTE: exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) else: exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) if to_reload: reload(pkg_resources) else: import pkg_resources if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: def quote (c): return c cmd = 'from setuptools.command.easy_install import main; main()' ws = pkg_resources.working_set if USE_DISTRIBUTE: requirement = 'distribute' else: requirement = 'setuptools' if is_jython: import subprocess assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION], env=dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ).wait() == 0 else: assert os.spawnle( os.P_WAIT, sys.executable, quote (sys.executable), '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION, dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout' + VERSION) import zc.buildout.buildout zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) zope.site-3.9.2/buildout.cfg000644 000766 000024 00000000600 11447354561 015667 0ustar00macstaff000000 000000 [buildout] develop = . parts = test coverage-test coverage-report [test] recipe = zc.recipe.testrunner eggs = zope.site [test] [coverage-test] recipe = zc.recipe.testrunner eggs = zope.site [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') zope.site-3.9.2/setup.cfg000644 000766 000024 00000000073 11447354567 015212 0ustar00macstaff000000 000000 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.site-3.9.2/setup.py000644 000766 000024 00000005261 11447354561 015101 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.site package """ import os from setuptools import setup, find_packages def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() setup(name='zope.site', version='3.9.2', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Local registries for zope component architecture', long_description=( read('README.txt') + '\n\n' + '.. contents::\n\n' + read('src', 'zope', 'site', 'site.txt') + '\n\n' + read('CHANGES.txt') ), keywords = "zope component architecture local", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.site', license='ZPL 2.1', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope'], extras_require=dict( test=[ 'zope.configuration', 'zope.testing', ]), install_requires=[ 'setuptools', 'zope.annotation', 'zope.container', 'zope.security', 'zope.component>=3.8.0', 'zope.event', 'zope.interface', 'zope.lifecycleevent', 'zope.location>=3.7.0', ], include_package_data = True, zip_safe = False, ) zope.site-3.9.2/src/000755 000766 000024 00000000000 11447354567 014160 5ustar00macstaff000000 000000 zope.site-3.9.2/src/zope/000755 000766 000024 00000000000 11447354567 015135 5ustar00macstaff000000 000000 zope.site-3.9.2/src/zope.site.egg-info/000755 000766 000024 00000000000 11447354567 017572 5ustar00macstaff000000 000000 zope.site-3.9.2/src/zope.site.egg-info/PKG-INFO000644 000766 000024 00000044034 11447354565 020672 0ustar00macstaff000000 000000 Metadata-Version: 1.0 Name: zope.site Version: 3.9.2 Summary: Local registries for zope component architecture Home-page: http://pypi.python.org/pypi/zope.site Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ===================================== Zope 3's Local Component Architecture ===================================== This package provides a local and persistent site manager implementation, so that one can register local utilities and adapters. It uses local adapter registries for its adapter and utility registry. The module also provides some facilities to organize the local software and ensures the correct behavior inside the ZODB. .. contents:: ============================= Sites and Local Site Managers ============================= This is an introduction of location-based component architecture. Creating and Accessing Sites ---------------------------- *Sites* are used to provide custom component setups for parts of your application or web site. Every folder: >>> from zope.site import folder >>> myfolder = folder.rootFolder() has the potential to become a site: >>> from zope.component.interfaces import ISite, IPossibleSite >>> IPossibleSite.providedBy(myfolder) True but is not yet one: >>> ISite.providedBy(myfolder) False If you would like your custom content component to be able to become a site, you can use the `SiteManagerContainer` mix-in class: >>> from zope import site >>> class MyContentComponent(site.SiteManagerContainer): ... pass >>> myContent = MyContentComponent() >>> IPossibleSite.providedBy(myContent) True >>> ISite.providedBy(myContent) False To convert a possible site to a real site, we have to provide a site manager: >>> sm = site.LocalSiteManager(myfolder) >>> myfolder.setSiteManager(sm) >>> ISite.providedBy(myfolder) True >>> myfolder.getSiteManager() is sm True Note that an event is generated when a local site manager is created: >>> from zope.component.eventtesting import getEvents >>> from zope.site.interfaces import INewLocalSite >>> [event] = getEvents(INewLocalSite) >>> event.manager is sm True If one tries to set a bogus site manager, a `ValueError` will be raised: >>> myfolder2 = folder.Folder() >>> myfolder2.setSiteManager(object) Traceback (most recent call last): ... ValueError: setSiteManager requires an IComponentLookup If the possible site has been changed to a site already, a `TypeError` is raised when one attempts to add a new site manager: >>> myfolder.setSiteManager(site.LocalSiteManager(myfolder)) Traceback (most recent call last): ... TypeError: Already a site There is also an adapter you can use to get the next site manager from any location: >>> myfolder['mysubfolder'] = folder.Folder() >>> import zope.component >>> zope.component.interfaces.IComponentLookup(myfolder['mysubfolder']) is sm True If the location passed is a site, the site manager of that site is returned: >>> zope.component.interfaces.IComponentLookup(myfolder) is sm True Using the Site Manager ---------------------- A site manager contains several *site management folders*, which are used to logically organize the software. When a site manager is initialized, a default site management folder is created: >>> sm = myfolder.getSiteManager() >>> default = sm['default'] >>> default.__class__ However, you can tell not to create the default site manager folder on LocalSiteManager creation: >>> nodefault = site.LocalSiteManager(myfolder, default_folder=False) >>> 'default' in nodefault False Also, note that when creating LocalSiteManager, its __parent__ is set to site that was passed to constructor and the __name__ is set to ++etc++site. >>> nodefault.__parent__ is myfolder True >>> nodefault.__name__ == '++etc++site' True You can easily create a new site management folder: >>> sm['mySMF'] = site.SiteManagementFolder() >>> sm['mySMF'].__class__ Once you have your site management folder -- let's use the default one -- we can register some components. Let's start with a utility: >>> import zope.interface >>> class IMyUtility(zope.interface.Interface): ... pass >>> import persistent >>> from zope.container.contained import Contained >>> class MyUtility(persistent.Persistent, Contained): ... zope.interface.implements(IMyUtility) ... def __init__(self, title): ... self.title = title ... def __repr__(self): ... return "%s('%s')" %(self.__class__.__name__, self.title) Now we can create an instance of our utility and put it in the site management folder and register it: >>> myutil = MyUtility('My custom utility') >>> default['myutil'] = myutil >>> sm.registerUtility(myutil, IMyUtility, 'u1') Now we can ask the site manager for the utility: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') Of course, the local site manager has also access to the global component registrations: >>> gutil = MyUtility('Global Utility') >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.registerUtility(gutil, IMyUtility, 'gutil') >>> sm.queryUtility(IMyUtility, 'gutil') MyUtility('Global Utility') Next let's see whether we can also successfully register an adapter as well. Here the adapter will provide the size of a file: >>> class IFile(zope.interface.Interface): ... pass >>> class ISized(zope.interface.Interface): ... pass >>> class File(object): ... zope.interface.implements(IFile) >>> class FileSize(object): ... zope.interface.implements(ISized) ... def __init__(self, context): ... self.context = context Now that we have the adapter we need to register it: >>> sm.registerAdapter(FileSize, [IFile]) Finally, we can get the adapter for a file: >>> file = File() >>> size = sm.queryAdapter(file, ISized, name='') >>> size.__class__ >>> size.context is file True By the way, once you set a site >>> from zope.component import hooks >>> hooks.setSite(myfolder) you can simply use the zope.component's `getSiteManager()` method to get the nearest site manager: >>> from zope.component import getSiteManager >>> getSiteManager() is sm True This also means that you can simply use zope.component to look up your utility >>> from zope.component import getUtility >>> getUtility(IMyUtility, 'gutil') MyUtility('Global Utility') or the adapter via the interface's `__call__` method: >>> size = ISized(file) >>> size.__class__ >>> size.context is file True Multiple Sites -------------- Until now we have only dealt with one local and the global site. But things really become interesting, once we have multiple sites. We can override other local configuration. This behaviour uses the notion of location, therefore we need to configure the zope.location package first: >>> import zope.configuration.xmlconfig >>> _ = zope.configuration.xmlconfig.string(""" ... ... ... ... ... """) Let's now create a new folder called `folder11`, add it to `myfolder` and make it a site: >>> myfolder11 = folder.Folder() >>> myfolder['myfolder11'] = myfolder11 >>> myfolder11.setSiteManager(site.LocalSiteManager(myfolder11)) >>> sm11 = myfolder11.getSiteManager() If we ask the second site manager for its next, we get >>> sm11.__bases__ == (sm, ) True and the first site manager should have the folling sub manager: >>> sm.subs == (sm11,) True If we now register a second utility with the same name and interface with the new site manager folder, >>> default11 = sm11['default'] >>> myutil11 = MyUtility('Utility, uno & uno') >>> default11['myutil'] = myutil11 >>> sm11.registerUtility(myutil11, IMyUtility, 'u1') then it will will be available in the second site manager >>> sm11.queryUtility(IMyUtility, 'u1') MyUtility('Utility, uno & uno') but not in the first one: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') It is also interesting to look at the use cases of moving and copying a site. To do that we create a second root folder and make it a site, so that site hierarchy is as follows: :: _____ global site _____ / \ myfolder1 myfolder2 | myfolder11 >>> myfolder2 = folder.rootFolder() >>> myfolder2.setSiteManager(site.LocalSiteManager(myfolder2)) Before we can move or copy sites, we need to register two event subscribers that manage the wiring of site managers after moving or copying: >>> from zope import container >>> gsm.registerHandler( ... site.changeSiteConfigurationAfterMove, ... (ISite, container.interfaces.IObjectMovedEvent), ... ) We only have to register one event listener, since the copy action causes an `IObjectAddedEvent` to be created, which is just a special type of `IObjectMovedEvent`. First, make sure that everything is setup correctly in the first place: >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs () Let's now move `myfolder11` from `myfolder` to `myfolder2`: >>> myfolder2['myfolder21'] = myfolder11 >>> del myfolder['myfolder11'] Now the next site manager for `myfolder11`'s site manager should have changed: >>> myfolder21 = myfolder11 >>> myfolder21.getSiteManager().__bases__ == (myfolder2.getSiteManager(), ) True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True >>> myfolder.getSiteManager().subs () Make sure that our interfaces and classes are picklable: >>> import sys >>> sys.modules['zope.site.tests'].IMyUtility = IMyUtility >>> IMyUtility.__module__ = 'zope.site.tests' >>> sys.modules['zope.site.tests'].MyUtility = MyUtility >>> MyUtility.__module__ = 'zope.site.tests' >>> from pickle import dumps, loads >>> data = dumps(myfolder2['myfolder21']) >>> myfolder['myfolder11'] = loads(data) >>> myfolder11 = myfolder['myfolder11'] >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True Finally, let's check that everything works fine when our folder is moved to the folder that doesn't contain any site manager. Our folder's sitemanager's bases should be set to global site manager. >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> nosm = folder.Folder() >>> nosm['root'] = myfolder11 >>> myfolder11.getSiteManager().__bases__ == (gsm, ) True ======= CHANGES ======= 3.9.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.testing`. 3.9.1 (2010-04-30) ------------------ - Removed use of 'zope.testing.doctest' in favor of stdlib's 'doctest. - Removed use of 'zope.testing.doctestunit' in favor of stdlib's 'doctest. 3.9.0 (2009-12-29) ------------------ - Avoid a test dependency on zope.copypastemove by testing the correct persistent behavior of a site manager using the normal pickle module. 3.8.0 (2009-12-15) ------------------ - Removed functional testing setup and dependency on zope.app.testing. 3.7.1 (2009-11-18) ------------------ - Moved the zope.site.hooks functionality to zope.component.hooks as it isn't actually dealing with zope.site's concept of a site. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.7.0 (2009-09-29) ------------------ - Cleaned up the undeclared dependency on zope.app.publication by moving the two relevant subscriber registrations and their tests to that package. - Dropped the dependency on zope.traversing which was only used to access zope.location functionality. Configure zope.location for some tests. - Demoted zope.configuration to a testing dependency. 3.6.4 (2009-09-01) ------------------ - Set __parent__ and __name__ in the LocalSiteManager's constructor after calling constructor of its superclasses, so __name__ doesn't get overwritten with empty string by the Components constructor. - Don't set __parent__ and __name__ attributes of site manager in SiteManagerContainer's ``setSiteManager`` method, as they're already set for LocalSiteManager. Other site manager implementations are not required to have those attributes at all, so we're not adding them anymore. 3.6.3 (2009-07-27) ------------------ - Propagate an ObjectRemovedEvent to the SiteManager upon removal of a SiteManagerContainer. 3.6.2 (2009-07-24) ------------------ - Fixed tests to pass with latest packages. - Removed failing test of persistent interfaces, since it did not test anything in this package and used the deprecated ``zodbcode`` module. - Fix NameError when calling ``zope.site.testing.siteSetUp(site=True)``. - The ``getNextUtility`` and ``queryNextUtility`` functions was moved to ``zope.component``. While backward-compatibility imports are provided, it's strongly recommended to update your imports. 3.6.1 (2009-02-28) ------------------ - Import symbols moved from zope.traversing to zope.location from the new location. - Don't fail when changing component registry bases while moving ISite object to non-ISite object. - Allow specify whether to create 'default' SiteManagementFolder on initializing LocalSiteManager. Use the ``default_folder`` argument. - Add a containment constraint to the SiteManagementFolder that makes it only available to be contained in ILocalSiteManagers and other ISiteManagementFolders. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old unused code. Update package description. 3.6.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. 3.5.1 (2009-01-27) ------------------ - Extracted from zope.app.component (trunk, 3.5.1 under development) as part of an effort to clean up dependencies between Zope packages. Keywords: zope component architecture local Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.site-3.9.2/src/zope.site.egg-info/SOURCES.txt000644 000766 000024 00000001532 11447354565 021455 0ustar00macstaff000000 000000 CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.site.egg-info/PKG-INFO src/zope.site.egg-info/SOURCES.txt src/zope.site.egg-info/dependency_links.txt src/zope.site.egg-info/namespace_packages.txt src/zope.site.egg-info/not-zip-safe src/zope.site.egg-info/requires.txt src/zope.site.egg-info/top_level.txt src/zope/site/__init__.py src/zope/site/configure.zcml src/zope/site/folder.py src/zope/site/hooks.py src/zope/site/interfaces.py src/zope/site/next.py src/zope/site/site.py src/zope/site/site.txt src/zope/site/testing.py src/zope/site/tests/__init__.py src/zope/site/tests/folder.txt src/zope/site/tests/test_folder.py src/zope/site/tests/test_localsitemanager.py src/zope/site/tests/test_registration.py src/zope/site/tests/test_site.py src/zope/site/tests/test_sitemanagercontainer.pyzope.site-3.9.2/src/zope.site.egg-info/dependency_links.txt000644 000766 000024 00000000001 11447354565 023636 0ustar00macstaff000000 000000 zope.site-3.9.2/src/zope.site.egg-info/namespace_packages.txt000644 000766 000024 00000000005 11447354565 024116 0ustar00macstaff000000 000000 zope zope.site-3.9.2/src/zope.site.egg-info/not-zip-safe000644 000766 000024 00000000001 11447354562 022013 0ustar00macstaff000000 000000 zope.site-3.9.2/src/zope.site.egg-info/requires.txt000644 000766 000024 00000000270 11447354565 022167 0ustar00macstaff000000 000000 setuptools zope.annotation zope.container zope.security zope.component>=3.8.0 zope.event zope.interface zope.lifecycleevent zope.location>=3.7.0 [test] zope.configuration zope.testingzope.site-3.9.2/src/zope.site.egg-info/top_level.txt000644 000766 000024 00000000005 11447354565 022315 0ustar00macstaff000000 000000 zope zope.site-3.9.2/src/zope/__init__.py000644 000766 000024 00000000070 11447354561 017235 0ustar00macstaff000000 000000 __import__('pkg_resources').declare_namespace(__name__) zope.site-3.9.2/src/zope/site/000755 000766 000024 00000000000 11447354567 016101 5ustar00macstaff000000 000000 zope.site-3.9.2/src/zope/site/__init__.py000644 000766 000024 00000002017 11447354561 020204 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Local Component Architecture """ from zope.site.site import (SiteManagerContainer, SiteManagementFolder, SiteManagerAdapter) from zope.site.site import LocalSiteManager, changeSiteConfigurationAfterMove from zope.site.site import threadSiteSubscriber from zope.site.site import clearThreadSiteSubscriber # BBB from zope.component import getNextUtility, queryNextUtility zope.site-3.9.2/src/zope/site/configure.zcml000644 000766 000024 00000004756 11447354561 020757 0ustar00macstaff000000 000000 zope.site-3.9.2/src/zope/site/folder.py000644 000766 000024 00000004571 11447354561 017727 0ustar00macstaff000000 000000 ############################################################################# # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## import zope.component.interfaces import zope.container.folder from zope.interface import implements, directlyProvides from zope.site.interfaces import IFolder, IRootFolder from zope.site.site import SiteManagerContainer class Folder(zope.container.folder.Folder, SiteManagerContainer): implements(IFolder) def rootFolder(): f = Folder() directlyProvides(f, IRootFolder) return f class FolderSublocations(object): """Get the sublocations of a folder The subobjects of a folder include it's contents and it's site manager if it is a site. >>> from zope.container.contained import Contained >>> folder = Folder() >>> folder['ob1'] = Contained() >>> folder['ob2'] = Contained() >>> folder['ob3'] = Contained() >>> subs = list(FolderSublocations(folder).sublocations()) >>> subs.remove(folder['ob1']) >>> subs.remove(folder['ob2']) >>> subs.remove(folder['ob3']) >>> subs [] >>> sm = Contained() >>> from zope.interface import directlyProvides >>> from zope.component.interfaces import IComponentLookup >>> directlyProvides(sm, IComponentLookup) >>> folder.setSiteManager(sm) >>> directlyProvides(folder, zope.component.interfaces.ISite) >>> subs = list(FolderSublocations(folder).sublocations()) >>> subs.remove(folder['ob1']) >>> subs.remove(folder['ob2']) >>> subs.remove(folder['ob3']) >>> subs.remove(sm) >>> subs [] """ def __init__(self, folder): self.folder = folder def sublocations(self): folder = self.folder for key in folder: yield folder[key] if zope.component.interfaces.ISite.providedBy(folder): yield folder.getSiteManager() zope.site-3.9.2/src/zope/site/hooks.py000644 000766 000024 00000002353 11447354561 017573 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Hooks for getting and setting a site in the thread global namespace. """ __docformat__ = 'restructuredtext' from zope.component.hooks import (read_property, SiteInfo, siteinfo, setSite, getSite, getSiteManager, adapter_hook, setHooks, resetHooks, setSite, clearSite) # BBB zope.site-3.9.2/src/zope/site/interfaces.py000644 000766 000024 00000006105 11447354561 020572 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Interfaces for the Local Component Architecture """ import zope.interface import zope.component.interfaces import zope.container.interfaces import zope.container.constraints import zope.location.interfaces from zope.annotation.interfaces import IAttributeAnnotatable class INewLocalSite(zope.interface.Interface): """Event: a local site was created """ manager = zope.interface.Attribute("The new site manager") class NewLocalSite(object): """Event: a local site was created """ zope.interface.implements(INewLocalSite) def __init__(self, manager): self.manager = manager class ILocalSiteManager(zope.component.interfaces.IComponents): """Site Managers act as containers for registerable components. If a Site Manager is asked for an adapter or utility, it checks for those it contains before using a context-based lookup to find another site manager to delegate to. If no other site manager is found they defer to the global site manager which contains file based utilities and adapters. """ subs = zope.interface.Attribute( "A collection of registries that describe the next level " "of the registry tree. They are the children of this " "registry node. This attribute should never be " "manipulated manually. Use `addSub()` and `removeSub()` " "instead.") def addSub(sub): """Add a new sub-registry to the node. Important: This method should *not* be used manually. It is automatically called by `setNext()`. To add a new registry to the tree, use `sub.setNext(self, self.base)` instead! """ def removeSub(sub): """Remove a sub-registry to the node. Important: This method should *not* be used manually. It is automatically called by `setNext()`. To remove a registry from the tree, use `sub.setNext(None)` instead! """ class ISiteManagementFolder(zope.container.interfaces.IContainer): """Component and component registration containers.""" zope.container.constraints.containers( ILocalSiteManager, '.ISiteManagementFolder') class IFolder(zope.container.interfaces.IContainer, zope.component.interfaces.IPossibleSite, IAttributeAnnotatable): """The standard Zope Folder object interface.""" class IRootFolder(IFolder, zope.location.interfaces.IRoot): """The standard Zope root Folder object interface.""" zope.site-3.9.2/src/zope/site/next.py000644 000766 000024 00000000102 11447354561 017414 0ustar00macstaff000000 000000 # BBB from zope.component import getNextUtility, queryNextUtility zope.site-3.9.2/src/zope/site/site.py000644 000766 000024 00000017275 11447354561 017425 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Site and Local Site Manager implementation A local site manager has a number of roles: - A local site manager, that provides a local adapter and utility registry. - A place to do TTW development and/or to manage database-based code. - A registry for persistent modules. The Zope 3 import hook uses the SiteManager to search for modules. """ import zope.event import zope.interface import zope.component import zope.component.persistentregistry import zope.component.hooks import zope.component.interfaces import zope.location import zope.location.interfaces from zope.component.interfaces import ComponentLookupError from zope.lifecycleevent import ObjectCreatedEvent from zope.filerepresentation.interfaces import IDirectoryFactory from zope.container.btree import BTreeContainer from zope.container.contained import Contained from zope.site import interfaces # BBB from zope.component.hooks import setSite class SiteManagementFolder(BTreeContainer): zope.interface.implements(interfaces.ISiteManagementFolder) class SMFolderFactory(object): zope.interface.implements(IDirectoryFactory) def __init__(self, context): self.context = context def __call__(self, name): return SiteManagementFolder() class SiteManagerContainer(Contained): """Implement access to the site manager (++etc++site). This is a mix-in that implements the IPossibleSite interface; for example, it is used by the Folder implementation. """ zope.interface.implements(zope.component.interfaces.IPossibleSite) _sm = None def getSiteManager(self): if self._sm is not None: return self._sm else: raise ComponentLookupError('no site manager defined') def setSiteManager(self, sm): if zope.component.interfaces.ISite.providedBy(self): raise TypeError("Already a site") if zope.component.interfaces.IComponentLookup.providedBy(sm): self._sm = sm else: raise ValueError('setSiteManager requires an IComponentLookup') zope.interface.directlyProvides( self, zope.component.interfaces.ISite, zope.interface.directlyProvidedBy(self)) zope.event.notify(interfaces.NewLocalSite(sm)) def _findNextSiteManager(site): while True: if zope.location.interfaces.IRoot.providedBy(site): # we're the root site, return None return None try: site = zope.location.interfaces.ILocationInfo(site).getParent() except TypeError: # there was not enough context; probably run from a test return None if zope.component.interfaces.ISite.providedBy(site): return site.getSiteManager() class _LocalAdapterRegistry( zope.component.persistentregistry.PersistentAdapterRegistry, zope.location.Location, ): pass class LocalSiteManager( BTreeContainer, zope.component.persistentregistry.PersistentComponents, ): """Local Site Manager implementation""" zope.interface.implements(interfaces.ILocalSiteManager) subs = () def _setBases(self, bases): # Update base subs for base in self.__bases__: if ((base not in bases) and interfaces.ILocalSiteManager.providedBy(base) ): base.removeSub(self) for base in bases: if ((base not in self.__bases__) and interfaces.ILocalSiteManager.providedBy(base) ): base.addSub(self) super(LocalSiteManager, self)._setBases(bases) def __init__(self, site, default_folder=True): BTreeContainer.__init__(self) zope.component.persistentregistry.PersistentComponents.__init__(self) # Locate the site manager self.__parent__ = site self.__name__ = '++etc++site' # Set base site manager next = _findNextSiteManager(site) if next is None: next = zope.component.getGlobalSiteManager() self.__bases__ = (next, ) # Setup default site management folder if requested if default_folder: folder = SiteManagementFolder() zope.event.notify(ObjectCreatedEvent(folder)) self['default'] = folder def _init_registries(self): self.adapters = _LocalAdapterRegistry() self.utilities = _LocalAdapterRegistry() self.adapters.__parent__ = self.utilities.__parent__ = self self.adapters.__name__ = u'adapters' self.utilities.__name__ = u'utilities' def addSub(self, sub): """See interfaces.registration.ILocatedRegistry""" self.subs += (sub, ) def removeSub(self, sub): """See interfaces.registration.ILocatedRegistry""" self.subs = tuple( [s for s in self.subs if s is not sub] ) def threadSiteSubscriber(ob, event): """A subscriber to BeforeTraverseEvent Sets the 'site' thread global if the object traversed is a site. """ zope.component.hooks.setSite(ob) def clearThreadSiteSubscriber(event): """A subscriber to EndRequestEvent Cleans up the site thread global after the request is processed. """ clearSite() # Clear the site thread global clearSite = zope.component.hooks.setSite try: from zope.testing.cleanup import addCleanUp except ImportError: pass else: addCleanUp(clearSite) @zope.component.adapter(zope.interface.Interface) @zope.interface.implementer(zope.component.interfaces.IComponentLookup) def SiteManagerAdapter(ob): """An adapter from ILocation to IComponentLookup. The ILocation is interpreted flexibly, we just check for ``__parent__``. """ current = ob while True: if zope.component.interfaces.ISite.providedBy(current): return current.getSiteManager() current = getattr(current, '__parent__', None) if current is None: # It is not a location or has no parent, so we return the global # site manager return zope.component.getGlobalSiteManager() def changeSiteConfigurationAfterMove(site, event): """After a site is moved, its site manager links have to be updated.""" if event.newParent is not None: next = _findNextSiteManager(site) if next is None: next = zope.component.getGlobalSiteManager() site.getSiteManager().__bases__ = (next, ) @zope.component.adapter( SiteManagerContainer, zope.container.interfaces.IObjectMovedEvent) def siteManagerContainerRemoved(container, event): # The relation between SiteManagerContainer and LocalSiteManager is a # kind of containment hierarchy, but it is not expressed via containment, # but rather via an attribute (_sm). # # When the parent is deleted, this needs to be propagated to the children, # and since we don't have "real" containment, we need to do that manually. try: sm = container.getSiteManager() except ComponentLookupError: pass else: for ignored in zope.component.subscribers((sm, event), None): pass # work happens during adapter fetch zope.site-3.9.2/src/zope/site/site.txt000644 000766 000024 00000024324 11447354561 017605 0ustar00macstaff000000 000000 ============================= Sites and Local Site Managers ============================= This is an introduction of location-based component architecture. Creating and Accessing Sites ---------------------------- *Sites* are used to provide custom component setups for parts of your application or web site. Every folder: >>> from zope.site import folder >>> myfolder = folder.rootFolder() has the potential to become a site: >>> from zope.component.interfaces import ISite, IPossibleSite >>> IPossibleSite.providedBy(myfolder) True but is not yet one: >>> ISite.providedBy(myfolder) False If you would like your custom content component to be able to become a site, you can use the `SiteManagerContainer` mix-in class: >>> from zope import site >>> class MyContentComponent(site.SiteManagerContainer): ... pass >>> myContent = MyContentComponent() >>> IPossibleSite.providedBy(myContent) True >>> ISite.providedBy(myContent) False To convert a possible site to a real site, we have to provide a site manager: >>> sm = site.LocalSiteManager(myfolder) >>> myfolder.setSiteManager(sm) >>> ISite.providedBy(myfolder) True >>> myfolder.getSiteManager() is sm True Note that an event is generated when a local site manager is created: >>> from zope.component.eventtesting import getEvents >>> from zope.site.interfaces import INewLocalSite >>> [event] = getEvents(INewLocalSite) >>> event.manager is sm True If one tries to set a bogus site manager, a `ValueError` will be raised: >>> myfolder2 = folder.Folder() >>> myfolder2.setSiteManager(object) Traceback (most recent call last): ... ValueError: setSiteManager requires an IComponentLookup If the possible site has been changed to a site already, a `TypeError` is raised when one attempts to add a new site manager: >>> myfolder.setSiteManager(site.LocalSiteManager(myfolder)) Traceback (most recent call last): ... TypeError: Already a site There is also an adapter you can use to get the next site manager from any location: >>> myfolder['mysubfolder'] = folder.Folder() >>> import zope.component >>> zope.component.interfaces.IComponentLookup(myfolder['mysubfolder']) is sm True If the location passed is a site, the site manager of that site is returned: >>> zope.component.interfaces.IComponentLookup(myfolder) is sm True Using the Site Manager ---------------------- A site manager contains several *site management folders*, which are used to logically organize the software. When a site manager is initialized, a default site management folder is created: >>> sm = myfolder.getSiteManager() >>> default = sm['default'] >>> default.__class__ However, you can tell not to create the default site manager folder on LocalSiteManager creation: >>> nodefault = site.LocalSiteManager(myfolder, default_folder=False) >>> 'default' in nodefault False Also, note that when creating LocalSiteManager, its __parent__ is set to site that was passed to constructor and the __name__ is set to ++etc++site. >>> nodefault.__parent__ is myfolder True >>> nodefault.__name__ == '++etc++site' True You can easily create a new site management folder: >>> sm['mySMF'] = site.SiteManagementFolder() >>> sm['mySMF'].__class__ Once you have your site management folder -- let's use the default one -- we can register some components. Let's start with a utility: >>> import zope.interface >>> class IMyUtility(zope.interface.Interface): ... pass >>> import persistent >>> from zope.container.contained import Contained >>> class MyUtility(persistent.Persistent, Contained): ... zope.interface.implements(IMyUtility) ... def __init__(self, title): ... self.title = title ... def __repr__(self): ... return "%s('%s')" %(self.__class__.__name__, self.title) Now we can create an instance of our utility and put it in the site management folder and register it: >>> myutil = MyUtility('My custom utility') >>> default['myutil'] = myutil >>> sm.registerUtility(myutil, IMyUtility, 'u1') Now we can ask the site manager for the utility: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') Of course, the local site manager has also access to the global component registrations: >>> gutil = MyUtility('Global Utility') >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.registerUtility(gutil, IMyUtility, 'gutil') >>> sm.queryUtility(IMyUtility, 'gutil') MyUtility('Global Utility') Next let's see whether we can also successfully register an adapter as well. Here the adapter will provide the size of a file: >>> class IFile(zope.interface.Interface): ... pass >>> class ISized(zope.interface.Interface): ... pass >>> class File(object): ... zope.interface.implements(IFile) >>> class FileSize(object): ... zope.interface.implements(ISized) ... def __init__(self, context): ... self.context = context Now that we have the adapter we need to register it: >>> sm.registerAdapter(FileSize, [IFile]) Finally, we can get the adapter for a file: >>> file = File() >>> size = sm.queryAdapter(file, ISized, name='') >>> size.__class__ >>> size.context is file True By the way, once you set a site >>> from zope.component import hooks >>> hooks.setSite(myfolder) you can simply use the zope.component's `getSiteManager()` method to get the nearest site manager: >>> from zope.component import getSiteManager >>> getSiteManager() is sm True This also means that you can simply use zope.component to look up your utility >>> from zope.component import getUtility >>> getUtility(IMyUtility, 'gutil') MyUtility('Global Utility') or the adapter via the interface's `__call__` method: >>> size = ISized(file) >>> size.__class__ >>> size.context is file True Multiple Sites -------------- Until now we have only dealt with one local and the global site. But things really become interesting, once we have multiple sites. We can override other local configuration. This behaviour uses the notion of location, therefore we need to configure the zope.location package first: >>> import zope.configuration.xmlconfig >>> _ = zope.configuration.xmlconfig.string(""" ... ... ... ... ... """) Let's now create a new folder called `folder11`, add it to `myfolder` and make it a site: >>> myfolder11 = folder.Folder() >>> myfolder['myfolder11'] = myfolder11 >>> myfolder11.setSiteManager(site.LocalSiteManager(myfolder11)) >>> sm11 = myfolder11.getSiteManager() If we ask the second site manager for its next, we get >>> sm11.__bases__ == (sm, ) True and the first site manager should have the folling sub manager: >>> sm.subs == (sm11,) True If we now register a second utility with the same name and interface with the new site manager folder, >>> default11 = sm11['default'] >>> myutil11 = MyUtility('Utility, uno & uno') >>> default11['myutil'] = myutil11 >>> sm11.registerUtility(myutil11, IMyUtility, 'u1') then it will will be available in the second site manager >>> sm11.queryUtility(IMyUtility, 'u1') MyUtility('Utility, uno & uno') but not in the first one: >>> sm.queryUtility(IMyUtility, 'u1') MyUtility('My custom utility') It is also interesting to look at the use cases of moving and copying a site. To do that we create a second root folder and make it a site, so that site hierarchy is as follows: :: _____ global site _____ / \ myfolder1 myfolder2 | myfolder11 >>> myfolder2 = folder.rootFolder() >>> myfolder2.setSiteManager(site.LocalSiteManager(myfolder2)) Before we can move or copy sites, we need to register two event subscribers that manage the wiring of site managers after moving or copying: >>> from zope import container >>> gsm.registerHandler( ... site.changeSiteConfigurationAfterMove, ... (ISite, container.interfaces.IObjectMovedEvent), ... ) We only have to register one event listener, since the copy action causes an `IObjectAddedEvent` to be created, which is just a special type of `IObjectMovedEvent`. First, make sure that everything is setup correctly in the first place: >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs () Let's now move `myfolder11` from `myfolder` to `myfolder2`: >>> myfolder2['myfolder21'] = myfolder11 >>> del myfolder['myfolder11'] Now the next site manager for `myfolder11`'s site manager should have changed: >>> myfolder21 = myfolder11 >>> myfolder21.getSiteManager().__bases__ == (myfolder2.getSiteManager(), ) True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True >>> myfolder.getSiteManager().subs () Make sure that our interfaces and classes are picklable: >>> import sys >>> sys.modules['zope.site.tests'].IMyUtility = IMyUtility >>> IMyUtility.__module__ = 'zope.site.tests' >>> sys.modules['zope.site.tests'].MyUtility = MyUtility >>> MyUtility.__module__ = 'zope.site.tests' >>> from pickle import dumps, loads >>> data = dumps(myfolder2['myfolder21']) >>> myfolder['myfolder11'] = loads(data) >>> myfolder11 = myfolder['myfolder11'] >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> myfolder.getSiteManager().subs[0] is myfolder11.getSiteManager() True >>> myfolder2.getSiteManager().subs[0] is myfolder21.getSiteManager() True Finally, let's check that everything works fine when our folder is moved to the folder that doesn't contain any site manager. Our folder's sitemanager's bases should be set to global site manager. >>> myfolder11.getSiteManager().__bases__ == (myfolder.getSiteManager(), ) True >>> nosm = folder.Folder() >>> nosm['root'] = myfolder11 >>> myfolder11.getSiteManager().__bases__ == (gsm, ) True zope.site-3.9.2/src/zope/site/testing.py000644 000766 000024 00000004217 11447354561 020126 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2001-2007 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Reusable functionality for testing site-related code """ import zope.component import zope.component.hooks import zope.component.interfaces import zope.container.interfaces import zope.container.testing import zope.site.site from zope.component.interfaces import IComponentLookup from zope.interface import Interface from zope.site import LocalSiteManager, SiteManagerAdapter from zope.site.folder import rootFolder def createSiteManager(folder, setsite=False): if not zope.component.interfaces.ISite.providedBy(folder): folder.setSiteManager(LocalSiteManager(folder)) if setsite: zope.component.hooks.setSite(folder) return folder.getSiteManager() def addUtility(sitemanager, name, iface, utility, suffix=''): """Add a utility to a site manager This helper function is useful for tests that need to set up utilities. """ folder_name = (name or (iface.__name__ + 'Utility')) + suffix default = sitemanager['default'] default[folder_name] = utility utility = default[folder_name] sitemanager.registerUtility(utility, iface, name) return utility def siteSetUp(site=False): zope.container.testing.setUp() zope.component.hooks.setHooks() zope.component.provideAdapter( SiteManagerAdapter, (Interface,), IComponentLookup) if site: site = rootFolder() createSiteManager(site, setsite=True) return site def siteTearDown(): zope.container.testing.tearDown() zope.component.hooks.resetHooks() zope.component.hooks.setSite() zope.site-3.9.2/src/zope/site/tests/000755 000766 000024 00000000000 11447354567 017243 5ustar00macstaff000000 000000 zope.site-3.9.2/src/zope/site/tests/__init__.py000644 000766 000024 00000000075 11447354561 021350 0ustar00macstaff000000 000000 # # This file is necessary to make this directory a package. zope.site-3.9.2/src/zope/site/tests/folder.txt000644 000766 000024 00000003364 11447354561 021257 0ustar00macstaff000000 000000 =============================== File representation for Folders =============================== Folders can be represented in file-system-like protocols (e.g. FTP). An adapter abstracts some internals away and adds support for accessing the '++etc++site' folder from those protocols. >>> from zope.site.folder import rootFolder >>> from zope.container.directory import ReadDirectory >>> folder = rootFolder() >>> from zope.site.site import LocalSiteManager >>> folder.setSiteManager(LocalSiteManager(folder)) >>> fs_folder = ReadDirectory(folder) As the root folder is a site, the ++etc++site object appears: >>> fs_folder.keys() ['++etc++site'] >>> fs_folder.get('++etc++site') >>> fs_folder['++etc++site'] >>> list(fs_folder.__iter__()) ['++etc++site'] >>> fs_folder.values() [] >>> len(fs_folder) 1 >>> fs_folder.items() [('++etc++site', )] >>> '++etc++site' in fs_folder True Let's add another folder to see how a non-site folder behaves: >>> from zope.site.folder import Folder >>> folder['test'] = Folder() The site folder now contains the new folder: >>> fs_folder.keys() [u'test', '++etc++site'] >>> fs_folder.get('test') >>> fs_folder['test'] >>> list(fs_folder.__iter__()) [u'test', '++etc++site'] >>> fs_folder.values() [, ] >>> len(fs_folder) 2 >>> fs_folder.items() [(u'test', ), ('++etc++site', )] >>> 'test' in fs_folder True zope.site-3.9.2/src/zope/site/tests/test_folder.py000644 000766 000024 00000001470 11447354561 022123 0ustar00macstaff000000 000000 from unittest import TestSuite, makeSuite import doctest from zope.site.folder import Folder from zope.site.testing import siteSetUp, siteTearDown from zope.site.tests.test_site import BaseTestSiteManagerContainer def setUp(test=None): siteSetUp() def tearDown(test=None): siteTearDown() class FolderTest(BaseTestSiteManagerContainer): def makeTestObject(self): return Folder() def test_suite(): flags = doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE return TestSuite(( makeSuite(FolderTest), doctest.DocTestSuite('zope.site.folder', setUp=setUp, tearDown=tearDown), doctest.DocFileSuite("folder.txt", setUp=setUp, tearDown=tearDown, optionflags=flags), )) zope.site-3.9.2/src/zope/site/tests/test_localsitemanager.py000644 000766 000024 00000003337 11447354561 024166 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2007 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Local sitemanager tests. """ import unittest from zope.interface import Interface from zope import site from zope.site.folder import Folder import zope.site.testing class I1(Interface): pass class TestLocalSiteManager(unittest.TestCase): def setUp(self): zope.site.testing.siteSetUp() self.util = object() self.root = Folder() self.root['site'] = Folder() subfolder = self.root['site'] subfolder.setSiteManager(site.LocalSiteManager(subfolder)) subfolder.getSiteManager().registerUtility(self.util, I1) def tearDown(self): zope.site.testing.siteTearDown() def testPersistence(self): from pickle import dumps, loads self.assert_( self.root['site'].getSiteManager().getUtility(I1) is self.util) data = dumps(self.root['site']) self.root['copied_site'] = loads(data) self.assert_( self.root['copied_site'].getSiteManager().getUtility(I1) is not self.util) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(TestLocalSiteManager), )) zope.site-3.9.2/src/zope/site/tests/test_registration.py000644 000766 000024 00000007757 11447354561 023400 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Registration Tests """ __docformat__ = "reStructuredText" import doctest import os import unittest import warnings import ZODB.FileStorage import persistent import transaction import zope.component.globalregistry import zope.component.testing as placelesssetup import zope.container.contained import zope.site from ZODB.DB import DB from ZODB.DemoStorage import DemoStorage from zope import interface # test class for testing data conversion class IFoo(interface.Interface): pass class Foo(persistent.Persistent, zope.container.contained.Contained): interface.implements(IFoo) name = '' def __init__(self, name=''): self.name = name def __repr__(self): return 'Foo(%r)' % self.name def setUp(test): placelesssetup.setUp(test) test.globs['showwarning'] = warnings.showwarning warnings.showwarning = lambda *a, **k: None def tearDown(test): warnings.showwarning = test.globs['showwarning'] placelesssetup.tearDown(test) def oldfs(): return FileStorage( os.path.join(os.path.dirname(__file__), 'gen3.fs'), read_only=True, ) # Work around a bug in ZODB # XXX fix ZODB class FileStorage(ZODB.FileStorage.FileStorage): def new_oid(self): self._lock_acquire() try: last = self._oid d = ord(last[-1]) if d < 255: # fast path for the usual case last = last[:-1] + chr(d+1) else: # there's a carry out of the last byte last_as_long, = _structunpack(">Q", last) last = _structpack(">Q", last_as_long + 1) self._oid = last return last finally: self._lock_release() class GlobalRegistry: pass base = zope.component.globalregistry.GlobalAdapterRegistry( GlobalRegistry, 'adapters') GlobalRegistry.adapters = base def clear_base(): base.__init__(GlobalRegistry, 'adapters') def test_deghostification_of_persistent_adapter_registries(): """ Note that this test duplicates one from zope.component.tests. We should be able to get rid of this one when we get rid of __setstate__ implementation we have in back35. We want to make sure that we see updates corrextly. >>> import ZODB.tests.util >>> db = ZODB.tests.util.DB() >>> tm1 = transaction.TransactionManager() >>> c1 = db.open(transaction_manager=tm1) >>> r1 = zope.site.site._LocalAdapterRegistry((base,)) >>> r2 = zope.site.site._LocalAdapterRegistry((r1,)) >>> c1.root()[1] = r1 >>> c1.root()[2] = r2 >>> tm1.commit() >>> r1._p_deactivate() >>> r2._p_deactivate() >>> tm2 = transaction.TransactionManager() >>> c2 = db.open(transaction_manager=tm2) >>> r1 = c2.root()[1] >>> r2 = c2.root()[2] >>> r1.lookup((), IFoo, '') >>> base.register((), IFoo, '', Foo('')) >>> r1.lookup((), IFoo, '') Foo('') >>> r2.lookup((), IFoo, '1') >>> r1.register((), IFoo, '1', Foo('1')) >>> r2.lookup((), IFoo, '1') Foo('1') >>> r1.lookup((), IFoo, '2') >>> r2.lookup((), IFoo, '2') >>> base.register((), IFoo, '2', Foo('2')) >>> r1.lookup((), IFoo, '2') Foo('2') >>> r2.lookup((), IFoo, '2') Foo('2') Cleanup: >>> db.close() >>> clear_base() """ def test_suite(): suite = unittest.TestSuite(( doctest.DocTestSuite(setUp=setUp, tearDown=tearDown) )) return suite zope.site-3.9.2/src/zope/site/tests/test_site.py000644 000766 000024 00000010055 11447354561 021613 0ustar00macstaff000000 000000 ############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Registration Tests """ __docformat__ = "reStructuredText" import doctest import unittest import zope.interface import zope.interface.verify from zope.component.interfaces import ISite, IPossibleSite from zope.site import folder from zope.site import interfaces from zope import site from zope.site import testing class SiteManagerStub(object): zope.interface.implements(interfaces.ILocalSiteManager) class CustomFolder(folder.Folder): def __init__(self, name): self.__name__ = name super(CustomFolder, self).__init__() def __repr__(self): return '<%s %s>' %(self.__class__.__name__, self.__name__) def test_SiteManagerAdapter(): """ The site manager adapter is used to find the nearest site for any given location. If the provided context is a site, >>> site = folder.Folder() >>> sm = SiteManagerStub() >>> site.setSiteManager(sm) then the adapter simply return's the site's site manager: >>> from zope.site import SiteManagerAdapter >>> SiteManagerAdapter(site) is sm True If the context is a location (i.e. has a `__parent__` attribute), >>> ob = folder.Folder() >>> ob.__parent__ = site >>> ob2 = folder.Folder() >>> ob2.__parent__ = ob we 'acquire' the closest site and return its site manager: >>> SiteManagerAdapter(ob) is sm True >>> SiteManagerAdapter(ob2) is sm True If we are unable to find a local site manager, then the global site manager is returned. >>> import zope.component >>> orphan = CustomFolder('orphan') >>> SiteManagerAdapter(orphan) is zope.component.getGlobalSiteManager() True """ class BaseTestSiteManagerContainer(unittest.TestCase): """This test is for objects that don't have site managers by default and that always give back the site manager they were given. Subclasses need to define a method, 'makeTestObject', that takes no arguments and that returns a new site manager container that has no site manager.""" def test_IPossibleSite_verify(self): zope.interface.verify.verifyObject(IPossibleSite, self.makeTestObject()) def test_get_and_set(self): smc = self.makeTestObject() self.failIf(ISite.providedBy(smc)) sm = site.LocalSiteManager(smc) smc.setSiteManager(sm) self.failUnless(ISite.providedBy(smc)) self.failUnless(smc.getSiteManager() is sm) zope.interface.verify.verifyObject(ISite, smc) def test_set_w_bogus_value(self): smc=self.makeTestObject() self.assertRaises(Exception, smc.setSiteManager, self) class SiteManagerContainerTest(BaseTestSiteManagerContainer): def makeTestObject(self): from zope.site import SiteManagerContainer return SiteManagerContainer() def setUp(test): testing.siteSetUp() def tearDown(test): testing.siteTearDown() class Layer(object): @staticmethod def setUp(): pass def test_suite(): site_suite = doctest.DocFileSuite('../site.txt', setUp=setUp, tearDown=tearDown) # XXX Isolate the site.txt tests within their own layer as they do some # component registration. site_suite.layer = Layer return unittest.TestSuite(( doctest.DocTestSuite(), unittest.makeSuite(SiteManagerContainerTest), site_suite, )) zope.site-3.9.2/src/zope/site/tests/test_sitemanagercontainer.py000644 000766 000024 00000004733 11447354561 025057 0ustar00macstaff000000 000000 ############################################################################# # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ """ import unittest import zope.component from zope.component import getSiteManager import zope.container.testing from zope.event import notify from zope.lifecycleevent import ObjectRemovedEvent from zope.lifecycleevent.interfaces import IObjectRemovedEvent from zope.site.folder import rootFolder from zope.site.site import SiteManagerContainer import zope.site.testing class Dummy(object): pass removed_called = False def removed_event(obj, event): global removed_called removed_called = True def dispatch_event(obj, event): sm = obj._sm if sm is not None: for k,v in sm.items(): notify(ObjectRemovedEvent(v, sm, k)) class SiteManagerContainerTest(unittest.TestCase): def setUp(self): self.root = rootFolder() zope.site.testing.siteSetUp(self.root) global removed_called removed_called = False sm = getSiteManager() sm.registerHandler(removed_event, (Dummy, IObjectRemovedEvent)) sm.registerHandler( dispatch_event, (SiteManagerContainer, IObjectRemovedEvent)) def tearDown(self): zope.site.testing.siteTearDown() def removed_event(self, event): self.removed_called = True def test_delete_smc_should_propagate_removed_event(self): container = SiteManagerContainer() self.root['container'] = container zope.site.testing.createSiteManager(container) container.getSiteManager()['child'] = Dummy() del self.root['container'] self.assert_(removed_called) def test_delete_when_smc_has_no_sitemanager(self): container = SiteManagerContainer() self.root['container'] = container try: del self.root['container'] except Exception, e: self.fail(e) def test_suite(): return unittest.makeSuite(SiteManagerContainerTest)