grokcore.component-2.5/0000775000175000017500000000000011750014424014256 5ustar jwjw00000000000000grokcore.component-2.5/buildout.cfg0000664000175000017500000000071111750014416016566 0ustar jwjw00000000000000[buildout] develop = . parts = interpreter test extends = http://svn.zope.org/repos/main/groktoolkit/trunk/grok.cfg versions = versions extensions = buildout.dumppickedversions [versions] grokcore.component = [interpreter] recipe = zc.recipe.egg eggs = grokcore.component interpreter = python [test] recipe = zc.recipe.testrunner eggs = grokcore.component grokcore.component[test] defaults = ['--tests-pattern', '^f?tests$', '-v', '--auto-color'] grokcore.component-2.5/PKG-INFO0000664000175000017500000004601711750014424015363 0ustar jwjw00000000000000Metadata-Version: 1.0 Name: grokcore.component Version: 2.5 Summary: Grok-like configuration for basic components (adapters, utilities, subscribers) Home-page: http://grok.zope.org Author: Grok Team Author-email: grok-dev@zope.org License: ZPL Download-URL: http://pypi.python.org/pypi/grokcore.component Description: This package provides base classes of basic component types for the Zope Component Architecture, as well as means for configuring and registering them directly in Python (without ZCML). .. contents:: How to set up ``grokcore.component`` ==================================== In the following we assume you're writing or extending an application that does bootstrap configuration using ZCML. There's always a single ZCML file that is executed when the application is started, which then includes everything else. Let's assume this file is called ``site.zcml`` (that's what it's called in Zope), so that file is what we'll be editing. In order to register the components that you wrote using the base classes and directives available from ``grokcore.component``, we'll use the ```` ZCML directive. But before we can use it, we need to make sure it's available to the ZCML machinery. We do this by including the meta configuration from ``grokcore.component``:: Put this line somewhere to the top of ``site.zcml``, next to other meta configuration includes. Now, further down the line, we can tell the machinery in ``grokcore.component`` to register all components in your package (let's say it's called ``helloworld``):: To sum up, your ``site.zcml`` file should look like something like this:: Examples ======== Adapter ------- Here's a simple adapter that may be useful in Zope. It extracts the languages that a user prefers from the request:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.i18n.interfaces import IUserPreferredLanguages class CookieLanguage(grokcore.component.Adapter): """Extract the preferred language from a cookie""" grokcore.component.context(IBrowserRequest) grokcore.component.implements(IUserPreferredLanguages) # No need to implement __init__, it's already provided by the base class. def getPreferredLanguages(self): # This an adapter for the request, so self.context is the request. request = self.context # Extract the preferred language from a cookie: lang = request.cookies.get('language', 'en') # According to IUserPreferredLanguages, we must return a list. return [lang] Multi-adapter ------------- Here's a multi-adapter that functions as a content provider as known from the ``zope.contentprovider`` library. Content providers are components that return snippets of HTML. They're multi-adapters for the content object (model), the request and the view that they're supposed to be a part of:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserPage from zope.contentprovider.interfaces import IContentProvider class HelloWorldProvider(grokcore.component.MultiAdapter): """Display Hello World!""" grokcore.component.adapts(Interface, IBrowserRequest, IBrowserPage) grokcore.component.implements(IContentProvider) def __init__(self, context, request, view): pass def update(self): pass def render(self): return u'

Hello World!

