zope.lifecycleevent-4.0.3/setup.cfg0000644000000000000000000000007312214345636015450 0ustar 00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.lifecycleevent-4.0.3/PKG-INFO0000644000000000000000000001311012214345636014720 0ustar 00000000000000Metadata-Version: 1.1 Name: zope.lifecycleevent Version: 4.0.3 Summary: Object life-cycle events Home-page: http://pypi.python.org/pypi/zope.lifecycleevent Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ================= Life-cycle events ================= In Zope, events are used by components to inform each other about relevant new objects and object modifications. To keep all subscribers up to date it is indispensable that the life cycle of an object is accompanied by various events. >>> from zope.event import notify >>> from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent >>> class Sample(object) : ... "Test class" >>> obj = Sample() >>> notify(ObjectCreatedEvent(obj)) >>> obj.modified = True >>> notify(ObjectModifiedEvent(obj)) Some event consumers like catalogs and caches may need more information to update themselves in an efficient manner. The necessary information can be provided as optional modification descriptions of the ObjectModifiedEvent. Some examples: >>> from zope.interface import Interface, Attribute, implementer >>> class IFile(Interface): ... data = Attribute("Data") ... >>> @implementer(IFile) ... class File(object): ... pass >>> file = File() >>> file.data = "123" >>> notify(ObjectModifiedEvent(obj, IFile)) This says that we modified something via IFile. Note that an interface is an acceptable description. In fact, we might allow pretty much anything as a description and it depends on your needs what kind of descriptions you use. ``zope.lifecycleevent`` Changelog ================================= 4.0.3 (2013-09-12) ------------------ - Dropped the dependency on ``zope.component`` as the interface and implementation of ``ObjectEvent`` is now in ``zope.interface``. Retained the dependency for the tests. - Fixed: ``.moved`` tried to notify the wrong event. 4.0.2 (2013-03-08) ------------------ - Add Trove classifiers indicating CPython and PyPy support. 4.0.1 (2013-02-11) ------------------ - Added `tox.ini`. 4.0.0 (2013-02-11) ------------------ - Test coverage at 100%. - Added support for Python 3.3 and PyPy. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.4 and 2.5. 3.7.0 (2011-03-17) ------------------ - Added convenience functions to parallel zope.lifecycleevent.modified for the other events defined in this package. 3.6.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.component [test]`. 3.6.1 (2010-04-30) ------------------ - Removed dependency on undeclared zope.testing.doctest. 3.6.0 (2009-12-29) ------------------ - Refactor tests to loose zope.annotation and zope.dublincore as dependencies. 3.5.2 (2009-05-17) ------------------ - ``IObjectMovedEvent``, ``IObjectAddedEvent``, ``IObjectRemovedEvent`` interfaces and ``ObjectMovedEvent``, ``ObjectAddedEvent`` and ``ObjectRemovedEvent`` classes copied here from zope.container (plus tests). The intent is to allow packages that rely on these interfaces or the event classes to rely on zope.lifecycleevent (which has few dependencies) instead of zope.container (which has many). 3.5.1 (2009-03-09) ------------------ - Remove deprecated code and thus remove dependency on zope.deferredimport. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Update package's description and documentation. 3.5.0 (2009-01-31) ------------------ - Remove old module declarations from classes. - Use zope.container instead of zope.app.container. 3.4.0 (2007-09-01) ------------------ Initial release as an independent package Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Software Development zope.lifecycleevent-4.0.3/tox.ini0000644000000000000000000000117112214345622015135 0ustar 00000000000000[tox] envlist = py26,py27,py33,pypy [testenv] commands = python setup.py test -q # without explicit deps, setup.py test will download a bunch of eggs into $PWD deps = zope.interface zope.component zope.event [testenv:coverage] basepython = python2.7 commands = # The installed version messes up nose's test discovery / coverage reporting # So, we uninstall that from the environment, and then install the editable # version, before running nosetests. pip uninstall -y zope.lifecycleevent pip install -e . nosetests --with-xunit --with-xcoverage deps = nose coverage nosexcover zope.lifecycleevent-4.0.3/setup.py0000644000000000000000000000517312214345622015342 0ustar 00000000000000############################################################################## # # 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.lifecycleevent 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.lifecycleevent', version='4.0.3', url='http://pypi.python.org/pypi/zope.lifecycleevent', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', license='ZPL 2.1', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development', ], description='Object life-cycle events', long_description=\ read('src', 'zope', 'lifecycleevent', 'README.txt') + '\n\n' + read('CHANGES.rst'), packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['zope',], include_package_data=True, install_requires=['setuptools', 'zope.interface', 'zope.event'], extras_require=dict( test = ['zope.component'] ), test_suite='zope.lifecycleevent.tests.test_suite', zip_safe=False, ) zope.lifecycleevent-4.0.3/buildout.cfg0000644000000000000000000000015412214345622016132 0ustar 00000000000000[buildout] develop = . parts = test [test] recipe = zc.recipe.testrunner eggs = zope.lifecycleevent [test] zope.lifecycleevent-4.0.3/bootstrap.py0000644000000000000000000002443512214345622016221 0ustar 00000000000000############################################################################## # # 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, urllib, urllib2, subprocess from optparse import OptionParser if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: quote = str # See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. stdout, stderr = subprocess.Popen( [sys.executable, '-Sc', 'try:\n' ' import ConfigParser\n' 'except ImportError:\n' ' print 1\n' 'else:\n' ' print 0\n'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() has_broken_dash_S = bool(int(stdout.strip())) # In order to be more robust in the face of system Pythons, we want to # run without site-packages loaded. This is somewhat tricky, in # particular because Python 2.6's distutils imports site, so starting # with the -S flag is not sufficient. However, we'll start with that: if not has_broken_dash_S and 'site' in sys.modules: # We will restart with python -S. args = sys.argv[:] args[0:0] = [sys.executable, '-S'] args = map(quote, args) os.execv(sys.executable, args) # Now we are running with -S. We'll get the clean sys.path, import site # because distutils will do it later, and then reset the path and clean # out any namespace packages from site-packages that might have been # loaded by .pth files. clean_path = sys.path[:] import site # imported because of its side effects sys.path[:] = clean_path for k, v in sys.modules.items(): if k in ('setuptools', 'pkg_resources') or ( hasattr(v, '__path__') and len(v.__path__) == 1 and not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))): # This is a namespace package. Remove it. sys.modules.pop(k) is_jython = sys.platform.startswith('java') setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' distribute_source = 'http://python-distribute.org/distribute_setup.py' # parsing arguments def normalize_to_url(option, opt_str, value, parser): if value: if '://' not in value: # It doesn't smell like a URL. value = 'file://%s' % ( urllib.pathname2url( os.path.abspath(os.path.expanduser(value))),) if opt_str == '--download-base' and not value.endswith('/'): # Download base needs a trailing slash to make the world happy. value += '/' else: value = None name = opt_str[2:].replace('-', '_') setattr(parser.values, name, value) usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --setup-source and --download-base to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="use_distribute", default=False, help="Use Distribute rather than Setuptools.") parser.add_option("--setup-source", action="callback", dest="setup_source", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or file location for the setup file. " "If you use Setuptools, this will default to " + setuptools_source + "; if you use Distribute, this " "will default to " + distribute_source + ".")) parser.add_option("--download-base", action="callback", dest="download_base", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or directory for downloading " "zc.buildout and either Setuptools or Distribute. " "Defaults to PyPI.")) parser.add_option("--eggs", help=("Specify a directory for storing eggs. Defaults to " "a temporary directory that is deleted when the " "bootstrap script completes.")) parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) 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 options.eggs: eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) else: eggs_dir = tempfile.mkdtemp() if options.setup_source is None: if options.use_distribute: options.setup_source = distribute_source else: options.setup_source = setuptools_source if options.accept_buildout_test_releases: args.insert(0, 'buildout:accept-buildout-test-releases=true') try: import pkg_resources import setuptools # A flag. Sometimes pkg_resources is installed alone. if not hasattr(pkg_resources, '_distribute'): raise ImportError except ImportError: ez_code = urllib2.urlopen( options.setup_source).read().replace('\r\n', '\n') ez = {} exec ez_code in ez setup_args = dict(to_dir=eggs_dir, download_delay=0) if options.download_base: setup_args['download_base'] = options.download_base if options.use_distribute: setup_args['no_fake'] = True if sys.version_info[:2] == (2, 4): setup_args['version'] = '0.6.32' ez['use_setuptools'](**setup_args) if 'pkg_resources' in sys.modules: reload(sys.modules['pkg_resources']) import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) cmd = [quote(sys.executable), '-c', quote('from setuptools.command.easy_install import main; main()'), '-mqNxd', quote(eggs_dir)] if not has_broken_dash_S: cmd.insert(1, '-S') find_links = options.download_base if not find_links: find_links = os.environ.get('bootstrap-testing-find-links') if not find_links and options.accept_buildout_test_releases: find_links = 'http://downloads.buildout.org/' if find_links: cmd.extend(['-f', quote(find_links)]) if options.use_distribute: setup_requirement = 'distribute' else: setup_requirement = 'setuptools' ws = pkg_resources.working_set setup_requirement_path = ws.find( pkg_resources.Requirement.parse(setup_requirement)).location env = dict( os.environ, PYTHONPATH=setup_requirement_path) requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setup_requirement_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if distv >= pkg_resources.parse_version('2dev'): continue if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement += '=='+version else: requirement += '<2dev' cmd.append(requirement) if is_jython: import subprocess exitcode = subprocess.Popen(cmd, env=env).wait() else: # Windows prefers this, apparently; otherwise we would prefer subprocess exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) if exitcode != 0: sys.stdout.flush() sys.stderr.flush() print ("An error occurred when trying to install zc.buildout. " "Look above this message for any errors that " "were output by easy_install.") sys.exit(exitcode) ws.add_entry(eggs_dir) ws.require(requirement) import zc.buildout.buildout # If there isn't already a command in the args, add bootstrap if not [a for a in args if '=' not in a]: args.append('bootstrap') # if -c was provided, we push it back into args for buildout's main function if options.config_file is not None: args[0:0] = ['-c', options.config_file] zc.buildout.buildout.main(args) if not options.eggs: # clean up temporary egg directory shutil.rmtree(eggs_dir) zope.lifecycleevent-4.0.3/README.rst0000644000000000000000000000005012214345622015304 0ustar 00000000000000See src/zope/lifecycleevent/README.txt. zope.lifecycleevent-4.0.3/MANIFEST.in0000644000000000000000000000020512214345622015355 0ustar 00000000000000include *.rst include *.txt include tox.ini include bootstrap.py include buildout.cfg recursive-include src * global-exclude *.pyc zope.lifecycleevent-4.0.3/LICENSE.txt0000644000000000000000000000402612214345622015447 0ustar 00000000000000Zope 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.lifecycleevent-4.0.3/COPYRIGHT.txt0000644000000000000000000000004012214345622015725 0ustar 00000000000000Zope Foundation and Contributorszope.lifecycleevent-4.0.3/CHANGES.rst0000644000000000000000000000424412214345622015430 0ustar 00000000000000``zope.lifecycleevent`` Changelog ================================= 4.0.3 (2013-09-12) ------------------ - Dropped the dependency on ``zope.component`` as the interface and implementation of ``ObjectEvent`` is now in ``zope.interface``. Retained the dependency for the tests. - Fixed: ``.moved`` tried to notify the wrong event. 4.0.2 (2013-03-08) ------------------ - Add Trove classifiers indicating CPython and PyPy support. 4.0.1 (2013-02-11) ------------------ - Added `tox.ini`. 4.0.0 (2013-02-11) ------------------ - Test coverage at 100%. - Added support for Python 3.3 and PyPy. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.4 and 2.5. 3.7.0 (2011-03-17) ------------------ - Added convenience functions to parallel zope.lifecycleevent.modified for the other events defined in this package. 3.6.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.component [test]`. 3.6.1 (2010-04-30) ------------------ - Removed dependency on undeclared zope.testing.doctest. 3.6.0 (2009-12-29) ------------------ - Refactor tests to loose zope.annotation and zope.dublincore as dependencies. 3.5.2 (2009-05-17) ------------------ - ``IObjectMovedEvent``, ``IObjectAddedEvent``, ``IObjectRemovedEvent`` interfaces and ``ObjectMovedEvent``, ``ObjectAddedEvent`` and ``ObjectRemovedEvent`` classes copied here from zope.container (plus tests). The intent is to allow packages that rely on these interfaces or the event classes to rely on zope.lifecycleevent (which has few dependencies) instead of zope.container (which has many). 3.5.1 (2009-03-09) ------------------ - Remove deprecated code and thus remove dependency on zope.deferredimport. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Update package's description and documentation. 3.5.0 (2009-01-31) ------------------ - Remove old module declarations from classes. - Use zope.container instead of zope.app.container. 3.4.0 (2007-09-01) ------------------ Initial release as an independent package zope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/top_level.txt0000644000000000000000000000000512214345632024606 0ustar 00000000000000zope zope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/requires.txt0000644000000000000000000000007312214345632024461 0ustar 00000000000000setuptools zope.interface zope.event [test] zope.componentzope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/not-zip-safe0000644000000000000000000000000112214345622024306 0ustar 00000000000000 zope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/namespace_packages.txt0000644000000000000000000000000512214345632026407 0ustar 00000000000000zope zope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/dependency_links.txt0000644000000000000000000000000112214345632026127 0ustar 00000000000000 zope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/SOURCES.txt0000644000000000000000000000113212214345632023742 0ustar 00000000000000CHANGES.rst COPYRIGHT.txt LICENSE.txt MANIFEST.in README.rst bootstrap.py buildout.cfg setup.py tox.ini src/zope/__init__.py src/zope.lifecycleevent.egg-info/PKG-INFO src/zope.lifecycleevent.egg-info/SOURCES.txt src/zope.lifecycleevent.egg-info/dependency_links.txt src/zope.lifecycleevent.egg-info/namespace_packages.txt src/zope.lifecycleevent.egg-info/not-zip-safe src/zope.lifecycleevent.egg-info/requires.txt src/zope.lifecycleevent.egg-info/top_level.txt src/zope/lifecycleevent/README.txt src/zope/lifecycleevent/__init__.py src/zope/lifecycleevent/interfaces.py src/zope/lifecycleevent/tests.pyzope.lifecycleevent-4.0.3/src/zope.lifecycleevent.egg-info/PKG-INFO0000644000000000000000000001311012214345632023152 0ustar 00000000000000Metadata-Version: 1.1 Name: zope.lifecycleevent Version: 4.0.3 Summary: Object life-cycle events Home-page: http://pypi.python.org/pypi/zope.lifecycleevent Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ================= Life-cycle events ================= In Zope, events are used by components to inform each other about relevant new objects and object modifications. To keep all subscribers up to date it is indispensable that the life cycle of an object is accompanied by various events. >>> from zope.event import notify >>> from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent >>> class Sample(object) : ... "Test class" >>> obj = Sample() >>> notify(ObjectCreatedEvent(obj)) >>> obj.modified = True >>> notify(ObjectModifiedEvent(obj)) Some event consumers like catalogs and caches may need more information to update themselves in an efficient manner. The necessary information can be provided as optional modification descriptions of the ObjectModifiedEvent. Some examples: >>> from zope.interface import Interface, Attribute, implementer >>> class IFile(Interface): ... data = Attribute("Data") ... >>> @implementer(IFile) ... class File(object): ... pass >>> file = File() >>> file.data = "123" >>> notify(ObjectModifiedEvent(obj, IFile)) This says that we modified something via IFile. Note that an interface is an acceptable description. In fact, we might allow pretty much anything as a description and it depends on your needs what kind of descriptions you use. ``zope.lifecycleevent`` Changelog ================================= 4.0.3 (2013-09-12) ------------------ - Dropped the dependency on ``zope.component`` as the interface and implementation of ``ObjectEvent`` is now in ``zope.interface``. Retained the dependency for the tests. - Fixed: ``.moved`` tried to notify the wrong event. 4.0.2 (2013-03-08) ------------------ - Add Trove classifiers indicating CPython and PyPy support. 4.0.1 (2013-02-11) ------------------ - Added `tox.ini`. 4.0.0 (2013-02-11) ------------------ - Test coverage at 100%. - Added support for Python 3.3 and PyPy. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.4 and 2.5. 3.7.0 (2011-03-17) ------------------ - Added convenience functions to parallel zope.lifecycleevent.modified for the other events defined in this package. 3.6.2 (2010-09-25) ------------------ - Added not declared, but needed test dependency on `zope.component [test]`. 3.6.1 (2010-04-30) ------------------ - Removed dependency on undeclared zope.testing.doctest. 3.6.0 (2009-12-29) ------------------ - Refactor tests to loose zope.annotation and zope.dublincore as dependencies. 3.5.2 (2009-05-17) ------------------ - ``IObjectMovedEvent``, ``IObjectAddedEvent``, ``IObjectRemovedEvent`` interfaces and ``ObjectMovedEvent``, ``ObjectAddedEvent`` and ``ObjectRemovedEvent`` classes copied here from zope.container (plus tests). The intent is to allow packages that rely on these interfaces or the event classes to rely on zope.lifecycleevent (which has few dependencies) instead of zope.container (which has many). 3.5.1 (2009-03-09) ------------------ - Remove deprecated code and thus remove dependency on zope.deferredimport. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Update package's description and documentation. 3.5.0 (2009-01-31) ------------------ - Remove old module declarations from classes. - Use zope.container instead of zope.app.container. 3.4.0 (2007-09-01) ------------------ Initial release as an independent package Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Software Development zope.lifecycleevent-4.0.3/src/zope/__init__.py0000644000000000000000000000007012214345622017474 0ustar 00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.lifecycleevent-4.0.3/src/zope/lifecycleevent/tests.py0000644000000000000000000002446212214345622022113 0ustar 00000000000000############################################################################## # # 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. # ############################################################################## """Object Event Tests """ import doctest import unittest import zope.component.testing from zope.lifecycleevent import ObjectCreatedEvent, created from zope.lifecycleevent import Attributes, Sequence from zope.lifecycleevent import ObjectModifiedEvent, modified from zope.lifecycleevent import ObjectCopiedEvent, copied class TestSequence(unittest.TestCase): def testSequence(self): from zope.interface import Interface, Attribute class ISample(Interface): field1 = Attribute("A test field") field2 = Attribute("A test field") field3 = Attribute("A test field") desc = Sequence(ISample, 'field1', 'field2') self.assertEqual(desc.interface, ISample) self.assertEqual(desc.keys, ('field1', 'field2')) class TestAttributes(unittest.TestCase): def testAttributes(self): from zope.lifecycleevent.interfaces import IObjectMovedEvent desc = Attributes(IObjectMovedEvent, "newName", "newParent") self.assertEqual(desc.interface, IObjectMovedEvent) self.assertEqual(desc.attributes, ('newName', 'newParent')) class TestObjectCreatedEvent(unittest.TestCase): klass = ObjectCreatedEvent object = object() def setUp(self): from zope.event import subscribers self._old_subscribers = subscribers[:] self.listener = [] subscribers[:] = [self.listener.append] self.event = self.klass(self.object) def tearDown(self): from zope.event import subscribers subscribers[:] = self._old_subscribers def testGetObject(self): self.assertEqual(self.event.object, self.object) def testCreated(self): created(self.object) self.assertEqual(len(self.listener), 1) self.assertEqual(self.listener[-1].object, self.object) class TestObjectModifiedEvent(unittest.TestCase): klass = ObjectModifiedEvent object = object() def setUp(self): from zope.event import subscribers self._old_subscribers = subscribers[:] self.listener = [] subscribers[:] = [self.listener.append] self.event = self.klass(self.object) def tearDown(self): from zope.event import subscribers subscribers[:] = self._old_subscribers def testGetObject(self): self.assertEqual(self.event.object, self.object) def testModified(self): modified(self.object) self.assertEqual(len(self.listener), 1) self.assertEqual(self.listener[-1].object, self.object) def testAttributes(self): from zope.interface import implementer, Interface, Attribute class ISample(Interface): field = Attribute("A test field") @implementer(ISample) class Sample(object): pass obj = Sample() obj.field = 42 attrs = Attributes(ISample, "field") modified(obj, attrs) self.assertEqual(self.listener[-1].object, obj) self.assertEqual(self.listener[-1].descriptions, (attrs,)) class TestObjectCopiedEvent(unittest.TestCase): klass = ObjectCopiedEvent original = object() object = object() def setUp(self): from zope.event import subscribers self._old_subscribers = subscribers[:] self.listener = [] subscribers[:] = [self.listener.append] self.event = self.klass(self.object, self.original) def tearDown(self): from zope.event import subscribers subscribers[:] = self._old_subscribers def testGetObject(self): self.assertEqual(self.event.object, self.object) def testCopied(self): copied(self.object, self.original) self.assertEqual(len(self.listener), 1) self.assertEqual(self.listener[-1].object, self.object) self.assertEqual(self.listener[-1].original, self.original) class TestObjectMovedEvent(unittest.TestCase): def _getTargetClass(self): from zope.lifecycleevent import ObjectMovedEvent return ObjectMovedEvent def _makeOne(self, *arg): return self._getTargetClass()(*arg) def test_it(self): ob = Context() old_parent = Context() new_parent = Context() event = self._makeOne(ob, old_parent, 'old_name', new_parent, 'new_name') self.assertEqual(event.object, ob) self.assertEqual(event.oldParent, old_parent) self.assertEqual(event.newParent, new_parent) self.assertEqual(event.newName, 'new_name') self.assertEqual(event.oldName, 'old_name') def test_verifyClass(self): from zope.interface.verify import verifyClass from zope.lifecycleevent.interfaces import IObjectMovedEvent verifyClass(IObjectMovedEvent, self._getTargetClass()) def test_verifyObject(self): from zope.interface.verify import verifyObject from zope.lifecycleevent.interfaces import IObjectMovedEvent verifyObject(IObjectMovedEvent, self._makeOne(None, None, None, None, None)) class TestObjectAddedEvent(unittest.TestCase): def _getTargetClass(self): from zope.lifecycleevent import ObjectAddedEvent return ObjectAddedEvent def _makeOne(self, *arg): return self._getTargetClass()(*arg) def test_it(self): ob = Context() new_parent = Context() event = self._makeOne(ob, new_parent, 'new_name') self.assertEqual(event.object, ob) self.assertEqual(event.newParent, new_parent) self.assertEqual(event.newName, 'new_name') self.assertEqual(event.oldParent, None) self.assertEqual(event.oldName, None) def test_it_Nones(self): ob = Context() new_parent = Context() ob.__parent__ = new_parent ob.__name__ = 'new_name' event = self._makeOne(ob, None, None) self.assertEqual(event.object, ob) self.assertEqual(event.newParent, new_parent) self.assertEqual(event.newName, 'new_name') self.assertEqual(event.oldParent, None) self.assertEqual(event.oldName, None) def test_verifyClass(self): from zope.interface.verify import verifyClass from zope.lifecycleevent.interfaces import IObjectAddedEvent verifyClass(IObjectAddedEvent, self._getTargetClass()) def test_verifyObject(self): from zope.interface.verify import verifyObject from zope.lifecycleevent.interfaces import IObjectAddedEvent parent = Context() ob = Context() verifyObject(IObjectAddedEvent, self._makeOne(ob, parent, 'new_name')) class TestObjectRemovedEvent(unittest.TestCase): def _getTargetClass(self): from zope.lifecycleevent import ObjectRemovedEvent return ObjectRemovedEvent def _makeOne(self, *arg): return self._getTargetClass()(*arg) def test_it(self): ob = Context() parent = Context() event = self._makeOne(ob, parent, 'name') self.assertEqual(event.object, ob) self.assertEqual(event.newParent, None) self.assertEqual(event.newName, None) self.assertEqual(event.oldParent, parent) self.assertEqual(event.oldName, 'name') def test_it_Nones(self): ob = Context() parent = Context() ob.__parent__ = parent ob.__name__ = 'name' event = self._makeOne(ob, None, None) self.assertEqual(event.object, ob) self.assertEqual(event.newParent, None) self.assertEqual(event.newName, None) self.assertEqual(event.oldParent, parent) self.assertEqual(event.oldName, 'name') def test_verifyClass(self): from zope.interface.verify import verifyClass from zope.lifecycleevent.interfaces import IObjectRemovedEvent verifyClass(IObjectRemovedEvent, self._getTargetClass()) def test_verifyObject(self): from zope.interface.verify import verifyObject from zope.lifecycleevent.interfaces import IObjectRemovedEvent parent = object() ob = object() verifyObject(IObjectRemovedEvent, self._makeOne(ob, parent, 'new_name')) class DummySubscriber: event = None def __call__(self, event): self.event = event class TestMoved(unittest.TestCase): """Testing .moved().""" def setUp(self): from zope.event import subscribers self._old_subscribers = subscribers[:] subscribers[:] = [DummySubscriber()] def tearDown(self): from zope.event import subscribers subscribers[:] = self._old_subscribers def test_it(self): from zope.lifecycleevent import moved, ObjectMovedEvent from zope.event import subscribers moved('object', 'oldParent', 'oldName', 'newParent', 'newName') event = subscribers[0].event self.assertTrue(isinstance(event, ObjectMovedEvent)) self.assertEqual(event.object, 'object') self.assertEqual(event.oldParent, 'oldParent') self.assertEqual(event.oldName, 'oldName') self.assertEqual(event.newParent, 'newParent') self.assertEqual(event.newName, 'newName') class Context: pass def test_suite(): return unittest.TestSuite(( unittest.makeSuite(TestAttributes), unittest.makeSuite(TestSequence), unittest.makeSuite(TestObjectCreatedEvent), unittest.makeSuite(TestObjectModifiedEvent), unittest.makeSuite(TestObjectCopiedEvent), unittest.makeSuite(TestObjectMovedEvent), unittest.makeSuite(TestObjectAddedEvent), unittest.makeSuite(TestObjectRemovedEvent), unittest.makeSuite(TestMoved), doctest.DocFileSuite('README.txt', tearDown=zope.component.testing.tearDown), )) if __name__ == '__main__': unittest.main(defaultTest='test_suite') zope.lifecycleevent-4.0.3/src/zope/lifecycleevent/interfaces.py0000644000000000000000000001017712214345622023072 0ustar 00000000000000############################################################################## # # Copyright (c) 2002, 2003 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. # ############################################################################## """Event-related interfaces """ __docformat__ = 'restructuredtext' from zope.interface import Interface, Attribute from zope.interface import interfaces class IZopeLifecycleEvent(Interface): def created(object): """Send an IObjectCreatedEvent for `object`.""" def modified(object, *descriptions): """Send an IObjectModifiedEvent for `object`. `descriptions` is a sequence of interfaces or fields which were updated. """ def copied(object, original): """Send an IObjectCopiedEvent for object. `original` is the object the copy was created from. """ def moved(object, oldParent, oldName, newParent, newName): """Send an IObjectMovedEvent for object. `oldParent` is the container `object` was removed from. `oldName` was the name used to store `object` in `oldParent`. `newParent` is the container `object` was added to. `newName` is the name used to store `object` in `newParent`. """ def added(object, newParent=None, newName=None): """Send an IObjectAddedEvent for object. `newParent` is the container `object` was added to. `newName` is the name used to store `object` in the container. These will be determined object.__parent__ and object.__name__ if None. """ def removed(object, oldParent=None, oldName=None): """Send an IObjectRemovedEvent for object. `oldParent` is the container `object` was removed from. `oldName` was the name used to store `object` in `oldParent`. These will be determined object.__parent__ and object.__name__ if None. """ class IObjectCreatedEvent(interfaces.IObjectEvent): """An object has been created. The location will usually be ``None`` for this event.""" class IObjectCopiedEvent(IObjectCreatedEvent): """An object has been copied""" original = Attribute("The original from which the copy was made") class IObjectModifiedEvent(interfaces.IObjectEvent): """An object has been modified""" class IModificationDescription(Interface): """ Marker interface for descriptions of object modifications. Can be used as a parameter of an IObjectModifiedEvent.""" class IAttributes(IModificationDescription): """ Describes the attributes of an interface. """ interface = Attribute("The involved interface.") attributes = Attribute("A sequence of modified attributes.") class ISequence(IModificationDescription): """ Describes the modified keys of a sequence-like interface. """ interface = Attribute("The involved interface.") keys = Attribute("A sequence of modified keys.") ############################################################################## # Moving Objects class IObjectMovedEvent(interfaces.IObjectEvent): """An object has been moved.""" oldParent = Attribute("The old location parent for the object.") oldName = Attribute("The old location name for the object.") newParent = Attribute("The new location parent for the object.") newName = Attribute("The new location name for the object.") ############################################################################## # Adding objects class IObjectAddedEvent(IObjectMovedEvent): """An object has been added to a container.""" ############################################################################## # Removing objects class IObjectRemovedEvent(IObjectMovedEvent): """An object has been removed from a container.""" zope.lifecycleevent-4.0.3/src/zope/lifecycleevent/__init__.py0000644000000000000000000001032712214345622022503 0ustar 00000000000000############################################################################## # # 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. # ############################################################################## """Life cycle events """ __docformat__ = 'restructuredtext' from zope.interface.interfaces import ObjectEvent from zope.interface import implementer, moduleProvides from zope.event import notify from zope.lifecycleevent.interfaces import IZopeLifecycleEvent from zope.lifecycleevent.interfaces import IObjectCreatedEvent from zope.lifecycleevent.interfaces import IObjectModifiedEvent from zope.lifecycleevent.interfaces import IObjectCopiedEvent from zope.lifecycleevent.interfaces import IObjectMovedEvent from zope.lifecycleevent.interfaces import IObjectAddedEvent from zope.lifecycleevent.interfaces import IObjectRemovedEvent from zope.lifecycleevent.interfaces import IAttributes from zope.lifecycleevent.interfaces import ISequence moduleProvides(IZopeLifecycleEvent) @implementer(IObjectCreatedEvent) class ObjectCreatedEvent(ObjectEvent): """An object has been created""" def created(object): notify(ObjectCreatedEvent(object)) @implementer(IAttributes) class Attributes(object): """Describes modified attributes of an interface.""" def __init__(self, interface, *attributes): self.interface = interface self.attributes = attributes @implementer(ISequence) class Sequence(object): """Describes modified keys of an interface.""" def __init__(self, interface, *keys): self.interface = interface self.keys = keys @implementer(IObjectModifiedEvent) class ObjectModifiedEvent(ObjectEvent): """An object has been modified""" def __init__(self, object, *descriptions): """Init with a list of modification descriptions.""" super(ObjectModifiedEvent, self).__init__(object) self.descriptions = descriptions def modified(object, *descriptions): notify(ObjectModifiedEvent(object, *descriptions)) @implementer(IObjectCopiedEvent) class ObjectCopiedEvent(ObjectCreatedEvent): """An object has been copied""" def __init__(self, object, original): super(ObjectCopiedEvent, self).__init__(object) self.original = original def copied(object, original): notify(ObjectCopiedEvent(object, original)) @implementer(IObjectMovedEvent) class ObjectMovedEvent(ObjectEvent): """An object has been moved""" def __init__(self, object, oldParent, oldName, newParent, newName): ObjectEvent.__init__(self, object) self.oldParent = oldParent self.oldName = oldName self.newParent = newParent self.newName = newName def moved(object, oldParent, oldName, newParent, newName): notify(ObjectMovedEvent(object, oldParent, oldName, newParent, newName)) @implementer(IObjectAddedEvent) class ObjectAddedEvent(ObjectMovedEvent): """An object has been added to a container""" def __init__(self, object, newParent=None, newName=None): if newParent is None: newParent = object.__parent__ if newName is None: newName = object.__name__ ObjectMovedEvent.__init__(self, object, None, None, newParent, newName) def added(object, newParent=None, newName=None): notify(ObjectAddedEvent(object, newParent, newName)) @implementer(IObjectRemovedEvent) class ObjectRemovedEvent(ObjectMovedEvent): """An object has been removed from a container""" def __init__(self, object, oldParent=None, oldName=None): if oldParent is None: oldParent = object.__parent__ if oldName is None: oldName = object.__name__ ObjectMovedEvent.__init__(self, object, oldParent, oldName, None, None) def removed(object, oldParent=None, oldName=None): notify(ObjectRemovedEvent(object, oldParent, oldName)) zope.lifecycleevent-4.0.3/src/zope/lifecycleevent/README.txt0000644000000000000000000000255412214345622022073 0ustar 00000000000000================= Life-cycle events ================= In Zope, events are used by components to inform each other about relevant new objects and object modifications. To keep all subscribers up to date it is indispensable that the life cycle of an object is accompanied by various events. >>> from zope.event import notify >>> from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent >>> class Sample(object) : ... "Test class" >>> obj = Sample() >>> notify(ObjectCreatedEvent(obj)) >>> obj.modified = True >>> notify(ObjectModifiedEvent(obj)) Some event consumers like catalogs and caches may need more information to update themselves in an efficient manner. The necessary information can be provided as optional modification descriptions of the ObjectModifiedEvent. Some examples: >>> from zope.interface import Interface, Attribute, implementer >>> class IFile(Interface): ... data = Attribute("Data") ... >>> @implementer(IFile) ... class File(object): ... pass >>> file = File() >>> file.data = "123" >>> notify(ObjectModifiedEvent(obj, IFile)) This says that we modified something via IFile. Note that an interface is an acceptable description. In fact, we might allow pretty much anything as a description and it depends on your needs what kind of descriptions you use.