' Global utility -------------- Here's a simple named utility, again from the Zope world. It's a translation domain. In other words, it contains translations of user messages and is invoked when the i18n machinery needs to translate something:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain class HelloWorldTranslationDomain(grokcore.component.GlobalUtility): grokcore.component.implements(ITranslationDomain) grokcore.component.name('helloworld') domain = u'helloworld' def translate(self, msgid, mapping=None, context=None, target_language=None, default=None): if target_language is None: preferred = IUserPreferredLanguages(context) target_language = preferred.getPreferredLanguages()[0] translations = {'de': u'Hallo Welt', 'nl': u'Hallo Wereld'} return translations.get(target_language, u'Hello World') Of course, it's silly to implement your own translation domain utility if there are already implementations available in ``zope.i18n`` (one that reads translations from a GNU gettext message catalog and a simple implementation for tests). Let's try to reuse that implementation and register an instance:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain from zope.i18n.simpletranslationdomain import SimpleTranslationDomain messages = {('de', u'Hello World'): u'Hallo Welt', ('nl', u'Hello World'): u'Hallo Wereld'} helloworld_domain = SimpleTranslationDomain(u'helloworld', messages) grokcore.component.global_utility(helloworld_domain, provides=ITranslationDomain, name='helloworld', direct=True) Global adapter -------------- Sometimes, you may have an object that should be registered as an adapter factory. It may have come from some other framework that configured that adapter for you, say, or you may have a class that you instantiate many times to get different variations on a particular adapter factory. In these cases, subclassing grokcore.component.Adapter or MultiAdapter is not possible. Instead, you can use the global_adapter() directive. Here is an example drawing on the ``z3c.form`` library, which provides an adapter factory factory for named widget attributes:: import zope.interface import zope.schema import grokcore.component import z3c.form.widget import ComputedWidgetAttribute class ISchema(Interface): """This schema will be used to power a z3c.form form""" field = zope.schema.TextLine(title=u"Sample field") ... label_override = z3c.form.widget.StaticWidgetAttribute( u"Override label", field=ISchema['field']) grokcore.component.global_adapter(label_override, name=u"label") In the example above, the provided and adapted interfaces are deduced from the object returned by the ``StaticWidgetAttribute`` factory. The full syntax for global_adapter is:: global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") The factory must be a callable (the adapter factory). Adapted interfaces are given as a tuple. You may use a single interface instead of a one-element tuple for single adapters. The provided interface is given as shown. The name defaults to u"" (an unnamed adapter). Handling events --------------- Here we see an event handler much like it occurs within Zope itself. It subscribes to the modified event for all annotatable objects (in other words, objects that can have metadata associated with them). When invoked, it updates the Dublin Core 'Modified' property accordingly:: import datetime import grokcore.component from zope.annotation.interfaces import IAnnotatable from zope.lifecycleevent.interfaces import IObjectModifiedEvent from zope.dublincore.interfaces import IZopeDublinCore @grokcore.component.subscribe(IAnnotatable, IObjectModifiedEvent) def updateDublinCoreAfterModification(obj, event): """Updated the Dublin Core 'Modified' property when a modified event is sent for an object.""" IZopeDublinCore(obj).modified = datetime.datetime.utcnow() Subscriptions ------------- Subscriptions look similar to Adapter, however, unlike regular adapters, subscription adapters are used when we want all of the adapters that adapt an object to a particular adapter. Analogous to MultiAdapter, there is a MultiSubscription component that "adapts" multiple objects. Changes ======= 2.5 (2012-05-01) ---------------- - Introduce provideUtility, providerAdapter, provideSubscriptionAdapter, provideHandler and provideInterface in grokcore.component. These by default delegate the registration of components to the global site manager like was done before, but provide the possibility for custom registries for the grokked components. - Fix the `global_adapter` to properly use information annotated by ``grok.adapter``, and using the IContext object if it was not specified. (Fix Launchpad issue #960097). - Add a ``key`` option to ``sort_components`` that behave like ``key`` options available on standard Python sort methods. 2.4 (2011-04-27) ---------------- - Fix the `global_adapter` directive implementation to accept an explicit "empty" name for nameless adapter registrations (as it used to be that providing an empty name in the registration would actually result in registering a named adapter in case the factory has a `grok.name`). 2.3 (2011-02-14) ---------------- - Implement the generic (Multi)Subscriptions components. 2.2 (2010-11-03) ---------------- - The default values computation for the context directive and the provides directive is now defined in the directives themselves. This means that where the values for these directives is being retrieved, the "default_context" function does not need to be passed along anymore for general cases. Analogous to this, when getting values for the provides directive the "default_provides" function does not need to be passed along in the general case. 2.1 (2010-11-01) ---------------- * Made package comply to zope.org repository policy. * Moved directives 'order' from grokcore.viewlet and 'path' from grokcore.view to this very package. * Tiny dependency adjustment: moved zope.event to test dependencies. * Port from 1.x branch exclude parameter to the Grok ZCML directive. * Port from 1.x branch the ignore of testing.py modules. 2.0 (2009-09-16) ---------------- * Use a newer version of Martian that has better support for inheritance. This is demonstrated in ``tests/inherit``. * The ``ContextGrokker`` and the ``scan.py`` module have gone away thanks the newer Martian. * Directive implementations (in their factory method) should *not* bind directives. Directive binding cannot take place at import time, but only at grok time. Binding directives during import time (when directives are executed) can lead to change problems. (we noticed this during our refactoring to use the new Martian). * Use 1.0b1 versions.cfg in Grok's release info instead of a local copy; a local copy for all grokcore packages is just too hard to maintain. 1.7 (2009-06-01) ---------------- * Add missing provider, global_adapter, implementsOnly, classProvides() to the module interface so that they are included in __all__ 1.6 (2009-04-10) ---------------- * Add convenience imports for implementsOnly() and classProvides() class declarations form zope.interface. * Add support for registering global adapters at module level:: grok.global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") Only 'factory' is required. If only a single interface is adapted, the second argument may be a single interface instead of a tuple. If the component has declared adapted/provided interfaces, the second and third arguments may be omitted. * Add support for an @provider decorator to let a function directly provide an interface:: @grok.provider(IFoo, IBar) def some_function(): ... This is equivalent to doing alsoProvides(some_function, IFoo, IBar). * Add support for named adapters with the @adapter decorator:: @grok.adapter(IAdaptedOne, IAdaptedTwo, name=u"foo") def some_function(one, two): ... 1.5.1 (2008-07-28) ------------------ * The ``IGrokcoreComponentAPI`` interface was missing declarations for the ``title`` and ``description`` directives. 1.5 (2008-07-22) ---------------- * Fix https://bugs.launchpad.net/grok/+bug/242353: grokcore.component contains old-style test setup. There is no `register_all_tests` method in grokcore.component.testing anymore. Use z3c.testsetup instead. * Allow functions that have been marked with @grok.subscribe also be registered with ``zope.component.provideHandler()`` manually. This is useful for unit tests where you may not want to grok a whole module. * Document grokcore.component's public API in an interface, ``IGrokcoreComponentAPI``. When you now do:: from grokcore.component import * only the items documented in that interface will be imported into your local namespace. 1.4 (2008-06-11) ---------------- * Ported class grokkers to make use of further improvements in Martian. This requires Martian 0.10. 1.3 (2008-05-14) ---------------- * Ported class grokkers to make use of the new declarative way of retrieving directive information from a class. This requires Martian 0.9.6. 1.2.1 (2008-05-04) ------------------ * Upgrade to Martian 0.9.5, which has a slight change in the signature of ``scan_for_classes``. * Remove an unnecessary import ``methods_from_class`` from ``grokcore.component.scan``. 1.2 (2008-05-04) ---------------- * Ported directives to Martian's new directive implementation. As a result, nearly all helper functions that were available from ``grokcore.component.util`` have been removed. The functionality is mostly available from the directives themselves now. * The ``baseclass`` directive has been moved to Martian. * The ``order`` directive and its helper functions have been moved back to Grok, as it was of no general use, but very specific to viewlets. 1.1 (2008-05-03) ---------------- * ``determine_module_component`` now looks for classes that implement a certain interface (such as ``IContext``), instead of taking a list of classes. If looking for ``IContext``, it still will find ``Context`` subclasses, as these were also made to implement ``IContext``. * Move the ``public_methods_from_class`` helper function back to Grok, it isn't used at all in ``grokcore.component``. 1.0.1 (2008-05-02) ------------------ * The grokkers for adapters and global utilities did not use the correct value for the *provided* interface in the configuration action discriminator. Because of this, uninformative and potentially wrong conflict errors would occur, as well as no conflict where a conflict should have occurred. * The grokker for the ``global_utility()`` directive did immediate registrations instead of generating configuration actions. Therefore it did not provoke ``ConflictErrors`` for conflicting registrations. * Improved documentation 1.0 (2008-05-01) ---------------- * Created ``grokcore.component`` in March 2008 by factoring basic component base classes and their directives and grokkers out of Grok. Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python grokcore.component-2.5/setup.py0000664000175000017500000000263611750014416016000 0ustar jwjw00000000000000from setuptools import setup, find_packages import os def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() long_description = ( read('README.txt') + '\n' + read('CHANGES.txt') ) tests_require = [ 'zope.event', ] setup( name='grokcore.component', version='2.5', author='Grok Team', author_email='grok-dev@zope.org', url='http://grok.zope.org', download_url='http://pypi.python.org/pypi/grokcore.component', description='Grok-like configuration for basic components ' '(adapters, utilities, subscribers)', long_description=long_description, license='ZPL', classifiers=['Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', ], packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['grokcore'], include_package_data=True, zip_safe=False, install_requires=['setuptools', 'martian >= 0.14', 'zope.component', 'zope.configuration', 'zope.interface', # Note: zope.testing is NOT just a test dependency here. 'zope.testing', ], tests_require=tests_require, extras_require={'test': tests_require}, ) grokcore.component-2.5/bootstrap.py0000664000175000017500000002336611750014416016660 0ustar jwjw00000000000000############################################################################## # # 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, textwrap, 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 sys.path[:] = clean_path for k, v in sys.modules.items(): if (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 -c was provided, we push it back into args for buildout's main function if options.config_file is not None: args += ['-c', options.config_file] 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.append('buildout:accept-buildout-test-releases=true') args.append('bootstrap') 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 ez['use_setuptools'](**setup_args) 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 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 _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 = '=='.join((requirement, version)) 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 zc.buildout.buildout.main(args) if not options.eggs: # clean up temporary egg directory shutil.rmtree(eggs_dir) grokcore.component-2.5/src/0000775000175000017500000000000011750014424015045 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/0000775000175000017500000000000011750014424016660 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/0000775000175000017500000000000011750014424020662 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/components.py0000664000175000017500000001003611750014416023422 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok components""" from zope.interface import implements from grokcore.component.interfaces import IContext class Adapter(object): """Base class for an adapter that adapts a single object (commonly referred to as the *context*). Use the ``context`` directive to specify which object to adapt and the ``implements`` directive to specify which interface the adapter will provide. If it's a named adapter, you may use the ``name`` directive to specify the name. .. attribute:: context The adapted object. """ def __init__(self, context): self.context = context class MultiAdapter(object): """Base class for an adapter that adapts *n* objects (where *n>=1*). Use the ``adapts`` directive to specify which kinds of objects are adapted and the ``implements`` directive to specify which interface the adapter will provide. If it's a named multi-adapter, you may use the ``name`` directive to specify the name. Note that contrary to the Adapter, the MultiAdapter base class does not provide an `__init__` method. An `__init__` needs to accept the same number of arguments as are used in the `adapts` directive. """ pass class GlobalUtility(object): """Base class to define a globally registered utility. Base class for a globally registered utility. Unless you use the ``direct`` directive to indicate that the class itself should be registered as a utility, the class will automatically be instantiated, therefore the constructor may not take any arguments. Use the ``implements`` directive to specify which interface the utility provides, or if that is not unambiguous, also use the ``provides`` directive to specify which of the implemented interfaces should be used when registering the utility. If it's a named utility, you may use the ``name`` directive to specify the name. """ pass class Subscription(object): """Base class for a subscription adapter. Subscriptions are similar to adapters, except that it is possible to register multiple unnamed subscriptions for identical ``context`` and ``provides``. Use the ``context`` directive to explicitly set the interface to adapt from. When omitted the current context is assumed. Use the ``implements`` directive to specify which interface the subscription provides, or if that is not unambiguous, also use the ``provides`` directive to specify which of the implemented interfaces should be used when registering the subscription. """ def __init__(self, context): self.context = context class MultiSubscription(object): """Base class for a subscription multi-adapter. MultiSubscriptions are similar to multi adapters, except that it is possible to register multiple unnamed subscriptions for identical ``adapts`` and ``provides``. Use the ``adapts`` directive to explicitly set the multiple interfaces to adapt from. Use the ``implements`` directive to specify which interface the subscription provides, or if that is not unambiguous, also use the ``provides`` directive to specify which of the implemented interfaces should be used when registering the multi subscription. """ class Context(object): """Subclasses of this will automatically be found as potential contexts for adapters and other types of context-dependent components. """ implements(IContext) grokcore.component-2.5/src/grokcore/component/__init__.py0000664000175000017500000000411011750014416022770 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok """ from zope.component import adapts adapts.__doc__ = "Declares the types of objects that a multi-adapter adapts." from zope.interface import implements, implementsOnly, classProvides from martian import baseclass from martian.error import GrokError, GrokImportError from martian import ClassGrokker, InstanceGrokker, GlobalGrokker from grokcore.component.components import ( Adapter, Context, GlobalUtility, MultiAdapter, MultiSubscription, Subscription, ) from grokcore.component.directive import ( context, description, direct, global_adapter, global_utility, name, order, path, provides, title, ) from grokcore.component.decorators import ( adapter, implementer, provider, subscribe, ) from grokcore.component.subscription import ( queryMultiSubscriptions, queryOrderedMultiSubscriptions, queryOrderedSubscriptions, querySubscriptions, ) from grokcore.component.util import ( getSiteManager, provideAdapter, provideHandler, provideInterface, provideSubscriptionAdapter, provideUtility, sort_components, ) # Import this module so that it's available as soon as you import the # 'grokcore.component' package. Useful for tests and interpreter examples. import grokcore.component.testing # Only export public API from grokcore.component.interfaces import IGrokcoreComponentAPI __all__ = list(IGrokcoreComponentAPI) grokcore.component-2.5/src/grokcore/component/testing.py0000664000175000017500000000342411750014416022715 0ustar jwjw00000000000000############################################################################## # # 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. # ############################################################################## """Grok test helpers """ import grokcore.component from zope.configuration.config import ConfigurationMachine from martian import scan from grokcore.component import zcml def grok(module_name): config = ConfigurationMachine() zcml.do_grok('grokcore.component.meta', config) zcml.do_grok(module_name, config) config.execute_actions() def grok_component(name, component, context=None, module_info=None, templates=None): if module_info is None: obj_module = getattr(component, '__grok_module__', None) if obj_module is None: obj_module = getattr(component, '__module__', None) module_info = scan.module_info_from_dotted_name(obj_module) module = module_info.getModule() if context is not None: grokcore.component.context.set(module, context) if templates is not None: module.__grok_templates__ = templates config = ConfigurationMachine() result = zcml.the_multi_grokker.grok(name, component, module_info=module_info, config=config) config.execute_actions() return result grokcore.component-2.5/src/grokcore/component/meta.zcml0000664000175000017500000000067311750014416022506 0ustar jwjw00000000000000 grokcore.component-2.5/src/grokcore/component/util.py0000664000175000017500000001073311750014416022216 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok utility functions. """ import types import zope.component.hooks from zope.interface.interfaces import IInterface from zope.interface import alsoProvides from grokcore.component import directive def _sort_key(component): # If components have a grok.order directive, sort by that. explicit_order, implicit_order = directive.order.bind().get(component) return (explicit_order, component.__module__, implicit_order, component.__class__.__name__) def sort_components(components, key=None): """Sort a list of components using the information provided by `grok.order`. """ sort_key = _sort_key if key is not None: sort_key = lambda item: _sort_key(key(item)) return sorted(components, key=sort_key) def getSiteManager(): site = zope.component.hooks.getSite() if site is None: sm = zope.component.getGlobalSiteManager() else: sm = site.getSiteManager() return sm def provideUtility(component, provides=None, name=u''): sm = getSiteManager() sm.registerUtility(component, provides, name, event=False) def provideAdapter(factory, adapts=None, provides=None, name=''): sm = getSiteManager() sm.registerAdapter(factory, adapts, provides, name, event=False) def provideSubscriptionAdapter(factory, adapts=None, provides=None): sm = getSiteManager() sm.registerSubscriptionAdapter(factory, adapts, provides, event=False) def provideHandler(factory, adapts=None): sm = getSiteManager() sm.registerHandler(factory, adapts, event=False) def provideInterface(id, interface, iface_type=None, info=''): """register Interface with global site manager as utility >>> gsm = zope.component.getGlobalSiteManager() >>> from zope.interface import Interface >>> from zope.interface.interfaces import IInterface >>> from zope.component.tests import ITestType >>> class I(Interface): ... pass >>> IInterface.providedBy(I) True >>> ITestType.providedBy(I) False >>> interfaces = gsm.getUtilitiesFor(ITestType) >>> list(interfaces) [] # provide first interface type >>> provideInterface('', I, ITestType) >>> ITestType.providedBy(I) True >>> interfaces = list(gsm.getUtilitiesFor(ITestType)) >>> [name for (name, iface) in interfaces] [u'zope.component.interface.I'] >>> [iface.__name__ for (name, iface) in interfaces] ['I'] # provide second interface type >>> class IOtherType(IInterface): ... pass >>> provideInterface('', I, IOtherType) >>> ITestType.providedBy(I) True >>> IOtherType.providedBy(I) True >>> interfaces = list(gsm.getUtilitiesFor(ITestType)) >>> [name for (name, iface) in interfaces] [u'zope.component.interface.I'] >>> interfaces = list(gsm.getUtilitiesFor(IOtherType)) >>> [name for (name, iface) in interfaces] [u'zope.component.interface.I'] >>> class I1(Interface): ... pass >>> provideInterface('', I1) >>> IInterface.providedBy(I1) True >>> ITestType.providedBy(I1) False >>> interfaces = list(gsm.getUtilitiesFor(ITestType)) >>> [name for (name, iface) in interfaces] [u'zope.component.interface.I'] >>> [iface.__name__ for (name, iface) in interfaces] ['I'] """ if not id: id = "%s.%s" % (interface.__module__, interface.__name__) if not IInterface.providedBy(interface): if not isinstance(interface, (type, types.ClassType)): raise TypeError(id, "is not an interface or class") return if iface_type is not None: if not iface_type.extends(IInterface): raise TypeError(iface_type, "is not an interface type") alsoProvides(interface, iface_type) else: iface_type = IInterface sm = getSiteManager() sm.registerUtility(interface, iface_type, id, info) grokcore.component-2.5/src/grokcore/component/interfaces.py0000664000175000017500000001771111750014416023367 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2008 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. # ############################################################################## """Public interfaces. """ from zope.interface import Interface, Attribute class IContext(Interface): """Marker interface for auto-association of context. The ``grok.context()`` directive is used to associate adapters with the class or interface they adapt. If there is only a single possible context object to adapt to in a module, you can leave out this directive and let the adapter associate automatically. If you want to make an object to be a candidate for this automatic association, you can subclass from ``grokcore.component.Context``. This implements this ``IContext`` directive. In some cases, you don't want to mix in a base class. You can instead mark up your class with ``zope.interface.implements(IContext)`` to make it a candidate for auto-association. """ class IBaseClasses(Interface): Adapter = Attribute("Base class for adapters.") ClassGrokker = Attribute("Base class to define a class grokker.") Context = Attribute("Base class for automatically associated contexts.") GlobalGrokker = Attribute("Base class to define a module grokker.") GlobalUtility = Attribute("Base class for global utilities.") InstanceGrokker = Attribute("Base class to define an instance grokker.") MultiAdapter = Attribute("Base class for multi-adapters.") MultiSubscription = Attribute( "Base class for subscription mult-adapters.") Subscription = Attribute("Base class for subscription adapters.") class IDirectives(Interface): def baseclass(): """Mark this class as a base class. This means it won't be grokked, though if it's a possible context, it can still serve as a context. """ def implements(*interfaces): """Declare that a class implements the given interfaces.""" def implementsOnly(*interfaces): """Declare that a class implements only the given interfaces. Interfaces implemented by base classes are explicitly not inherited. """ def classProvides(*interfaces): """Declare that a class (as opposed to instances of the class) directly provides the given interfaces. """ def adapts(*classes_or_interfaces): """Declare that a class adapts objects of the given classes or interfaces.""" def context(class_or_interface): """Declare the context for views, adapters, etc. This directive can be used on module and class level. When used on module level, it will set the context for all views, adapters, etc. in that module. When used on class level, it will set the context for that particular class.""" def name(name): """Declare the name of a view or adapter/multi-adapter. This directive can only be used on class level.""" def title(title): """Set a human-readable title for a component (e.g. a permission, menu item, etc.). This directive expects pure ASCII strings or Unicode and can only be used on a class level.""" def description(description): """Set a human-readable description for a component (e.g. a permission, menu item, etc.). This directive expects pure ASCII strings or Unicode and can only be used on a class level.""" def provides(interface): """Explicitly specify with which interface a component will be looked up.""" def global_utility(factory, provides=None, name=u''): """Register a global utility. factory - the factory that creates the global utility provides - the interface the utility should be looked up with name - the name of the utility """ def global_adapter(factory, adapts=None, provides=None, name=u''): """Register a global adapter. factory - the adapter factory, a callable adapts - an interface or list of interfaces adapted provides - the interface provided by the adapter name - the name of the adapter """ def direct(): """Specify whether the class should be used for the component or whether it should be used to instantiate the component. This directive can be used on GlobalUtility-based classes to indicate whether the class itself should be registered as a utility, or an instance of it. """ def order(value=None): """Control the ordering of components. If the value is specified, the order will be determined by sorting on it. If no value is specified, the order will be determined by definition order within the module. If the directive is absent, the order will be determined by class name. (unfortunately our preferred default behavior on absence which would be like grok.order() without argument is hard to implement in Python) Inter-module order is by dotted name of the module the components are in; unless an explicit argument is specified to ``grok.order()``, components are grouped by module. The function grok.util.sort_components can be used to sort components according to these rules. """ class IDecorators(Interface): def subscribe(*classes_or_interfaces): """Declare that a function subscribes to an event or a combination of objects and events.""" def adapter(*classes_or_interfaces): """Describes that a function adapts an object or a combination of objects. """ def implementer(*interfaces): """Describes that a function that's used as an adapter implements an interface or a number of interfaces. """ def provider(*interfaces): """Describes that a function directly provides an interface or a number of interfaces. """ class IGrokErrors(Interface): def GrokError(message, component): """Error indicating that a problem occurrend during the grokking of a module (at "grok time").""" def GrokImportError(*args): """Error indicating a problem at import time.""" class IMartianAPI(Interface): """Part of Martian's API exposed by grokcore.component. """ ClassGrokker = Attribute("Grokker for classes.") GlobalGrokker = Attribute("Grokker that's invoked for a module.") InstanceGrokker = Attribute("Grokker for instances.") class IGrokcoreComponentAPI( IBaseClasses, IDecorators, IDirectives, IGrokErrors, IMartianAPI, ): """grokcore.component's public API. """ getSiteManager = Attribute('Get the site manager for the nearest site.') provideAdapter = Attribute('Registers an adapters') provideHandler = Attribute('Registers an handler') provideInterface = Attribute('Regsiters an interfaces as a utility') provideSubscriptionAdapter = Attribute( 'Registers an subscriptions adapter') provideUtility = Attribute('Registers an utility') querySubscriptions = Attribute("Function to query subscriptions.") queryOrderedSubscriptions = Attribute( "Function to query subscription in order.") queryMultiSubscriptions = Attribute("Function to query subscriptions.") queryOrderedMultiSubscriptions = Attribute( "Function to query subscriptions in order.") sort_components = Attribute( 'Sort a list of components using the information provided by ' '`grok.order`.') grokcore.component-2.5/src/grokcore/component/directive.py0000664000175000017500000001423111750014416023214 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok directives. """ import martian import martian.util from martian.error import GrokError, GrokImportError from martian.util import scan_for_classes from zope import interface from zope.interface.interfaces import IInterface from grokcore.component.interfaces import IContext class global_utility(martian.MultipleTimesDirective): """Registers an instance of ``class`` (or ``class`` itself, depending on the value of the ``direct`` parameter) as a global utility. This allows you to register global utilities that don't inherit from the ``GlobalUtility`` base class. :param class: The class to register as a global utility. :param provides: Optionally, the interface the utility will provide. :param name: Optionally, a name for a named utility registration. :type name: string or unicode :param direct: Optionally, a flag indicating the class directly provides the interfaces, and it needs not to be instantiated. :type direct: boolean """ scope = martian.MODULE def factory(self, factory, provides=None, name=u'', direct=False): if provides is not None and not IInterface.providedBy(provides): raise GrokImportError( "You can only pass an interface to the " "provides argument of %s." % self.name) return (factory, provides, name, direct) class global_adapter(martian.MultipleTimesDirective): """Registers the ``factory`` callable as a global adapter. This allows you to register global adapters that don't inherit from the ``Adapter`` or ``MultiAdapter`` base classes. :param factory: The class that implements the adaptation. :param adapts: Optionally, a single interface or a tuple of multiple interfaces to adapts from. If omitted, this information is deduced from the annotation on the factory. If no adapted interface can be determined the current context will be assumed. :param provides: Optionally, the interface the adapter will provide. If omitted, this information is deduced from the annotations on the factory. :param name: Optionally, a name for a named adapter registration. :type name: string or unicode """ scope = martian.MODULE def factory(self, factory, adapts=None, provides=None, name=None): if provides is not None and not IInterface.providedBy(provides): raise GrokImportError( "You can only pass an interface to the " "provides argument of %s." % self.name) if adapts is None: adapts = getattr(factory, '__component_adapts__', None) elif not isinstance(adapts, (list, tuple,)): adapts = (adapts,) elif isinstance(adapts, list): adapts = tuple(adapts) return (factory, adapts, provides, name) class name(martian.Directive): """Declares the name of a named utility, named adapter, etc. """ scope = martian.CLASS store = martian.ONCE validate = martian.validateText default = u'' class context(martian.Directive): """Declares the type of object that the adapter (or a similar context- dependent component) adapts. :param context: Interface (in this case all objects providing this interface will be eligible contexts for the adaptation) or a class (then only instances of that particular class are eligible). """ scope = martian.CLASS_OR_MODULE store = martian.ONCE validate = martian.validateInterfaceOrClass @classmethod def get_default(cls, component, module=None, **data): components = list(scan_for_classes(module, IContext)) if len(components) == 0: raise GrokError( "No module-level context for %r, please use the 'context' " "directive." % (component), component) elif len(components) == 1: component = components[0] else: raise GrokError( "Multiple possible contexts for %r, please use the 'context' " "directive." % (component), component) return component class title(martian.Directive): """Declares the human-readable title of a component (such as a permission, role, etc.) """ scope = martian.CLASS store = martian.ONCE validate = martian.validateText class description(title): pass class direct(martian.MarkerDirective): """Declares that a ``GlobalUtility`` class should be registered as a utility itself, rather than an instance of it. """ scope = martian.CLASS class order(martian.Directive): scope = martian.CLASS store = martian.ONCE default = 0, 0 _order = 0 def factory(self, value=0): order._order += 1 return value, order._order class path(martian.Directive): scope = martian.CLASS store = martian.ONCE validate = martian.validateText class provides(martian.Directive): """Declares the interface that a adapter or utility provides for the registration, as opposed to potentially multiple interfaces that the class implements. :param interface: The interface the registered component will provide. """ scope = martian.CLASS store = martian.ONCE validate = martian.validateInterface @classmethod def get_default(cls, component, module, **data): martian.util.check_implements_one(component) return list(interface.implementedBy(component))[0] grokcore.component-2.5/src/grokcore/component/meta.py0000664000175000017500000002221111750014416022161 0ustar jwjw00000000000000############################################################################# # # Copyright (c) 2006-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. # ############################################################################## """Grokkers for the various components.""" import operator import martian import martian.util import grokcore.component import zope.component.interface from zope import component, interface from martian.error import GrokError from zope.interface import implementedBy def _provides(component, module=None, **data): martian.util.check_implements_one(component) return list(interface.implementedBy(component))[0] def default_global_utility_provides(component, module, direct, **data): if direct: martian.util.check_provides_one(component) return list(interface.providedBy(component))[0] return _provides(component) class AdapterGrokker(martian.ClassGrokker): martian.component(grokcore.component.Adapter) martian.directive(grokcore.component.context) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, context, provides, name, **kw): config.action( discriminator=('adapter', context, provides, name), callable=grokcore.component.provideAdapter, args=(factory, (context,), provides, name), ) return True class MultiAdapterGrokker(martian.ClassGrokker): martian.component(grokcore.component.MultiAdapter) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, provides, name, **kw): for_ = component.adaptedBy(factory) if for_ is None: raise GrokError("%r must specify which contexts it adapts " "(use the 'adapts' directive to specify)." % factory, factory) config.action( discriminator=('adapter', for_, provides, name), callable=grokcore.component.provideAdapter, args=(factory, None, provides, name), ) return True class SubscriptionGrokker(martian.ClassGrokker): martian.component(grokcore.component.Subscription) martian.directive(grokcore.component.context) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, context, provides, name, **kw): config.action( discriminator=None, callable=grokcore.component.provideSubscriptionAdapter, args=(factory, (context,), provides), ) return True class MultiSubscriptionGrokker(martian.ClassGrokker): martian.component(grokcore.component.MultiSubscription) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, provides, name, **kw): adapts = component.adaptedBy(factory) if adapts is None: raise GrokError("%r must specify which contexts it adapts " "(use the 'adapts' directive to specify)." % factory, factory) config.action( discriminator=None, callable=grokcore.component.provideSubscriptionAdapter, args=(factory, adapts, provides), ) return True class GlobalUtilityGrokker(martian.ClassGrokker): martian.component(grokcore.component.GlobalUtility) # This needs to happen before the FilesystemPageTemplateGrokker grokker # happens, since it relies on the ITemplateFileFactories being grokked. martian.priority(1100) martian.directive(grokcore.component.direct) martian.directive(grokcore.component.provides, get_default=default_global_utility_provides) martian.directive(grokcore.component.name) def execute(self, factory, config, direct, provides, name, **kw): if not direct: factory = factory() config.action( discriminator=('utility', provides, name), callable=grokcore.component.provideUtility, args=(factory, provides, name), ) return True class ImplementerDecoratorGrokker(martian.GlobalGrokker): def grok(self, name, module, module_info, config, **kw): adapters = module_info.getAnnotation('grok.adapters', []) subscribers = set(map(operator.itemgetter(0), module_info.getAnnotation('grok.subscribers', []))) for function in adapters: if function in subscribers: # We don't register functions that are decorated with # grok.implementer() *and* the grok.subscribe() # decorator. These are registered as so called # subcribers and not as regular adapters. continue interfaces = getattr(function, '__component_adapts__', None) if interfaces is None: context = grokcore.component.context.bind().get(module) interfaces = (context, ) name = getattr(function, '__component_name__', u"") config.action( discriminator=('adapter', interfaces, function.__implemented__, name), callable=grokcore.component.provideAdapter, args=(function, interfaces, function.__implemented__, name), ) return True class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker): def grok(self, name, module, module_info, config, **kw): infos = grokcore.component.global_utility.bind().get(module) for factory, provides, name, direct in infos: if direct is None: direct = grokcore.component.direct.bind().get(factory) if provides is None: bound = grokcore.component.provides.bind(default=None) provides = bound.get(factory) if not name: name = grokcore.component.name.bind().get(factory) if direct: obj = factory if provides is None: martian.util.check_provides_one(obj) provides = list(interface.providedBy(obj))[0] else: obj = factory() if provides is None: provides = _provides(factory) config.action( discriminator=('utility', provides, name), callable=grokcore.component.provideUtility, args=(obj, provides, name), ) return True class GlobalAdapterDirectiveGrokker(martian.GlobalGrokker): def grok(self, name, module, module_info, config, **kw): infos = grokcore.component.global_adapter.bind().get(module) for factory, adapts, provides, name in infos: if provides is None: bound = grokcore.component.provides.bind(default=None) provides = bound.get(factory) if adapts is None: adapts = (grokcore.component.context.bind().get(module),) if name is None: name = grokcore.component.name.bind().get(factory) config.action( discriminator=('adapter', adapts, provides, name), callable=grokcore.component.provideAdapter, args=(factory, adapts, provides, name), ) return True class SubscriberDirectiveGrokker(martian.GlobalGrokker): def grok(self, name, module, module_info, config, **kw): subscribers = module_info.getAnnotation('grok.subscribers', []) for factory, subscribed in subscribers: provides = None implemented = list(implementedBy(factory)) if len(implemented) == 1: provides = implemented[0] # provideHandler is essentially the same as # provideSubscriptionAdapter, where provided=None. However, # handlers and subscription adapters are tracked in # separately so we cannot exchange one registration call # for the the other. if provides is None: config.action( discriminator=None, callable=grokcore.component.provideHandler, args=(factory, subscribed)) else: config.action( discriminator=None, callable=grokcore.component.provideSubscriptionAdapter, args=(factory, subscribed, provides)) for iface in subscribed: config.action( discriminator=None, callable=grokcore.component.provideInterface, args=('', iface)) return True grokcore.component-2.5/src/grokcore/component/subscription.py0000664000175000017500000000333111750014416023761 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok subscriptions functions. """ from zope import component from grokcore.component import util def queryOrderedMultiSubscriptions(components, interface): return util.sort_components(component.subscribers(components, interface)) def queryOrderedSubscriptions(component, interface): return queryOrderedMultiSubscriptions((component, ), interface) def queryMultiSubscriptions(components, interface): """Query for subscriptions on the `components` providing `interface`. :parameter components: tuple of components to lookup the subscription for. :parameter interface: interface that the subscriptions should provide. :return: a list of subscriptions. """ return component.subscribers(components, interface) def querySubscriptions(component, interface): """Query for subscriptions on `component` providing `interface`. :parameter component: a component to lookup the subscriptions for. :parameter interface: interface that the subscriptions should provide. :return: a list of subscription. """ return queryMultiSubscriptions((component,), interface) grokcore.component-2.5/src/grokcore/component/decorators.py0000664000175000017500000001123711750014416023406 0ustar jwjw00000000000000############################################################################## # # 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. # ############################################################################## """Grok """ import sys import types import zope.component import zope.interface from martian.util import frame_is_module from martian.error import GrokImportError from zope.interface.declarations import DescriptorAwareMetaClasses class subscribe: """Declares that a function is to be registered as an event handler for the specified objects. Normally, an event handler is simply registered as a subscriber for the event interface. In case of object events, the event handler is registered as a subscriber for the object type and the event interface. """ def __init__(self, *args): self.subscribed = args def __call__(self, function): frame = sys._getframe(1) if not frame_is_module(frame): raise GrokImportError("@grok.subscribe can only be used on module " "level.") if not self.subscribed: raise GrokImportError("@grok.subscribe requires at least one " "argument.") # Add the function and subscribed interfaces to the # grok.subscribers module annotation. subscribers = frame.f_locals.get('__grok_subscribers__', None) if subscribers is None: frame.f_locals['__grok_subscribers__'] = subscribers = [] subscribers.append((function, self.subscribed)) # Also store the subscribed interfaces on the # attribute__component_adapts__ for provideHandler to register # the subscriber (in case you don't grok your package and # register it manually) return zope.component.adapter(*self.subscribed)(function) class adapter(zope.component.adapter): """Registers the function as an adapter for the specific interface. The ``name`` argument must be a keyword argument and is optional. If given, a named adapter is registered. """ # Override the z.c.adapter decorator to force sanity checking and # have better error reporting and add the ability to capture the name def __init__(self, *interfaces, **kw): if not interfaces: raise GrokImportError( "@grok.adapter requires at least one argument.") if type(interfaces[0]) is types.FunctionType: raise GrokImportError( "@grok.adapter requires at least one argument.") self.name = u"" if kw: if 'name' in kw: self.name = kw.pop('name') if kw: raise GrokImportError( "@grok.adapter got unexpected keyword arguments: %s" % ','.join(kw.keys())) zope.component.adapter.__init__(self, *interfaces) def __call__(self, ob): ob = zope.component.adapter.__call__(self, ob) if self.name: ob.__component_name__ = self.name return ob class implementer(zope.interface.implementer): """Declares that the function implements a certain interface (or a number of interfaces). This is useful when a function serves as an object factory, e.g. as an adapter. """ def __call__(self, ob): # XXX we do not have function grokkers (yet) so we put the annotation # on the module. frame = sys._getframe(1) adapters = frame.f_locals.get('__grok_adapters__', None) if adapters is None: frame.f_locals['__grok_adapters__'] = adapters = [] adapters.append(ob) return zope.interface.implementer.__call__(self, ob) class provider: """Declares that the function object provides a certain interface (or a number of interfaces). This is akin to calling directlyProvides() on the function object. """ def __init__(self, *interfaces): self.interfaces = interfaces def __call__(self, ob): if isinstance(ob, DescriptorAwareMetaClasses): raise TypeError("Can't use implementer with classes. Use one of " "the class-declaration functions instead." ) zope.interface.alsoProvides(ob, *self.interfaces) return ob grokcore.component-2.5/src/grokcore/component/templates/0000775000175000017500000000000011750014424022660 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/templates/default_display_form.pt0000664000175000017500000000147311750014416027427 0ustar jwjw00000000000000
   
grokcore.component-2.5/src/grokcore/component/templates/default_edit_form.pt0000664000175000017500000000377711750014416026720 0ustar jwjw00000000000000

Label

Form status summary
  • Error Type
error
grokcore.component-2.5/src/grokcore/component/zcml.py0000664000175000017500000000420311750014416022201 0ustar jwjw00000000000000############################################################################## # # Copyright (c) 2006-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. # ############################################################################## """Grok ZCML directives.""" from zope.interface import Interface from zope.configuration.fields import GlobalObject from zope.schema import TextLine import martian class IGrokDirective(Interface): """Grok a package or module.""" package = GlobalObject( title=u"Package", description=u"The package or module to be analyzed by grok.", required=False) exclude = TextLine( title=u"Exclude", description=u"Name to exclude in the grokking process.", required=False) # add a cleanup hook so that grok will bootstrap itself again whenever # the Component Architecture is torn down. def resetBootstrap(): # we need to make sure that the grokker registry is clean again the_module_grokker.clear() from zope.testing.cleanup import addCleanUp addCleanUp(resetBootstrap) the_multi_grokker = martian.MetaMultiGrokker() the_module_grokker = martian.ModuleGrokker(the_multi_grokker) def skip_tests(name): return name in ['tests', 'ftests', 'testing'] def grokDirective(_context, package, exclude=None): if not exclude: exclude = None do_grok(package.__name__, _context, extra_exclude=exclude) def do_grok(dotted_name, config, extra_exclude=None): if extra_exclude is not None: def exclude_filter(name): return skip_tests(name) or extra_exclude == name else: exclude_filter = skip_tests martian.grok_dotted_name( dotted_name, the_module_grokker, exclude_filter=exclude_filter, config=config) grokcore.component-2.5/src/grokcore/component/tests/0000775000175000017500000000000011750014424022024 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/utility/0000775000175000017500000000000011750014424023527 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/utility/__init__.py0000664000175000017500000000002411750014416025635 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/utility/providesmany.py0000664000175000017500000000126211750014416026623 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility that are supposed to be registered directly as utilities and which provide more than one interface must specify which interface to use for the registration: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: provides more than one interface (use grok.provides to specify which one to use). """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ISpikyClub(interface.Interface): pass class Club(grok.GlobalUtility): interface.classProvides(IClub, ISpikyClub) grok.direct() grokcore.component-2.5/src/grokcore/component/tests/utility/providesmany2.py0000664000175000017500000000127511750014416026711 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility that are supposed to be registered directly as utilities and which provide more than one interface must specify which interface to use for the registration: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: provides more than one interface (use grok.provides to specify which one to use). """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ISpikyClub(interface.Interface): pass class Club(object): interface.classProvides(IClub, ISpikyClub) grok.global_utility(Club, direct=True) grokcore.component-2.5/src/grokcore/component/tests/utility/implementsmany2.py0000664000175000017500000000116411750014416027230 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility that implement more than one interface must specify which interface to use for the registration: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: is implementing more than one interface (use grok.provides to specify which one to use). """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ISpikyClub(interface.Interface): pass class Club(object): grok.implements(IClub, ISpikyClub) grok.global_utility(Club) grokcore.component-2.5/src/grokcore/component/tests/utility/providesnone.py0000664000175000017500000000062511750014416026620 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must provide at least one interface (use zope.interface.classProvides to specify). """ import grokcore.component as grok class Club(grok.GlobalUtility): grok.direct() grokcore.component-2.5/src/grokcore/component/tests/utility/implementsnone.py0000664000175000017500000000060111750014416027134 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Club(grok.GlobalUtility): pass grokcore.component-2.5/src/grokcore/component/tests/utility/implementsnone2.py0000664000175000017500000000062111750014416027220 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Club(object): pass grok.global_utility(Club) grokcore.component-2.5/src/grokcore/component/tests/utility/conflict.py0000664000175000017500000000521611750014416025707 0ustar jwjw00000000000000""" Trying to register two utilities for the same interface (and potentially under the same name) will generate a configuration conflict: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... ConfigurationConflictError: Conflicting configuration actions For: ('utility', , 'class and module') For: ('utility', , 'direct class') For: ('utility', , 'explicit class') For: ('utility', , 'implicit class') For: ('utility', , 'mixed class') """ import grokcore.component as grok from zope.interface import Interface, classProvides class IUtilityInterface(Interface): pass class IAnotherInterface(Interface): pass class Implicit1(grok.GlobalUtility): grok.implements(IUtilityInterface) grok.name('implicit class') class Implicit2(grok.GlobalUtility): grok.implements(IUtilityInterface) grok.name('implicit class') class Explicit1(grok.GlobalUtility): grok.implements(IUtilityInterface, IAnotherInterface) grok.provides(IUtilityInterface) grok.name('explicit class') class Explicit2(grok.GlobalUtility): grok.implements(IUtilityInterface, IAnotherInterface) grok.provides(IUtilityInterface) grok.name('explicit class') class Mixed1(grok.GlobalUtility): grok.implements(IUtilityInterface, IAnotherInterface) grok.provides(IUtilityInterface) grok.name('mixed class') class Mixed2(grok.GlobalUtility): grok.implements(IUtilityInterface) grok.name('mixed class') class Direct1(grok.GlobalUtility): classProvides(IUtilityInterface) grok.name('direct class') grok.direct() class Direct2(grok.GlobalUtility): classProvides(IUtilityInterface) grok.name('direct class') grok.direct() class ClassLevel(grok.GlobalUtility): """This utility inherits from Grok's base class and is registered this way.""" grok.implements(IUtilityInterface) grok.name('class and module') class ModuleLevel(object): """This utility doesn't inherit from Grok's base class and is registered explicitly using the module-level directive below.""" grok.implements(IUtilityInterface) grok.global_utility(ModuleLevel, name='class and module') grokcore.component-2.5/src/grokcore/component/tests/utility/implementsmany.py0000664000175000017500000000114311750014416027143 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility that implement more than one interface must specify which interface to use for the registration: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: is implementing more than one interface (use grok.provides to specify which one to use). """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ISpikyClub(interface.Interface): pass class Club(grok.GlobalUtility): grok.implements(IClub, ISpikyClub) grokcore.component-2.5/src/grokcore/component/tests/utility/providesnone2.py0000664000175000017500000000065111750014416026701 0ustar jwjw00000000000000""" Subclasses of grok.GlobalUtility must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must provide at least one interface (use zope.interface.classProvides to specify). """ import grokcore.component as grok class Club(object): pass grok.global_utility(Club, direct=True) grokcore.component-2.5/src/grokcore/component/tests/utility/utility.py0000664000175000017500000001224511750014416025611 0ustar jwjw00000000000000""" Global utilities can be created by subclassing grok.GlobalUtility: >>> grok.testing.grok(__name__) >>> from zope import component >>> normal_club = component.getUtility(IClub) >>> IClub.providedBy(normal_club) True >>> isinstance(normal_club, NormalClub) True Named utilities are registered using grok.name: >>> huge_club = component.getUtility(IClub, name='huge') >>> IClub.providedBy(huge_club) True >>> isinstance(huge_club, HugeClub) True A utility can explicitly specify which interface it should be looked up with. >>> spiky_club = component.getUtility(IClub, name='spiky') >>> isinstance(spiky_club, SpikyClub) True >>> component.getUtility(ISpikyClub, name='spiky') Traceback (most recent call last): ... ComponentLookupError: (, 'spiky') If a utility implements more than one interface, it has to specify the one to use with 'grok.provides': >>> nightclub = component.getUtility(INightClub) >>> INightClub.providedBy(nightclub) True >>> isinstance(nightclub, NightClub) True You can make the class the utility by providing the grok.direct() directive, if you also use interface.classProvides instead of grok.provides. This is useful for utilities that do nothing but create instances: >>> clubmaker = component.getUtility(IClubMaker, 'maker') >>> IClubMaker.providedBy(clubmaker) True >>> clubmaker is ClubMaker True Utilities (including classes that do not subclass from grok.GlobalUtility) can be (re-)registered using grok.global_utility: >>> fireplace = component.getUtility(IFireplace) >>> IFireplace.providedBy(fireplace) True >>> isinstance(fireplace, Fireplace) True >>> fireplace = component.getUtility(IFireplace, name='hot') >>> IFireplace.providedBy(fireplace) True >>> isinstance(fireplace, Fireplace) True >>> home = component.getUtility(IHome) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True >>> night = component.getUtility(INightClub, name='cool') >>> IClub.providedBy(night) True >>> isinstance(night, NightClub) True >>> spiky = component.getUtility(ISpikyClub) >>> ISpikyClub.providedBy(spiky) True >>> isinstance(spiky, NightClub) True When re-registering a grok.GlobalUtility, the directives grok.name and grok.provides on the class will be used, but can be overriden in the grok.global_utility directive: >>> small = component.getUtility(ISmallClub, name='tiny') >>> ISmallClub.providedBy(small) True >>> isinstance(small, SmallClub) True >>> small2 = component.getUtility(ITinyClub, name='tiny') >>> ISmallClub.providedBy(small2) True >>> isinstance(small2, SmallClub) True >>> small is not small2 True >>> small3 = component.getUtility(ISmallClub, name='small') >>> ISmallClub.providedBy(small3) True >>> isinstance(small3, SmallClub) True >>> small3 is not small2 and small3 is not small True Normally one registers a utility factory, such as the class, as a global utility. It is also possible to register an arbitrary object directly as a global utility. You do this by passing a 'direct' argument set to 'True'. This can be useful if one needs to register functions (such as factory functions) that can be looked up as a utility, or if the class you want to register as a global utility has an __init__ that takes arguments, where you want to do the instantiation yourself. Let's look up an instance we registered this way: >>> small4 = component.getUtility(ISmallClub, name='smallish') >>> ISmallClub.providedBy(small4) True >>> isinstance(small4, SmallClub) True """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ISpikyClub(IClub): pass class ISmallClub(IClub): pass class ITinyClub(IClub): pass class INightClub(interface.Interface): pass class IClubMaker(interface.Interface): pass class NormalClub(grok.GlobalUtility): grok.implements(IClub) class HugeClub(grok.GlobalUtility): grok.implements(IClub) grok.name('huge') class SpikyClub(grok.GlobalUtility): grok.implements(ISpikyClub) grok.provides(IClub) grok.name('spiky') class NightClub(grok.GlobalUtility): grok.implements(INightClub, ISpikyClub) grok.provides(INightClub) class SmallClub(grok.GlobalUtility): grok.implements(ISmallClub, ITinyClub) grok.provides(ISmallClub) grok.name('tiny') class ClubMaker(grok.GlobalUtility): grok.implements(IClub) interface.classProvides(IClubMaker) grok.direct() grok.name('maker') class IFireplace(interface.Interface): pass class IHome(interface.Interface): pass class Fireplace(object): grok.implements(IFireplace) class Home(object): grok.implements(IFireplace, IHome) grok.global_utility(Fireplace) grok.global_utility(Fireplace, name='hot') grok.global_utility(Home, provides=IHome) grok.global_utility(NightClub, name='cool') grok.global_utility(NightClub, provides=ISpikyClub) grok.global_utility(SmallClub, provides=ITinyClub) grok.global_utility(SmallClub, name='small') grok.global_utility(SmallClub(), name='smallish', direct=True) grokcore.component-2.5/src/grokcore/component/tests/order/0000775000175000017500000000000011750014424023137 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/order/arg_orderdirective.py0000664000175000017500000000165111750014416027360 0ustar jwjw00000000000000""" If the grok.order directive is present with arguments, sorting will be done by the order specified. >>> from grokcore.component import sort_components >>> components = [First(), Second(), Third(), Fourth(), Fifth()] >>> sort_components(components) [<...Fifth object at ...>, <...Fourth object at ...>, <...Third object at ...>, <...Second object at ...>, <...First object at ...>] You can use the key option: >>> from operator import itemgetter >>> components = [(1, First()), (2, Second()), (3, Third())] >>> sort_components(components, key=itemgetter(1)) [(3, <...Third object at ...>), (2, <...Second object at ...>), (1, <...First object at ...>)] """ import grokcore.component as grok class First(object): grok.order(5) class Second(object): grok.order(4) class Third(object): grok.order(3) class Fourth(object): grok.order(2) class Fifth(object): grok.order(1) grokcore.component-2.5/src/grokcore/component/tests/order/__init__.py0000664000175000017500000000000211750014416025241 0ustar jwjw00000000000000# grokcore.component-2.5/src/grokcore/component/tests/order/combined_orderdirective.py0000664000175000017500000000136211750014416030366 0ustar jwjw00000000000000""" If the grok.order directive is specified with other classes that don't have the order specified, then the order will be determined by first sorting on the order specified, and then by the definition order. >>> components = [First(), Second(), Third(), Fourth(), Fifth()] >>> from grokcore.component import sort_components >>> sort_components(components) [<...Third object at ...>, <...Fourth object at ...>, <...Second object at ...>, <...Fifth object at ...>, <...First object at ...>] """ import grokcore.component as grok class First(object): grok.order(2) class Second(object): grok.order(1) class Third(object): grok.order() class Fourth(object): grok.order() class Fifth(object): grok.order(1) grokcore.component-2.5/src/grokcore/component/tests/order/noarg_orderdirective.py0000664000175000017500000000120511750014416027710 0ustar jwjw00000000000000""" If the grok.order directive is present with no arguments, sorting will be done by definition order. >>> components = [First(), Second(), Third(), Fourth(), Fifth()] >>> from grokcore.component import sort_components >>> sort_components(components) [<...First object at ...>, <...Second object at ...>, <...Third object at ...>, <...Fourth object at ...>, <...Fifth object at ...>] """ import grokcore.component as grok class First(object): grok.order() class Second(object): grok.order() class Third(object): grok.order() class Fourth(object): grok.order() class Fifth(object): grok.order() grokcore.component-2.5/src/grokcore/component/tests/order/nodirective.py0000664000175000017500000000104111750014416026021 0ustar jwjw00000000000000""" If the grok.order directive is absent, sorting will be done by class name. >>> components = [First(), Second(), Third(), Fourth(), Fifth()] >>> from grokcore.component import sort_components >>> sort_components(components) [<...Fifth object at ...>, <...First object at ...>, <...Fourth object at ...>, <...Second object at ...>, <...Third object at ...>] """ class First(object): pass class Second(object): pass class Third(object): pass class Fourth(object): pass class Fifth(object): pass grokcore.component-2.5/src/grokcore/component/tests/order/inter2.py0000664000175000017500000000026611750014416024721 0ustar jwjw00000000000000""" This module used by inter1 tests """ import grokcore.component as grok class Four(object): grok.order(1) class Five(object): pass class Six(object): grok.order() grokcore.component-2.5/src/grokcore/component/tests/order/combinednoorder_orderdirective.py0000664000175000017500000000134011750014416031753 0ustar jwjw00000000000000""" If the grok.order directive is specified with other classes that don't have the order specified, then the order will be determined by first sorting on the order specified, and then by the definition order. >>> components = [First(), Second(), Third(), Fourth(), Fifth()] >>> from grokcore.component import sort_components >>> sort_components(components) [<...Fifth object at ...>, <...Third object at ...>, <...First object at ...>, <...Fourth object at ...>, <...Second object at ...>] """ import grokcore.component as grok class First(object): grok.order() class Second(object): grok.order(1) class Third(object): pass class Fourth(object): grok.order() class Fifth(object): pass grokcore.component-2.5/src/grokcore/component/tests/order/inter1.py0000664000175000017500000000155711750014416024724 0ustar jwjw00000000000000""" The ordering works like so: 1. Objects with explicit ordering (if combined with objects with no ordering not specified, then the orderless objects come first) 2. Objects with same ordering get grouped by module import order 3. Internal order within module 4. If no ordering is specified by any objects, then objects are sorted alphabetically by class name >>> from inter2 import Four, Five, Six >>> components = [One(), Two(), Three(), Four(), Five(), Six()] >>> from grokcore.component import sort_components >>> sort_components(components) [<...Three object at ...>, <...One object at ...>, <...Five object at ...>, <...Six object at ...>, <...Four object at ...>, <...Two object at ...>] """ import grokcore.component as grok class One(object): grok.order() class Two(object): grok.order(2) class Three(object): pass grokcore.component-2.5/src/grokcore/component/tests/directive/0000775000175000017500000000000011750014424024002 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/directive/__init__.py0000664000175000017500000000002411750014416026110 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/directive/argumenterror_fixture.py0000664000175000017500000000014011750014416031012 0ustar jwjw00000000000000import grokcore.component as grok class Foo(object): grok.name('too', 'many', 'arguments') grokcore.component-2.5/src/grokcore/component/tests/directive/multipletimes.py0000664000175000017500000000210411750014416027247 0ustar jwjw00000000000000""" Since grok.global_utility is a MultipleTimesDirective, there is a list of GlobalUtilityInfo objects annotated on the module. >>> from martian import scan >>> import grokcore.component as grok >>> from grokcore.component.tests.directive import multipletimes >>> guis = grok.global_utility.bind().get(multipletimes) >>> len(guis) 2 >>> factory, provides, name, direct = guis[0] >>> factory >>> provides >>> name 'foo' >>> factory, provides, name, direct = guis[1] >>> factory >>> provides is None True >>> name u'' """ import grokcore.component as grok from zope import interface class IClub(interface.Interface): pass class ICave(interface.Interface): pass class Club(object): grok.implements(IClub) class Cave(object): grok.implements(ICave) grok.global_utility(Club, provides=IClub, name='foo') grok.global_utility(Cave) grokcore.component-2.5/src/grokcore/component/tests/directive/argumenterror.py0000664000175000017500000000026511750014416027254 0ustar jwjw00000000000000""" >>> import grokcore.component.tests.directive.argumenterror_fixture Traceback (most recent call last): ... TypeError: name takes exactly 1 argument (3 given) """ grokcore.component-2.5/src/grokcore/component/tests/__init__.py0000664000175000017500000000004011750014416024130 0ustar jwjw00000000000000# make this directory a package grokcore.component-2.5/src/grokcore/component/tests/grokker/0000775000175000017500000000000011750014424023470 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/grokker/continue_scanning.py0000664000175000017500000000213311750014416027546 0ustar jwjw00000000000000""" A Grokker can declare that scanning should continue, so that other Grokkers can still perform actions on the grokked components. Here we define AlphaGrokker which has higher priority than BetaGrokker but does not block BetaGrokker from picking up the same component:: >>> import grokcore.component as grok >>> grok.testing.grok(__name__) In the fixture there is AlphaBetaSub that inherits from both Alpha and Beta. Thus, both Grokkers are executed, with AlphaGrokker coming before BetaGrokker:: >>> grok.testing.grok('grokcore.component.tests.grokker.continue_scanning_fixture') alpha beta """ import martian class Alpha(object): pass class Beta(object): pass class AlphaGrokker(martian.ClassGrokker): martian.component(Alpha) martian.priority(1) # we need to go before BetaGrokker def grok(self, name, factory, module_info, config, **kw): print "alpha" return True class BetaGrokker(martian.ClassGrokker): martian.component(Beta) def grok(self, name, factory, module_info, config, **kw): print "beta" return True grokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce.py0000664000175000017500000000167711750014416025704 0ustar jwjw00000000000000""" We define a grokker AlphaGrokker for a component called Alpha. We first need to grok the module defining the grokkers, in order to get them registered. Usually this would be triggered from a meta.zcml in a package, that would grok the module containing the grokkers (e.g. meta.py). We do it manually now:: >>> import grokcore.component as grok >>> grok.testing.grok('grokcore.component.tests.grokker.onlyonce_fixture._meta') This _meta.py module then will be grokked again during 'normal' grok time. Grok will not re-register the grokkers as this could have unwanted side-effects. It will grok the components of course. NOTE: the module is called _meta to make sure it is grokked (although its grokker registration should be ignored) before the other files. The modules are picked up in alphabetical order. To simulate this, we grok the whole package:: >>> grok.testing.grok('grokcore.component.tests.grokker.onlyonce_fixture') alpha """ grokcore.component-2.5/src/grokcore/component/tests/grokker/grokcomponent.py0000664000175000017500000000334711750014416026737 0ustar jwjw00000000000000""" Let's first grok the meta module to define some basic grokkers:: >>> import grokcore.component as grok >>> grok.testing.grok('grokcore.component.meta') It is possible to grok an individual component. Let's define an adapter:: >>> from zope.interface import Interface >>> class IMyInterface(Interface): ... pass >>> class SomeClass(object): ... pass >>> class MyAdapter(grok.Adapter): ... grok.provides(IMyInterface) ... grok.context(SomeClass) To grok this adapter, you can simply write this:: >>> grok.testing.grok_component('MyAdapter', MyAdapter) True We can now use the adapter:: >>> instance = SomeClass() >>> adapter = IMyInterface(instance) >>> isinstance(adapter, MyAdapter) True We can use grok_component with only two arguments because we know the adapter grokker is not looking for more. Sometimes we need to supply an extra argument however:: >>> class ISecondInterface(Interface): ... pass >>> class SecondAdapter(grok.Adapter): ... grok.provides(ISecondInterface) This adapter does not supply its own context. Trying to do what we did before will therefore fail:: >>> grok.testing.grok_component('SecondAdapter', SecondAdapter) Traceback (most recent call last): ... GrokError: No module-level context for , please use the 'context' directive. So we need to supply the context ourselves:: >>> grok.testing.grok_component('SecondAdapter', SecondAdapter, context=SomeClass) True Now we can use the SecondAdapter as well:: >>> adapter = ISecondInterface(instance) >>> isinstance(adapter, SecondAdapter) True The next optional argument is module_info and the final argument is templates. """ grokcore.component-2.5/src/grokcore/component/tests/grokker/__init__.py0000664000175000017500000000000111750014416025571 0ustar jwjw00000000000000 grokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce_fixture/0000775000175000017500000000000011750014424027064 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce_fixture/__init__.py0000664000175000017500000000002111750014416031167 0ustar jwjw00000000000000# fixture packagegrokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce_fixture/implementation.py0000664000175000017500000000007411750014416032465 0ustar jwjw00000000000000from component import Alpha class AlphaSub(Alpha): passgrokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce_fixture/_meta.py0000664000175000017500000000032411750014416030523 0ustar jwjw00000000000000import martian from component import Alpha class AlphaGrokker(martian.ClassGrokker): martian.component(Alpha) def grok(self, name, factory, module_info, **kw): print "alpha" return True grokcore.component-2.5/src/grokcore/component/tests/grokker/onlyonce_fixture/component.py0000664000175000017500000000011511750014416031436 0ustar jwjw00000000000000import grokcore.component as grok class Alpha(object): grok.baseclass() grokcore.component-2.5/src/grokcore/component/tests/grokker/continue_scanning_fixture.py0000664000175000017500000000016611750014416031320 0ustar jwjw00000000000000from grokcore.component.tests.grokker.continue_scanning import Alpha, Beta class AlphaBetaSub(Alpha, Beta): pass grokcore.component-2.5/src/grokcore/component/tests/grokker/priority_fixture.py0000664000175000017500000000042011750014416027466 0ustar jwjw00000000000000import grokcore.component.tests.grokker.priority class AlphaSub(grokcore.component.tests.grokker.priority.Alpha): pass class BetaSub(grokcore.component.tests.grokker.priority.Beta): pass class GammaSub(grokcore.component.tests.grokker.priority.Gamma): pass grokcore.component-2.5/src/grokcore/component/tests/grokker/priority.py0000664000175000017500000000227511750014416025732 0ustar jwjw00000000000000""" We define grokkers for the three base classes Alpha, Beta, and Gamma with different priorities: - AlphaGrokker with priority 0 (default) - BetaGrokker with priority 1 - GammaGrokker with priority -1 >>> import grokcore.component as grok >>> grok.testing.grok(__name__) We grok a module that implements subclasses for Alpha, Beta, and Gamma and our grokkers get executed in the order of priority (highest first):: >>> grok.testing.grok('grokcore.component.tests.grokker.priority_fixture') beta alpha gamma """ import martian class Alpha(object): pass class Beta(object): pass class Gamma(object): pass class AlphaGrokker(martian.ClassGrokker): martian.component(Alpha) def grok(self, name, factory, module_info, **kw): print "alpha" return True class BetaGrokker(martian.ClassGrokker): martian.component(Beta) martian.priority(1) def grok(self, name, factory, module_info, **kw): print "beta" return True class GammaGrokker(martian.ClassGrokker): martian.component(Gamma) martian.priority(-1) def grok(self, name, factory, module_info, **kw): print "gamma" return True grokcore.component-2.5/src/grokcore/component/tests/api.txt0000664000175000017500000000124111750014416023335 0ustar jwjw00000000000000The grokcore.component API ========================== The grokcore.component API is described by the ``grokcore.component.interfaces.IGrokcoreComponentAPI`` interface. When you do >>> from grokcore.component import * only those objects described in that API interface are imported into your local namespace. In other words, if we take the list of things that have been imported and subtract the things that have been defined in the API interface, we'll end with pretty much nothing: >>> from grokcore.component.interfaces import IGrokcoreComponentAPI >>> sorted(set(locals()) - set(IGrokcoreComponentAPI)) ['IGrokcoreComponentAPI', '__builtins__', '__file__'] grokcore.component-2.5/src/grokcore/component/tests/grok_component.txt0000664000175000017500000000244311750014416025615 0ustar jwjw00000000000000Test grok_component() in an ordinary doctest. We already have tests for grok_component(), but these were placed inside a module. We will now test grok_component() in a pure doctest context. This used to demonstrate an error in martian when dealing with the __builtin__ module (fixed in martian 0.9.2). grokcore.component.testing.grok_component() can be used to grok individual components within a doctest, such as adapters. It sets up just enough context for some grokking to work, though more complicated grokkers which need module context (such as view grokkers) might not work. This defines the object we want to provide an adapter for:: >>> class Bar(object): ... pass This is the interface that we want to adapt to:: >>> from zope.interface import Interface >>> class IFoo(Interface): ... pass This is the adapter itself:: >>> import grokcore.component as grok >>> class MyAdapter(grok.Adapter): ... grok.provides(IFoo) ... grok.context(Bar) Now we will register the adapter using grok_component():: >>> from grokcore.component.testing import grok, grok_component >>> grok('grokcore.component.meta') >>> grok_component('MyAdapter', MyAdapter) True The adapter should now be available:: >>> adapted = IFoo(Bar()) >>> isinstance(adapted, MyAdapter) True grokcore.component-2.5/src/grokcore/component/tests/subscriptions/0000775000175000017500000000000011750014424024733 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/subscriptions/multisubscriptions_no_adapts.py0000664000175000017500000000076011750014416033323 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must specify which contexts it adapts (use the 'adapts' directive to specify). """ import grokcore.component as grok from zope import interface class IRenovate(interface.Interface): def takedown(): pass class CaveGardenRenovator(grok.MultiSubscription): grok.provides(IRenovate) grokcore.component-2.5/src/grokcore/component/tests/subscriptions/multisubscriptions_no_interface.py0000664000175000017500000000070311750014416034004 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Cave(grok.Context): pass class Garden(grok.Context): pass class CaveGardenRedecorator(grok.MultiSubscription): pass grokcore.component-2.5/src/grokcore/component/tests/subscriptions/multisubscriptions.py0000664000175000017500000000466211750014416031300 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave('Tilburg cave') >>> martijn = Mammoth('Martijn') You can query a subscriptions using multiple components. You will get all subscriptions registered for office and cave (since office is a base class of cave): >>> subscriptions = grok.queryMultiSubscriptions((cave, martijn), IActivity) >>> subscriptions [, , ] >>> _ = map(lambda s: s.do(), subscriptions) Martijn is sleeping at Tilburg cave. Martijn is feeding himself at Tilburg cave. Martijn is writing code at Tilburg cave! Now, Martijn goes to the office. You will only get subscriptions registered for office: >>> office = Office('Grok corp(r)(tm) headquarters') >>> office_subscriptions = grok.queryMultiSubscriptions( ... (office, martijn), IActivity) >>> office_subscriptions [] >>> _ = map(lambda s: s.do(), office_subscriptions) Martijn is sleeping at Grok corp(r)(tm) headquarters. """ import grokcore.component as grok from zope import interface class Office(grok.Context): def __init__(self, name): self.name = name # All caves are a kind of office. class Cave(Office): pass class Mammoth(grok.Context): def __init__(self, name): self.name = name class IActivity(interface.Interface): def do(): """Do something. """ class Sleep(grok.MultiSubscription): grok.implements(IActivity) grok.adapts(Office, Mammoth) def __init__(self, where, who): self.where = where self.who = who def do(self): print '%s is sleeping at %s.' % (self.who.name, self.where.name) class DayTimeActivity(grok.MultiSubscription): grok.implements(IActivity) grok.adapts(Cave, Mammoth) grok.baseclass() def __init__(self, where, who): self.where = where self.who = who def do(self): print 'nothing' class Food(DayTimeActivity): def do(self): print '%s is feeding himself at %s.' % (self.who.name, self.where.name) class WritingCode(DayTimeActivity): def do(self): print '%s is writing code at %s!' % (self.who.name, self.where.name) grokcore.component-2.5/src/grokcore/component/tests/subscriptions/subscriptions_no_interface.py0000664000175000017500000000060311750014416032730 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Cave(grok.Context): pass class CaveProcessor(grok.Subscription): pass grokcore.component-2.5/src/grokcore/component/tests/subscriptions/__init__.py0000664000175000017500000000002411750014416027041 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/subscriptions/ordered_subscriptions.py0000664000175000017500000000350411750014416031723 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave() You can query the subscriptions and sort them with the information provided by grok.order: >>> ordered_subscriptions = grok.queryOrderedSubscriptions(cave, ICleaner) >>> ordered_subscriptions [, , ] >>> _ = map(lambda s: s.work(), ordered_subscriptions) Monday cleaning! Wednesday cleaning! Saturday cleaning! If you use the regular query method, they won't be sorted: >>> subscriptions = grok.querySubscriptions(cave, ICleaner) >>> subscriptions [, , ] >>> _ = map(lambda s: s.work(), subscriptions) Monday cleaning! Saturday cleaning! Wednesday cleaning! """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class ICleaner(interface.Interface): def work(): """Clean that cave. """ class MondayCleaner(grok.Subscription): grok.implements(ICleaner) grok.order(1) def work(self): print 'Monday cleaning!' class WednesdayCleaner(grok.Subscription): grok.implements(ICleaner) grok.order(3) def work(self): print 'Wednesday cleaning!' class SaturdayCleaner(grok.Subscription): grok.implements(ICleaner) grok.order(6) def work(self): print 'Saturday cleaning!' grokcore.component-2.5/src/grokcore/component/tests/subscriptions/subscriptions_no_context.py0000664000175000017500000000070511750014416032457 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: No module-level context for , please use the 'context' directive. """ import grokcore.component as grok from zope import interface class ITask(interface.Interface): def finish(): pass class CaveProcessor(grok.Subscription): grok.provides(ITask) grokcore.component-2.5/src/grokcore/component/tests/subscriptions/decorator.py0000664000175000017500000000143511750014416027273 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave('sweet home') >>> subscriptions = grok.querySubscriptions(cave, IActivity) >>> subscriptions [] Subscription adapters are not registered as regular adapters: >>> from zope import component >>> component.queryAdapter(cave, IActivity) """ import grokcore.component as grok from zope import interface class Cave(grok.Context): def __init__(self, name): self.name = name class IActivity(interface.Interface): pass class DebuggingGrokcore(object): def __init__(self, where): self.where = where @grok.subscribe(Cave) @grok.implementer(IActivity) def debugging(content): return DebuggingGrokcore(content) grokcore.component-2.5/src/grokcore/component/tests/subscriptions/subscriptions.py0000664000175000017500000000255511750014416030224 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave('sweet home') >>> subscriptions = grok.querySubscriptions(cave, ICleaner) >>> subscriptions [, , ] >>> _ = map(lambda s: s.work(), subscriptions) Monday cleaning sweet home! Saturday cleaning sweet home! Wednesday cleaning sweet home! Subscription adapters are not registered as regular adapters: >>> component.queryAdapter(cave, ICleaner) """ import grokcore.component as grok from zope import interface, component class Cave(grok.Context): def __init__(self, name): self.name = name class ICleaner(interface.Interface): def work(): """Clean that cave. """ class MondayCleaner(grok.Subscription): grok.implements(ICleaner) def work(self): print 'Monday cleaning %s!' % self.context.name class WednesdayCleaner(grok.Subscription): grok.provides(ICleaner) def work(self): print 'Wednesday cleaning %s!' % self.context.name class SaturdayCleaner(grok.Subscription): grok.implements(ICleaner) def work(self): print 'Saturday cleaning %s!' % self.context.name grokcore.component-2.5/src/grokcore/component/tests/subscriptions/ordered_multisubscriptions.py0000664000175000017500000000506011750014416032775 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave('Tilburg cave') >>> martijn = Mammoth('Martijn') You can query a subscriptions using multiple components and sort them using `grok.order` information: >>> ordered_subscriptions = grok.queryOrderedMultiSubscriptions( ... (cave, martijn), IActivity) >>> ordered_subscriptions [, , ] >>> _ = map(lambda a: a.do(), ordered_subscriptions) Martijn is cooking in Tilburg cave! Martijn is growing pumpkins in Tilburg cave! Martijn is cleaning the Tilburg cave. Or choose not to: >>> subscriptions = grok.queryMultiSubscriptions( ... (cave, martijn), IActivity) (still need to sort them on class name in order to have a working doctest) >>> subscriptions = sorted(subscriptions, key=lambda s: s.__class__.__name__) >>> subscriptions [, , ] >>> _ = map(lambda a: a.do(), subscriptions) Martijn is cleaning the Tilburg cave. Martijn is cooking in Tilburg cave! Martijn is growing pumpkins in Tilburg cave! """ import grokcore.component as grok from zope import interface class Cave(grok.Context): def __init__(self, name): self.name = name class Mammoth(grok.Context): def __init__(self, name): self.name = name class IActivity(interface.Interface): def do(): """Do something. """ class DayTimeActivity(grok.MultiSubscription): grok.provides(IActivity) grok.adapts(Cave, Mammoth) grok.baseclass() def __init__(self, where, who): self.where = where self.who = who def do(self): print 'Doing nothing.' class Cleaning(DayTimeActivity): grok.order(99) def do(self): print '%s is cleaning the %s.' % (self.who.name, self.where.name) class Cooking(DayTimeActivity): grok.order(10) def do(self): print '%s is cooking in %s!' % (self.who.name, self.where.name) class Gardening(DayTimeActivity): grok.order(15) def do(self): print '%s is growing pumpkins in %s!' % (self.who.name, self.where.name) grokcore.component-2.5/src/grokcore/component/tests/view/0000775000175000017500000000000011750014424022776 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/view/__init__.py0000664000175000017500000000002411750014416025104 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/view/nomodulename.py0000664000175000017500000000034611750014416026037 0ustar jwjw00000000000000""" You can't call grok.name on a module: >>> import grokcore.component.tests.view.nomodulename_fixture Traceback (most recent call last): ... GrokImportError: The 'name' directive can only be used on class level. """ grokcore.component-2.5/src/grokcore/component/tests/view/nomodulename_fixture.py0000664000175000017500000000012211750014416027575 0ustar jwjw00000000000000""" This should fail: """ import grokcore.component as grok grok.name('viewname') grokcore.component-2.5/src/grokcore/component/tests/adapter/0000775000175000017500000000000011750014424023444 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/adapter/order.py0000664000175000017500000000066611750014416025142 0ustar jwjw00000000000000""" If the model is defined after the adapter, it should still be grokked properly: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) class Cave(grok.Context): pass grokcore.component-2.5/src/grokcore/component/tests/adapter/providerdecorator.py0000664000175000017500000000126111750014416027554 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> IMarker.providedBy(not_marked) False >>> IMarker.providedBy(marked) True >>> IMarker.providedBy(double_marked) True >>> IMarker2.providedBy(not_marked) False >>> IMarker2.providedBy(marked) False >>> IMarker2.providedBy(double_marked) True >>> marked() 123 >>> double_marked() 234 """ import grokcore.component as grok from zope import interface class IMarker(interface.Interface): pass class IMarker2(interface.Interface): pass @grok.provider(IMarker) def marked(): return 123 @grok.provider(IMarker, IMarker2) def double_marked(): return 234 def not_marked(): return 456grokcore.component-2.5/src/grokcore/component/tests/adapter/multiple.py0000664000175000017500000000076111750014416025656 0ustar jwjw00000000000000""" Multiple models lead to ambiguity: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: Multiple possible contexts for , please use the 'context' directive. """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class Club(grok.Context): pass class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/adapter/nomodel.py0000664000175000017500000000067311750014416025462 0ustar jwjw00000000000000""" If no model can be found in the module, we get an error: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: No module-level context for , please use the 'context' directive. """ import grokcore.component as grok from zope import interface class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/adapter/implementsnonemulti.py0000664000175000017500000000067111750014416030133 0ustar jwjw00000000000000""" Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Cave(grok.Context): pass class Home(grok.MultiAdapter): pass grokcore.component-2.5/src/grokcore/component/tests/adapter/adapterdecorator.py0000664000175000017500000000353011750014416027343 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> >>> cave = Cave() >>> home = IHome(cave) >>> home.id u'default' >>> IHome.providedBy(home) True >>> >>> isinstance(home, Home) True >>> morehome = IMoreHome(cave) >>> morehome.id u'default' >>> IHome.providedBy(morehome) True >>> isinstance(morehome, Home) True >>> yetanotherhome = IYetAnotherHome(cave) >>> IHome.providedBy(yetanotherhome) True >>> isinstance(yetanotherhome, Home) True >>> yetanotherhome.id u'default' >>> from grokcore.component.tests.adapter import noarguments_fixture Traceback (most recent call last): ... GrokImportError: @grok.adapter requires at least one argument. >>> from grokcore.component.tests.adapter import functionasargument_fixture Traceback (most recent call last): ... GrokImportError: @grok.adapter requires at least one argument. >>> from zope.component import getAdapter >>> home = getAdapter(cave, IHome, name='home') >>> home.id u'secondary' """ import grokcore.component as grok from zope import interface class IDummy(interface.Interface): pass class ICave(interface.Interface): pass class IHome(interface.Interface): pass class IMoreHome(interface.Interface): pass class IYetAnotherHome(interface.Interface): pass class Cave(grok.Context): grok.implements(ICave) pass class Home(object): grok.implements(IHome) def __init__(self, id=u"default"): self.id = id @grok.adapter(Cave) @grok.implementer(IHome) def home_for_cave(cave): return Home() @grok.adapter(ICave) @grok.implementer(IMoreHome) def more_home_for_cave(cave): return Home() @grok.implementer(IYetAnotherHome) def yet_another_home_for_cave(cave): return Home() @grok.adapter(Cave, name=u"home") @grok.implementer(IHome) def home_for_cave_named(cave): return Home(u"secondary")grokcore.component-2.5/src/grokcore/component/tests/adapter/__init__.py0000664000175000017500000000002411750014416025552 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/adapter/multiadaptsnone.py0000664000175000017500000000075411750014416027234 0ustar jwjw00000000000000""" Subclasses of grok.MultiAdapter must declare what they adapt, using grok.adapts: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must specify which contexts it adapts (use the 'adapts' directive to specify). """ import grokcore.component as grok from zope import interface class IHome(interface.Interface): pass class Home(grok.MultiAdapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/adapter/functioncontext.py0000664000175000017500000000145511750014416027256 0ustar jwjw00000000000000""" You can't call grok.context from a function: >>> func() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be used on class or module level. You can't call grok.context from a method either: >>> SomeClass().meth() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be used on class or module level. """ import grokcore.component as grok from grokcore.component.tests.adapter.adapter import Cave def func(): """We don't allow calling `grok.context` from anything else than a module or a class""" grok.context(Cave) class SomeClass(object): def meth(self): """We don't allow calling `grok.context` from anything else than a module or a class""" grok.context(Cave) grokcore.component-2.5/src/grokcore/component/tests/adapter/classorinterface.py0000664000175000017500000000221411750014416027345 0ustar jwjw00000000000000""" You can only use `grok.context` with interfaces or classes and not with anything else: >>> function_context() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called with a class or an interface. >>> string_context() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called with a class or an interface. >>> module_context() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called with a class or an interface. >>> instance_context() Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called with a class or an interface. """ import grokcore.component as grok def function_context(): def a(): pass class FunctionContext(object): grok.context(a) def string_context(): class StringContext(object): grok.context('string') def module_context(): class ModuleContext(object): grok.context(grok) def instance_context(): obj = object() class InstanceContext(object): grok.context(obj) grokcore.component-2.5/src/grokcore/component/tests/adapter/multiadapter.py0000664000175000017500000000365611750014416026524 0ustar jwjw00000000000000""" Multi-Adapters are supported by subclassing grok.MultiAdapter, giving multiple arguments to grok.adapts, and supplying a matching __init__(): >>> grok.testing.grok(__name__) >>> cave = Cave() >>> fireplace = Fireplace() >>> from zope import component >>> home = component.getMultiAdapter((cave, fireplace)) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True >>> home.cave is cave True >>> home.fireplace is fireplace True This also works for named adapters using grok.name: >>> home = component.getMultiAdapter((cave, fireplace), name='home2') >>> IHome.providedBy(home) True >>> isinstance(home, Home2) True >>> home.cave is cave True >>> home.fireplace is fireplace True Multiadapters that implement more than one interface can use grok.provides to specify the one to use: >>> home = component.getMultiAdapter((cave, fireplace), name='home3') >>> IHome.providedBy(home) True >>> isinstance(home, Home3) True >>> home.cave is cave True >>> home.fireplace is fireplace True """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class Fireplace(grok.Context): pass class IHome(interface.Interface): pass class Home(grok.MultiAdapter): grok.adapts(Cave, Fireplace) grok.implements(IHome) def __init__(self, cave, fireplace): self.cave = cave self.fireplace = fireplace class Home2(grok.MultiAdapter): grok.adapts(Cave, Fireplace) grok.implements(IHome) grok.name('home2') def __init__(self, cave, fireplace): self.cave = cave self.fireplace = fireplace class IFireplace(interface.Interface): pass class Home3(grok.MultiAdapter): grok.adapts(Cave, Fireplace) grok.implements(IHome, IFireplace) grok.provides(IHome) grok.name('home3') def __init__(self, cave, fireplace): self.cave = cave self.fireplace = fireplace grokcore.component-2.5/src/grokcore/component/tests/adapter/modulecontextmultiple_fixture.py0000664000175000017500000000025411750014416032234 0ustar jwjw00000000000000import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class Club(grok.Context): pass grok.context(Cave) grok.context(Club) grokcore.component-2.5/src/grokcore/component/tests/adapter/implementsnone.py0000664000175000017500000000065711750014416027064 0ustar jwjw00000000000000""" Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: must implement at least one interface (use grok.implements to specify). """ import grokcore.component as grok class Cave(grok.Context): pass class Home(grok.Adapter): pass grokcore.component-2.5/src/grokcore/component/tests/adapter/classcontext.py0000664000175000017500000000073211750014416026533 0ustar jwjw00000000000000""" Explicit class-level context in case of multiple models: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class Club(grok.Context): pass class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grok.context(Cave) grokcore.component-2.5/src/grokcore/component/tests/adapter/adapter.py0000664000175000017500000000117311750014416025441 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True >>> fireplace = IFireplace(cave) >>> IFireplace.providedBy(fireplace) True >>> isinstance(fireplace, Fireplace) True """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) class IFireplace(interface.Interface): pass class Fireplace(grok.Adapter): grok.implements(IFireplace, IHome) grok.provides(IFireplace) grokcore.component-2.5/src/grokcore/component/tests/adapter/importedmodel.py0000664000175000017500000000077511750014416026674 0ustar jwjw00000000000000""" Imported model and adapter won't be grokked: >>> import grokcore.component as grok >>> grok.testing.grok(__name__) >>> from grokcore.component.tests.adapter.adapter import IHome >>> cave = Cave() >>> home = IHome(cave) Traceback (most recent call last): ... TypeError: ('Could not adapt', , ) """ from grokcore.component.tests.adapter.adapter import Cave, Home grokcore.component-2.5/src/grokcore/component/tests/adapter/interfacemodule.py0000664000175000017500000000127511750014416027172 0ustar jwjw00000000000000""" You can also specify interfaces instead of classes with `grok.context` (module-level): >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True >>> hole = Hole() >>> home = IHome(hole) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class ICave(interface.Interface): pass class Cave(grok.Context): grok.implements(ICave) class Hole(grok.Context): grok.implements(ICave) grok.context(ICave) class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/adapter/namedadapter.py0000664000175000017500000000135111750014416026444 0ustar jwjw00000000000000""" You can register a named adapter by using grok.name: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) Traceback (most recent call last): ... TypeError: ('Could not adapt', , ) >>> from zope.component import getAdapter >>> home = getAdapter(cave, IHome, name='home') >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grok.name('home') grokcore.component-2.5/src/grokcore/component/tests/adapter/classcontextmultiple_fixture.py0000664000175000017500000000026111750014416032052 0ustar jwjw00000000000000import grokcore.component as grok class Cave(grok.Context): pass class Club(grok.Context): pass class Anything(object): grok.context(Cave) grok.context(Club) grokcore.component-2.5/src/grokcore/component/tests/adapter/oldstyleclass.py0000664000175000017500000000062411750014416026706 0ustar jwjw00000000000000""" Old-style classes are also supported: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class Cave: pass class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grok.context(Cave) grokcore.component-2.5/src/grokcore/component/tests/adapter/globaladapter.py0000664000175000017500000000652111750014416026624 0ustar jwjw00000000000000""" >>> grok.testing.grok(__name__) >>> from zope.component import getAdapter, getMultiAdapter >>> cave = Cave() >>> fireplace = Fireplace() >>> home = IHome(cave) >>> home.id u'one' >>> home = getAdapter(cave, IHome, name=u"two") >>> home.id u'two' >>> home = getAdapter(cave, IHome, name=u"three") >>> home.id u'three' >>> home = getAdapter(cave, IHome, name=u"four") >>> home.id u'four' >>> home = getAdapter(fireplace, IHome, name=u"five") >>> home.id u'five' >>> home = getMultiAdapter((cave, fireplace), IHome) >>> home.id u'six' >>> home = getAdapter(fireplace, IHome, name=u'seven') >>> home.id u'seven-a' >>> home = getMultiAdapter((cave, fireplace), IHome, name=u'seven') >>> home.id u'seven-b' >>> garage = getAdapter(cave, IGarage, name='named_garage_factory_name') >>> garage.id u"I'm a garage" >>> garage = getAdapter(cave, IGarage) >>> garage.id u"I'm a garage" """ import grokcore.component as grok from zope import interface from zope.interface import implementer class Cave(grok.Context): pass class Fireplace(object): pass class IHome(interface.Interface): pass class Home(object): grok.implements(IHome) def __init__(self, id): self.id = id class CaveHomeFactory(object): grok.implements(IHome) def __init__(self, id): self.id = id def __call__(self, context): return Home(self.id) class CaveFireplaceHomeFactory(object): def __init__(self, id): self.id = id def __call__(self, cave, fireplace): return Home(self.id) factory1 = CaveHomeFactory(u"one") factory2 = CaveHomeFactory(u"two") factory3 = CaveHomeFactory(u"three") factory4 = CaveHomeFactory(u"four") factory5 = CaveHomeFactory(u"five") factory6 = CaveFireplaceHomeFactory(u"six") factory7a = CaveHomeFactory(u"seven-a") factory7b = CaveFireplaceHomeFactory(u"seven-b") # make some direct assertions implementer(IHome)(factory3) implementer(IHome)(factory4) implementer(IHome)(factory5) implementer(IHome)(factory6) implementer(IHome)(factory7a) implementer(IHome)(factory7b) grok.adapter(Fireplace)(factory5) grok.adapter(Fireplace)(factory7a) grok.adapter(Cave, Fireplace)(factory7b) # should accept single value for adapts grok.global_adapter(factory1, Cave, IHome) # should accept tuple for adapts grok.global_adapter(factory2, (Cave,), IHome, name=u"two") # should look at the provided interface grok.global_adapter(factory3, Cave, name=u"three") # should pick the canonical context grok.global_adapter(factory4, name=u"four") # should use __component_adapts__ grok.global_adapter(factory5, name=u"five") # should work as multi-adapter grok.global_adapter(factory6, (Cave, Fireplace,)) # should use __component_adapts__ adapting one object grok.global_adapter(factory7a, name=u"seven") # should use __component_adapts__ adaping two objects grok.global_adapter(factory7b, name=u"seven") class IGarage(interface.Interface): pass class NamedGarageFactory(object): grok.implements(IGarage) grok.name('named_garage_factory_name') def __init__(self, context): self.id = u"I'm a garage" implementer(IGarage)(NamedGarageFactory) # should register a named adapter grok.global_adapter(NamedGarageFactory, Cave, IGarage) # should override component's name grok.global_adapter(NamedGarageFactory, Cave, IGarage, name=u'') grokcore.component-2.5/src/grokcore/component/tests/adapter/importedmodel2.py0000664000175000017500000000120711750014416026745 0ustar jwjw00000000000000""" Grok error because import model doesn't count as context: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: No module-level context for , please use the 'context' directive. """ import grokcore.component as grok from grokcore.component.tests.adapter.adapter import Cave from zope import interface class IPainting(interface.Interface): pass class Painting(grok.Adapter): """ Grokking of this should fail because there's no model (only an imported one which doesn't count). """ grok.implements(IPainting) grokcore.component-2.5/src/grokcore/component/tests/adapter/conflict.py0000664000175000017500000000214711750014416025624 0ustar jwjw00000000000000""" Registering two adapters for the same target interface should provoke a conflict, even if the interface is guessed (instead of being explicitly declared with grok.provides): >>> grok.testing.grok(__name__) Traceback (most recent call last): ... ConfigurationConflictError: Conflicting configuration actions For: ('adapter', , , u'') """ import grokcore.component as grok from zope.interface import Interface class ICave(Interface): pass class IDecoration(Interface): pass class ICaveCleaning(Interface): pass class Cave(object): grok.implements(ICave) class ImplicitProvides(grok.Adapter): """Here the provided interface is guessed because the class only implements one interface.""" grok.context(ICave) grok.implements(IDecoration) class ExplicitProvides(grok.Adapter): """Here the provided interface is specific explicitly.""" grok.context(ICave) grok.implements(IDecoration, ICaveCleaning) grok.provides(IDecoration) grokcore.component-2.5/src/grokcore/component/tests/adapter/interface.py0000664000175000017500000000127711750014416025766 0ustar jwjw00000000000000""" You can also specify interfaces instead of classes with `grok.context` (class-level): >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True >>> hole = Hole() >>> home = IHome(hole) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class ICave(interface.Interface): pass class Cave(grok.Context): grok.implements(ICave) class Hole(grok.Context): grok.implements(ICave) class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grok.context(ICave) grokcore.component-2.5/src/grokcore/component/tests/adapter/functionasargument_fixture.py0000664000175000017500000000032211750014416031476 0ustar jwjw00000000000000import grokcore.component as grok from zope import interface class IDummy(interface.Interface): pass @grok.adapter @grok.implementer(IDummy) def decorator_called_with_function_as_argument(cave): pass grokcore.component-2.5/src/grokcore/component/tests/adapter/classcontextimported.py0000664000175000017500000000075311750014416030302 0ustar jwjw00000000000000""" Explicit class-level context for an imported model: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> painting = IPainting(cave) >>> IPainting.providedBy(painting) True >>> isinstance(painting, Painting) True """ import grokcore.component as grok from grokcore.component.tests.adapter.adapter import Cave from zope import interface class IPainting(interface.Interface): pass class Painting(grok.Adapter): grok.implements(IPainting) grok.context(Cave) grokcore.component-2.5/src/grokcore/component/tests/adapter/modulecontext.py0000664000175000017500000000073011750014416026711 0ustar jwjw00000000000000""" Explicit module-level context in case of multiple models: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class Club(grok.Context): pass grok.context(Cave) class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/adapter/implementsmany.py0000664000175000017500000000112711750014416027062 0ustar jwjw00000000000000""" Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one interface: >>> grok.testing.grok(__name__) Traceback (most recent call last): ... GrokError: is implementing more than one interface (use grok.provides to specify which one to use). """ import grokcore.component as grok from zope import interface class Cave(grok.Context): pass class IHome(interface.Interface): pass class IFireplace(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome, IFireplace) grokcore.component-2.5/src/grokcore/component/tests/adapter/modulecontextimported.py0000664000175000017500000000075111750014416030460 0ustar jwjw00000000000000""" Explicit module-level context for an imported model: >>> grok.testing.grok(__name__) >>> cave = Cave() >>> painting = IPainting(cave) >>> IPainting.providedBy(painting) True >>> isinstance(painting, Painting) True """ import grokcore.component as grok from grokcore.component.tests.adapter.adapter import Cave from zope import interface grok.context(Cave) class IPainting(interface.Interface): pass class Painting(grok.Adapter): grok.implements(IPainting) grokcore.component-2.5/src/grokcore/component/tests/adapter/modulecontextmultiple.py0000664000175000017500000000043111750014416030463 0ustar jwjw00000000000000""" You can't call grok.context multiple times on module level: >>> import grokcore.component.tests.adapter.modulecontextmultiple_fixture Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called once per class or module. """ grokcore.component-2.5/src/grokcore/component/tests/adapter/classcontextmultiple.py0000664000175000017500000000043011750014416030302 0ustar jwjw00000000000000""" You can't call grok.context multiple times on class level: >>> import grokcore.component.tests.adapter.classcontextmultiple_fixture Traceback (most recent call last): ... GrokImportError: The 'context' directive can only be called once per class or module. """ grokcore.component-2.5/src/grokcore/component/tests/adapter/noarguments_fixture.py0000664000175000017500000000031411750014416030125 0ustar jwjw00000000000000import grokcore.component as grok from zope import interface class IDummy(interface.Interface): pass @grok.adapter() @grok.implementer(IDummy) def decorator_called_with_no_arguments(cave): pass grokcore.component-2.5/src/grokcore/component/tests/adapter/alphabetical.py0000664000175000017500000000076611750014416026441 0ustar jwjw00000000000000""" Grok does not depend on the alphabetical order: >>> grok.testing.grok(__name__) >>> cave = ZCave() >>> home = IHome(cave) >>> IHome.providedBy(home) True >>> isinstance(home, Home) True """ import grokcore.component as grok from zope import interface class ZCave(grok.Context): """we call this `ZCave` because we want to test that we do not depend on alphabetical order""" class IHome(interface.Interface): pass class Home(grok.Adapter): grok.implements(IHome) grokcore.component-2.5/src/grokcore/component/tests/test_grok.py0000664000175000017500000000443311750014416024404 0ustar jwjw00000000000000import re import unittest import traceback import doctest from pkg_resources import resource_listdir from zope.testing import cleanup, renormalizing import zope.component.eventtesting def setUpZope(test): zope.component.eventtesting.setUp(test) def cleanUpZope(test): cleanup.cleanUp() checker = renormalizing.RENormalizing([ # str(Exception) has changed from Python 2.4 to 2.5 (due to # Exception now being a new-style class). This changes the way # exceptions appear in traceback printouts. (re.compile(r"ConfigurationExecutionError: :"), r'ConfigurationExecutionError: \1:'), ]) def suiteFromPackage(name): files = resource_listdir(__name__, name) suite = unittest.TestSuite() for filename in files: if not filename.endswith('.py'): continue if filename.endswith('_fixture.py'): continue if filename == '__init__.py': continue dottedname = 'grokcore.component.tests.%s.%s' % (name, filename[:-3]) try: test = doctest.DocTestSuite(dottedname, setUp=setUpZope, tearDown=cleanUpZope, checker=checker, optionflags=doctest.ELLIPSIS+ doctest.NORMALIZE_WHITESPACE) except ImportError: # or should this accept anything? traceback.print_exc() raise suite.addTest(test) return suite def test_suite(): suite = unittest.TestSuite() for name in ['adapter', 'directive', 'grokker', 'utility', 'view', 'event', 'inherit', 'order', 'subscriptions']: suite.addTest(suiteFromPackage(name)) api = doctest.DocFileSuite('api.txt') suite.addTest(api) # this test cannot follow the normal testing pattern, as the # bug it tests for is only exposed in the context of a doctest grok_component = doctest.DocFileSuite('grok_component.txt', setUp=setUpZope, tearDown=cleanUpZope) suite.addTest(grok_component) return suite if __name__ == '__main__': unittest.main(defaultTest='test_suite') grokcore.component-2.5/src/grokcore/component/tests/inherit/0000775000175000017500000000000011750014424023466 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/inherit/__init__.py0000664000175000017500000000000211750014416025570 0ustar jwjw00000000000000# grokcore.component-2.5/src/grokcore/component/tests/inherit/inherit_fixture.py0000664000175000017500000000041411750014416027250 0ustar jwjw00000000000000import grokcore.component from zope.interface import Interface class Foo(grokcore.component.Context): pass grokcore.component.context(Foo) class IAnder(Interface): pass class FooAdapter(grokcore.component.Adapter): grokcore.component.provides(IAnder) grokcore.component-2.5/src/grokcore/component/tests/inherit/inherit.py0000664000175000017500000000131311750014416025501 0ustar jwjw00000000000000""" We expect the module-level grok.context to be inherited by subclasses of an adapter that is associated with this directive. FooAdapter is such an adapter, defined in inherit_fixture. In this module we've inherited from it. Explicit module-level context for an imported model: >>> grok.testing.grok(__name__) >>> from zope import component >>> o = component.getAdapter(inherit_fixture.Foo(), inherit_fixture.IAnder, ... name='bar') >>> isinstance(o, BarAdapter) True """ import grokcore.component as grok from grokcore.component.tests.inherit import inherit_fixture # FooAdapter has a module-level grok.context to associate it class BarAdapter(inherit_fixture.FooAdapter): grok.name('bar') grokcore.component-2.5/src/grokcore/component/tests/event/0000775000175000017500000000000011750014424023145 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore/component/tests/event/__init__.py0000664000175000017500000000002411750014416025253 0ustar jwjw00000000000000# this is a package grokcore.component-2.5/src/grokcore/component/tests/event/errorconditions_fixture.py0000664000175000017500000000012011750014416030502 0ustar jwjw00000000000000import grokcore.component as grok @grok.subscribe() def subscriber(): pass grokcore.component-2.5/src/grokcore/component/tests/event/errorconditions.py0000664000175000017500000000162111750014416026743 0ustar jwjw00000000000000""" @grok.subscribe can only be used on module level: >>> function_context() Traceback (most recent call last): ... GrokImportError: @grok.subscribe can only be used on module level. >>> class_context() Traceback (most recent call last): ... GrokImportError: @grok.subscribe can only be used on module level. @grok.subscribe can not be called without arguments: >>> import grokcore.component.tests.event.errorconditions_fixture Traceback (most recent call last): ... GrokImportError: @grok.subscribe requires at least one argument. """ import grokcore.component as grok from zope.component.interfaces import IObjectEvent def function_context(): @grok.subscribe(grok.Context, IObjectEvent) def subscriber(): pass def class_context(): class Wrapper: @grok.subscribe(grok.Context, IObjectEvent) def subscriber(self): pass grokcore.component-2.5/src/grokcore/component/tests/event/provideHandler.py0000664000175000017500000000142111750014416026464 0ustar jwjw00000000000000""" When you use the @grokcore.component.subscribe decorator, you can also use zope.component.provideHandler to register the subscriber. This can be useful for unittests where you may not want to grok everything in a module but just enable certain components. >>> from zope.component import provideHandler >>> provideHandler(mammothAdded) >>> manfred = Mammoth('Manfred') >>> import zope.event >>> zope.event.notify(ObjectEvent(manfred)) >>> mammoths ['Manfred'] """ import grokcore.component as grok from zope.component.interfaces import IObjectEvent, ObjectEvent class Mammoth(object): def __init__(self, name): self.name = name mammoths = [] @grok.subscribe(Mammoth, IObjectEvent) def mammothAdded(mammoth, event): mammoths.append(mammoth.name) grokcore.component-2.5/src/grokcore/component/tests/event/subscriber.py0000664000175000017500000000151411750014416025664 0ustar jwjw00000000000000""" You can subscribe to events using the @grok.subscribe decorator: >>> grok.testing.grok(__name__) >>> manfred = Mammoth('Manfred') >>> zope.event.notify(ObjectEvent(manfred)) >>> mammoths ['Manfred'] >>> mammoths2 ['Manfred'] The decorated event handling function can also be called directly: >>> mammothAdded(Mammoth('Max'),None) >>> mammoths ['Manfred', 'Max'] """ import zope.event import grokcore.component as grok from zope.component.interfaces import IObjectEvent, ObjectEvent class Mammoth(object): def __init__(self, name): self.name = name mammoths = [] mammoths2 = [] @grok.subscribe(Mammoth, IObjectEvent) def mammothAdded(mammoth, event): mammoths.append(mammoth.name) @grok.subscribe(Mammoth, IObjectEvent) def mammothAddedInstance(mammoth, event): mammoths2.append(mammoth.name) grokcore.component-2.5/src/grokcore/__init__.py0000664000175000017500000000031011750014416020764 0ustar jwjw00000000000000# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) grokcore.component-2.5/src/grokcore.component.egg-info/0000775000175000017500000000000011750014424022353 5ustar jwjw00000000000000grokcore.component-2.5/src/grokcore.component.egg-info/PKG-INFO0000664000175000017500000004601711750014421023455 0ustar jwjw00000000000000Metadata-Version: 1.0 Name: grokcore.component Version: 2.5 Summary: Grok-like configuration for basic components (adapters, utilities, subscribers) Home-page: http://grok.zope.org Author: Grok Team Author-email: grok-dev@zope.org License: ZPL Download-URL: http://pypi.python.org/pypi/grokcore.component Description: This package provides base classes of basic component types for the Zope Component Architecture, as well as means for configuring and registering them directly in Python (without ZCML). .. contents:: How to set up ``grokcore.component`` ==================================== In the following we assume you're writing or extending an application that does bootstrap configuration using ZCML. There's always a single ZCML file that is executed when the application is started, which then includes everything else. Let's assume this file is called ``site.zcml`` (that's what it's called in Zope), so that file is what we'll be editing. In order to register the components that you wrote using the base classes and directives available from ``grokcore.component``, we'll use the ```` ZCML directive. But before we can use it, we need to make sure it's available to the ZCML machinery. We do this by including the meta configuration from ``grokcore.component``:: Put this line somewhere to the top of ``site.zcml``, next to other meta configuration includes. Now, further down the line, we can tell the machinery in ``grokcore.component`` to register all components in your package (let's say it's called ``helloworld``):: To sum up, your ``site.zcml`` file should look like something like this:: Examples ======== Adapter ------- Here's a simple adapter that may be useful in Zope. It extracts the languages that a user prefers from the request:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.i18n.interfaces import IUserPreferredLanguages class CookieLanguage(grokcore.component.Adapter): """Extract the preferred language from a cookie""" grokcore.component.context(IBrowserRequest) grokcore.component.implements(IUserPreferredLanguages) # No need to implement __init__, it's already provided by the base class. def getPreferredLanguages(self): # This an adapter for the request, so self.context is the request. request = self.context # Extract the preferred language from a cookie: lang = request.cookies.get('language', 'en') # According to IUserPreferredLanguages, we must return a list. return [lang] Multi-adapter ------------- Here's a multi-adapter that functions as a content provider as known from the ``zope.contentprovider`` library. Content providers are components that return snippets of HTML. They're multi-adapters for the content object (model), the request and the view that they're supposed to be a part of:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserPage from zope.contentprovider.interfaces import IContentProvider class HelloWorldProvider(grokcore.component.MultiAdapter): """Display Hello World!""" grokcore.component.adapts(Interface, IBrowserRequest, IBrowserPage) grokcore.component.implements(IContentProvider) def __init__(self, context, request, view): pass def update(self): pass def render(self): return u'

Hello World!

' Global utility -------------- Here's a simple named utility, again from the Zope world. It's a translation domain. In other words, it contains translations of user messages and is invoked when the i18n machinery needs to translate something:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain class HelloWorldTranslationDomain(grokcore.component.GlobalUtility): grokcore.component.implements(ITranslationDomain) grokcore.component.name('helloworld') domain = u'helloworld' def translate(self, msgid, mapping=None, context=None, target_language=None, default=None): if target_language is None: preferred = IUserPreferredLanguages(context) target_language = preferred.getPreferredLanguages()[0] translations = {'de': u'Hallo Welt', 'nl': u'Hallo Wereld'} return translations.get(target_language, u'Hello World') Of course, it's silly to implement your own translation domain utility if there are already implementations available in ``zope.i18n`` (one that reads translations from a GNU gettext message catalog and a simple implementation for tests). Let's try to reuse that implementation and register an instance:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain from zope.i18n.simpletranslationdomain import SimpleTranslationDomain messages = {('de', u'Hello World'): u'Hallo Welt', ('nl', u'Hello World'): u'Hallo Wereld'} helloworld_domain = SimpleTranslationDomain(u'helloworld', messages) grokcore.component.global_utility(helloworld_domain, provides=ITranslationDomain, name='helloworld', direct=True) Global adapter -------------- Sometimes, you may have an object that should be registered as an adapter factory. It may have come from some other framework that configured that adapter for you, say, or you may have a class that you instantiate many times to get different variations on a particular adapter factory. In these cases, subclassing grokcore.component.Adapter or MultiAdapter is not possible. Instead, you can use the global_adapter() directive. Here is an example drawing on the ``z3c.form`` library, which provides an adapter factory factory for named widget attributes:: import zope.interface import zope.schema import grokcore.component import z3c.form.widget import ComputedWidgetAttribute class ISchema(Interface): """This schema will be used to power a z3c.form form""" field = zope.schema.TextLine(title=u"Sample field") ... label_override = z3c.form.widget.StaticWidgetAttribute( u"Override label", field=ISchema['field']) grokcore.component.global_adapter(label_override, name=u"label") In the example above, the provided and adapted interfaces are deduced from the object returned by the ``StaticWidgetAttribute`` factory. The full syntax for global_adapter is:: global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") The factory must be a callable (the adapter factory). Adapted interfaces are given as a tuple. You may use a single interface instead of a one-element tuple for single adapters. The provided interface is given as shown. The name defaults to u"" (an unnamed adapter). Handling events --------------- Here we see an event handler much like it occurs within Zope itself. It subscribes to the modified event for all annotatable objects (in other words, objects that can have metadata associated with them). When invoked, it updates the Dublin Core 'Modified' property accordingly:: import datetime import grokcore.component from zope.annotation.interfaces import IAnnotatable from zope.lifecycleevent.interfaces import IObjectModifiedEvent from zope.dublincore.interfaces import IZopeDublinCore @grokcore.component.subscribe(IAnnotatable, IObjectModifiedEvent) def updateDublinCoreAfterModification(obj, event): """Updated the Dublin Core 'Modified' property when a modified event is sent for an object.""" IZopeDublinCore(obj).modified = datetime.datetime.utcnow() Subscriptions ------------- Subscriptions look similar to Adapter, however, unlike regular adapters, subscription adapters are used when we want all of the adapters that adapt an object to a particular adapter. Analogous to MultiAdapter, there is a MultiSubscription component that "adapts" multiple objects. Changes ======= 2.5 (2012-05-01) ---------------- - Introduce provideUtility, providerAdapter, provideSubscriptionAdapter, provideHandler and provideInterface in grokcore.component. These by default delegate the registration of components to the global site manager like was done before, but provide the possibility for custom registries for the grokked components. - Fix the `global_adapter` to properly use information annotated by ``grok.adapter``, and using the IContext object if it was not specified. (Fix Launchpad issue #960097). - Add a ``key`` option to ``sort_components`` that behave like ``key`` options available on standard Python sort methods. 2.4 (2011-04-27) ---------------- - Fix the `global_adapter` directive implementation to accept an explicit "empty" name for nameless adapter registrations (as it used to be that providing an empty name in the registration would actually result in registering a named adapter in case the factory has a `grok.name`). 2.3 (2011-02-14) ---------------- - Implement the generic (Multi)Subscriptions components. 2.2 (2010-11-03) ---------------- - The default values computation for the context directive and the provides directive is now defined in the directives themselves. This means that where the values for these directives is being retrieved, the "default_context" function does not need to be passed along anymore for general cases. Analogous to this, when getting values for the provides directive the "default_provides" function does not need to be passed along in the general case. 2.1 (2010-11-01) ---------------- * Made package comply to zope.org repository policy. * Moved directives 'order' from grokcore.viewlet and 'path' from grokcore.view to this very package. * Tiny dependency adjustment: moved zope.event to test dependencies. * Port from 1.x branch exclude parameter to the Grok ZCML directive. * Port from 1.x branch the ignore of testing.py modules. 2.0 (2009-09-16) ---------------- * Use a newer version of Martian that has better support for inheritance. This is demonstrated in ``tests/inherit``. * The ``ContextGrokker`` and the ``scan.py`` module have gone away thanks the newer Martian. * Directive implementations (in their factory method) should *not* bind directives. Directive binding cannot take place at import time, but only at grok time. Binding directives during import time (when directives are executed) can lead to change problems. (we noticed this during our refactoring to use the new Martian). * Use 1.0b1 versions.cfg in Grok's release info instead of a local copy; a local copy for all grokcore packages is just too hard to maintain. 1.7 (2009-06-01) ---------------- * Add missing provider, global_adapter, implementsOnly, classProvides() to the module interface so that they are included in __all__ 1.6 (2009-04-10) ---------------- * Add convenience imports for implementsOnly() and classProvides() class declarations form zope.interface. * Add support for registering global adapters at module level:: grok.global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") Only 'factory' is required. If only a single interface is adapted, the second argument may be a single interface instead of a tuple. If the component has declared adapted/provided interfaces, the second and third arguments may be omitted. * Add support for an @provider decorator to let a function directly provide an interface:: @grok.provider(IFoo, IBar) def some_function(): ... This is equivalent to doing alsoProvides(some_function, IFoo, IBar). * Add support for named adapters with the @adapter decorator:: @grok.adapter(IAdaptedOne, IAdaptedTwo, name=u"foo") def some_function(one, two): ... 1.5.1 (2008-07-28) ------------------ * The ``IGrokcoreComponentAPI`` interface was missing declarations for the ``title`` and ``description`` directives. 1.5 (2008-07-22) ---------------- * Fix https://bugs.launchpad.net/grok/+bug/242353: grokcore.component contains old-style test setup. There is no `register_all_tests` method in grokcore.component.testing anymore. Use z3c.testsetup instead. * Allow functions that have been marked with @grok.subscribe also be registered with ``zope.component.provideHandler()`` manually. This is useful for unit tests where you may not want to grok a whole module. * Document grokcore.component's public API in an interface, ``IGrokcoreComponentAPI``. When you now do:: from grokcore.component import * only the items documented in that interface will be imported into your local namespace. 1.4 (2008-06-11) ---------------- * Ported class grokkers to make use of further improvements in Martian. This requires Martian 0.10. 1.3 (2008-05-14) ---------------- * Ported class grokkers to make use of the new declarative way of retrieving directive information from a class. This requires Martian 0.9.6. 1.2.1 (2008-05-04) ------------------ * Upgrade to Martian 0.9.5, which has a slight change in the signature of ``scan_for_classes``. * Remove an unnecessary import ``methods_from_class`` from ``grokcore.component.scan``. 1.2 (2008-05-04) ---------------- * Ported directives to Martian's new directive implementation. As a result, nearly all helper functions that were available from ``grokcore.component.util`` have been removed. The functionality is mostly available from the directives themselves now. * The ``baseclass`` directive has been moved to Martian. * The ``order`` directive and its helper functions have been moved back to Grok, as it was of no general use, but very specific to viewlets. 1.1 (2008-05-03) ---------------- * ``determine_module_component`` now looks for classes that implement a certain interface (such as ``IContext``), instead of taking a list of classes. If looking for ``IContext``, it still will find ``Context`` subclasses, as these were also made to implement ``IContext``. * Move the ``public_methods_from_class`` helper function back to Grok, it isn't used at all in ``grokcore.component``. 1.0.1 (2008-05-02) ------------------ * The grokkers for adapters and global utilities did not use the correct value for the *provided* interface in the configuration action discriminator. Because of this, uninformative and potentially wrong conflict errors would occur, as well as no conflict where a conflict should have occurred. * The grokker for the ``global_utility()`` directive did immediate registrations instead of generating configuration actions. Therefore it did not provoke ``ConflictErrors`` for conflicting registrations. * Improved documentation 1.0 (2008-05-01) ---------------- * Created ``grokcore.component`` in March 2008 by factoring basic component base classes and their directives and grokkers out of Grok. Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python grokcore.component-2.5/src/grokcore.component.egg-info/dependency_links.txt0000664000175000017500000000000111750014421026416 0ustar jwjw00000000000000 grokcore.component-2.5/src/grokcore.component.egg-info/SOURCES.txt0000664000175000017500000001374111750014422024243 0ustar jwjw00000000000000CHANGES.txt COPYRIGHT.txt CREDITS.txt INSTALL.txt LICENSE.txt README.txt TODO.txt bootstrap.py buildout.cfg setup.py src/grokcore/__init__.py src/grokcore.component.egg-info/PKG-INFO src/grokcore.component.egg-info/SOURCES.txt src/grokcore.component.egg-info/dependency_links.txt src/grokcore.component.egg-info/namespace_packages.txt src/grokcore.component.egg-info/not-zip-safe src/grokcore.component.egg-info/requires.txt src/grokcore.component.egg-info/top_level.txt src/grokcore/component/__init__.py src/grokcore/component/components.py src/grokcore/component/decorators.py src/grokcore/component/directive.py src/grokcore/component/interfaces.py src/grokcore/component/meta.py src/grokcore/component/meta.zcml src/grokcore/component/subscription.py src/grokcore/component/testing.py src/grokcore/component/util.py src/grokcore/component/zcml.py src/grokcore/component/templates/default_display_form.pt src/grokcore/component/templates/default_edit_form.pt src/grokcore/component/tests/__init__.py src/grokcore/component/tests/api.txt src/grokcore/component/tests/grok_component.txt src/grokcore/component/tests/test_grok.py src/grokcore/component/tests/adapter/__init__.py src/grokcore/component/tests/adapter/adapter.py src/grokcore/component/tests/adapter/adapterdecorator.py src/grokcore/component/tests/adapter/alphabetical.py src/grokcore/component/tests/adapter/classcontext.py src/grokcore/component/tests/adapter/classcontextimported.py src/grokcore/component/tests/adapter/classcontextmultiple.py src/grokcore/component/tests/adapter/classcontextmultiple_fixture.py src/grokcore/component/tests/adapter/classorinterface.py src/grokcore/component/tests/adapter/conflict.py src/grokcore/component/tests/adapter/functionasargument_fixture.py src/grokcore/component/tests/adapter/functioncontext.py src/grokcore/component/tests/adapter/globaladapter.py src/grokcore/component/tests/adapter/implementsmany.py src/grokcore/component/tests/adapter/implementsnone.py src/grokcore/component/tests/adapter/implementsnonemulti.py src/grokcore/component/tests/adapter/importedmodel.py src/grokcore/component/tests/adapter/importedmodel2.py src/grokcore/component/tests/adapter/interface.py src/grokcore/component/tests/adapter/interfacemodule.py src/grokcore/component/tests/adapter/modulecontext.py src/grokcore/component/tests/adapter/modulecontextimported.py src/grokcore/component/tests/adapter/modulecontextmultiple.py src/grokcore/component/tests/adapter/modulecontextmultiple_fixture.py src/grokcore/component/tests/adapter/multiadapter.py src/grokcore/component/tests/adapter/multiadaptsnone.py src/grokcore/component/tests/adapter/multiple.py src/grokcore/component/tests/adapter/namedadapter.py src/grokcore/component/tests/adapter/noarguments_fixture.py src/grokcore/component/tests/adapter/nomodel.py src/grokcore/component/tests/adapter/oldstyleclass.py src/grokcore/component/tests/adapter/order.py src/grokcore/component/tests/adapter/providerdecorator.py src/grokcore/component/tests/directive/__init__.py src/grokcore/component/tests/directive/argumenterror.py src/grokcore/component/tests/directive/argumenterror_fixture.py src/grokcore/component/tests/directive/multipletimes.py src/grokcore/component/tests/event/__init__.py src/grokcore/component/tests/event/errorconditions.py src/grokcore/component/tests/event/errorconditions_fixture.py src/grokcore/component/tests/event/provideHandler.py src/grokcore/component/tests/event/subscriber.py src/grokcore/component/tests/grokker/__init__.py src/grokcore/component/tests/grokker/continue_scanning.py src/grokcore/component/tests/grokker/continue_scanning_fixture.py src/grokcore/component/tests/grokker/grokcomponent.py src/grokcore/component/tests/grokker/onlyonce.py src/grokcore/component/tests/grokker/priority.py src/grokcore/component/tests/grokker/priority_fixture.py src/grokcore/component/tests/grokker/onlyonce_fixture/__init__.py src/grokcore/component/tests/grokker/onlyonce_fixture/_meta.py src/grokcore/component/tests/grokker/onlyonce_fixture/component.py src/grokcore/component/tests/grokker/onlyonce_fixture/implementation.py src/grokcore/component/tests/inherit/__init__.py src/grokcore/component/tests/inherit/inherit.py src/grokcore/component/tests/inherit/inherit_fixture.py src/grokcore/component/tests/order/__init__.py src/grokcore/component/tests/order/arg_orderdirective.py src/grokcore/component/tests/order/combined_orderdirective.py src/grokcore/component/tests/order/combinednoorder_orderdirective.py src/grokcore/component/tests/order/inter1.py src/grokcore/component/tests/order/inter2.py src/grokcore/component/tests/order/noarg_orderdirective.py src/grokcore/component/tests/order/nodirective.py src/grokcore/component/tests/subscriptions/__init__.py src/grokcore/component/tests/subscriptions/decorator.py src/grokcore/component/tests/subscriptions/multisubscriptions.py src/grokcore/component/tests/subscriptions/multisubscriptions_no_adapts.py src/grokcore/component/tests/subscriptions/multisubscriptions_no_interface.py src/grokcore/component/tests/subscriptions/ordered_multisubscriptions.py src/grokcore/component/tests/subscriptions/ordered_subscriptions.py src/grokcore/component/tests/subscriptions/subscriptions.py src/grokcore/component/tests/subscriptions/subscriptions_no_context.py src/grokcore/component/tests/subscriptions/subscriptions_no_interface.py src/grokcore/component/tests/utility/__init__.py src/grokcore/component/tests/utility/conflict.py src/grokcore/component/tests/utility/implementsmany.py src/grokcore/component/tests/utility/implementsmany2.py src/grokcore/component/tests/utility/implementsnone.py src/grokcore/component/tests/utility/implementsnone2.py src/grokcore/component/tests/utility/providesmany.py src/grokcore/component/tests/utility/providesmany2.py src/grokcore/component/tests/utility/providesnone.py src/grokcore/component/tests/utility/providesnone2.py src/grokcore/component/tests/utility/utility.py src/grokcore/component/tests/view/__init__.py src/grokcore/component/tests/view/nomodulename.py src/grokcore/component/tests/view/nomodulename_fixture.pygrokcore.component-2.5/src/grokcore.component.egg-info/top_level.txt0000664000175000017500000000001111750014421025072 0ustar jwjw00000000000000grokcore grokcore.component-2.5/src/grokcore.component.egg-info/requires.txt0000664000175000017500000000015311750014421024747 0ustar jwjw00000000000000setuptools martian >= 0.14 zope.component zope.configuration zope.interface zope.testing [test] zope.eventgrokcore.component-2.5/src/grokcore.component.egg-info/not-zip-safe0000664000175000017500000000000111750014416024602 0ustar jwjw00000000000000 grokcore.component-2.5/src/grokcore.component.egg-info/namespace_packages.txt0000664000175000017500000000001111750014421026673 0ustar jwjw00000000000000grokcore grokcore.component-2.5/CHANGES.txt0000664000175000017500000001543311750014416016076 0ustar jwjw00000000000000Changes ======= 2.5 (2012-05-01) ---------------- - Introduce provideUtility, providerAdapter, provideSubscriptionAdapter, provideHandler and provideInterface in grokcore.component. These by default delegate the registration of components to the global site manager like was done before, but provide the possibility for custom registries for the grokked components. - Fix the `global_adapter` to properly use information annotated by ``grok.adapter``, and using the IContext object if it was not specified. (Fix Launchpad issue #960097). - Add a ``key`` option to ``sort_components`` that behave like ``key`` options available on standard Python sort methods. 2.4 (2011-04-27) ---------------- - Fix the `global_adapter` directive implementation to accept an explicit "empty" name for nameless adapter registrations (as it used to be that providing an empty name in the registration would actually result in registering a named adapter in case the factory has a `grok.name`). 2.3 (2011-02-14) ---------------- - Implement the generic (Multi)Subscriptions components. 2.2 (2010-11-03) ---------------- - The default values computation for the context directive and the provides directive is now defined in the directives themselves. This means that where the values for these directives is being retrieved, the "default_context" function does not need to be passed along anymore for general cases. Analogous to this, when getting values for the provides directive the "default_provides" function does not need to be passed along in the general case. 2.1 (2010-11-01) ---------------- * Made package comply to zope.org repository policy. * Moved directives 'order' from grokcore.viewlet and 'path' from grokcore.view to this very package. * Tiny dependency adjustment: moved zope.event to test dependencies. * Port from 1.x branch exclude parameter to the Grok ZCML directive. * Port from 1.x branch the ignore of testing.py modules. 2.0 (2009-09-16) ---------------- * Use a newer version of Martian that has better support for inheritance. This is demonstrated in ``tests/inherit``. * The ``ContextGrokker`` and the ``scan.py`` module have gone away thanks the newer Martian. * Directive implementations (in their factory method) should *not* bind directives. Directive binding cannot take place at import time, but only at grok time. Binding directives during import time (when directives are executed) can lead to change problems. (we noticed this during our refactoring to use the new Martian). * Use 1.0b1 versions.cfg in Grok's release info instead of a local copy; a local copy for all grokcore packages is just too hard to maintain. 1.7 (2009-06-01) ---------------- * Add missing provider, global_adapter, implementsOnly, classProvides() to the module interface so that they are included in __all__ 1.6 (2009-04-10) ---------------- * Add convenience imports for implementsOnly() and classProvides() class declarations form zope.interface. * Add support for registering global adapters at module level:: grok.global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") Only 'factory' is required. If only a single interface is adapted, the second argument may be a single interface instead of a tuple. If the component has declared adapted/provided interfaces, the second and third arguments may be omitted. * Add support for an @provider decorator to let a function directly provide an interface:: @grok.provider(IFoo, IBar) def some_function(): ... This is equivalent to doing alsoProvides(some_function, IFoo, IBar). * Add support for named adapters with the @adapter decorator:: @grok.adapter(IAdaptedOne, IAdaptedTwo, name=u"foo") def some_function(one, two): ... 1.5.1 (2008-07-28) ------------------ * The ``IGrokcoreComponentAPI`` interface was missing declarations for the ``title`` and ``description`` directives. 1.5 (2008-07-22) ---------------- * Fix https://bugs.launchpad.net/grok/+bug/242353: grokcore.component contains old-style test setup. There is no `register_all_tests` method in grokcore.component.testing anymore. Use z3c.testsetup instead. * Allow functions that have been marked with @grok.subscribe also be registered with ``zope.component.provideHandler()`` manually. This is useful for unit tests where you may not want to grok a whole module. * Document grokcore.component's public API in an interface, ``IGrokcoreComponentAPI``. When you now do:: from grokcore.component import * only the items documented in that interface will be imported into your local namespace. 1.4 (2008-06-11) ---------------- * Ported class grokkers to make use of further improvements in Martian. This requires Martian 0.10. 1.3 (2008-05-14) ---------------- * Ported class grokkers to make use of the new declarative way of retrieving directive information from a class. This requires Martian 0.9.6. 1.2.1 (2008-05-04) ------------------ * Upgrade to Martian 0.9.5, which has a slight change in the signature of ``scan_for_classes``. * Remove an unnecessary import ``methods_from_class`` from ``grokcore.component.scan``. 1.2 (2008-05-04) ---------------- * Ported directives to Martian's new directive implementation. As a result, nearly all helper functions that were available from ``grokcore.component.util`` have been removed. The functionality is mostly available from the directives themselves now. * The ``baseclass`` directive has been moved to Martian. * The ``order`` directive and its helper functions have been moved back to Grok, as it was of no general use, but very specific to viewlets. 1.1 (2008-05-03) ---------------- * ``determine_module_component`` now looks for classes that implement a certain interface (such as ``IContext``), instead of taking a list of classes. If looking for ``IContext``, it still will find ``Context`` subclasses, as these were also made to implement ``IContext``. * Move the ``public_methods_from_class`` helper function back to Grok, it isn't used at all in ``grokcore.component``. 1.0.1 (2008-05-02) ------------------ * The grokkers for adapters and global utilities did not use the correct value for the *provided* interface in the configuration action discriminator. Because of this, uninformative and potentially wrong conflict errors would occur, as well as no conflict where a conflict should have occurred. * The grokker for the ``global_utility()`` directive did immediate registrations instead of generating configuration actions. Therefore it did not provoke ``ConflictErrors`` for conflicting registrations. * Improved documentation 1.0 (2008-05-01) ---------------- * Created ``grokcore.component`` in March 2008 by factoring basic component base classes and their directives and grokkers out of Grok. grokcore.component-2.5/COPYRIGHT.txt0000664000175000017500000000004011750014416016362 0ustar jwjw00000000000000Zope Foundation and Contributorsgrokcore.component-2.5/TODO.txt0000664000175000017500000000024211750014416015563 0ustar jwjw00000000000000==== TODO ==== - The testing infrastructure needs to be broken out into "grokcore.testing". - The interfaces need to be broken out into "grokcore.interfaces". grokcore.component-2.5/README.txt0000664000175000017500000002056011750014416015760 0ustar jwjw00000000000000This package provides base classes of basic component types for the Zope Component Architecture, as well as means for configuring and registering them directly in Python (without ZCML). .. contents:: How to set up ``grokcore.component`` ==================================== In the following we assume you're writing or extending an application that does bootstrap configuration using ZCML. There's always a single ZCML file that is executed when the application is started, which then includes everything else. Let's assume this file is called ``site.zcml`` (that's what it's called in Zope), so that file is what we'll be editing. In order to register the components that you wrote using the base classes and directives available from ``grokcore.component``, we'll use the ```` ZCML directive. But before we can use it, we need to make sure it's available to the ZCML machinery. We do this by including the meta configuration from ``grokcore.component``:: Put this line somewhere to the top of ``site.zcml``, next to other meta configuration includes. Now, further down the line, we can tell the machinery in ``grokcore.component`` to register all components in your package (let's say it's called ``helloworld``):: To sum up, your ``site.zcml`` file should look like something like this:: Examples ======== Adapter ------- Here's a simple adapter that may be useful in Zope. It extracts the languages that a user prefers from the request:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.i18n.interfaces import IUserPreferredLanguages class CookieLanguage(grokcore.component.Adapter): """Extract the preferred language from a cookie""" grokcore.component.context(IBrowserRequest) grokcore.component.implements(IUserPreferredLanguages) # No need to implement __init__, it's already provided by the base class. def getPreferredLanguages(self): # This an adapter for the request, so self.context is the request. request = self.context # Extract the preferred language from a cookie: lang = request.cookies.get('language', 'en') # According to IUserPreferredLanguages, we must return a list. return [lang] Multi-adapter ------------- Here's a multi-adapter that functions as a content provider as known from the ``zope.contentprovider`` library. Content providers are components that return snippets of HTML. They're multi-adapters for the content object (model), the request and the view that they're supposed to be a part of:: import grokcore.component from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserPage from zope.contentprovider.interfaces import IContentProvider class HelloWorldProvider(grokcore.component.MultiAdapter): """Display Hello World!""" grokcore.component.adapts(Interface, IBrowserRequest, IBrowserPage) grokcore.component.implements(IContentProvider) def __init__(self, context, request, view): pass def update(self): pass def render(self): return u'

Hello World!

' Global utility -------------- Here's a simple named utility, again from the Zope world. It's a translation domain. In other words, it contains translations of user messages and is invoked when the i18n machinery needs to translate something:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain class HelloWorldTranslationDomain(grokcore.component.GlobalUtility): grokcore.component.implements(ITranslationDomain) grokcore.component.name('helloworld') domain = u'helloworld' def translate(self, msgid, mapping=None, context=None, target_language=None, default=None): if target_language is None: preferred = IUserPreferredLanguages(context) target_language = preferred.getPreferredLanguages()[0] translations = {'de': u'Hallo Welt', 'nl': u'Hallo Wereld'} return translations.get(target_language, u'Hello World') Of course, it's silly to implement your own translation domain utility if there are already implementations available in ``zope.i18n`` (one that reads translations from a GNU gettext message catalog and a simple implementation for tests). Let's try to reuse that implementation and register an instance:: import grokcore.component from zope.i18n.interfaces import ITranslationDomain from zope.i18n.simpletranslationdomain import SimpleTranslationDomain messages = {('de', u'Hello World'): u'Hallo Welt', ('nl', u'Hello World'): u'Hallo Wereld'} helloworld_domain = SimpleTranslationDomain(u'helloworld', messages) grokcore.component.global_utility(helloworld_domain, provides=ITranslationDomain, name='helloworld', direct=True) Global adapter -------------- Sometimes, you may have an object that should be registered as an adapter factory. It may have come from some other framework that configured that adapter for you, say, or you may have a class that you instantiate many times to get different variations on a particular adapter factory. In these cases, subclassing grokcore.component.Adapter or MultiAdapter is not possible. Instead, you can use the global_adapter() directive. Here is an example drawing on the ``z3c.form`` library, which provides an adapter factory factory for named widget attributes:: import zope.interface import zope.schema import grokcore.component import z3c.form.widget import ComputedWidgetAttribute class ISchema(Interface): """This schema will be used to power a z3c.form form""" field = zope.schema.TextLine(title=u"Sample field") ... label_override = z3c.form.widget.StaticWidgetAttribute( u"Override label", field=ISchema['field']) grokcore.component.global_adapter(label_override, name=u"label") In the example above, the provided and adapted interfaces are deduced from the object returned by the ``StaticWidgetAttribute`` factory. The full syntax for global_adapter is:: global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name") The factory must be a callable (the adapter factory). Adapted interfaces are given as a tuple. You may use a single interface instead of a one-element tuple for single adapters. The provided interface is given as shown. The name defaults to u"" (an unnamed adapter). Handling events --------------- Here we see an event handler much like it occurs within Zope itself. It subscribes to the modified event for all annotatable objects (in other words, objects that can have metadata associated with them). When invoked, it updates the Dublin Core 'Modified' property accordingly:: import datetime import grokcore.component from zope.annotation.interfaces import IAnnotatable from zope.lifecycleevent.interfaces import IObjectModifiedEvent from zope.dublincore.interfaces import IZopeDublinCore @grokcore.component.subscribe(IAnnotatable, IObjectModifiedEvent) def updateDublinCoreAfterModification(obj, event): """Updated the Dublin Core 'Modified' property when a modified event is sent for an object.""" IZopeDublinCore(obj).modified = datetime.datetime.utcnow() Subscriptions ------------- Subscriptions look similar to Adapter, however, unlike regular adapters, subscription adapters are used when we want all of the adapters that adapt an object to a particular adapter. Analogous to MultiAdapter, there is a MultiSubscription component that "adapts" multiple objects. grokcore.component-2.5/setup.cfg0000664000175000017500000000007311750014424016077 0ustar jwjw00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 grokcore.component-2.5/INSTALL.txt0000664000175000017500000000107411750014416016130 0ustar jwjw00000000000000Preparing for grok development ------------------------------ Install setuptools on your system, or use a setuptools-based environment like a "virtualenv" or a "buildout", and then install "grokcore.component". Doing it from the command line looks like:: $ sudo easy_install -U grokcore.component Then you can try importing it from your Python code. Running the tests ----------------- To run the "grokcore.component" tests, you need to download the source code from version control and run the following command which the buildout will create:: $ bin/test grokcore.component-2.5/LICENSE.txt0000664000175000017500000000402611750014416016104 0ustar jwjw00000000000000Zope 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. grokcore.component-2.5/CREDITS.txt0000664000175000017500000000022111750014416016110 0ustar jwjw00000000000000CREDITS ======= This package was extracted from the Grok web framework. For credits, see the CREDITS file in the main ``grok`` project itself.