launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #00018
[Merge] lp:~flacoste/oops-tools/buildoutification into lp:~launchpad-pqm/oops-tools/trunk
Francis J. Lacoste has proposed merging lp:~flacoste/oops-tools/buildoutification into lp:~launchpad-pqm/oops-tools/trunk.
Requested reviews:
Oops Tools development team (oops-tools-dev)
This branch turns oopstools into a buildout-based project.
The diff is huge because of the removal of all the dependencies under lib/, the diff of significant changes can be found at http://pastebin.ubuntu.com/309857/ (I removed all removal under lib/ and the boiler plate files related to buildout: bootstrap.py, _bootstrap, ez_setup.py)
The branch will look for the dependencies in download-cache. The easiest way to set it up is to checkout lazr-source-dependencies there.
Django is controlled through djangorecipe (a buildout recipe for Django application). That recipe takes care of creating a manage.py wrapper called django in the bin directory. There is also a bin/test wrapper used to run all of the tests.
I moved all script wrappers to be generated through buildout.
The configuration is also automatically generated using buildout and z3c.recipe.filetemplate
I added a production.cfg buildout config that can be used for production deployment. This allowed me to remove the TESTING setting.
Let me know if you have any questions
The attached diff has been truncated due to its size.
--
https://code.launchpad.net/~flacoste/oops-tools/buildoutification/+merge/14436
Your team Launchpad code reviewers is subscribed to branch lp:~launchpad-pqm/oops-tools/trunk.
=== modified file '.bzrignore'
--- .bzrignore 2009-04-22 21:57:01 +0000
+++ .bzrignore 2009-11-04 20:00:28 +0000
@@ -1,2 +1,14 @@
+bin
+build
+develop-eggs
+download-cache
+eggs
+oops.db
+parts
tags
-oops.db
+TAGS
+*.egg-info
+*.egg
+.installed.cfg
+apache/*
+src/oopstools/settings.py
=== modified file 'Makefile'
--- Makefile 2009-10-26 21:15:47 +0000
+++ Makefile 2009-11-04 20:00:28 +0000
@@ -1,35 +1,35 @@
-PYTHON = python2.5
PYTHON_SRC := $(wildcard *.py) $(wildcard test/*.py)
.PHONY: test lint check clean tags run dbreset harness
test:
- DJANGO_SETTINGS_MODULE=oopstools.settings PYTHONPATH=$(PWD):$(PWD)/lib/:$(PWD)/oopstools/oops/ $(PYTHON) oopstools/manage.py test
+ bin/test
lint:
pyflakes $(PYTHON_SRC)
pylint --rcfile=etc/pylintrc $(PYTHON_SRC)
-check: test
+check:
+ @echo Tests should be run manually.
-clean:
+clean:
find . -type f -name '*.py[co]' -exec rm -f {} \;
tags:
- ctags -R .
+ bin/tags
run:
- $(PYTHON) oopstools/manage.py runserver 8000
+ bin/django runserver 8000
dbreset:
- $(PYTHON) oopstools/manage.py reset oops
+ bin/django reset oops
harness:
- $(PYTHON) oopstools/manage.py shell
+ bin/django shell
update_db:
- DJANGO_SETTINGS_MODULE=oopstools.settings PYTHONPATH=$(PWD):$(PWD)/lib/:$(PWD)/oopstools/oops/ $(PYTHON) update_db.py
+ bin/update_db
load_sample_data:
- $(PYTHON) oopstools/manage.py loaddata initial_data.json && DJANGO_SETTINGS_MODULE=oopstools.settings PYTHONPATH=$(PWD):$(PWD)/lib/:$(PWD)/oopstools/oops/ $(PYTHON) load_sample_data.py
+ bin/django loaddata initial_data.json && bin/load_sample_data
=== renamed file 'README' => 'README.txt'
--- README 2009-08-11 23:19:32 +0000
+++ README.txt 2009-11-04 20:00:28 +0000
@@ -5,13 +5,11 @@
= Dependencies =
-oopstools requires the following packages:
+OOPStools uses buldout for configuration, so any missing dependencies will be
+downloaded from PyPI. To install, simply use:
- * python-django
- * python-genshi
- * python-pysqlite2
- * python-mechanize
- * python-beautifulsoup
+ * python bootstrap.py
+ * bin/buildout
To run under apache with mod_wsgi (recommended)
@@ -23,20 +21,18 @@
= Deployment using mod_wsgi =
+Update the production.cfg file with your database configuration and the paths
+to your OOPS directories:
+
+[configuration]
+db-name = /path/to/your/oops.db
+index-template = 'index-launchpad.html' or 'index-ubuntuone.html'
+oopsdir = /path/to/oops/reports
To deploy oops tools make sure all the dependecies are installed.
- * Change in apache/oopstools.wsgi:
-
- path = /path/to/oopstoolsbranch
-
- * Change in oopstools/settings.py the following variables:
-
- DATABASE_NAME = /path/to/your/oops.db
- TESTING = False
- OOPSDIR = /path/to/oops/reports
- INDEX_TEMPLATE = 'index-launchpad.html' or 'index-ubuntuone.html'
-
- * Run python oopstools/manage.py syncdb
+ * bin/buildout -c production.cfg
+
+ * Run bin/django syncdb
* Copy apache/lp-oops.canonical.dev.mod_wsgi to /etc/apache2/sites-available/
(Change the filename and contents accordingly to your deployment)
@@ -45,13 +41,12 @@
= Running locally =
Sometimes Launchpad developers want to run oops-tools to help analyse locally
-generated OOPS reports. To do that:
-
- * Change in oopstools/settings.py the following variables:
-
- DATABASE_NAME = /path/to/your/oops.db
- OOPSDIR = /path/to/oops/reports
-
- * Run python oopstools/manage.py syncdb
+generated OOPS reports.
+
+By default, the OOPS db is saved in /tmp. Change the configuration of the
+datbase in buildout.cfg and re-run buildout. You'll also want to update
+oopsdir configuration key.
+
+ * Run bin/django syncdb
* `make run` at the root of the oops-tools directory
* Point your browser to http://localhost:8000/oops
=== added directory '_bootstrap'
=== added file '_bootstrap/COPYRIGHT.txt'
--- _bootstrap/COPYRIGHT.txt 1970-01-01 00:00:00 +0000
+++ _bootstrap/COPYRIGHT.txt 2009-11-04 20:00:28 +0000
@@ -0,0 +1,9 @@
+Copyright (c) 2004-2009 Zope Corporation 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.
=== added file '_bootstrap/LICENSE.txt'
--- _bootstrap/LICENSE.txt 1970-01-01 00:00:00 +0000
+++ _bootstrap/LICENSE.txt 2009-11-04 20:00:28 +0000
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+ accompanying copyright notice, this list of conditions,
+ and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+ copyright notice, this list of conditions, and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+ endorse or promote products derived from this software
+ without prior written permission from the copyright
+ holders.
+
+4. The right to distribute this software or to use it for
+ any purpose does not give you the right to use
+ Servicemarks (sm) or Trademarks (tm) of the copyright
+ holders. Use of them is covered by separate agreement
+ with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+ files to carry prominent notices stating that you changed
+ the files and the date of any change.
+
+Disclaimer
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+ AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
\ No newline at end of file
=== added file '_bootstrap/bootstrap.py'
--- _bootstrap/bootstrap.py 1970-01-01 00:00:00 +0000
+++ _bootstrap/bootstrap.py 2009-11-04 20:00:28 +0000
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation 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.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+try:
+ import pkg_resources
+except ImportError:
+ ez = {}
+ exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+ import pkg_resources
+
+if sys.platform == 'win32':
+ def quote(c):
+ if ' ' in c:
+ return '"%s"' % c # work around spawn lamosity on windows
+ else:
+ return c
+else:
+ def quote (c):
+ return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws = pkg_resources.working_set
+
+if is_jython:
+ import subprocess
+
+ assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+ quote(tmpeggs), 'zc.buildout'],
+ env=dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ).wait() == 0
+
+else:
+ assert os.spawnle(
+ os.P_WAIT, sys.executable, quote (sys.executable),
+ '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
=== added symlink 'bootstrap.py'
=== target is u'_bootstrap/bootstrap.py'
=== added directory 'buildout-templates'
=== added directory 'buildout-templates/apache'
=== renamed file 'apache/lp-oops.canonical.dev.mod_python' => 'buildout-templates/apache/lp-oops.canonical.dev.mod_python.in'
--- apache/lp-oops.canonical.dev.mod_python 2009-04-27 21:53:02 +0000
+++ buildout-templates/apache/lp-oops.canonical.dev.mod_python.in 2009-11-04 20:00:28 +0000
@@ -8,9 +8,6 @@
#
NameVirtualHost 127.0.0.55:80
-#XXX only needed if django was installed from egg
-PythonInterpreter oopstools
-PythonImport "/home/matsubara/devel/canonical/oops-tools/oops-tools-django/oopstools/egg-location.py" oopstools
<VirtualHost 127.0.0.55:80>
ServerName lp-oops.canonical.dev
@@ -20,9 +17,8 @@
<Location "/oops/">
#XXX remove this for production instance
- SetEnv TESTING True
SetHandler python-program
- PythonPath "['/home/matsubara/devel/canonical/oops-tools/oops-tools-django/', '/home/matsubara/devel/canonical/oops-tools/oops-tools-django/oopstools'] + sys.path"
+ PythonPath "${string-paths}"
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE oopstools.settings
PythonDebug On
=== renamed file 'apache/lp-oops.canonical.dev.mod_wsgi' => 'buildout-templates/apache/lp-oops.canonical.dev.mod_wsgi.in'
--- apache/lp-oops.canonical.dev.mod_wsgi 2009-09-08 19:54:46 +0000
+++ buildout-templates/apache/lp-oops.canonical.dev.mod_wsgi.in 2009-11-04 20:00:28 +0000
@@ -7,8 +7,6 @@
# http://lp-oops.canonical.dev/summary/ ???
#
NameVirtualHost 127.0.0.55:80
-#XXX only needed if django was installed from egg
-PythonImport "/home/matsubara/devel/canonical/oops-tools/trunk/oopstools/egg-location.py" oopstools
<VirtualHost 127.0.0.55:80>
ServerName lp-oops.canonical.dev
@@ -19,13 +17,13 @@
ErrorLog /var/log/apache2/lp-oops.canonical.dev.error-log
CustomLog /var/log/apache2/lp-oops.canonical.dev.access-log combined
- Alias /static/ /home/matsubara/devel/canonical/oops-tools/trunk/oopstools/oops/static/
+ Alias /static/ ${buildout:directory}/src/oopstools/oops/static/
- <Directory /home/matsubara/devel/canonical/oops-tools/trunk/oopstools/oops/static/>
+ <Directory ${buildout:directory}/src/oopstools/oops/static/>
Order deny,allow
Allow from all
</Directory>
- WSGIScriptAlias / /home/matsubara/devel/canonical/trunk/oops-summary/apache/oopstools.wsgi
+ WSGIScriptAlias / ${buildout:bin-directory}/oopstools.wsgi
</VirtualHost>
=== added directory 'buildout-templates/bin'
=== renamed file 'apache/oopstools.wsgi' => 'buildout-templates/bin/oopstools.wsgi.in'
--- apache/oopstools.wsgi 2009-09-08 19:54:46 +0000
+++ buildout-templates/bin/oopstools.wsgi.in 2009-11-04 20:00:28 +0000
@@ -1,12 +1,11 @@
import os
import sys
-#XXX change this for production
-path = "/home/matsubara/devel/canonical/oops-tools/trunk/"
-# don't re-add the path over and over again in case this file is reloaded
-# see http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode
-if path not in sys.path:
- sys.path.append(path)
+paths = [${string-paths}]
+
+for path in paths:
+ if path not in sys.path:
+ sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = "oopstools.settings"
import django.core.handlers.wsgi
=== added directory 'buildout-templates/src'
=== added directory 'buildout-templates/src/oopstools'
=== renamed file 'oopstools/settings.py' => 'buildout-templates/src/oopstools/settings.py.in'
--- oopstools/settings.py 2009-08-29 23:26:29 +0000
+++ buildout-templates/src/oopstools/settings.py.in 2009-11-04 20:00:28 +0000
@@ -9,15 +9,20 @@
MANAGERS = ADMINS
-DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
-# XXX fix this so it won't depend on abspath.
+# 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_ENGINE = '${configuration:db-engine}'
# XXX database file *and* parent directory needs to be writable by apache
# process. See http://django.freelancernepal.com/errors/django-says-unable-to-open-database-file-when-using-sqlite3/
-DATABASE_NAME = '/home/matsubara/oopsdb/oops.db' # Or path to database file if using sqlite3.
-DATABASE_USER = '' # Not used with sqlite3.
-DATABASE_PASSWORD = '' # Not used with sqlite3.
-DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
-DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+# Or path to database file if using sqlite3.
+DATABASE_NAME = "${configuration:db-name}"
+# Not used with sqlite3.
+DATABASE_USER = "${configuration:db-user}"
+# Not used with sqlite3.
+DATABASE_PASSWORD = "${configuration:db-password}"
+# Set to empty string for localhost. Not used with sqlite3.
+DATABASE_HOST = "${configuration:db-host}"
+# Set to empty string for default. Not used with sqlite3.
+DATABASE_PORT = "${configuration:db-port}"
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
@@ -76,26 +81,25 @@
TEST_RUNNER = 'oopstools.oops.test.test_runner.run_tests'
-import os.path
-HERE = os.path.dirname(__file__)
-
-STATIC_DOC_ROOT = os.path.join(HERE, 'oops', 'static')
+import os
+
+ROOT = "${buildout:directory}"
+BIN_DIR = "${buildout:bin-directory}"
+
+STATIC_DOC_ROOT = os.path.join(ROOT, 'src', 'oopstools', 'oops', 'static')
GENSHI_TEMPLATE_DIRS = (
- os.path.join(HERE, 'oops', 'templates'),
+ os.path.join(ROOT, 'src', 'oopstools', 'oops', 'templates'),
)
-#XXX: set to False on production instance
-TESTING = True
-
-if TESTING:
- OOPSDIR = os.path.join(HERE, 'oops', 'test', 'files', 'oops-sample')
-else:
- # Set to the corresponding dirs for your deployment
- OOPSDIR = ['/srv/launchpad.net-logs/',
- '/srv/launchpad.net-logs/scripts/forster/mailman-xmlrpc/']
-
-# Swap index pages for LP or U1
-INDEX_TEMPLATE = 'index-launchpad.html'
+
+# XXX: If we could get this in a convenient format from
+# z3c.recipe.filetemplate it would be better.
+paths = """
+ ${configuration:oopsdir}
+"""
+OOPSDIR = [path.strip() for path in paths.split()]
+
+INDEX_TEMPLATE = ${configuration:index-template}
INSTALLED_APPS = (
'django.contrib.auth',
=== added file 'buildout.cfg'
--- buildout.cfg 1970-01-01 00:00:00 +0000
+++ buildout.cfg 2009-11-04 20:00:28 +0000
@@ -0,0 +1,72 @@
+[buildout]
+parts =
+ filetemplates
+ django
+ docs
+ scripts
+ tags
+unzip = true
+eggs-directory = eggs
+download-cache = download-cache
+
+# Disable this option temporarily if you want buildout to find software
+# dependencies *other* than those in our download-cache. Once you have the
+# desired software, reenable this option (and check in the new software to
+# lp:lazr-source-dependencies if this is going to be reviewed/merged/deployed.)
+install-from-cache = true
+
+# This also will need to be temporarily disabled or changed for package
+# upgrades. Newly-added packages should also add their desired version number
+# to versions.cfg.
+extends = versions.cfg
+
+# allow-picked-versions = false # A buildout bug is not allowing this to work.
+prefer-final = true
+
+develop = .
+
+[configuration]
+db-engine = sqlite3
+db-name = /tmp/oopstools.db
+db-user =
+db-password =
+db-host =
+db-port =
+oopsdir = ${buildout:directory}/src/oopstools/oops/test/files/oops-sample
+index-template = 'index-launchpad.html'
+
+[django]
+recipe = djangorecipe
+version = 1.1.1
+project = oopstools
+projectegg = oopstools
+settings = settings
+test = oopstools
+eggs = oopstools
+
+[filetemplates]
+recipe = z3c.recipe.filetemplate
+eggs = oopstools
+extra-paths = ${scripts:extra-paths}
+source-directory = buildout-templates
+
+[docs]
+recipe = z3c.recipe.sphinxdoc
+eggs = oopstools [docs]
+index-doc = README.txt
+default.css =
+layout.html =
+
+[scripts]
+recipe = zc.recipe.egg
+interpreter = py
+eggs = oopstools
+ docutils
+# XXX: djangorecipe doesn't install Django as part of the normal omelette.
+extra-paths = ${buildout:directory}/parts/django
+initialization = import os
+ os.environ['DJANGO_SETTINGS_MODULE'] = 'oopstools.settings'
+
+[tags]
+recipe = z3c.recipe.tag:tags
+eggs = oopstools
=== added file 'ez_setup.py'
--- ez_setup.py 1970-01-01 00:00:00 +0000
+++ ez_setup.py 2009-11-04 20:00:28 +0000
@@ -0,0 +1,241 @@
+#!python
+"""Bootstrap setuptools installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+ from ez_setup import use_setuptools
+ use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import sys
+DEFAULT_VERSION = "0.6c8"
+DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
+
+md5_data = {
+ 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
+ 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
+ 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
+ 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
+ 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
+ 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
+ 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
+ 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
+ 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
+ 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
+ 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
+ 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
+ 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
+ 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
+ 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
+ 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
+ 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
+ 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
+ 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
+ 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
+ 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
+ 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
+ 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
+ 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
+ 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
+ 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
+ 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
+ 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
+ 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
+ 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
+}
+
+import sys, os
+
+def _validate_md5(egg_name, data):
+ if egg_name in md5_data:
+ from md5 import md5
+ digest = md5(data).hexdigest()
+ if digest != md5_data[egg_name]:
+ print >>sys.stderr, (
+ "md5 validation of %s failed! (Possible download problem?)"
+ % egg_name
+ )
+ sys.exit(2)
+ return data
+
+
+def use_setuptools(
+ version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
+ download_delay=15, min_version=None
+):
+ """Automatically find/download setuptools and make it available on sys.path
+
+ `version` should be a valid setuptools version number that is available
+ as an egg for download under the `download_base` URL (which should end with
+ a '/'). `to_dir` is the directory where setuptools will be downloaded, if
+ it is not already available. If `download_delay` is specified, it should
+ be the number of seconds that will be paused before initiating a download,
+ should one be required. If an older version of setuptools is installed,
+ this routine will print a message to ``sys.stderr`` and raise SystemExit in
+ an attempt to abort the calling script.
+ """
+ # Work around a hack in the ez_setup.py file from simplejson==1.7.3.
+ if min_version:
+ version = min_version
+
+ was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
+ def do_download():
+ egg = download_setuptools(version, download_base, to_dir, download_delay)
+ sys.path.insert(0, egg)
+ import setuptools; setuptools.bootstrap_install_from = egg
+ try:
+ import pkg_resources
+ except ImportError:
+ return do_download()
+ try:
+ pkg_resources.require("setuptools>="+version); return
+ except pkg_resources.VersionConflict, e:
+ if was_imported:
+ print >>sys.stderr, (
+ "The required version of setuptools (>=%s) is not available, and\n"
+ "can't be installed while this script is running. Please install\n"
+ " a more recent version first, using 'easy_install -U setuptools'."
+ "\n\n(Currently using %r)"
+ ) % (version, e.args[0])
+ sys.exit(2)
+ else:
+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
+ return do_download()
+ except pkg_resources.DistributionNotFound:
+ return do_download()
+
+def download_setuptools(
+ version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
+ delay = 15
+):
+ """Download setuptools from a specified location and return its filename
+
+ `version` should be a valid setuptools version number that is available
+ as an egg for download under the `download_base` URL (which should end
+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
+ `delay` is the number of seconds to pause before an actual download attempt.
+ """
+ import urllib2, shutil
+ egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
+ url = download_base + egg_name
+ saveto = os.path.join(to_dir, egg_name)
+ src = dst = None
+ if not os.path.exists(saveto): # Avoid repeated downloads
+ try:
+ from distutils import log
+ if delay:
+ log.warn("""
+---------------------------------------------------------------------------
+This script requires setuptools version %s to run (even to display
+help). I will attempt to download it for you (from
+%s), but
+you may need to enable firewall access for this script first.
+I will start the download in %d seconds.
+
+(Note: if this machine does not have network access, please obtain the file
+
+ %s
+
+and place it in this directory before rerunning this script.)
+---------------------------------------------------------------------------""",
+ version, download_base, delay, url
+ ); from time import sleep; sleep(delay)
+ log.warn("Downloading %s", url)
+ src = urllib2.urlopen(url)
+ # Read/write all in one block, so we don't create a corrupt file
+ # if the download is interrupted.
+ data = _validate_md5(egg_name, src.read())
+ dst = open(saveto,"wb"); dst.write(data)
+ finally:
+ if src: src.close()
+ if dst: dst.close()
+ return os.path.realpath(saveto)
+
+def main(argv, version=DEFAULT_VERSION):
+ """Install or upgrade setuptools and EasyInstall"""
+ try:
+ import setuptools
+ except ImportError:
+ egg = None
+ try:
+ egg = download_setuptools(version, delay=0)
+ sys.path.insert(0,egg)
+ from setuptools.command.easy_install import main
+ return main(list(argv)+[egg]) # we're done here
+ finally:
+ if egg and os.path.exists(egg):
+ os.unlink(egg)
+ else:
+ if setuptools.__version__ == '0.0.1':
+ print >>sys.stderr, (
+ "You have an obsolete version of setuptools installed. Please\n"
+ "remove it from your system entirely before rerunning this script."
+ )
+ sys.exit(2)
+
+ req = "setuptools>="+version
+ import pkg_resources
+ try:
+ pkg_resources.require(req)
+ except pkg_resources.VersionConflict:
+ try:
+ from setuptools.command.easy_install import main
+ except ImportError:
+ from easy_install import main
+ main(list(argv)+[download_setuptools(delay=0)])
+ sys.exit(0) # try to force an exit
+ else:
+ if argv:
+ from setuptools.command.easy_install import main
+ main(argv)
+ else:
+ print "Setuptools version",version,"or greater has been installed."
+ print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
+
+def update_md5(filenames):
+ """Update our built-in md5 registry"""
+
+ import re
+ from md5 import md5
+
+ for name in filenames:
+ base = os.path.basename(name)
+ f = open(name,'rb')
+ md5_data[base] = md5(f.read()).hexdigest()
+ f.close()
+
+ data = [" %r: %r,\n" % it for it in md5_data.items()]
+ data.sort()
+ repl = "".join(data)
+
+ import inspect
+ srcfile = inspect.getsourcefile(sys.modules[__name__])
+ f = open(srcfile, 'rb'); src = f.read(); f.close()
+
+ match = re.search("\nmd5_data = {\n([^}]+)}", src)
+ if not match:
+ print >>sys.stderr, "Internal error!"
+ sys.exit(2)
+
+ src = src[:match.start(1)] + repl + src[match.end(1):]
+ f = open(srcfile,'w')
+ f.write(src)
+ f.close()
+
+
+if __name__=='__main__':
+ if len(sys.argv)>2 and sys.argv[1]=='--md5update':
+ update_md5(sys.argv[2:])
+ else:
+ main(sys.argv[1:])
+
+
+
+
+
=== removed directory 'lib'
=== removed file 'lib/BeautifulSoup.py'
--- lib/BeautifulSoup.py 2008-11-07 14:14:21 +0000
+++ lib/BeautifulSoup.py 1970-01-01 00:00:00 +0000
@@ -1,1767 +0,0 @@
-"""Beautiful Soup
-Elixir and Tonic
-"The Screen-Scraper's Friend"
-http://www.crummy.com/software/BeautifulSoup/
-
-Beautiful Soup parses a (possibly invalid) XML or HTML document into a
-tree representation. It provides methods and Pythonic idioms that make
-it easy to navigate, search, and modify the tree.
-
-A well-formed XML/HTML document yields a well-formed data
-structure. An ill-formed XML/HTML document yields a correspondingly
-ill-formed data structure. If your document is only locally
-well-formed, you can use this library to find and process the
-well-formed part of it. The BeautifulSoup class
-
-Beautiful Soup works with Python 2.2 and up. It has no external
-dependencies, but you'll have more success at converting data to UTF-8
-if you also install these three packages:
-
-* chardet, for auto-detecting character encodings
- http://chardet.feedparser.org/
-* cjkcodecs and iconv_codec, which add more encodings to the ones supported
- by stock Python.
- http://cjkpython.i18n.org/
-
-Beautiful Soup defines classes for two main parsing strategies:
-
- * BeautifulStoneSoup, for parsing XML, SGML, or your domain-specific
- language that kind of looks like XML.
-
- * BeautifulSoup, for parsing run-of-the-mill HTML code, be it valid
- or invalid. This class has web browser-like heuristics for
- obtaining a sensible parse tree in the face of common HTML errors.
-
-Beautiful Soup also defines a class (UnicodeDammit) for autodetecting
-the encoding of an HTML or XML document, and converting it to
-Unicode. Much of this code is taken from Mark Pilgrim's Universal Feed Parser.
-
-For more than you ever wanted to know about Beautiful Soup, see the
-documentation:
-http://www.crummy.com/software/BeautifulSoup/documentation.html
-
-"""
-from __future__ import generators
-
-__author__ = "Leonard Richardson (leonardr@xxxxxxxxxxxx)"
-__version__ = "3.0.4"
-__copyright__ = "Copyright (c) 2004-2007 Leonard Richardson"
-__license__ = "PSF"
-
-from sgmllib import SGMLParser, SGMLParseError
-import codecs
-import types
-import re
-import sgmllib
-try:
- from htmlentitydefs import name2codepoint
-except ImportError:
- name2codepoint = {}
-
-#This hack makes Beautiful Soup able to parse XML with namespaces
-sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*')
-
-DEFAULT_OUTPUT_ENCODING = "utf-8"
-
-# First, the classes that represent markup elements.
-
-class PageElement:
- """Contains the navigational information for some part of the page
- (either a tag or a piece of text)"""
-
- def setup(self, parent=None, previous=None):
- """Sets up the initial relations between this element and
- other elements."""
- self.parent = parent
- self.previous = previous
- self.next = None
- self.previousSibling = None
- self.nextSibling = None
- if self.parent and self.parent.contents:
- self.previousSibling = self.parent.contents[-1]
- self.previousSibling.nextSibling = self
-
- def replaceWith(self, replaceWith):
- oldParent = self.parent
- myIndex = self.parent.contents.index(self)
- if hasattr(replaceWith, 'parent') and replaceWith.parent == self.parent:
- # We're replacing this element with one of its siblings.
- index = self.parent.contents.index(replaceWith)
- if index and index < myIndex:
- # Furthermore, it comes before this element. That
- # means that when we extract it, the index of this
- # element will change.
- myIndex = myIndex - 1
- self.extract()
- oldParent.insert(myIndex, replaceWith)
-
- def extract(self):
- """Destructively rips this element out of the tree."""
- if self.parent:
- try:
- self.parent.contents.remove(self)
- except ValueError:
- pass
-
- #Find the two elements that would be next to each other if
- #this element (and any children) hadn't been parsed. Connect
- #the two.
- lastChild = self._lastRecursiveChild()
- nextElement = lastChild.next
-
- if self.previous:
- self.previous.next = nextElement
- if nextElement:
- nextElement.previous = self.previous
- self.previous = None
- lastChild.next = None
-
- self.parent = None
- if self.previousSibling:
- self.previousSibling.nextSibling = self.nextSibling
- if self.nextSibling:
- self.nextSibling.previousSibling = self.previousSibling
- self.previousSibling = self.nextSibling = None
-
- def _lastRecursiveChild(self):
- "Finds the last element beneath this object to be parsed."
- lastChild = self
- while hasattr(lastChild, 'contents') and lastChild.contents:
- lastChild = lastChild.contents[-1]
- return lastChild
-
- def insert(self, position, newChild):
- if (isinstance(newChild, basestring)
- or isinstance(newChild, unicode)) \
- and not isinstance(newChild, NavigableString):
- newChild = NavigableString(newChild)
-
- position = min(position, len(self.contents))
- if hasattr(newChild, 'parent') and newChild.parent != None:
- # We're 'inserting' an element that's already one
- # of this object's children.
- if newChild.parent == self:
- index = self.find(newChild)
- if index and index < position:
- # Furthermore we're moving it further down the
- # list of this object's children. That means that
- # when we extract this element, our target index
- # will jump down one.
- position = position - 1
- newChild.extract()
-
- newChild.parent = self
- previousChild = None
- if position == 0:
- newChild.previousSibling = None
- newChild.previous = self
- else:
- previousChild = self.contents[position-1]
- newChild.previousSibling = previousChild
- newChild.previousSibling.nextSibling = newChild
- newChild.previous = previousChild._lastRecursiveChild()
- if newChild.previous:
- newChild.previous.next = newChild
-
- newChildsLastElement = newChild._lastRecursiveChild()
-
- if position >= len(self.contents):
- newChild.nextSibling = None
-
- parent = self
- parentsNextSibling = None
- while not parentsNextSibling:
- parentsNextSibling = parent.nextSibling
- parent = parent.parent
- if not parent: # This is the last element in the document.
- break
- if parentsNextSibling:
- newChildsLastElement.next = parentsNextSibling
- else:
- newChildsLastElement.next = None
- else:
- nextChild = self.contents[position]
- newChild.nextSibling = nextChild
- if newChild.nextSibling:
- newChild.nextSibling.previousSibling = newChild
- newChildsLastElement.next = nextChild
-
- if newChildsLastElement.next:
- newChildsLastElement.next.previous = newChildsLastElement
- self.contents.insert(position, newChild)
-
- def findNext(self, name=None, attrs={}, text=None, **kwargs):
- """Returns the first item that matches the given criteria and
- appears after this Tag in the document."""
- return self._findOne(self.findAllNext, name, attrs, text, **kwargs)
-
- def findAllNext(self, name=None, attrs={}, text=None, limit=None,
- **kwargs):
- """Returns all items that match the given criteria and appear
- before after Tag in the document."""
- return self._findAll(name, attrs, text, limit, self.nextGenerator)
-
- def findNextSibling(self, name=None, attrs={}, text=None, **kwargs):
- """Returns the closest sibling to this Tag that matches the
- given criteria and appears after this Tag in the document."""
- return self._findOne(self.findNextSiblings, name, attrs, text,
- **kwargs)
-
- def findNextSiblings(self, name=None, attrs={}, text=None, limit=None,
- **kwargs):
- """Returns the siblings of this Tag that match the given
- criteria and appear after this Tag in the document."""
- return self._findAll(name, attrs, text, limit,
- self.nextSiblingGenerator, **kwargs)
- fetchNextSiblings = findNextSiblings # Compatibility with pre-3.x
-
- def findPrevious(self, name=None, attrs={}, text=None, **kwargs):
- """Returns the first item that matches the given criteria and
- appears before this Tag in the document."""
- return self._findOne(self.findAllPrevious, name, attrs, text, **kwargs)
-
- def findAllPrevious(self, name=None, attrs={}, text=None, limit=None,
- **kwargs):
- """Returns all items that match the given criteria and appear
- before this Tag in the document."""
- return self._findAll(name, attrs, text, limit, self.previousGenerator,
- **kwargs)
- fetchPrevious = findAllPrevious # Compatibility with pre-3.x
-
- def findPreviousSibling(self, name=None, attrs={}, text=None, **kwargs):
- """Returns the closest sibling to this Tag that matches the
- given criteria and appears before this Tag in the document."""
- return self._findOne(self.findPreviousSiblings, name, attrs, text,
- **kwargs)
-
- def findPreviousSiblings(self, name=None, attrs={}, text=None,
- limit=None, **kwargs):
- """Returns the siblings of this Tag that match the given
- criteria and appear before this Tag in the document."""
- return self._findAll(name, attrs, text, limit,
- self.previousSiblingGenerator, **kwargs)
- fetchPreviousSiblings = findPreviousSiblings # Compatibility with pre-3.x
-
- def findParent(self, name=None, attrs={}, **kwargs):
- """Returns the closest parent of this Tag that matches the given
- criteria."""
- # NOTE: We can't use _findOne because findParents takes a different
- # set of arguments.
- r = None
- l = self.findParents(name, attrs, 1)
- if l:
- r = l[0]
- return r
-
- def findParents(self, name=None, attrs={}, limit=None, **kwargs):
- """Returns the parents of this Tag that match the given
- criteria."""
-
- return self._findAll(name, attrs, None, limit, self.parentGenerator,
- **kwargs)
- fetchParents = findParents # Compatibility with pre-3.x
-
- #These methods do the real heavy lifting.
-
- def _findOne(self, method, name, attrs, text, **kwargs):
- r = None
- l = method(name, attrs, text, 1, **kwargs)
- if l:
- r = l[0]
- return r
-
- def _findAll(self, name, attrs, text, limit, generator, **kwargs):
- "Iterates over a generator looking for things that match."
-
- if isinstance(name, SoupStrainer):
- strainer = name
- else:
- # Build a SoupStrainer
- strainer = SoupStrainer(name, attrs, text, **kwargs)
- results = ResultSet(strainer)
- g = generator()
- while True:
- try:
- i = g.next()
- except StopIteration:
- break
- if i:
- found = strainer.search(i)
- if found:
- results.append(found)
- if limit and len(results) >= limit:
- break
- return results
-
- #These Generators can be used to navigate starting from both
- #NavigableStrings and Tags.
- def nextGenerator(self):
- i = self
- while i:
- i = i.next
- yield i
-
- def nextSiblingGenerator(self):
- i = self
- while i:
- i = i.nextSibling
- yield i
-
- def previousGenerator(self):
- i = self
- while i:
- i = i.previous
- yield i
-
- def previousSiblingGenerator(self):
- i = self
- while i:
- i = i.previousSibling
- yield i
-
- def parentGenerator(self):
- i = self
- while i:
- i = i.parent
- yield i
-
- # Utility methods
- def substituteEncoding(self, str, encoding=None):
- encoding = encoding or "utf-8"
- return str.replace("%SOUP-ENCODING%", encoding)
-
- def toEncoding(self, s, encoding=None):
- """Encodes an object to a string in some encoding, or to Unicode.
- ."""
- if isinstance(s, unicode):
- if encoding:
- s = s.encode(encoding)
- elif isinstance(s, str):
- if encoding:
- s = s.encode(encoding)
- else:
- s = unicode(s)
- else:
- if encoding:
- s = self.toEncoding(str(s), encoding)
- else:
- s = unicode(s)
- return s
-
-class NavigableString(unicode, PageElement):
-
- def __getattr__(self, attr):
- """text.string gives you text. This is for backwards
- compatibility for Navigable*String, but for CData* it lets you
- get the string without the CData wrapper."""
- if attr == 'string':
- return self
- else:
- raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr)
-
- def __unicode__(self):
- return self.__str__(None)
-
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- if encoding:
- return self.encode(encoding)
- else:
- return self
-
-class CData(NavigableString):
-
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- return "<![CDATA[%s]]>" % NavigableString.__str__(self, encoding)
-
-class ProcessingInstruction(NavigableString):
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- output = self
- if "%SOUP-ENCODING%" in output:
- output = self.substituteEncoding(output, encoding)
- return "<?%s?>" % self.toEncoding(output, encoding)
-
-class Comment(NavigableString):
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- return "<!--%s-->" % NavigableString.__str__(self, encoding)
-
-class Declaration(NavigableString):
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- return "<!%s>" % NavigableString.__str__(self, encoding)
-
-class Tag(PageElement):
-
- """Represents a found HTML tag with its attributes and contents."""
-
- XML_SPECIAL_CHARS_TO_ENTITIES = { "'" : "squot",
- '"' : "quote",
- "&" : "amp",
- "<" : "lt",
- ">" : "gt" }
-
- def __init__(self, parser, name, attrs=None, parent=None,
- previous=None):
- "Basic constructor."
-
- # We don't actually store the parser object: that lets extracted
- # chunks be garbage-collected
- self.parserClass = parser.__class__
- self.isSelfClosing = parser.isSelfClosingTag(name)
- self.name = name
- if attrs == None:
- attrs = []
- self.attrs = attrs
- self.contents = []
- self.setup(parent, previous)
- self.hidden = False
- self.containsSubstitutions = False
-
- def get(self, key, default=None):
- """Returns the value of the 'key' attribute for the tag, or
- the value given for 'default' if it doesn't have that
- attribute."""
- return self._getAttrMap().get(key, default)
-
- def has_key(self, key):
- return self._getAttrMap().has_key(key)
-
- def __getitem__(self, key):
- """tag[key] returns the value of the 'key' attribute for the tag,
- and throws an exception if it's not there."""
- return self._getAttrMap()[key]
-
- def __iter__(self):
- "Iterating over a tag iterates over its contents."
- return iter(self.contents)
-
- def __len__(self):
- "The length of a tag is the length of its list of contents."
- return len(self.contents)
-
- def __contains__(self, x):
- return x in self.contents
-
- def __nonzero__(self):
- "A tag is non-None even if it has no contents."
- return True
-
- def __setitem__(self, key, value):
- """Setting tag[key] sets the value of the 'key' attribute for the
- tag."""
- self._getAttrMap()
- self.attrMap[key] = value
- found = False
- for i in range(0, len(self.attrs)):
- if self.attrs[i][0] == key:
- self.attrs[i] = (key, value)
- found = True
- if not found:
- self.attrs.append((key, value))
- self._getAttrMap()[key] = value
-
- def __delitem__(self, key):
- "Deleting tag[key] deletes all 'key' attributes for the tag."
- for item in self.attrs:
- if item[0] == key:
- self.attrs.remove(item)
- #We don't break because bad HTML can define the same
- #attribute multiple times.
- self._getAttrMap()
- if self.attrMap.has_key(key):
- del self.attrMap[key]
-
- def __call__(self, *args, **kwargs):
- """Calling a tag like a function is the same as calling its
- findAll() method. Eg. tag('a') returns a list of all the A tags
- found within this tag."""
- return apply(self.findAll, args, kwargs)
-
- def __getattr__(self, tag):
- #print "Getattr %s.%s" % (self.__class__, tag)
- if len(tag) > 3 and tag.rfind('Tag') == len(tag)-3:
- return self.find(tag[:-3])
- elif tag.find('__') != 0:
- return self.find(tag)
-
- def __eq__(self, other):
- """Returns true iff this tag has the same name, the same attributes,
- and the same contents (recursively) as the given tag.
-
- NOTE: right now this will return false if two tags have the
- same attributes in a different order. Should this be fixed?"""
- if not hasattr(other, 'name') or not hasattr(other, 'attrs') or not hasattr(other, 'contents') or self.name != other.name or self.attrs != other.attrs or len(self) != len(other):
- return False
- for i in range(0, len(self.contents)):
- if self.contents[i] != other.contents[i]:
- return False
- return True
-
- def __ne__(self, other):
- """Returns true iff this tag is not identical to the other tag,
- as defined in __eq__."""
- return not self == other
-
- def __repr__(self, encoding=DEFAULT_OUTPUT_ENCODING):
- """Renders this tag as a string."""
- return self.__str__(encoding)
-
- def __unicode__(self):
- return self.__str__(None)
-
- def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING,
- prettyPrint=False, indentLevel=0):
- """Returns a string or Unicode representation of this tag and
- its contents. To get Unicode, pass None for encoding.
-
- NOTE: since Python's HTML parser consumes whitespace, this
- method is not certain to reproduce the whitespace present in
- the original string."""
-
- encodedName = self.toEncoding(self.name, encoding)
-
- attrs = []
- if self.attrs:
- for key, val in self.attrs:
- fmt = '%s="%s"'
- if isString(val):
- if self.containsSubstitutions and '%SOUP-ENCODING%' in val:
- val = self.substituteEncoding(val, encoding)
-
- # The attribute value either:
- #
- # * Contains no embedded double quotes or single quotes.
- # No problem: we enclose it in double quotes.
- # * Contains embedded single quotes. No problem:
- # double quotes work here too.
- # * Contains embedded double quotes. No problem:
- # we enclose it in single quotes.
- # * Embeds both single _and_ double quotes. This
- # can't happen naturally, but it can happen if
- # you modify an attribute value after parsing
- # the document. Now we have a bit of a
- # problem. We solve it by enclosing the
- # attribute in single quotes, and escaping any
- # embedded single quotes to XML entities.
- if '"' in val:
- fmt = "%s='%s'"
- # This can't happen naturally, but it can happen
- # if you modify an attribute value after parsing.
- if "'" in val:
- val = val.replace("'", "&squot;")
-
- # Now we're okay w/r/t quotes. But the attribute
- # value might also contain angle brackets, or
- # ampersands that aren't part of entities. We need
- # to escape those to XML entities too.
- val = re.sub("([<>]|&(?![^\s]+;))",
- lambda x: "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";",
- val)
-
- attrs.append(fmt % (self.toEncoding(key, encoding),
- self.toEncoding(val, encoding)))
- close = ''
- closeTag = ''
- if self.isSelfClosing:
- close = ' /'
- else:
- closeTag = '</%s>' % encodedName
-
- indentTag, indentContents = 0, 0
- if prettyPrint:
- indentTag = indentLevel
- space = (' ' * (indentTag-1))
- indentContents = indentTag + 1
- contents = self.renderContents(encoding, prettyPrint, indentContents)
- if self.hidden:
- s = contents
- else:
- s = []
- attributeString = ''
- if attrs:
- attributeString = ' ' + ' '.join(attrs)
- if prettyPrint:
- s.append(space)
- s.append('<%s%s%s>' % (encodedName, attributeString, close))
- if prettyPrint:
- s.append("\n")
- s.append(contents)
- if prettyPrint and contents and contents[-1] != "\n":
- s.append("\n")
- if prettyPrint and closeTag:
- s.append(space)
- s.append(closeTag)
- if prettyPrint and closeTag and self.nextSibling:
- s.append("\n")
- s = ''.join(s)
- return s
-
- def prettify(self, encoding=DEFAULT_OUTPUT_ENCODING):
- return self.__str__(encoding, True)
-
- def renderContents(self, encoding=DEFAULT_OUTPUT_ENCODING,
- prettyPrint=False, indentLevel=0):
- """Renders the contents of this tag as a string in the given
- encoding. If encoding is None, returns a Unicode string.."""
- s=[]
- for c in self:
- text = None
- if isinstance(c, NavigableString):
- text = c.__str__(encoding)
- elif isinstance(c, Tag):
- s.append(c.__str__(encoding, prettyPrint, indentLevel))
- if text and prettyPrint:
- text = text.strip()
- if text:
- if prettyPrint:
- s.append(" " * (indentLevel-1))
- s.append(text)
- if prettyPrint:
- s.append("\n")
- return ''.join(s)
-
- #Soup methods
-
- def find(self, name=None, attrs={}, recursive=True, text=None,
- **kwargs):
- """Return only the first child of this Tag matching the given
- criteria."""
- r = None
- l = self.findAll(name, attrs, recursive, text, 1, **kwargs)
- if l:
- r = l[0]
- return r
- findChild = find
-
- def findAll(self, name=None, attrs={}, recursive=True, text=None,
- limit=None, **kwargs):
- """Extracts a list of Tag objects that match the given
- criteria. You can specify the name of the Tag and any
- attributes you want the Tag to have.
-
- The value of a key-value pair in the 'attrs' map can be a
- string, a list of strings, a regular expression object, or a
- callable that takes a string and returns whether or not the
- string matches for some custom definition of 'matches'. The
- same is true of the tag name."""
- generator = self.recursiveChildGenerator
- if not recursive:
- generator = self.childGenerator
- return self._findAll(name, attrs, text, limit, generator, **kwargs)
- findChildren = findAll
-
- # Pre-3.x compatibility methods
- first = find
- fetch = findAll
-
- def fetchText(self, text=None, recursive=True, limit=None):
- return self.findAll(text=text, recursive=recursive, limit=limit)
-
- def firstText(self, text=None, recursive=True):
- return self.find(text=text, recursive=recursive)
-
- #Utility methods
-
- def append(self, tag):
- """Appends the given tag to the contents of this tag."""
- self.contents.append(tag)
-
- #Private methods
-
- def _getAttrMap(self):
- """Initializes a map representation of this tag's attributes,
- if not already initialized."""
- if not getattr(self, 'attrMap'):
- self.attrMap = {}
- for (key, value) in self.attrs:
- self.attrMap[key] = value
- return self.attrMap
-
- #Generator methods
- def childGenerator(self):
- for i in range(0, len(self.contents)):
- yield self.contents[i]
- raise StopIteration
-
- def recursiveChildGenerator(self):
- stack = [(self, 0)]
- while stack:
- tag, start = stack.pop()
- if isinstance(tag, Tag):
- for i in range(start, len(tag.contents)):
- a = tag.contents[i]
- yield a
- if isinstance(a, Tag) and tag.contents:
- if i < len(tag.contents) - 1:
- stack.append((tag, i+1))
- stack.append((a, 0))
- break
- raise StopIteration
-
-# Next, a couple classes to represent queries and their results.
-class SoupStrainer:
- """Encapsulates a number of ways of matching a markup element (tag or
- text)."""
-
- def __init__(self, name=None, attrs={}, text=None, **kwargs):
- self.name = name
- if isString(attrs):
- kwargs['class'] = attrs
- attrs = None
- if kwargs:
- if attrs:
- attrs = attrs.copy()
- attrs.update(kwargs)
- else:
- attrs = kwargs
- self.attrs = attrs
- self.text = text
-
- def __str__(self):
- if self.text:
- return self.text
- else:
- return "%s|%s" % (self.name, self.attrs)
-
- def searchTag(self, markupName=None, markupAttrs={}):
- found = None
- markup = None
- if isinstance(markupName, Tag):
- markup = markupName
- markupAttrs = markup
- callFunctionWithTagData = callable(self.name) \
- and not isinstance(markupName, Tag)
-
- if (not self.name) \
- or callFunctionWithTagData \
- or (markup and self._matches(markup, self.name)) \
- or (not markup and self._matches(markupName, self.name)):
- if callFunctionWithTagData:
- match = self.name(markupName, markupAttrs)
- else:
- match = True
- markupAttrMap = None
- for attr, matchAgainst in self.attrs.items():
- if not markupAttrMap:
- if hasattr(markupAttrs, 'get'):
- markupAttrMap = markupAttrs
- else:
- markupAttrMap = {}
- for k,v in markupAttrs:
- markupAttrMap[k] = v
- attrValue = markupAttrMap.get(attr)
- if not self._matches(attrValue, matchAgainst):
- match = False
- break
- if match:
- if markup:
- found = markup
- else:
- found = markupName
- return found
-
- def search(self, markup):
- #print 'looking for %s in %s' % (self, markup)
- found = None
- # If given a list of items, scan it for a text element that
- # matches.
- if isList(markup) and not isinstance(markup, Tag):
- for element in markup:
- if isinstance(element, NavigableString) \
- and self.search(element):
- found = element
- break
- # If it's a Tag, make sure its name or attributes match.
- # Don't bother with Tags if we're searching for text.
- elif isinstance(markup, Tag):
- if not self.text:
- found = self.searchTag(markup)
- # If it's text, make sure the text matches.
- elif isinstance(markup, NavigableString) or \
- isString(markup):
- if self._matches(markup, self.text):
- found = markup
- else:
- raise Exception, "I don't know how to match against a %s" \
- % markup.__class__
- return found
-
- def _matches(self, markup, matchAgainst):
- #print "Matching %s against %s" % (markup, matchAgainst)
- result = False
- if matchAgainst == True and type(matchAgainst) == types.BooleanType:
- result = markup != None
- elif callable(matchAgainst):
- result = matchAgainst(markup)
- else:
- #Custom match methods take the tag as an argument, but all
- #other ways of matching match the tag name as a string.
- if isinstance(markup, Tag):
- markup = markup.name
- if markup and not isString(markup):
- markup = unicode(markup)
- #Now we know that chunk is either a string, or None.
- if hasattr(matchAgainst, 'match'):
- # It's a regexp object.
- result = markup and matchAgainst.search(markup)
- elif isList(matchAgainst):
- result = markup in matchAgainst
- elif hasattr(matchAgainst, 'items'):
- result = markup.has_key(matchAgainst)
- elif matchAgainst and isString(markup):
- if isinstance(markup, unicode):
- matchAgainst = unicode(matchAgainst)
- else:
- matchAgainst = str(matchAgainst)
-
- if not result:
- result = matchAgainst == markup
- return result
-
-class ResultSet(list):
- """A ResultSet is just a list that keeps track of the SoupStrainer
- that created it."""
- def __init__(self, source):
- list.__init__([])
- self.source = source
-
-# Now, some helper functions.
-
-def isList(l):
- """Convenience method that works with all 2.x versions of Python
- to determine whether or not something is listlike."""
- return hasattr(l, '__iter__') \
- or (type(l) in (types.ListType, types.TupleType))
-
-def isString(s):
- """Convenience method that works with all 2.x versions of Python
- to determine whether or not something is stringlike."""
- try:
- return isinstance(s, unicode) or isintance(s, basestring)
- except NameError:
- return isinstance(s, str)
-
-def buildTagMap(default, *args):
- """Turns a list of maps, lists, or scalars into a single map.
- Used to build the SELF_CLOSING_TAGS, NESTABLE_TAGS, and
- NESTING_RESET_TAGS maps out of lists and partial maps."""
- built = {}
- for portion in args:
- if hasattr(portion, 'items'):
- #It's a map. Merge it.
- for k,v in portion.items():
- built[k] = v
- elif isList(portion):
- #It's a list. Map each item to the default.
- for k in portion:
- built[k] = default
- else:
- #It's a scalar. Map it to the default.
- built[portion] = default
- return built
-
-# Now, the parser classes.
-
-class BeautifulStoneSoup(Tag, SGMLParser):
-
- """This class contains the basic parser and search code. It defines
- a parser that knows nothing about tag behavior except for the
- following:
-
- You can't close a tag without closing all the tags it encloses.
- That is, "<foo><bar></foo>" actually means
- "<foo><bar></bar></foo>".
-
- [Another possible explanation is "<foo><bar /></foo>", but since
- this class defines no SELF_CLOSING_TAGS, it will never use that
- explanation.]
-
- This class is useful for parsing XML or made-up markup languages,
- or when BeautifulSoup makes an assumption counter to what you were
- expecting."""
-
- XML_ENTITY_LIST = {}
- for i in Tag.XML_SPECIAL_CHARS_TO_ENTITIES.values():
- XML_ENTITY_LIST[i] = True
-
- SELF_CLOSING_TAGS = {}
- NESTABLE_TAGS = {}
- RESET_NESTING_TAGS = {}
- QUOTE_TAGS = {}
-
- MARKUP_MASSAGE = [(re.compile('(<[^<>]*)/>'),
- lambda x: x.group(1) + ' />'),
- (re.compile('<!\s+([^<>]*)>'),
- lambda x: '<!' + x.group(1) + '>')
- ]
-
- ROOT_TAG_NAME = u'[document]'
-
- HTML_ENTITIES = "html"
- XML_ENTITIES = "xml"
-
- def __init__(self, markup="", parseOnlyThese=None, fromEncoding=None,
- markupMassage=True, smartQuotesTo=XML_ENTITIES,
- convertEntities=None, selfClosingTags=None):
- """The Soup object is initialized as the 'root tag', and the
- provided markup (which can be a string or a file-like object)
- is fed into the underlying parser.
-
- sgmllib will process most bad HTML, and the BeautifulSoup
- class has some tricks for dealing with some HTML that kills
- sgmllib, but Beautiful Soup can nonetheless choke or lose data
- if your data uses self-closing tags or declarations
- incorrectly.
-
- By default, Beautiful Soup uses regexes to sanitize input,
- avoiding the vast majority of these problems. If the problems
- don't apply to you, pass in False for markupMassage, and
- you'll get better performance.
-
- The default parser massage techniques fix the two most common
- instances of invalid HTML that choke sgmllib:
-
- <br/> (No space between name of closing tag and tag close)
- <! --Comment--> (Extraneous whitespace in declaration)
-
- You can pass in a custom list of (RE object, replace method)
- tuples to get Beautiful Soup to scrub your input the way you
- want."""
-
- self.parseOnlyThese = parseOnlyThese
- self.fromEncoding = fromEncoding
- self.smartQuotesTo = smartQuotesTo
- self.convertEntities = convertEntities
- if self.convertEntities:
- # It doesn't make sense to convert encoded characters to
- # entities even while you're converting entities to Unicode.
- # Just convert it all to Unicode.
- self.smartQuotesTo = None
- self.instanceSelfClosingTags = buildTagMap(None, selfClosingTags)
- SGMLParser.__init__(self)
-
- if hasattr(markup, 'read'): # It's a file-type object.
- markup = markup.read()
- self.markup = markup
- self.markupMassage = markupMassage
- try:
- self._feed()
- except StopParsing:
- pass
- self.markup = None # The markup can now be GCed
-
- def _feed(self, inDocumentEncoding=None):
- # Convert the document to Unicode.
- markup = self.markup
- if isinstance(markup, unicode):
- if not hasattr(self, 'originalEncoding'):
- self.originalEncoding = None
- else:
- dammit = UnicodeDammit\
- (markup, [self.fromEncoding, inDocumentEncoding],
- smartQuotesTo=self.smartQuotesTo)
- markup = dammit.unicode
- self.originalEncoding = dammit.originalEncoding
- if markup:
- if self.markupMassage:
- if not isList(self.markupMassage):
- self.markupMassage = self.MARKUP_MASSAGE
- for fix, m in self.markupMassage:
- markup = fix.sub(m, markup)
- self.reset()
-
- SGMLParser.feed(self, markup)
- # Close out any unfinished strings and close all the open tags.
- self.endData()
- while self.currentTag.name != self.ROOT_TAG_NAME:
- self.popTag()
-
- def __getattr__(self, methodName):
- """This method routes method call requests to either the SGMLParser
- superclass or the Tag superclass, depending on the method name."""
- #print "__getattr__ called on %s.%s" % (self.__class__, methodName)
-
- if methodName.find('start_') == 0 or methodName.find('end_') == 0 \
- or methodName.find('do_') == 0:
- return SGMLParser.__getattr__(self, methodName)
- elif methodName.find('__') != 0:
- return Tag.__getattr__(self, methodName)
- else:
- raise AttributeError
-
- def isSelfClosingTag(self, name):
- """Returns true iff the given string is the name of a
- self-closing tag according to this parser."""
- return self.SELF_CLOSING_TAGS.has_key(name) \
- or self.instanceSelfClosingTags.has_key(name)
-
- def reset(self):
- Tag.__init__(self, self, self.ROOT_TAG_NAME)
- self.hidden = 1
- SGMLParser.reset(self)
- self.currentData = []
- self.currentTag = None
- self.tagStack = []
- self.quoteStack = []
- self.pushTag(self)
-
- def popTag(self):
- tag = self.tagStack.pop()
- # Tags with just one string-owning child get the child as a
- # 'string' property, so that soup.tag.string is shorthand for
- # soup.tag.contents[0]
- if len(self.currentTag.contents) == 1 and \
- isinstance(self.currentTag.contents[0], NavigableString):
- self.currentTag.string = self.currentTag.contents[0]
-
- #print "Pop", tag.name
- if self.tagStack:
- self.currentTag = self.tagStack[-1]
- return self.currentTag
-
- def pushTag(self, tag):
- #print "Push", tag.name
- if self.currentTag:
- self.currentTag.append(tag)
- self.tagStack.append(tag)
- self.currentTag = self.tagStack[-1]
-
- def endData(self, containerClass=NavigableString):
- if self.currentData:
- currentData = ''.join(self.currentData)
- if not currentData.strip():
- if '\n' in currentData:
- currentData = '\n'
- else:
- currentData = ' '
- self.currentData = []
- if self.parseOnlyThese and len(self.tagStack) <= 1 and \
- (not self.parseOnlyThese.text or \
- not self.parseOnlyThese.search(currentData)):
- return
- o = containerClass(currentData)
- o.setup(self.currentTag, self.previous)
- if self.previous:
- self.previous.next = o
- self.previous = o
- self.currentTag.contents.append(o)
-
-
- def _popToTag(self, name, inclusivePop=True):
- """Pops the tag stack up to and including the most recent
- instance of the given tag. If inclusivePop is false, pops the tag
- stack up to but *not* including the most recent instqance of
- the given tag."""
- #print "Popping to %s" % name
- if name == self.ROOT_TAG_NAME:
- return
-
- numPops = 0
- mostRecentTag = None
- for i in range(len(self.tagStack)-1, 0, -1):
- if name == self.tagStack[i].name:
- numPops = len(self.tagStack)-i
- break
- if not inclusivePop:
- numPops = numPops - 1
-
- for i in range(0, numPops):
- mostRecentTag = self.popTag()
- return mostRecentTag
-
- def _smartPop(self, name):
-
- """We need to pop up to the previous tag of this type, unless
- one of this tag's nesting reset triggers comes between this
- tag and the previous tag of this type, OR unless this tag is a
- generic nesting trigger and another generic nesting trigger
- comes between this tag and the previous tag of this type.
-
- Examples:
- <p>Foo<b>Bar<p> should pop to 'p', not 'b'.
- <p>Foo<table>Bar<p> should pop to 'table', not 'p'.
- <p>Foo<table><tr>Bar<p> should pop to 'tr', not 'p'.
- <p>Foo<b>Bar<p> should pop to 'p', not 'b'.
-
- <li><ul><li> *<li>* should pop to 'ul', not the first 'li'.
- <tr><table><tr> *<tr>* should pop to 'table', not the first 'tr'
- <td><tr><td> *<td>* should pop to 'tr', not the first 'td'
- """
-
- nestingResetTriggers = self.NESTABLE_TAGS.get(name)
- isNestable = nestingResetTriggers != None
- isResetNesting = self.RESET_NESTING_TAGS.has_key(name)
- popTo = None
- inclusive = True
- for i in range(len(self.tagStack)-1, 0, -1):
- p = self.tagStack[i]
- if (not p or p.name == name) and not isNestable:
- #Non-nestable tags get popped to the top or to their
- #last occurance.
- popTo = name
- break
- if (nestingResetTriggers != None
- and p.name in nestingResetTriggers) \
- or (nestingResetTriggers == None and isResetNesting
- and self.RESET_NESTING_TAGS.has_key(p.name)):
-
- #If we encounter one of the nesting reset triggers
- #peculiar to this tag, or we encounter another tag
- #that causes nesting to reset, pop up to but not
- #including that tag.
- popTo = p.name
- inclusive = False
- break
- p = p.parent
- if popTo:
- self._popToTag(popTo, inclusive)
-
- def unknown_starttag(self, name, attrs, selfClosing=0):
- #print "Start tag %s: %s" % (name, attrs)
- if self.quoteStack:
- #This is not a real tag.
- #print "<%s> is not real!" % name
- attrs = ''.join(map(lambda(x, y): ' %s="%s"' % (x, y), attrs))
- self.handle_data('<%s%s>' % (name, attrs))
- return
- self.endData()
-
- if not self.isSelfClosingTag(name) and not selfClosing:
- self._smartPop(name)
-
- if self.parseOnlyThese and len(self.tagStack) <= 1 \
- and (self.parseOnlyThese.text or not self.parseOnlyThese.searchTag(name, attrs)):
- return
-
- tag = Tag(self, name, attrs, self.currentTag, self.previous)
- if self.previous:
- self.previous.next = tag
- self.previous = tag
- self.pushTag(tag)
- if selfClosing or self.isSelfClosingTag(name):
- self.popTag()
- if name in self.QUOTE_TAGS:
- #print "Beginning quote (%s)" % name
- self.quoteStack.append(name)
- self.literal = 1
- return tag
-
- def unknown_endtag(self, name):
- #print "End tag %s" % name
- if self.quoteStack and self.quoteStack[-1] != name:
- #This is not a real end tag.
- #print "</%s> is not real!" % name
- self.handle_data('</%s>' % name)
- return
- self.endData()
- self._popToTag(name)
- if self.quoteStack and self.quoteStack[-1] == name:
- self.quoteStack.pop()
- self.literal = (len(self.quoteStack) > 0)
-
- def handle_data(self, data):
- self.currentData.append(data)
-
- def _toStringSubclass(self, text, subclass):
- """Adds a certain piece of text to the tree as a NavigableString
- subclass."""
- self.endData()
- self.handle_data(text)
- self.endData(subclass)
-
- def handle_pi(self, text):
- """Handle a processing instruction as a ProcessingInstruction
- object, possibly one with a %SOUP-ENCODING% slot into which an
- encoding will be plugged later."""
- if text[:3] == "xml":
- text = "xml version='1.0' encoding='%SOUP-ENCODING%'"
- self._toStringSubclass(text, ProcessingInstruction)
-
- def handle_comment(self, text):
- "Handle comments as Comment objects."
- self._toStringSubclass(text, Comment)
-
- def handle_charref(self, ref):
- "Handle character references as data."
- if self.convertEntities in [self.HTML_ENTITIES,
- self.XML_ENTITIES]:
- data = unichr(int(ref))
- else:
- data = '&#%s;' % ref
- self.handle_data(data)
-
- def handle_entityref(self, ref):
- """Handle entity references as data, possibly converting known
- HTML entity references to the corresponding Unicode
- characters."""
- data = None
- if self.convertEntities == self.HTML_ENTITIES or \
- (self.convertEntities == self.XML_ENTITIES and \
- self.XML_ENTITY_LIST.get(ref)):
- try:
- data = unichr(name2codepoint[ref])
- except KeyError:
- pass
- if not data:
- data = '&%s;' % ref
- self.handle_data(data)
-
- def handle_decl(self, data):
- "Handle DOCTYPEs and the like as Declaration objects."
- self._toStringSubclass(data, Declaration)
-
- def parse_declaration(self, i):
- """Treat a bogus SGML declaration as raw data. Treat a CDATA
- declaration as a CData object."""
- j = None
- if self.rawdata[i:i+9] == '<![CDATA[':
- k = self.rawdata.find(']]>', i)
- if k == -1:
- k = len(self.rawdata)
- data = self.rawdata[i+9:k]
- j = k+3
- self._toStringSubclass(data, CData)
- else:
- try:
- j = SGMLParser.parse_declaration(self, i)
- except SGMLParseError:
- toHandle = self.rawdata[i:]
- self.handle_data(toHandle)
- j = i + len(toHandle)
- return j
-
-class BeautifulSoup(BeautifulStoneSoup):
-
- """This parser knows the following facts about HTML:
-
- * Some tags have no closing tag and should be interpreted as being
- closed as soon as they are encountered.
-
- * The text inside some tags (ie. 'script') may contain tags which
- are not really part of the document and which should be parsed
- as text, not tags. If you want to parse the text as tags, you can
- always fetch it and parse it explicitly.
-
- * Tag nesting rules:
-
- Most tags can't be nested at all. For instance, the occurance of
- a <p> tag should implicitly close the previous <p> tag.
-
- <p>Para1<p>Para2
- should be transformed into:
- <p>Para1</p><p>Para2
-
- Some tags can be nested arbitrarily. For instance, the occurance
- of a <blockquote> tag should _not_ implicitly close the previous
- <blockquote> tag.
-
- Alice said: <blockquote>Bob said: <blockquote>Blah
- should NOT be transformed into:
- Alice said: <blockquote>Bob said: </blockquote><blockquote>Blah
-
- Some tags can be nested, but the nesting is reset by the
- interposition of other tags. For instance, a <tr> tag should
- implicitly close the previous <tr> tag within the same <table>,
- but not close a <tr> tag in another table.
-
- <table><tr>Blah<tr>Blah
- should be transformed into:
- <table><tr>Blah</tr><tr>Blah
- but,
- <tr>Blah<table><tr>Blah
- should NOT be transformed into
- <tr>Blah<table></tr><tr>Blah
-
- Differing assumptions about tag nesting rules are a major source
- of problems with the BeautifulSoup class. If BeautifulSoup is not
- treating as nestable a tag your page author treats as nestable,
- try ICantBelieveItsBeautifulSoup, MinimalSoup, or
- BeautifulStoneSoup before writing your own subclass."""
-
- def __init__(self, *args, **kwargs):
- if not kwargs.has_key('smartQuotesTo'):
- kwargs['smartQuotesTo'] = self.HTML_ENTITIES
- BeautifulStoneSoup.__init__(self, *args, **kwargs)
-
- SELF_CLOSING_TAGS = buildTagMap(None,
- ['br' , 'hr', 'input', 'img', 'meta',
- 'spacer', 'link', 'frame', 'base'])
-
- QUOTE_TAGS = {'script': None}
-
- #According to the HTML standard, each of these inline tags can
- #contain another tag of the same type. Furthermore, it's common
- #to actually use these tags this way.
- NESTABLE_INLINE_TAGS = ['span', 'font', 'q', 'object', 'bdo', 'sub', 'sup',
- 'center']
-
- #According to the HTML standard, these block tags can contain
- #another tag of the same type. Furthermore, it's common
- #to actually use these tags this way.
- NESTABLE_BLOCK_TAGS = ['blockquote', 'div', 'fieldset', 'ins', 'del']
-
- #Lists can contain other lists, but there are restrictions.
- NESTABLE_LIST_TAGS = { 'ol' : [],
- 'ul' : [],
- 'li' : ['ul', 'ol'],
- 'dl' : [],
- 'dd' : ['dl'],
- 'dt' : ['dl'] }
-
- #Tables can contain other tables, but there are restrictions.
- NESTABLE_TABLE_TAGS = {'table' : [],
- 'tr' : ['table', 'tbody', 'tfoot', 'thead'],
- 'td' : ['tr'],
- 'th' : ['tr'],
- 'thead' : ['table'],
- 'tbody' : ['table'],
- 'tfoot' : ['table'],
- }
-
- NON_NESTABLE_BLOCK_TAGS = ['address', 'form', 'p', 'pre']
-
- #If one of these tags is encountered, all tags up to the next tag of
- #this type are popped.
- RESET_NESTING_TAGS = buildTagMap(None, NESTABLE_BLOCK_TAGS, 'noscript',
- NON_NESTABLE_BLOCK_TAGS,
- NESTABLE_LIST_TAGS,
- NESTABLE_TABLE_TAGS)
-
- NESTABLE_TAGS = buildTagMap([], NESTABLE_INLINE_TAGS, NESTABLE_BLOCK_TAGS,
- NESTABLE_LIST_TAGS, NESTABLE_TABLE_TAGS)
-
- # Used to detect the charset in a META tag; see start_meta
- CHARSET_RE = re.compile("((^|;)\s*charset=)([^;]*)")
-
- def start_meta(self, attrs):
- """Beautiful Soup can detect a charset included in a META tag,
- try to convert the document to that charset, and re-parse the
- document from the beginning."""
- httpEquiv = None
- contentType = None
- contentTypeIndex = None
- tagNeedsEncodingSubstitution = False
-
- for i in range(0, len(attrs)):
- key, value = attrs[i]
- key = key.lower()
- if key == 'http-equiv':
- httpEquiv = value
- elif key == 'content':
- contentType = value
- contentTypeIndex = i
-
- if httpEquiv and contentType: # It's an interesting meta tag.
- match = self.CHARSET_RE.search(contentType)
- if match:
- if getattr(self, 'declaredHTMLEncoding') or \
- (self.originalEncoding == self.fromEncoding):
- # This is our second pass through the document, or
- # else an encoding was specified explicitly and it
- # worked. Rewrite the meta tag.
- newAttr = self.CHARSET_RE.sub\
- (lambda(match):match.group(1) +
- "%SOUP-ENCODING%", value)
- attrs[contentTypeIndex] = (attrs[contentTypeIndex][0],
- newAttr)
- tagNeedsEncodingSubstitution = True
- else:
- # This is our first pass through the document.
- # Go through it again with the new information.
- newCharset = match.group(3)
- if newCharset and newCharset != self.originalEncoding:
- self.declaredHTMLEncoding = newCharset
- self._feed(self.declaredHTMLEncoding)
- raise StopParsing
- tag = self.unknown_starttag("meta", attrs)
- if tag and tagNeedsEncodingSubstitution:
- tag.containsSubstitutions = True
-
-class StopParsing(Exception):
- pass
-
-class ICantBelieveItsBeautifulSoup(BeautifulSoup):
-
- """The BeautifulSoup class is oriented towards skipping over
- common HTML errors like unclosed tags. However, sometimes it makes
- errors of its own. For instance, consider this fragment:
-
- <b>Foo<b>Bar</b></b>
-
- This is perfectly valid (if bizarre) HTML. However, the
- BeautifulSoup class will implicitly close the first b tag when it
- encounters the second 'b'. It will think the author wrote
- "<b>Foo<b>Bar", and didn't close the first 'b' tag, because
- there's no real-world reason to bold something that's already
- bold. When it encounters '</b></b>' it will close two more 'b'
- tags, for a grand total of three tags closed instead of two. This
- can throw off the rest of your document structure. The same is
- true of a number of other tags, listed below.
-
- It's much more common for someone to forget to close a 'b' tag
- than to actually use nested 'b' tags, and the BeautifulSoup class
- handles the common case. This class handles the not-co-common
- case: where you can't believe someone wrote what they did, but
- it's valid HTML and BeautifulSoup screwed up by assuming it
- wouldn't be."""
-
- I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS = \
- ['em', 'big', 'i', 'small', 'tt', 'abbr', 'acronym', 'strong',
- 'cite', 'code', 'dfn', 'kbd', 'samp', 'strong', 'var', 'b',
- 'big']
-
- I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS = ['noscript']
-
- NESTABLE_TAGS = buildTagMap([], BeautifulSoup.NESTABLE_TAGS,
- I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS,
- I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS)
-
-class MinimalSoup(BeautifulSoup):
- """The MinimalSoup class is for parsing HTML that contains
- pathologically bad markup. It makes no assumptions about tag
- nesting, but it does know which tags are self-closing, that
- <script> tags contain Javascript and should not be parsed, that
- META tags may contain encoding information, and so on.
-
- This also makes it better for subclassing than BeautifulStoneSoup
- or BeautifulSoup."""
-
- RESET_NESTING_TAGS = buildTagMap('noscript')
- NESTABLE_TAGS = {}
-
-class BeautifulSOAP(BeautifulStoneSoup):
- """This class will push a tag with only a single string child into
- the tag's parent as an attribute. The attribute's name is the tag
- name, and the value is the string child. An example should give
- the flavor of the change:
-
- <foo><bar>baz</bar></foo>
- =>
- <foo bar="baz"><bar>baz</bar></foo>
-
- You can then access fooTag['bar'] instead of fooTag.barTag.string.
-
- This is, of course, useful for scraping structures that tend to
- use subelements instead of attributes, such as SOAP messages. Note
- that it modifies its input, so don't print the modified version
- out.
-
- I'm not sure how many people really want to use this class; let me
- know if you do. Mainly I like the name."""
-
- def popTag(self):
- if len(self.tagStack) > 1:
- tag = self.tagStack[-1]
- parent = self.tagStack[-2]
- parent._getAttrMap()
- if (isinstance(tag, Tag) and len(tag.contents) == 1 and
- isinstance(tag.contents[0], NavigableString) and
- not parent.attrMap.has_key(tag.name)):
- parent[tag.name] = tag.contents[0]
- BeautifulStoneSoup.popTag(self)
-
-#Enterprise class names! It has come to our attention that some people
-#think the names of the Beautiful Soup parser classes are too silly
-#and "unprofessional" for use in enterprise screen-scraping. We feel
-#your pain! For such-minded folk, the Beautiful Soup Consortium And
-#All-Night Kosher Bakery recommends renaming this file to
-#"RobustParser.py" (or, in cases of extreme enterprisitude,
-#"RobustParserBeanInterface.class") and using the following
-#enterprise-friendly class aliases:
-class RobustXMLParser(BeautifulStoneSoup):
- pass
-class RobustHTMLParser(BeautifulSoup):
- pass
-class RobustWackAssHTMLParser(ICantBelieveItsBeautifulSoup):
- pass
-class RobustInsanelyWackAssHTMLParser(MinimalSoup):
- pass
-class SimplifyingSOAPParser(BeautifulSOAP):
- pass
-
-######################################################
-#
-# Bonus library: Unicode, Dammit
-#
-# This class forces XML data into a standard format (usually to UTF-8
-# or Unicode). It is heavily based on code from Mark Pilgrim's
-# Universal Feed Parser. It does not rewrite the XML or HTML to
-# reflect a new encoding: that happens in BeautifulStoneSoup.handle_pi
-# (XML) and BeautifulSoup.start_meta (HTML).
-
-# Autodetects character encodings.
-# Download from http://chardet.feedparser.org/
-try:
- import chardet
-# import chardet.constants
-# chardet.constants._debug = 1
-except:
- chardet = None
-chardet = None
-
-# cjkcodecs and iconv_codec make Python know about more character encodings.
-# Both are available from http://cjkpython.i18n.org/
-# They're built in if you use Python 2.4.
-try:
- import cjkcodecs.aliases
-except:
- pass
-try:
- import iconv_codec
-except:
- pass
-
-class UnicodeDammit:
- """A class for detecting the encoding of a *ML document and
- converting it to a Unicode string. If the source encoding is
- windows-1252, can replace MS smart quotes with their HTML or XML
- equivalents."""
-
- # This dictionary maps commonly seen values for "charset" in HTML
- # meta tags to the corresponding Python codec names. It only covers
- # values that aren't in Python's aliases and can't be determined
- # by the heuristics in find_codec.
- CHARSET_ALIASES = { "macintosh" : "mac-roman",
- "x-sjis" : "shift-jis" }
-
- def __init__(self, markup, overrideEncodings=[],
- smartQuotesTo='xml'):
- self.markup, documentEncoding, sniffedEncoding = \
- self._detectEncoding(markup)
- self.smartQuotesTo = smartQuotesTo
- self.triedEncodings = []
- if markup == '' or isinstance(markup, unicode):
- self.originalEncoding = None
- self.unicode = unicode(markup)
- return
-
- u = None
- for proposedEncoding in overrideEncodings:
- u = self._convertFrom(proposedEncoding)
- if u: break
- if not u:
- for proposedEncoding in (documentEncoding, sniffedEncoding):
- u = self._convertFrom(proposedEncoding)
- if u: break
-
- # If no luck and we have auto-detection library, try that:
- if not u and chardet and not isinstance(self.markup, unicode):
- u = self._convertFrom(chardet.detect(self.markup)['encoding'])
-
- # As a last resort, try utf-8 and windows-1252:
- if not u:
- for proposed_encoding in ("utf-8", "windows-1252"):
- u = self._convertFrom(proposed_encoding)
- if u: break
- self.unicode = u
- if not u: self.originalEncoding = None
-
- def _subMSChar(self, orig):
- """Changes a MS smart quote character to an XML or HTML
- entity."""
- sub = self.MS_CHARS.get(orig)
- if type(sub) == types.TupleType:
- if self.smartQuotesTo == 'xml':
- sub = '&#x%s;' % sub[1]
- else:
- sub = '&%s;' % sub[0]
- return sub
-
- def _convertFrom(self, proposed):
- proposed = self.find_codec(proposed)
- if not proposed or proposed in self.triedEncodings:
- return None
- self.triedEncodings.append(proposed)
- markup = self.markup
-
- # Convert smart quotes to HTML if coming from an encoding
- # that might have them.
- if self.smartQuotesTo and proposed.lower() in("windows-1252",
- "iso-8859-1",
- "iso-8859-2"):
- markup = re.compile("([\x80-\x9f])").sub \
- (lambda(x): self._subMSChar(x.group(1)),
- markup)
-
- try:
- # print "Trying to convert document to %s" % proposed
- u = self._toUnicode(markup, proposed)
- self.markup = u
- self.originalEncoding = proposed
- except Exception, e:
- # print "That didn't work!"
- # print e
- return None
- #print "Correct encoding: %s" % proposed
- return self.markup
-
- def _toUnicode(self, data, encoding):
- '''Given a string and its encoding, decodes the string into Unicode.
- %encoding is a string recognized by encodings.aliases'''
-
- # strip Byte Order Mark (if present)
- if (len(data) >= 4) and (data[:2] == '\xfe\xff') \
- and (data[2:4] != '\x00\x00'):
- encoding = 'utf-16be'
- data = data[2:]
- elif (len(data) >= 4) and (data[:2] == '\xff\xfe') \
- and (data[2:4] != '\x00\x00'):
- encoding = 'utf-16le'
- data = data[2:]
- elif data[:3] == '\xef\xbb\xbf':
- encoding = 'utf-8'
- data = data[3:]
- elif data[:4] == '\x00\x00\xfe\xff':
- encoding = 'utf-32be'
- data = data[4:]
- elif data[:4] == '\xff\xfe\x00\x00':
- encoding = 'utf-32le'
- data = data[4:]
- newdata = unicode(data, encoding)
- return newdata
-
- def _detectEncoding(self, xml_data):
- """Given a document, tries to detect its XML encoding."""
- xml_encoding = sniffed_xml_encoding = None
- try:
- if xml_data[:4] == '\x4c\x6f\xa7\x94':
- # EBCDIC
- xml_data = self._ebcdic_to_ascii(xml_data)
- elif xml_data[:4] == '\x00\x3c\x00\x3f':
- # UTF-16BE
- sniffed_xml_encoding = 'utf-16be'
- xml_data = unicode(xml_data, 'utf-16be').encode('utf-8')
- elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') \
- and (xml_data[2:4] != '\x00\x00'):
- # UTF-16BE with BOM
- sniffed_xml_encoding = 'utf-16be'
- xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8')
- elif xml_data[:4] == '\x3c\x00\x3f\x00':
- # UTF-16LE
- sniffed_xml_encoding = 'utf-16le'
- xml_data = unicode(xml_data, 'utf-16le').encode('utf-8')
- elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and \
- (xml_data[2:4] != '\x00\x00'):
- # UTF-16LE with BOM
- sniffed_xml_encoding = 'utf-16le'
- xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8')
- elif xml_data[:4] == '\x00\x00\x00\x3c':
- # UTF-32BE
- sniffed_xml_encoding = 'utf-32be'
- xml_data = unicode(xml_data, 'utf-32be').encode('utf-8')
- elif xml_data[:4] == '\x3c\x00\x00\x00':
- # UTF-32LE
- sniffed_xml_encoding = 'utf-32le'
- xml_data = unicode(xml_data, 'utf-32le').encode('utf-8')
- elif xml_data[:4] == '\x00\x00\xfe\xff':
- # UTF-32BE with BOM
- sniffed_xml_encoding = 'utf-32be'
- xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8')
- elif xml_data[:4] == '\xff\xfe\x00\x00':
- # UTF-32LE with BOM
- sniffed_xml_encoding = 'utf-32le'
- xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8')
- elif xml_data[:3] == '\xef\xbb\xbf':
- # UTF-8 with BOM
- sniffed_xml_encoding = 'utf-8'
- xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8')
- else:
- sniffed_xml_encoding = 'ascii'
- pass
- xml_encoding_match = re.compile \
- ('^<\?.*encoding=[\'"](.*?)[\'"].*\?>')\
- .match(xml_data)
- except:
- xml_encoding_match = None
- if xml_encoding_match:
- xml_encoding = xml_encoding_match.groups()[0].lower()
- if sniffed_xml_encoding and \
- (xml_encoding in ('iso-10646-ucs-2', 'ucs-2', 'csunicode',
- 'iso-10646-ucs-4', 'ucs-4', 'csucs4',
- 'utf-16', 'utf-32', 'utf_16', 'utf_32',
- 'utf16', 'u16')):
- xml_encoding = sniffed_xml_encoding
- return xml_data, xml_encoding, sniffed_xml_encoding
-
-
- def find_codec(self, charset):
- return self._codec(self.CHARSET_ALIASES.get(charset, charset)) \
- or (charset and self._codec(charset.replace("-", ""))) \
- or (charset and self._codec(charset.replace("-", "_"))) \
- or charset
-
- def _codec(self, charset):
- if not charset: return charset
- codec = None
- try:
- codecs.lookup(charset)
- codec = charset
- except LookupError:
- pass
- return codec
-
- EBCDIC_TO_ASCII_MAP = None
- def _ebcdic_to_ascii(self, s):
- c = self.__class__
- if not c.EBCDIC_TO_ASCII_MAP:
- emap = (0,1,2,3,156,9,134,127,151,141,142,11,12,13,14,15,
- 16,17,18,19,157,133,8,135,24,25,146,143,28,29,30,31,
- 128,129,130,131,132,10,23,27,136,137,138,139,140,5,6,7,
- 144,145,22,147,148,149,150,4,152,153,154,155,20,21,158,26,
- 32,160,161,162,163,164,165,166,167,168,91,46,60,40,43,33,
- 38,169,170,171,172,173,174,175,176,177,93,36,42,41,59,94,
- 45,47,178,179,180,181,182,183,184,185,124,44,37,95,62,63,
- 186,187,188,189,190,191,192,193,194,96,58,35,64,39,61,34,
- 195,97,98,99,100,101,102,103,104,105,196,197,198,199,200,
- 201,202,106,107,108,109,110,111,112,113,114,203,204,205,
- 206,207,208,209,126,115,116,117,118,119,120,121,122,210,
- 211,212,213,214,215,216,217,218,219,220,221,222,223,224,
- 225,226,227,228,229,230,231,123,65,66,67,68,69,70,71,72,
- 73,232,233,234,235,236,237,125,74,75,76,77,78,79,80,81,
- 82,238,239,240,241,242,243,92,159,83,84,85,86,87,88,89,
- 90,244,245,246,247,248,249,48,49,50,51,52,53,54,55,56,57,
- 250,251,252,253,254,255)
- import string
- c.EBCDIC_TO_ASCII_MAP = string.maketrans( \
- ''.join(map(chr, range(256))), ''.join(map(chr, emap)))
- return s.translate(c.EBCDIC_TO_ASCII_MAP)
-
- MS_CHARS = { '\x80' : ('euro', '20AC'),
- '\x81' : ' ',
- '\x82' : ('sbquo', '201A'),
- '\x83' : ('fnof', '192'),
- '\x84' : ('bdquo', '201E'),
- '\x85' : ('hellip', '2026'),
- '\x86' : ('dagger', '2020'),
- '\x87' : ('Dagger', '2021'),
- '\x88' : ('circ', '2C6'),
- '\x89' : ('permil', '2030'),
- '\x8A' : ('Scaron', '160'),
- '\x8B' : ('lsaquo', '2039'),
- '\x8C' : ('OElig', '152'),
- '\x8D' : '?',
- '\x8E' : ('#x17D', '17D'),
- '\x8F' : '?',
- '\x90' : '?',
- '\x91' : ('lsquo', '2018'),
- '\x92' : ('rsquo', '2019'),
- '\x93' : ('ldquo', '201C'),
- '\x94' : ('rdquo', '201D'),
- '\x95' : ('bull', '2022'),
- '\x96' : ('ndash', '2013'),
- '\x97' : ('mdash', '2014'),
- '\x98' : ('tilde', '2DC'),
- '\x99' : ('trade', '2122'),
- '\x9a' : ('scaron', '161'),
- '\x9b' : ('rsaquo', '203A'),
- '\x9c' : ('oelig', '153'),
- '\x9d' : '?',
- '\x9e' : ('#x17E', '17E'),
- '\x9f' : ('Yuml', ''),}
-
-#######################################################################
-
-
-#By default, act as an HTML pretty-printer.
-if __name__ == '__main__':
- import sys
- soup = BeautifulSoup(sys.stdin.read())
- print soup.prettify()
=== removed directory 'lib/zope'
=== removed file 'lib/zope/__init__.py'
--- lib/zope/__init__.py 2008-08-27 05:59:29 +0000
+++ lib/zope/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,15 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-#
-# This file is necessary to make this directory a package.
=== removed directory 'lib/zope/deprecation'
=== removed file 'lib/zope/deprecation/DEPENDENCIES.cfg'
--- lib/zope/deprecation/DEPENDENCIES.cfg 2008-08-29 01:47:36 +0000
+++ lib/zope/deprecation/DEPENDENCIES.cfg 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-zope.testing
=== removed file 'lib/zope/deprecation/README.txt'
--- lib/zope/deprecation/README.txt 2008-08-29 01:47:36 +0000
+++ lib/zope/deprecation/README.txt 1970-01-01 00:00:00 +0000
@@ -1,173 +0,0 @@
-===============
-Deprecation API
-===============
-
-When we started working on Zope 3.1, we noticed that the hardest part of the
-development process was to ensure backward-compatibility and correctly mark
-deprecated modules, classes, functions, methods and properties. This module
-provides a simple function called `deprecated(names, reason)` to deprecate the
-previously mentioned Python objects.
-
-Let's start with a demonstration of deprecating any name inside a module. To
-demonstrate the functionality, I have placed the following code inside the
-`tests.py` file of this package:
-
- from zope.deprecation import deprecated
- demo1 = 1
- deprecated('demo1', 'demo1 is no more.')
-
- demo2 = 2
- deprecated('demo2', 'demo2 is no more.')
-
- demo3 = 3
- deprecated('demo3', 'demo3 is no more.')
-
-The first argument to the `deprecated()` function is a list of names that
-should be declared deprecated. If the first argument is a string, it is
-interpreted as one name. The second argument is the reason the particular name
-has been deprecated. It is good practice to also list the version in which the
-name will be removed completely.
-
-Let's now see how the deprecation warnings are displayed.
-
- >>> from zope.deprecation import tests
- >>> tests.demo1
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: demo1: demo1 is no more.
- ...
- 1
-
- >>> import zope.deprecation.tests
- >>> zope.deprecation.tests.demo2
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: demo2: demo2 is no more.
- ...
- 2
-
-You can see that merely importing the affected module or one of its parents
-does not cause a deprecation warning. Only when we try to access the name in
-the module, we get a deprecation warning. On the other hand, if we import the
-name directly, the deprecation warning will be raised immediately.
-
- >>> from zope.deprecation.tests import demo3
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: demo3: demo3 is no more.
- ...
-
-Also, once a deprecation warning has been displayed, it is not shown again:
-
- >>> from zope.deprecation import tests
- >>> tests.demo1
- 1
-
-New let's see how properties and methods can be deprecated. We are going to
-use the same function as before, except that this time, we do not pass in names
-as first argument, but the method or attribute itself. The function then
-returns a wrapper that sends out a deprecation warning when the attribute or
-method is accessed.
-
- >>> from zope.deprecation import deprecation
- >>> class MyComponent(object):
- ... foo = property(lambda self: 1)
- ... foo = deprecation.deprecated(foo, 'foo is no more.')
- ...
- ... bar = 2
- ...
- ... def blah(self):
- ... return 3
- ... blah = deprecation.deprecated(blah, 'blah() is no more.')
- ...
- ... def splat(self):
- ... return 4
-
-And here is the result:
-
- >>> my = MyComponent()
- >>> my.foo
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: foo is no more.
- ...
- 1
- >>> my.bar
- 2
- >>> my.blah()
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: blah() is no more.
- ...
- 3
- >>> my.splat()
- 4
-
-
-Temporarily Turning Off Deprecation Warnings
---------------------------------------------
-
-In some cases it is desireable to turn off the deprecation warnings for a
-short time. To support such a feature, the `zope.deprecation` package provides
-an attribute called `__show__`. One can ask for its status by calling it:
-
- >>> from zope.deprecation import __show__
- >>> __show__()
- True
-
- >>> class Foo(object):
- ... bar = property(lambda self: 1)
- ... bar = deprecation.deprecated(bar, 'bar is no more.')
- ... blah = property(lambda self: 1)
- ... blah = deprecation.deprecated(blah, 'blah is no more.')
- >>> foo = Foo()
-
- >>> foo.bar
- From tests.py's showwarning():
- ...README.txt:1: DeprecationWarning: bar is no more.
- ...
- 1
-
-You can turn off the depraction warnings using
-
- >>> __show__.off()
- >>> __show__()
- False
-
- >>> foo.blah
- 1
-
-Now, you can also nest several turn-offs, so that calling `off()` multiple
-times is meaningful:
-
- >>> __show__.stack
- [False]
-
- >>> __show__.off()
- >>> __show__.stack
- [False, False]
-
- >>> __show__.on()
- >>> __show__.stack
- [False]
- >>> __show__()
- False
-
- >>> __show__.on()
- >>> __show__.stack
- []
- >>> __show__()
- True
-
-You can also reset `__show__` to `True`:
-
- >>> __show__.off()
- >>> __show__.off()
- >>> __show__()
- False
-
- >>> __show__.reset()
- >>> __show__()
- True
-
-Finally, you cannot call `on()` without having called `off()` before:
-
- >>> __show__.on()
- Traceback (most recent call last):
- ...
- IndexError: pop from empty list
=== removed file 'lib/zope/deprecation/__init__.py'
--- lib/zope/deprecation/__init__.py 2008-08-29 01:47:36 +0000
+++ lib/zope/deprecation/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,26 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation 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.
-#
-##############################################################################
-"""Deprecation Package
-
-$Id: __init__.py 37507 2005-07-27 22:48:36Z anguenot $
-"""
-__docformat__ = "reStructuredText"
-
-from zope.deprecation.deprecation import deprecated, ShowSwitch
-
-# This attribute can be used to temporarly deactivate deprecation
-# warnings, so that backward-compatibility code can import other
-# backward-compatiblity components without warnings being produced.
-
-__show__ = ShowSwitch()
=== removed file 'lib/zope/deprecation/deprecation.py'
--- lib/zope/deprecation/deprecation.py 2008-08-29 01:47:36 +0000
+++ lib/zope/deprecation/deprecation.py 1970-01-01 00:00:00 +0000
@@ -1,154 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation 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.
-#
-##############################################################################
-"""Deprecation Support
-
-This module provides utilities to ease the development of backward-compatible
-code.
-
-$Id: deprecation.py 40198 2005-11-17 20:49:20Z jim $
-"""
-__docformat__ = "reStructuredText"
-import sys
-import types
-import warnings
-
-import zope.deprecation
-
-
-class ShowSwitch(object):
- """Simple stack-based switch."""
-
- def __init__(self):
- self.stack = []
-
- def on(self):
- self.stack.pop()
-
- def off(self):
- self.stack.append(False)
-
- def reset(self):
- self.stack = []
-
- def __call__(self):
- return self.stack == []
-
- def __repr__(self):
- return '<ShowSwitch %s>' %(self() and 'on' or 'off')
-
-
-ogetattr = object.__getattribute__
-class DeprecationProxy(object):
-
- def __init__(self, module):
- self.__original_module = module
- self.__deprecated = {}
-
- def deprecate(self, names, message):
- """Deprecate the given names."""
- if not isinstance(names, (tuple, list)):
- names = (names,)
- for name in names:
- self.__deprecated[name] = message
-
- def __getattribute__(self, name):
- if name == 'deprecate' or name.startswith('_DeprecationProxy__'):
- return ogetattr(self, name)
-
- if name == '__class__':
- return types.ModuleType
-
- if name in ogetattr(self, '_DeprecationProxy__deprecated'):
- if zope.deprecation.__show__():
- warnings.warn(
- name + ': ' + self.__deprecated[name],
- DeprecationWarning, 2)
-
- return getattr(ogetattr(self, '_DeprecationProxy__original_module'),
- name)
-
- def __setattr__(self, name, value):
- if name.startswith('_DeprecationProxy__'):
- return object.__setattr__(self, name, value)
-
- setattr(self.__original_module, name, value)
-
- def __delattr__(self, name):
- if name.startswith('_DeprecationProxy__'):
- return object.__delattr__(self, name)
-
- delattr(self.__original_module, name)
-
-
-class DeprecatedGetProperty(object):
-
- def __init__(self, prop, message):
- self.message = message
- self.prop = prop
-
- def __get__(self, inst, klass):
- if zope.deprecation.__show__():
- warnings.warn(self.message, DeprecationWarning, 2)
- return self.prop.__get__(inst, klass)
-
-class DeprecatedGetSetProperty(DeprecatedGetProperty):
-
- def __set__(self, inst, prop):
- if zope.deprecation.__show__():
- warnings.warn(self.message, DeprecationWarning, 2)
- self.prop.__set__(inst, prop)
-
-class DeprecatedGetSetDeleteProperty(DeprecatedGetSetProperty):
-
- def __delete__(self, inst):
- if zope.deprecation.__show__():
- warnings.warn(self.message, DeprecationWarning, 2)
- self.prop.__delete__(inst)
-
-def DeprecatedMethod(method, message):
-
- def deprecated_method(self, *args, **kw):
- if zope.deprecation.__show__():
- warnings.warn(message, DeprecationWarning, 2)
- return method(self, *args, **kw)
-
- return deprecated_method
-
-
-def deprecated(specifier, message):
- """Deprecate the given names."""
-
- # We are inside a module
- if isinstance(specifier, (str, unicode, list, tuple)):
- locals = sys._getframe(1).f_locals
- if '__name__' in locals:
- modname = locals['__name__']
-
- if not isinstance(sys.modules[modname], DeprecationProxy):
- sys.modules[modname] = DeprecationProxy(sys.modules[modname])
- sys.modules[modname].deprecate(specifier, message)
-
-
- # ... that means the specifier is a method or attribute of the class
- if isinstance(specifier, types.FunctionType):
- return DeprecatedMethod(specifier, message)
- else:
- prop = specifier
- if hasattr(prop, '__get__') and hasattr(prop, '__set__') and \
- hasattr(prop, '__delete__'):
- return DeprecatedGetSetDeleteProperty(prop, message)
- elif hasattr(prop, '__get__') and hasattr(prop, '__set__'):
- return DeprecatedGetSetProperty(prop, message)
- elif hasattr(prop, '__get__'):
- return DeprecatedGetProperty(prop, message)
=== removed file 'lib/zope/deprecation/tests.py'
--- lib/zope/deprecation/tests.py 2008-08-29 01:47:36 +0000
+++ lib/zope/deprecation/tests.py 1970-01-01 00:00:00 +0000
@@ -1,56 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Component Architecture Tests
-
-$Id: tests.py 30324 2005-05-11 09:45:33Z hdima $
-"""
-import sys
-import unittest
-import warnings
-from zope.testing import doctest
-
-# Used in doctests
-from deprecation import deprecated
-demo1 = 1
-deprecated('demo1', 'demo1 is no more.')
-
-demo2 = 2
-deprecated('demo2', 'demo2 is no more.')
-
-demo3 = 3
-deprecated('demo3', 'demo3 is no more.')
-
-
-orig_showwarning = warnings.showwarning
-
-def showwarning(message, category, filename, lineno, file=None):
- sys.stdout.write("From tests.py's showwarning():\n")
- sys.stdout.write(
- warnings.formatwarning(message, category, filename, lineno))
-
-def setUp(test):
- warnings.showwarning = showwarning
-
-def tearDown(test):
- warnings.showwarning = orig_showwarning
-
-def test_suite():
- return unittest.TestSuite((
- doctest.DocFileSuite('README.txt',
- setUp=setUp, tearDown=tearDown,
- optionflags=doctest.ELLIPSIS),
- ))
-
-if __name__ == "__main__":
- unittest.main(defaultTest='test_suite')
=== removed directory 'lib/zope/i18nmessageid'
=== removed file 'lib/zope/i18nmessageid/DEPENDENCIES.cfg'
--- lib/zope/i18nmessageid/DEPENDENCIES.cfg 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/DEPENDENCIES.cfg 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-zope.testing
-zope.deprecation
=== removed file 'lib/zope/i18nmessageid/SETUP.cfg'
--- lib/zope/i18nmessageid/SETUP.cfg 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/SETUP.cfg 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-<extension _zope_i18nmessageid_message>
- source _zope_i18nmessageid_message.c
-</extension>
=== removed file 'lib/zope/i18nmessageid/__init__.py'
--- lib/zope/i18nmessageid/__init__.py 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,38 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""I18n Messages
-
-$Id: __init__.py 39525 2005-10-20 12:28:29Z philikon $
-"""
-##############################################################################
-# BBB 2005/10/10 -- MessageIDs are to be removed for Zope 3.3
-#
-import zope.deprecation
-zope.deprecation.__show__.off()
-from zope.i18nmessageid.messageid import MessageID, MessageIDFactory
-zope.deprecation.__show__.on()
-zope.deprecation.deprecated('MessageID',
- 'Mutable i18n messages ("message ids") have been '
- 'deprecated in favour of immutable ones and will '
- 'be removed in Zope 3.3. Please use '
- 'zope.i18nmessageid.Message instead.')
-zope.deprecation.deprecated('MessageIDFactory',
- 'Mutable i18n messages ("message ids") have been '
- 'deprecated in favour of immutable ones and will '
- 'be removed in Zope 3.3. Please use '
- 'use zope.i18nmessageid.MessageFactory instead.')
-#
-##############################################################################
-
-from zope.i18nmessageid.message import Message, MessageFactory
=== removed file 'lib/zope/i18nmessageid/_zope_i18nmessageid_message.c'
--- lib/zope/i18nmessageid/_zope_i18nmessageid_message.c 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/_zope_i18nmessageid_message.c 1970-01-01 00:00:00 +0000
@@ -1,266 +0,0 @@
-/*############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-############################################################################*/
-
-/* $Id: _zope_i18nmessageid_message.c 27645 2004-09-22 18:59:35Z philikon $ */
-
-#include "Python.h"
-
-/* these macros make gc support easier; they are only available in
- Python 2.4 and borrowed from there */
-
-#ifndef Py_CLEAR
-#define Py_CLEAR(op) \
- do { \
- if (op) { \
- PyObject *tmp = (op); \
- (op) = NULL; \
- Py_DECREF(tmp); \
- } \
- } while (0)
-#endif
-
-#ifndef Py_VISIT
-#define Py_VISIT(op) \
- do { \
- if (op) { \
- int vret = visit((op), arg); \
- if (vret) \
- return vret; \
- } \
- } while (0)
-#endif
-
-/* ----------------------------------------------------- */
-
-typedef struct {
- PyUnicodeObject base;
- PyObject *domain;
- PyObject *default_;
- PyObject *mapping;
-} Message;
-
-static PyTypeObject MessageType;
-
-static PyObject *
-Message_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"value", "domain", "default", "mapping", NULL};
- PyObject *value, *domain=NULL, *default_=NULL, *mapping=NULL, *s;
- Message *self;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
- &value, &domain, &default_, &mapping))
- return NULL;
-
- args = Py_BuildValue("(O)", value);
- if (args == NULL)
- return NULL;
-
- s = PyUnicode_Type.tp_new(type, args, NULL);
- Py_DECREF(args);
- if (s == NULL)
- return NULL;
-
- if (! PyObject_TypeCheck(s, &MessageType))
- {
- PyErr_SetString(PyExc_TypeError,
- "unicode.__new__ didn't return a Message");
- Py_DECREF(s);
- return NULL;
- }
-
- self = (Message*)s;
-
- if (PyObject_TypeCheck(value, &MessageType))
- {
- self->domain = ((Message *)value)->domain;
- self->default_ = ((Message *)value)->default_;
- self->mapping = ((Message *)value)->mapping;
- }
- else
- {
- self->domain = self->default_ = self->mapping = NULL;
- }
-
- if (domain != NULL)
- self->domain = domain;
-
- if (default_ != NULL)
- self->default_ = default_;
-
- if (mapping != NULL)
- self->mapping = mapping;
-
- Py_XINCREF(self->mapping);
- Py_XINCREF(self->default_);
- Py_XINCREF(self->domain);
-
- return (PyObject *)self;
-}
-
-/* Code to access structure members by accessing attributes */
-
-#include "structmember.h"
-
-static PyMemberDef Message_members[] = {
- { "domain", T_OBJECT, offsetof(Message, domain), RO },
- { "default", T_OBJECT, offsetof(Message, default_), RO },
- { "mapping", T_OBJECT, offsetof(Message, mapping), RO },
- {NULL} /* Sentinel */
-};
-
-static int
-Message_traverse(Message *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->domain);
- Py_VISIT(self->default_);
- Py_VISIT(self->mapping);
- return 0;
-}
-
-static int
-Message_clear(Message *self)
-{
- Py_CLEAR(self->domain);
- Py_CLEAR(self->default_);
- Py_CLEAR(self->mapping);
- return 0;
-}
-
-static void
-Message_dealloc(Message *self)
-{
- Message_clear(self);
- self->base.ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject *
-Message_reduce(Message *self)
-{
- PyObject *value, *result;
- value = PyObject_CallFunctionObjArgs((PyObject *)&PyUnicode_Type, self, NULL);
- if (value == NULL)
- return NULL;
- result = Py_BuildValue("(O(OOOO))", self->base.ob_type,
- value,
- self->domain ? self->domain : Py_None,
- self->default_ ? self->default_ : Py_None,
- self->mapping ? self->mapping : Py_None);
- Py_DECREF(value);
- return result;
-}
-
-static PyMethodDef Message_methods[] = {
- {"__reduce__", (PyCFunction)Message_reduce, METH_NOARGS,
- "Reduce messages to a serializable form."},
- {NULL} /* Sentinel */
-};
-
-
-static char MessageType__doc__[] =
-"Message\n"
-"\n"
-"This is a string used as a message. It has a domain attribute that is\n"
-"its source domain, and a default attribute that is its default text to\n"
-"display when there is no translation. domain may be None meaning there is\n"
-"no translation domain. default may also be None, in which case the\n"
-"message id itself implicitly serves as the default text.\n";
-
-statichere PyTypeObject
-MessageType = {
- PyObject_HEAD_INIT(NULL)
- /* ob_size */ 0,
- /* tp_name */ "zope.i18nmessageid.message."
- "Message",
- /* tp_basicsize */ sizeof(Message),
- /* tp_itemsize */ 0,
- /* tp_dealloc */ (destructor)&Message_dealloc,
- /* tp_print */ (printfunc)0,
- /* tp_getattr */ (getattrfunc)0,
- /* tp_setattr */ (setattrfunc)0,
- /* tp_compare */ (cmpfunc)0,
- /* tp_repr */ (reprfunc)0,
- /* tp_as_number */ 0,
- /* tp_as_sequence */ 0,
- /* tp_as_mapping */ 0,
- /* tp_hash */ (hashfunc)0,
- /* tp_call */ (ternaryfunc)0,
- /* tp_str */ (reprfunc)0,
- /* tp_getattro */ (getattrofunc)0,
- /* tp_setattro */ (setattrofunc)0,
- /* tp_as_buffer */ 0,
- /* tp_flags */ Py_TPFLAGS_DEFAULT
- | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_GC,
- /* tp_doc */ MessageType__doc__,
- /* tp_traverse */ (traverseproc)Message_traverse,
- /* tp_clear */ (inquiry)Message_clear,
- /* tp_richcompare */ (richcmpfunc)0,
- /* tp_weaklistoffset */ (long)0,
- /* tp_iter */ (getiterfunc)0,
- /* tp_iternext */ (iternextfunc)0,
- /* tp_methods */ Message_methods,
- /* tp_members */ Message_members,
- /* tp_getset */ 0,
- /* tp_base */ 0,
- /* tp_dict */ 0, /* internal use */
- /* tp_descr_get */ (descrgetfunc)0,
- /* tp_descr_set */ (descrsetfunc)0,
- /* tp_dictoffset */ 0,
- /* tp_init */ (initproc)0,
- /* tp_alloc */ (allocfunc)0,
- /* tp_new */ (newfunc)Message_new,
- /* tp_free */ 0, /* Low-level free-mem routine */
- /* tp_is_gc */ (inquiry)0, /* For PyObject_IS_GC */
-};
-
-/* End of code for Message objects */
-/* -------------------------------------------------------- */
-
-
-/* List of methods defined in the module */
-
-static struct PyMethodDef _zope_i18nmessageid_message_methods[] = {
- {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
-};
-
-
-static char _zope_i18nmessageid_message_module_documentation[] =
-"I18n Messages"
-;
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-init_zope_i18nmessageid_message(void)
-{
- PyObject *m;
- /* Initialize types: */
- MessageType.tp_base = &PyUnicode_Type;
- if (PyType_Ready(&MessageType) < 0)
- return;
-
- /* Create the module and add the functions */
- m = Py_InitModule3("_zope_i18nmessageid_message",
- _zope_i18nmessageid_message_methods,
- _zope_i18nmessageid_message_module_documentation);
-
- if (m == NULL)
- return;
-
- /* Add types: */
- if (PyModule_AddObject(m, "Message", (PyObject *)&MessageType) < 0)
- return;
-}
=== removed file 'lib/zope/i18nmessageid/message.py'
--- lib/zope/i18nmessageid/message.py 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/message.py 1970-01-01 00:00:00 +0000
@@ -1,188 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""I18n Messages
-
-$Id: message.py 39074 2005-10-11 20:54:02Z srichter $
-"""
-__docformat__ = "reStructuredText"
-
-class Message(unicode):
- """Message (Python implementation)
-
- This is a string used as a message. It has a domain attribute that is
- its source domain, and a default attribute that is its default text to
- display when there is no translation. domain may be None meaning there is
- no translation domain. default may also be None, in which case the
- message id itself implicitly serves as the default text.
-
- These are the doc tests from message.txt. Note that we have to create the
- message manually since MessageFactory would return the C implementation.
-
- >>> from zope.i18nmessageid.message import pyMessage as Message
- >>> robot = Message(u"robot-message", 'futurama', u"${name} is a robot.")
-
- >>> robot
- u'robot-message'
- >>> isinstance(robot, unicode)
- True
-
- >>> robot.default
- u'${name} is a robot.'
- >>> robot.mapping
-
- Only the python implementation has a _readonly attribute
- >>> robot._readonly
- True
-
- >>> robot.domain = "planetexpress"
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
- >>> robot.default = u"${name} is not a robot."
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
- >>> robot.mapping = {u'name': u'Bender'}
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
- >>> new_robot = Message(robot, mapping={u'name': u'Bender'})
- >>> new_robot
- u'robot-message'
- >>> new_robot.domain
- 'futurama'
- >>> new_robot.default
- u'${name} is a robot.'
- >>> new_robot.mapping
- {u'name': u'Bender'}
-
- >>> callable, args = new_robot.__reduce__()
- >>> callable is Message
- True
- >>> args
- (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
-
- >>> fembot = Message(u'fembot')
- >>> callable, args = fembot.__reduce__()
- >>> callable is Message
- True
- >>> args
- (u'fembot', None, None, None)
-
- Change classes for pickle tests
- >>> import zope.i18nmessageid.message
- >>> oldMessage = zope.i18nmessageid.message.Message
- >>> zope.i18nmessageid.message.Message = Message
-
- At first check if pickling and unpicklung from pyMessage to pyMessage works
- >>> from pickle import dumps, loads
- >>> pystate = dumps(new_robot)
- >>> pickle_bot = loads(pystate)
- >>> pickle_bot, pickle_bot.domain, pickle_bot.default, pickle_bot.mapping
- (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
- >>> pickle_bot._readonly
- True
- >>> from zope.i18nmessageid.message import pyMessage
- >>> pickle_bot.__reduce__()[0] is pyMessage
- True
- >>> del pickle_bot
-
- At second check if cMessage is able to load the state of a pyMessage
- >>> from _zope_i18nmessageid_message import Message
- >>> zope.i18nmessageid.message.Message = Message
- >>> c_bot = loads(pystate)
- >>> c_bot, c_bot.domain, c_bot.default, c_bot.mapping
- (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
- >>> c_bot._readonly
- Traceback (most recent call last):
- AttributeError: 'zope.i18nmessageid.message.Message' object has no attribute '_readonly'
- >>> from _zope_i18nmessageid_message import Message as cMessage
- >>> c_bot.__reduce__()[0] is cMessage
- True
-
- At last check if pyMessage can load a state of cMessage
- >>> cstate = dumps(c_bot)
- >>> del c_bot
- >>> from zope.i18nmessageid.message import pyMessage as Message
- >>> zope.i18nmessageid.message.Message = Message
- >>> py_bot = loads(cstate)
- >>> py_bot, py_bot.domain, py_bot.default, py_bot.mapping
- (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
- >>> py_bot._readonly
- True
- >>> py_bot.__reduce__()[0] is pyMessage
- True
-
- Both pickle states should be equal
- >>> pystate == cstate
- True
-
- Finally restore classes for other unit tests
- >>> zope.i18nmessageid.message.Message = oldMessage
- """
-
- __slots__ = ('domain', 'default', 'mapping', '_readonly')
-
- def __new__(cls, ustr, domain=None, default=None, mapping=None):
- self = unicode.__new__(cls, ustr)
- if isinstance(ustr, self.__class__):
- domain = ustr.domain and ustr.domain[:] or domain
- default = ustr.default and ustr.default[:] or default
- mapping = ustr.mapping and ustr.mapping.copy() or mapping
- ustr = unicode(ustr)
- self.domain = domain
- if default is None:
- # MessageID does: self.default = ustr
- self.default = default
- else:
- self.default = unicode(default)
- self.mapping = mapping
- self._readonly = True
- return self
-
- def __setattr__(self, key, value):
- """Message is immutable
-
- It cannot be changed once the message id is created.
- """
- if getattr(self, '_readonly', False):
- raise TypeError('readonly attribute')
- else:
- return unicode.__setattr__(self, key, value)
-
- def __reduce__(self):
- return self.__class__, self.__getstate__()
-
- def __getstate__(self):
- return unicode(self), self.domain, self.default, self.mapping
-
-# save a copy for the unit tests
-pyMessage = Message
-
-try:
- from _zope_i18nmessageid_message import Message
-except ImportError:
- pass
-
-class MessageFactory(object):
- """Factory for creating i18n messages."""
-
- def __init__(self, domain):
- self._domain = domain
-
- def __call__(self, ustr, default=None, mapping=None):
- return Message(ustr, self._domain, default, mapping)
=== removed file 'lib/zope/i18nmessageid/messageid.py'
--- lib/zope/i18nmessageid/messageid.py 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/messageid.py 1970-01-01 00:00:00 +0000
@@ -1,114 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Message IDs.
-
-$Id: messageid.py 39060 2005-10-11 18:36:08Z philikon $
-"""
-import zope.deprecation
-zope.deprecation.deprecated('MessageID',
- 'Mutable i18n messages ("message ids") have been '
- 'deprecated in favour of immutable ones and will '
- 'be removed in Zope 3.3. Please use '
- 'zope.i18nmessageid.Message instead.')
-zope.deprecation.deprecated('MessageIDFactory',
- 'Mutable i18n messages ("message ids") have been '
- 'deprecated in favour of immutable ones and will '
- 'be removed in Zope 3.3. Please use '
- 'use zope.i18nmessageid.MessageFactory instead.')
-
-class MessageID(unicode):
- """Message ID.
-
- This is a string used as a message ID. It has a domain attribute that is
- its source domain, and a default attribute that is its default text to
- display when there is no translation. domain may be None meaning there is
- no translation domain. default may also be None, in which case the
- message id itself implicitly serves as the default text.
-
- MessageID objects also have a mapping attribute which must be set after
- construction of the object. This is used when translating and
- substituting variables.
-
- To instanciate MessageIDs, it is recommended to use MessageIDFactory:
-
- >>> fact = MessageIDFactory('test')
-
- Now we can use the factory to make MessageIDs. Note that MessageID
- is a subclass of unicode:
-
- >>> id = fact(u'this is a test')
- >>> isinstance(id, MessageID)
- True
- >>> isinstance(id, unicode)
- True
-
- Additional parameters, such as the i18n domain and the default
- text are available through attributes:
-
- >>> id.domain
- 'test'
- >>> id.default
- u'this is a test'
-
- You can also reset the default text:
-
- >>> id.default = u'blah'
- >>> id.default
- u'blah'
-
- It is quite common to pass an abstract identifier as message id
- and then a default text:
-
- >>> id = fact(u'test-id', 'default test')
- >>> id
- u'test-id'
- >>> id.default
- u'default test'
- >>> id.domain
- 'test'
- """
-
- __slots__ = ('domain', 'default', 'mapping')
-
- def __new__(cls, ustr, domain=None, default=None):
- self = unicode.__new__(cls, ustr)
- self.domain = domain
- if default is None:
- self.default = ustr
- else:
- self.default = unicode(default)
- self.mapping = {}
- return self
-
- def __getstate__(self):
- return unicode(self), self.domain, self.default, self.mapping
-
- def __setstate__(self, (ustr, domain, default, mapping)):
- super(MessageID, self).__init__(ustr)
- self.domain = domain
- if default is None:
- self.default = ustr
- else:
- self.default = default
- self.mapping = mapping
-
-
-class MessageIDFactory(object):
- """Factory for creating MessageIDs."""
-
- def __init__(self, domain):
- self._domain = domain
-
- def __call__(self, ustr, default=None):
- return MessageID(ustr, self._domain, default)
=== removed file 'lib/zope/i18nmessageid/messages.txt'
--- lib/zope/i18nmessageid/messages.txt 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/messages.txt 1970-01-01 00:00:00 +0000
@@ -1,125 +0,0 @@
-=============
-I18n Messages
-=============
-
-Rationale
----------
-
-To translate any text, we must be able to discover the source domain
-of the text. A source domain is an identifier that identifies a
-project that produces program source strings. Source strings occur as
-literals in python programs, text in templates, and some text in XML
-data. The project implies a source language and an application
-context.
-
-We can think of a source domain as a collection of messages and
-associated translation strings.
-
-We often need to create unicode strings that will be displayed by
-separate views. The view cannot translate the string without knowing
-its source domain. A string or unicode literal carries no domain
-information, therefore we use messages. Messages are unicode strings
-which carry a translation source domain and possibly a default
-translation. They are created by a message factory. The message
-factory is created by calling ``MessageFactory`` with the source
-domain.
-
-
-Example
--------
-
-In this example, we create a message factory and assign it to _. By
-convention, we use _ as the name of our factory to be compatible with
-translatable string extraction tools such as xgettext. We then call _
-with a string that needs to be translatable:
-
- >>> from zope.i18nmessageid import MessageFactory, Message
- >>> _ = MessageFactory("futurama")
- >>> robot = _(u"robot-message", u"${name} is a robot.")
-
-Messages at first seem like they are unicode strings:
-
- >>> robot
- u'robot-message'
- >>> isinstance(robot, unicode)
- True
-
-The additional domain, default and mapping information is available
-through attributes:
-
- >>> robot.default
- u'${name} is a robot.'
- >>> robot.mapping
- >>> robot.domain
- 'futurama'
-
-The message's attributes are considered part of the immutable message
-object. They cannot be changed once the message id is created:
-
- >>> robot.domain = "planetexpress"
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
- >>> robot.default = u"${name} is not a robot."
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
- >>> robot.mapping = {u'name': u'Bender'}
- Traceback (most recent call last):
- ...
- TypeError: readonly attribute
-
-If you need to change their information, you'll have to make a new
-message id object:
-
- >>> new_robot = Message(robot, mapping={u'name': u'Bender'})
- >>> new_robot
- u'robot-message'
- >>> new_robot.domain
- 'futurama'
- >>> new_robot.default
- u'${name} is a robot.'
- >>> new_robot.mapping
- {u'name': u'Bender'}
-
-Last but not least, messages are reduceable for pickling:
-
- >>> callable, args = new_robot.__reduce__()
- >>> callable is Message
- True
- >>> args
- (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
-
- >>> fembot = Message(u'fembot')
- >>> callable, args = fembot.__reduce__()
- >>> callable is Message
- True
- >>> args
- (u'fembot', None, None, None)
-
-
-Message IDs and backward compatability
---------------------------------------
-
-The change to immutability is not a simple refactoring that can be
-coped with backward compatible APIs--it is a change in semantics.
-Because immutability is one of those "you either have it or you don't"
-things (like pregnancy or death), we will not be able to support both
-in one implementation.
-
-The proposed solution for backward compatability is to support both
-implementations in parallel, deprecating the mutable one. A separate
-factory, ``MessageFactory``, instantiates immutable messages, while
-the deprecated old one continues to work like before.
-
-The roadmap to immutable-only message ids is proposed as follows:
-
- Zope 3.1: Immutable message ids are introduced. Security
- declarations for mutable message ids are provided to make the
- stripping of security proxies unnecessary.
-
- Zope 3.2: Mutable message ids are deprecated.
-
- Zope 3.3: Mutable message ids are removed.
=== removed file 'lib/zope/i18nmessageid/tests.py'
--- lib/zope/i18nmessageid/tests.py 2008-08-29 01:47:36 +0000
+++ lib/zope/i18nmessageid/tests.py 1970-01-01 00:00:00 +0000
@@ -1,29 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Message ID tests.
-
-$Id: tests.py 29137 2005-02-14 11:35:28Z tiran $
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite, DocFileSuite
-
-def test_suite():
- return unittest.TestSuite((
- DocTestSuite('zope.i18nmessageid.messageid'),
- DocTestSuite('zope.i18nmessageid.message'),
- DocFileSuite('messages.txt', package='zope.i18nmessageid'),
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest="test_suite")
=== removed directory 'lib/zope/interface'
=== removed file 'lib/zope/interface/DEPENDENCIES.cfg'
--- lib/zope/interface/DEPENDENCIES.cfg 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/DEPENDENCIES.cfg 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-zope.testing
=== removed file 'lib/zope/interface/PUBLICATION.cfg'
--- lib/zope/interface/PUBLICATION.cfg 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/PUBLICATION.cfg 1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-Metadata-Version: 1.0
-Name: zope.interface
-Summary: Zope 3 Interface Infrastructure
-Author: Zope Corporation and Contributors
-Author-email: zope3-dev@xxxxxxxx
-License: ZPL 2.1
-Description:
- The implementation of interface definitions for Zope 3.
=== removed file 'lib/zope/interface/README.ru.txt'
--- lib/zope/interface/README.ru.txt 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/README.ru.txt 1970-01-01 00:00:00 +0000
@@ -1,689 +0,0 @@
-==========
-ÐнÑеÑÑейÑÑ
-==========
-
-.. contents::
-
-ÐнÑеÑÑейÑÑ - ÑÑо обÑекÑÑ ÑпеÑиÑиÑиÑÑÑÑие (докÑменÑиÑÑÑÑие) внеÑнее поведение
-обÑекÑов коÑоÑÑе иÑ
"пÑедоÑÑавлÑÑÑ". ÐнÑеÑÑейÑÑ Ð¾Ð¿ÑеделÑÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ ÑеÑез
-ÑледÑÑÑие ÑоÑÑавлÑÑÑие:
-
-- ÐеÑоÑмалÑнÑÑ Ð´Ð¾ÐºÑменÑаÑÐ¸Ñ Ð² ÑÑÑокаÑ
докÑменÑаÑии
-
-- ÐпÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов
-
-- ÐнваÑианÑÑ, пÑедÑÑавленнÑе ÑÑловиÑми коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑоблÑденÑ
- Ð´Ð»Ñ Ð¾Ð±ÑекÑов пÑедоÑÑавлÑÑÑиÑ
инÑеÑÑейÑ
-
-ÐпÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов опиÑÑваÑÑ ÐºÐ¾Ð½ÐºÑеÑнÑе аÑÑибÑÑÑ. Ðни опÑеделÑÑÑ
-Ð¸Ð¼Ñ Ð°ÑÑибÑÑа и пÑедоÑÑавлÑÑÑ Ð´Ð¾ÐºÑменÑаÑÐ¸Ñ Ð¸ огÑаниÑÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð½Ð°Ñений
-аÑÑибÑÑа. ÐпÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов могÑÑ Ð±ÑÑÑ Ð·Ð°Ð´Ð°Ð½Ñ Ð½ÐµÑколÑкими пÑÑÑми
-как Ð¼Ñ Ñвидим ниже.
-
-ÐпÑеделение инÑеÑÑейÑов
-=======================
-
-ÐнÑеÑÑейÑÑ Ð¾Ð¿ÑеделÑÑÑÑÑ Ñ Ð¸ÑполÑзованием клÑÑевого Ñлова class:
-
- >>> import zope.interface
- >>> class IFoo(zope.interface.Interface):
- ... """Foo blah blah"""
- ...
- ... x = zope.interface.Attribute("""X blah blah""")
- ...
- ... def bar(q, r=None):
- ... """bar blah blah"""
-
-РпÑимеÑе вÑÑе Ð¼Ñ Ñоздали инÑеÑÑÐµÐ¹Ñ `IFoo`. ÐÑ Ð½Ð°ÑледÑем его оÑ
-клаÑÑа `zope.interface.Interface`, коÑоÑÑй ÑвлÑеÑÑÑ ÑодиÑелÑÑким инÑеÑÑейÑом
-Ð´Ð»Ñ Ð²ÑеÑ
инÑеÑÑейÑов, как `object` - ÑÑо ÑодиÑелÑÑкий клаÑÑ Ð´Ð»Ñ Ð²ÑеÑ
новÑÑ
-клаÑÑов [#create]_. ÐаннÑй инÑеÑÑÐµÐ¹Ñ Ð½Ðµ ÑвлÑеÑÑÑ ÐºÐ»Ð°ÑÑом, а ÑвлÑеÑÑÑ
-ÐнÑеÑÑейÑом, ÑкземплÑÑом `InterfaceClass`::
-
- >>> type(IFoo)
- <class 'zope.interface.interface.InterfaceClass'>
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ запÑоÑиÑÑ Ñ Ð¸Ð½ÑеÑÑейÑа его докÑменÑаÑиÑ::
-
- >>> IFoo.__doc__
- 'Foo blah blah'
-
-и его имÑ::
-
- >>> IFoo.__name__
- 'IFoo'
-
-и даже модÑÐ»Ñ Ð² коÑоÑом он опÑеделен::
-
- >>> IFoo.__module__
- '__main__'
-
-ÐÐ°Ñ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ Ð¾Ð¿ÑеделÑÐµÑ Ð´Ð²Ð° аÑÑибÑÑа:
-
-`x`
- ÐÑо пÑоÑÑейÑÐ°Ñ ÑоÑма опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов. ÐпÑеделÑÑÑÑÑ Ð¸Ð¼Ñ
- и ÑÑÑока докÑменÑаÑии. ФоÑмалÑно здеÑÑ Ð½Ðµ опÑеделÑеÑÑÑ Ð½Ð¸Ñего более.
-
-`bar`
- ÐÑо меÑод. ÐеÑÐ¾Ð´Ñ Ð¾Ð¿ÑеделÑÑÑÑÑ ÐºÐ°Ðº обÑÑнÑе ÑÑнкÑии. ÐеÑод - ÑÑо пÑоÑÑо
- аÑÑибÑÑ ÐºÐ¾ÑоÑÑй должен бÑÑÑ Ð²ÑзÑваемÑм Ñ Ñказанием ÑигнаÑÑÑÑ,
- пÑедоÑÑавлÑемой опÑеделением ÑÑнкÑии.
-
- Ðадо оÑмеÑиÑÑ, ÑÑо аÑгÑÐ¼ÐµÐ½Ñ `self` не ÑказÑваеÑÑÑ Ð´Ð»Ñ `bar`. ÐнÑеÑÑейÑ
- докÑменÑиÑÑÐµÑ ÐºÐ°Ðº обÑÐµÐºÑ *иÑполÑзÑеÑÑÑ*. Ðогда меÑÐ¾Ð´Ñ ÑкземплÑÑов клаÑÑов
- вÑзÑваÑÑÑÑ Ð¼Ñ Ð½Ðµ пеÑедаем аÑгÑÐ¼ÐµÐ½Ñ `self`, Ñаким обÑазом аÑгÑÐ¼ÐµÐ½Ñ `self`
- не вклÑÑаеÑÑÑ Ð¸ в ÑигнаÑÑÑÑ Ð¸Ð½ÑеÑÑейÑа. ÐÑгÑÐ¼ÐµÐ½Ñ `self` в меÑодаÑ
- ÑкземплÑÑов клаÑÑов на Ñамом деле деÑÐ°Ð»Ñ ÑеализаÑии ÑкземплÑÑов клаÑÑов
- в Python. ÐÑÑгие обÑекÑÑ ÐºÑоме ÑкземплÑÑов клаÑÑов могÑÑ Ð¿ÑедоÑÑавлÑÑÑ
- инÑеÑÑейÑÑ Ð¸ иÑ
меÑÐ¾Ð´Ñ Ð¼Ð¾Ð³ÑÑ Ð½Ðµ бÑÑÑ Ð¼ÐµÑодами ÑкземплÑÑов клаÑÑов. ÐлÑ
- пÑимеÑа модÑли могÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð¸ иÑ
меÑÐ¾Ð´Ñ Ð¾Ð±ÑÑно пÑоÑÑо
- ÑÑнкÑии. Ðаже ÑкземплÑÑÑ Ð¼Ð¾Ð³ÑÑ Ð¸Ð¼ÐµÑÑ Ð¼ÐµÑÐ¾Ð´Ñ Ð½Ðµ ÑвлÑÑÑиеÑÑ Ð¼ÐµÑодами
- ÑкземплÑÑов клаÑÑа.
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ полÑÑиÑÑ Ð´Ð¾ÑÑÑп к аÑÑибÑÑам опÑеделеннÑм инÑеÑÑейÑом иÑполÑзÑÑ
-ÑинÑÐ°ÐºÑ Ð´Ð¾ÑÑÑпа к ÑлеменÑам маÑÑива::
-
- >>> x = IFoo['x']
- >>> type(x)
- <class 'zope.interface.interface.Attribute'>
- >>> x.__name__
- 'x'
- >>> x.__doc__
- 'X blah blah'
-
- >>> IFoo.get('x').__name__
- 'x'
-
- >>> IFoo.get('y')
-
-Ðожно иÑполÑзоваÑÑ `in` Ð´Ð»Ñ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑодеÑÐ¶Ð¸Ñ Ð»Ð¸ инÑеÑÑейÑ
-опÑеделенное имÑ::
-
- >>> 'x' in IFoo
- True
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð¸ÑеÑаÑÐ¾Ñ Ð´Ð»Ñ Ð¸Ð½ÑеÑÑейÑов ÑÑо Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð²Ñе имена
-коÑоÑÑе инÑеÑÑейÑÑ Ð¾Ð¿ÑеделÑÑÑ::
-
- >>> names = list(IFoo)
- >>> names.sort()
- >>> names
- ['bar', 'x']
-
-Ðадо помниÑÑ, ÑÑо инÑеÑÑейÑÑ Ð½Ðµ ÑвлÑÑÑÑÑ ÐºÐ»Ð°ÑÑами. ÐÑ Ð½Ðµ можем полÑÑиÑÑ
-доÑÑÑп к опÑеделениÑм аÑÑибÑÑов ÑеÑез доÑÑÑп к аÑÑибÑÑам инÑеÑÑейÑов::
-
- >>> IFoo.x
- Traceback (most recent call last):
- File "<stdin>", line 1, in ?
- AttributeError: 'InterfaceClass' object has no attribute 'x'
-
-ÐеÑÐ¾Ð´Ñ Ñакже пÑедоÑÑавлÑÑÑ Ð´Ð¾ÑÑÑп к ÑигнаÑÑÑе меÑода::
-
- >>> bar = IFoo['bar']
- >>> bar.getSignatureString()
- '(q, r=None)'
-
- (ÐеÑÐ¾Ð´Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸Ð¼ÐµÑÑ Ð»ÑÑÑий API. ÐÑо Ñо, ÑÑо должно бÑÑÑ ÑлÑÑÑено.)
-
-ÐбÑÑвление инÑеÑÑейÑов
-======================
-
-ÐпÑеделив инÑеÑÑÐµÑ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑепеÑÑ *обÑÑвиÑÑ*, ÑÑо обÑекÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð¸Ñ
.
-ÐеÑед опиÑанием деÑалей опÑеделим некоÑоÑÑе ÑеÑминÑ:
-
-*пÑедоÑÑавлÑÑÑ*
- ÐÑ Ð³Ð¾Ð²Ð¾Ñим, ÑÑо обÑекÑÑ *пÑедоÑÑавлÑÑÑ* инÑеÑÑейÑÑ. ÐÑли обÑекÑ
- пÑедоÑÑавлÑÐµÑ Ð¸Ð½ÑеÑÑейÑ, Ñогда инÑеÑÑÐµÐ¹Ñ ÑпеÑиÑиÑиÑÑÐµÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ обÑекÑа.
- ÐÑÑгими Ñловами, инÑеÑÑейÑÑ ÑпеÑиÑиÑиÑÑÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ обÑекÑов коÑоÑÑе
- пÑедоÑÑавлÑÑÑ Ð¸Ñ
.
-
-*ÑеализоваÑÑ*
- ÐÑ Ð¾Ð±ÑÑно говоÑим ÑÑо клаÑÑÑ *ÑеализÑÑÑ* инÑеÑÑейÑÑ. ÐÑли клаÑÑ
- ÑеализÑÐµÑ Ð¸Ð½ÑеÑÑейÑ, Ñогда ÑкземплÑÑÑ ÑÑого клаÑÑа пÑедоÑÑавлÑÑÑ
- даннÑй инÑеÑÑейÑ. ÐбÑекÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÐºÐ¾ÑоÑÑе иÑ
клаÑÑÑ
- ÑеализÑÑÑ [#factory]_. (ÐбÑекÑÑ Ñакже могÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð½Ð°Ð¿ÑÑмÑÑ
- плÑÑ Ðº Ñем коÑоÑÑе ÑеализÑÑÑ Ð¸Ñ
клаÑÑÑ.)
-
- Ðажно помниÑÑ, ÑÑо клаÑÑÑ Ð¾Ð±ÑÑно не пÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÐºÐ¾ÑоÑÑе
- они ÑеализÑÑÑ.
-
- ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ обобÑиÑÑ ÑÑо до ÑабÑик. ÐÐ»Ñ Ð»Ñбого вÑзÑваемого обÑекÑа Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼
- обÑÑвиÑÑ ÑÑо он пÑÐ¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ Ð¾Ð±ÑекÑÑ ÐºÐ¾ÑоÑÑе пÑедоÑÑавлÑÑÑ ÐºÐ°ÐºÐ¸Ðµ-либо
- инÑеÑÑейÑÑ Ñказав, ÑÑо ÑабÑика ÑеализÑÐµÑ Ð´Ð°Ð½Ð½Ñе инÑеÑÑейÑÑ.
-
-ТепеÑÑ Ð¿Ð¾Ñле Ñого как Ð¼Ñ Ð¾Ð¿Ñеделили ÑÑи ÑеÑÐ¼Ð¸Ð½Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ поговоÑиÑÑ Ð¾Ð±
-API Ð´Ð»Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð½ÑеÑÑейÑов.
-
-ÐбÑвление ÑеализÑемÑÑ
инÑеÑÑеÑов
---------------------------------
-
-Ðаиболее ÑаÑÑо иÑполÑзÑемÑй пÑÑÑ Ð´Ð»Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð½ÑеÑÑейÑов - ÑÑо иÑполÑзование
-ÑÑнкÑии implements в опÑеделении клаÑÑа::
-
- >>> class Foo:
- ... zope.interface.implements(IFoo)
- ...
- ... def __init__(self, x=None):
- ... self.x = x
- ...
- ... def bar(self, q, r=None):
- ... return q, r, self.x
- ...
- ... def __repr__(self):
- ... return "Foo(%s)" % self.x
-
-Ð ÑÑом пÑимеÑе Ð¼Ñ Ð¾Ð±ÑÑвили, ÑÑо `Foo` ÑеализÑÐµÑ `IFoo`. ÐÑо знаÑиÑ, ÑÑо
-ÑкземплÑÑÑ `Foo` пÑедоÑÑавлÑÑÑ `IFoo`. ÐоÑле данного обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐµÑÑÑ
-неÑколÑко пÑÑей Ð´Ð»Ñ Ð°Ð½Ð°Ð»Ð¸Ð·Ð° обÑÑвлений. Ðо-пеÑвÑÑ
Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑпÑоÑиÑÑ
-ÑÑо инÑеÑÑÐµÐ¹Ñ Ñеализован клаÑÑом::
-
- >>> IFoo.implementedBy(Foo)
- True
-
-Также Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑпÑоÑиÑÑ ÐµÑли инÑеÑÑÐµÐ¹Ñ Ð¿ÑедоÑÑавлÑеÑÑÑ Ð¾Ð±ÑекÑами клаÑÑа::
-
- >>> foo = Foo()
- >>> IFoo.providedBy(foo)
- True
-
-ÐонеÑно `Foo` не пÑедоÑÑавлÑÐµÑ `IFoo`, он ÑеализÑÐµÑ ÐµÐ³Ð¾::
-
- >>> IFoo.providedBy(Foo)
- False
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ Ñакже ÑзнаÑÑ ÐºÐ°ÐºÐ¸Ðµ инÑеÑÑейÑÑ ÑеализÑÑÑÑÑ Ð¾Ð±ÑекÑами::
-
- >>> list(zope.interface.implementedBy(Foo))
- [<InterfaceClass __main__.IFoo>]
-
-ÐÑо оÑибка ÑпÑаÑиваÑÑ Ð¿Ñо инÑеÑÑейÑÑ ÑеализÑемÑе невÑзÑваемÑм обÑекÑом::
-
- >>> IFoo.implementedBy(foo)
- Traceback (most recent call last):
- ...
- TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
- >>> list(zope.interface.implementedBy(foo))
- Traceback (most recent call last):
- ...
- TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-Также можно ÑзнаÑÑ ÐºÐ°ÐºÐ¸Ðµ инÑеÑÑейÑÑ Ð¿ÑедоÑÑавлÑÑÑÑÑ Ð¾Ð±ÑекÑами::
-
- >>> list(zope.interface.providedBy(foo))
- [<InterfaceClass __main__.IFoo>]
- >>> list(zope.interface.providedBy(Foo))
- []
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ обÑÑвиÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÑеализÑемÑе дÑÑгими ÑабÑиками (кÑоме клаÑÑов).
-ÐÑо можно ÑделаÑÑ Ð¸ÑполÑзÑÑ Ð´ÐµÐºÐ¾ÑаÑÐ¾Ñ `implementer` (в ÑÑиле Python 2.4).
-ÐÐ»Ñ Ð²ÐµÑÑий Python ниже 2.4 ÑÑо бÑÐ´ÐµÑ Ð²ÑглÑдеÑÑ ÑледÑÑÑим обÑазом:
-
- >>> def yfoo(y):
- ... foo = Foo()
- ... foo.y = y
- ... return foo
- >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
-
- >>> list(zope.interface.implementedBy(yfoo))
- [<InterfaceClass __main__.IFoo>]
-
-Ðадо замеÑиÑÑ, ÑÑо декоÑаÑÐ¾Ñ implementer Ð¼Ð¾Ð¶ÐµÑ Ð¼Ð¾Ð´Ð¸ÑиÑиÑоваÑÑ Ñвои аÑгÑменÑÑ.
-ÐÑзÑваÑÑÐ°Ñ ÑÑоÑона не должна пÑедполагаÑÑ, ÑÑо вÑегда бÑÐ´ÐµÑ ÑоздаваÑÑÑÑ
-новÑй обÑекÑ.
-
-Также надо оÑмеÑиÑÑ, ÑÑо как минимÑм ÑейÑÐ°Ñ implementer не Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ
-Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов:
-
- >>> zope.interface.implementer(IFoo)(Foo)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: Can't use implementer with classes.
- Use one of the class-declaration functions instead.
-
-ÐбÑÑвление пÑедоÑÑавлÑемÑÑ
инÑеÑÑейÑов
---------------------------------------
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ обÑÑвлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð½Ð°Ð¿ÑÑмÑÑ Ð¿ÑедоÑÑавлÑемÑе обÑекÑами. ÐÑедположим
-ÑÑо Ð¼Ñ Ñ
оÑим докÑменÑиÑоваÑÑ ÑÑо Ð´ÐµÐ»Ð°ÐµÑ Ð¼ÐµÑод `__init__` клаÑÑа `Foo`. ÐÑо
-*ÑоÑно* не ÑаÑÑÑ `IFoo`. ÐбÑÑно Ð¼Ñ Ð½Ðµ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð½Ð°Ð¿ÑÑмÑÑ Ð²ÑзÑваÑÑ Ð¼ÐµÑод `__init__`
-Ð´Ð»Ñ ÑкземплÑÑов Foo. СкоÑее меÑод `__init__` ÑвлÑеÑÑÑ ÑаÑÑÑÑ Ð¼ÐµÑода `__call__`
-клаÑÑа `Foo`::
-
- >>> class IFooFactory(zope.interface.Interface):
- ... """Create foos"""
- ...
- ... def __call__(x=None):
- ... """Create a foo
- ...
- ... The argument provides the initial value for x ...
- ... """
-
-У Ð½Ð°Ñ ÐµÑÑÑ ÐºÐ»Ð°ÑÑ Ð¿ÑедоÑÑавлÑÑÑий даннÑй инÑеÑÑейÑ, Ñаким обÑазом Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼
-обÑÑвиÑÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ ÐºÐ»Ð°ÑÑа::
-
- >>> zope.interface.directlyProvides(Foo, IFooFactory)
-
-ТепеÑÑ Ð¼Ñ Ð²Ð¸Ð´Ð¸Ð¼, ÑÑо Foo Ñже пÑедоÑÑавлÑÐµÑ Ð¸Ð½ÑеÑÑейÑÑ::
-
- >>> list(zope.interface.providedBy(Foo))
- [<InterfaceClass __main__.IFooFactory>]
- >>> IFooFactory.providedBy(Foo)
- True
-
-ÐбÑÑвление инÑеÑÑейÑов клаÑÑа доÑÑаÑоÑно ÑаÑÑÐ°Ñ Ð¾Ð¿ÐµÑаÑÐ¸Ñ Ð¸ Ð´Ð»Ñ Ð½ÐµÐµ еÑÑÑ
-ÑпеÑиалÑÐ½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ `classProvides`, коÑоÑÐ°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð¾Ð±ÑÑвлÑÑÑ
-инÑеÑÑейÑÑ Ð¿Ñи опÑеделении клаÑÑа::
-
- >>> class Foo2:
- ... zope.interface.implements(IFoo)
- ... zope.interface.classProvides(IFooFactory)
- ...
- ... def __init__(self, x=None):
- ... self.x = x
- ...
- ... def bar(self, q, r=None):
- ... return q, r, self.x
- ...
- ... def __repr__(self):
- ... return "Foo(%s)" % self.x
-
- >>> list(zope.interface.providedBy(Foo2))
- [<InterfaceClass __main__.IFooFactory>]
- >>> IFooFactory.providedBy(Foo2)
- True
-
-ÐоÑ
Ð¾Ð¶Ð°Ñ ÑÑнкÑÐ¸Ñ `moduleProvides` поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð¾Ð±ÑÑвление инÑеÑÑейÑов пÑи
-опÑеделении модÑлÑ. ÐÐ»Ñ Ð¿ÑимеÑа ÑмоÑÑиÑе иÑполÑзование вÑзова
-`moduleProvides` в `zope.interface.__init__`, коÑоÑÑй обÑÑвлÑеÑ, ÑÑо
-Ð¿Ð°ÐºÐµÑ `zope.interface` пÑедоÑÑавлÑÐµÑ `IInterfaceDeclaration`.
-
-Ðногда Ð¼Ñ Ñ
оÑим обÑÑвиÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÑкземплÑÑов, даже еÑли ÑÑи ÑкземплÑÑÑ
-Ñже беÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð¾Ñ ÑвоиÑ
клаÑÑов. ÐÑедположим, ÑÑо Ð¼Ñ Ñоздаем новÑй
-инÑеÑÑÐµÐ¹Ñ `ISpecial`::
-
- >>> class ISpecial(zope.interface.Interface):
- ... reason = zope.interface.Attribute("Reason why we're special")
- ... def brag():
- ... "Brag about being special"
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑделаÑÑ ÑозданнÑй ÑкземплÑÑ foo ÑпеÑиалÑнÑм пÑедоÑÑавив аÑÑибÑÑÑ
-`reason` и `brag`::
-
- >>> foo.reason = 'I just am'
- >>> def brag():
- ... return "I'm special!"
- >>> foo.brag = brag
- >>> foo.reason
- 'I just am'
- >>> foo.brag()
- "I'm special!"
-
-и обÑÑвив инÑеÑÑейÑ::
-
- >>> zope.interface.directlyProvides(foo, ISpecial)
-
-Ñаким обÑазом новÑй инÑеÑÑÐµÐ¹Ñ Ð²ÐºÐ»ÑÑаеÑÑÑ Ð² ÑпиÑок пÑедоÑÑавлÑемÑÑ
инÑеÑÑейÑов::
-
- >>> ISpecial.providedBy(foo)
- True
- >>> list(zope.interface.providedBy(foo))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-ÐÑ Ñакже можем опÑеделиÑÑ, ÑÑо инÑеÑÑейÑÑ Ð½Ð°Ð¿ÑÑмÑÑ Ð¿ÑедоÑÑавлÑÑÑÑÑ
-обÑекÑами::
-
- >>> list(zope.interface.directlyProvidedBy(foo))
- [<InterfaceClass __main__.ISpecial>]
-
- >>> newfoo = Foo()
- >>> list(zope.interface.directlyProvidedBy(newfoo))
- []
-
-ÐаÑледÑемÑе обÑÑвлениÑ
-----------------------
-
-ÐбÑÑно обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ð°ÑледÑÑÑÑÑ::
-
- >>> class SpecialFoo(Foo):
- ... zope.interface.implements(ISpecial)
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
- >>> list(zope.interface.implementedBy(SpecialFoo))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
- >>> list(zope.interface.providedBy(SpecialFoo()))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-Ðногда Ð¼Ñ Ð½Ðµ Ñ
оÑим наÑледоваÑÑ Ð¾Ð±ÑÑвлениÑ. Ð ÑÑом ÑлÑÑае Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼
-иÑполÑзоваÑÑ `implementsOnly` вмеÑÑо `implements`::
-
- >>> class Special(Foo):
- ... zope.interface.implementsOnly(ISpecial)
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
- >>> list(zope.interface.implementedBy(Special))
- [<InterfaceClass __main__.ISpecial>]
-
- >>> list(zope.interface.providedBy(Special()))
- [<InterfaceClass __main__.ISpecial>]
-
-ÐнеÑние обÑÑвлениÑ
-------------------
-
-ÐбÑÑно Ð¼Ñ Ñоздаем обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑеализаÑии как ÑаÑÑÑ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа. Ðногда
-Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ заÑ
оÑеÑÑ ÑоздаÑÑ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð²Ð½Ðµ обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа. ÐÐ»Ñ Ð¿ÑимеÑа,
-Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ Ñ
оÑеÑÑ Ð¾Ð±ÑÑвиÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов коÑоÑÑе пиÑали не мÑ.
-ÐÐ»Ñ ÑÑого Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÑÑнкÑÐ¸Ñ `classImplements`::
-
- >>> class C:
- ... pass
-
- >>> zope.interface.classImplements(C, IFoo)
- >>> list(zope.interface.implementedBy(C))
- [<InterfaceClass __main__.IFoo>]
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ `classImplementsOnly` Ð´Ð»Ñ Ð¸ÑклÑÑÐµÐ½Ð¸Ñ Ð½Ð°ÑледÑемÑÑ
-инÑеÑÑейÑов::
-
- >>> class C(Foo):
- ... pass
-
- >>> zope.interface.classImplementsOnly(C, ISpecial)
- >>> list(zope.interface.implementedBy(C))
- [<InterfaceClass __main__.ISpecial>]
-
-ÐбÑекÑÑ Ð¾Ð±ÑÑвлений
-------------------
-
-Ðогда Ð¼Ñ Ð¾Ð±ÑÑвлÑем инÑеÑÑейÑÑ Ð¼Ñ Ñоздаем обÑÐµÐºÑ *обÑÑвлениÑ*. Ðогда мÑ
-запÑаÑиваем обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑÑÑ Ð¾Ð±ÑÐµÐºÑ Ð¾Ð±ÑÑвлениÑ::
-
- >>> type(zope.interface.implementedBy(Special))
- <class 'zope.interface.declarations.Implements'>
-
-ÐбÑекÑÑ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸ обÑекÑÑ Ð¸Ð½ÑеÑÑейÑов во многом поÑ
ожи дÑÑг на дÑÑга.
-Ðа Ñамом деле они даже имеÑÑ Ð¾Ð±Ñий базовÑй клаÑÑ. Ðажно понÑÑÑ, ÑÑо они могÑÑ
-иÑполÑзоваÑÑÑÑ Ñам где в обÑÑвлениÑÑ
ожидаÑÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ. ÐÐ¾Ñ Ð¿ÑоÑÑой
-пÑимеÑ::
-
- >>> class Special2(Foo):
- ... zope.interface.implementsOnly(
- ... zope.interface.implementedBy(Foo),
- ... ISpecial,
- ... )
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
-ÐбÑÑвление здеÑÑ Ð¿ÑакÑиÑеÑки Ñакое же как
-``zope.interface.implements(ISpecial)``, оÑлиÑие ÑолÑко в поÑÑдке
-инÑеÑÑейÑов в иÑоговом обÑÑвлениÑ::
-
- >>> list(zope.interface.implementedBy(Special2))
- [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
-
-ÐаÑледование инÑеÑÑейÑов
-========================
-
-ÐнÑеÑÑейÑÑ Ð¼Ð¾Ð³ÑÑ ÑаÑÑиÑÑÑÑ Ð´ÑÑгие инÑеÑÑейÑÑ. Ðни делаÑÑ ÑÑо пÑоÑÑо
-показÑÐ²Ð°Ñ ÑÑи инÑеÑÑейÑÑ ÐºÐ°Ðº базовÑе::
-
- >>> class IBlat(zope.interface.Interface):
- ... """Blat blah blah"""
- ...
- ... y = zope.interface.Attribute("y blah blah")
- ... def eek():
- ... """eek blah blah"""
-
- >>> IBlat.__bases__
- (<InterfaceClass zope.interface.Interface>,)
-
- >>> class IBaz(IFoo, IBlat):
- ... """Baz blah"""
- ... def eek(a=1):
- ... """eek in baz blah"""
- ...
-
- >>> IBaz.__bases__
- (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
-
- >>> names = list(IBaz)
- >>> names.sort()
- >>> names
- ['bar', 'eek', 'x', 'y']
-
-ÐамеÑим, ÑÑо `IBaz` пеÑеопÑеделÑÐµÑ eek::
-
- >>> IBlat['eek'].__doc__
- 'eek blah blah'
- >>> IBaz['eek'].__doc__
- 'eek in baz blah'
-
-ÐÑ Ð±Ñли оÑÑоÑÐ¾Ð¶Ð½Ñ Ð¿ÐµÑеопÑеделÑÑ eek ÑовмеÑÑимÑм пÑÑем. Ðогда инÑеÑÑейÑ
-ÑаÑÑиÑÑеÑÑÑ, ÑаÑÑиÑеннÑй инÑеÑÑÐµÐ¹Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ ÑовмеÑÑимÑм [#compat]_ Ñ
-ÑаÑÑиÑÑемÑми инÑеÑÑейÑами.
-
-ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ запÑоÑиÑÑ ÑаÑÑиÑÑÐµÑ Ð»Ð¸ один из инÑеÑÑейÑов дÑÑгой::
-
- >>> IBaz.extends(IFoo)
- True
- >>> IBlat.extends(IFoo)
- False
-
-ÐамеÑим, ÑÑо инÑеÑÑейÑÑ Ð½Ðµ ÑаÑÑиÑÑÑÑ Ñами ÑебÑ::
-
- >>> IBaz.extends(IBaz)
- False
-
-Ðногда Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ Ñ
оÑеÑÑ ÑÑо Ð±Ñ Ð¾Ð½Ð¸ ÑаÑÑиÑÑли Ñами ÑебÑ, но вмеÑÑо ÑÑого
-Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ `isOrExtends`::
-
- >>> IBaz.isOrExtends(IBaz)
- True
- >>> IBaz.isOrExtends(IFoo)
- True
- >>> IFoo.isOrExtends(IBaz)
- False
-
-Ðогда Ð¼Ñ Ð¿ÑименÑем иÑеÑаÑÐ¸Ñ Ðº инÑеÑÑеÑÑ Ð¼Ñ Ð¿Ð¾Ð»ÑÑаем вÑе имена коÑоÑÑе он
-опÑеделÑÐµÑ Ð²ÐºÐ»ÑÑÐ°Ñ Ð¸Ð¼ÐµÐ½Ð° опÑеделеннÑе Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²ÑÑ
инÑеÑÑеÑов. Ðногда
-Ð¼Ñ Ñ
оÑим полÑÑиÑÑ *ÑолÑко* имена опÑеделеннÑе инÑеÑÑейÑом напÑÑмÑÑ.
-ÐÐ»Ñ ÑÑого Ð¼Ñ Ð¸ÑполÑзÑем меÑод `names`::
-
- >>> list(IBaz.names())
- ['eek']
-
-ÐаÑледование в ÑлÑÑае опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов
---------------------------------------------
-
-ÐнÑеÑÑÐµÐ¹Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÐµÑеопÑеделÑÑÑ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов из базовÑÑ
инÑеÑÑейÑов.
-ÐÑли два базовÑÑ
инÑеÑÑейÑа опÑеделÑÑÑ Ð¾Ð´Ð¸Ð½ и ÑÐ¾Ñ Ð¶Ðµ аÑÑибÑÑ Ð°ÑÑибÑÑ
-наÑледÑеÑÑÑ Ð¾Ñ Ð±Ð¾Ð»ÐµÐµ ÑпеÑиÑиÑного инÑеÑÑейÑа. ÐÐ»Ñ Ð¿ÑимеÑа:
-
- >>> class IBase(zope.interface.Interface):
- ...
- ... def foo():
- ... "base foo doc"
-
- >>> class IBase1(IBase):
- ... pass
-
- >>> class IBase2(IBase):
- ...
- ... def foo():
- ... "base2 foo doc"
-
- >>> class ISub(IBase1, IBase2):
- ... pass
-
-ÐпÑеделение ISub Ð´Ð»Ñ foo бÑÐ´ÐµÑ Ð¸Ð· IBase2 Ñ.к. IBase2 более ÑпеÑиÑиÑен длÑ
-IBase:
-
- >>> ISub['foo'].__doc__
- 'base2 foo doc'
-
-ÐамеÑим, ÑÑо ÑÑо оÑлиÑаеÑÑÑ Ð¾Ñ Ð¿Ð¾Ð¸Ñка в глÑбинÑ.
-
-Ðногда полезно ÑзнаÑÑ, ÑÑо инÑеÑÑÐµÐ¹Ñ Ð¾Ð¿ÑеделÑÐµÑ Ð°ÑÑибÑÑ Ð½Ð°Ð¿ÑÑмÑÑ. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼
-иÑполÑзоваÑÑ Ð¼ÐµÑод direct Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð½Ð°Ð¿ÑÑмÑÑ Ð¾Ð¿ÑеделеннÑÑ
аÑÑибÑÑов:
-
- >>> IBase.direct('foo').__doc__
- 'base foo doc'
-
- >>> ISub.direct('foo')
-
-СпеÑиÑикаÑии
-------------
-
-ÐнÑеÑÑейÑÑ Ð¸ обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ - ÑÑо ÑпеÑиалÑнÑе ÑлÑÑаи ÑпеÑиÑикаÑий. ÐпиÑание
-вÑÑе Ð´Ð»Ñ Ð½Ð°ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½ÑеÑÑейÑов можно пÑимениÑÑ Ð¸ к обÑÑвлениÑм и
-к ÑпеÑиÑикаÑиÑм. ÐбÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑакÑиÑеÑки ÑаÑÑиÑÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÐºÐ¾ÑоÑÑе они
-обÑÑвлÑÑÑ:
-
- >>> class Baz:
- ... zope.interface.implements(IBaz)
-
- >>> baz_implements = zope.interface.implementedBy(Baz)
- >>> baz_implements.__bases__
- (<InterfaceClass __main__.IBaz>,)
-
- >>> baz_implements.extends(IFoo)
- True
-
- >>> baz_implements.isOrExtends(IFoo)
- True
- >>> baz_implements.isOrExtends(baz_implements)
- True
-
-СпеÑиÑикаÑии (инÑеÑÑейÑÑ Ð¸ обÑÑвлениÑ) пÑедоÑÑавлÑÑÑ Ð°ÑÑибÑÑ `__sro__`
-коÑоÑÑй опиÑÑÐ²Ð°ÐµÑ ÑпеÑиÑикаÑÐ¸Ñ Ð¸ вÑеÑ
ее пÑедков:
-
- >>> baz_implements.__sro__
- (<implementedBy __main__.Baz>,
- <InterfaceClass __main__.IBaz>,
- <InterfaceClass __main__.IFoo>,
- <InterfaceClass __main__.IBlat>,
- <InterfaceClass zope.interface.Interface>)
-
-ÐомеÑеннÑе знаÑениÑ
-===================
-
-ÐнÑеÑÑейÑÑ Ð¸ опиÑÐ°Ð½Ð¸Ñ Ð°ÑÑибÑÑов поддеÑживаÑÑ Ð¼ÐµÑ
анизм ÑаÑÑиÑениÑ
-заимÑÑвованнÑй из UML и назÑваемÑй "помеÑеннÑе знаÑениÑ" коÑоÑÑй позволÑеÑ
-ÑоÑ
ÑанÑÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе даннÑе::
-
- >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
- >>> IFoo.setTaggedValue('author', 'Jim Fulton')
- >>> IFoo.getTaggedValue('date-modified')
- '2004-04-01'
- >>> IFoo.queryTaggedValue('date-modified')
- '2004-04-01'
- >>> IFoo.queryTaggedValue('datemodified')
- >>> tags = list(IFoo.getTaggedValueTags())
- >>> tags.sort()
- >>> tags
- ['author', 'date-modified']
-
-ÐÑÑибÑÑÑ ÑÑнкÑий конвеÑÑиÑÑÑÑÑÑ Ð² помеÑеннÑе знаÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð³Ð´Ð° ÑоздаÑÑÑÑ
-опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов меÑода::
-
- >>> class IBazFactory(zope.interface.Interface):
- ... def __call__():
- ... "create one"
- ... __call__.return_type = IBaz
-
- >>> IBazFactory['__call__'].getTaggedValue('return_type')
- <InterfaceClass __main__.IBaz>
-
-ÐнваÑианÑÑ
-==========
-
-ÐнÑеÑÑейÑÑ Ð¼Ð¾Ð³ÑÑ Ð¾Ð¿Ð¸ÑÑваÑÑ ÑÑÐ»Ð¾Ð²Ð¸Ñ ÐºÐ¾ÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑоблÑÐ´ÐµÐ½Ñ Ð´Ð»Ñ Ð¾Ð±ÑекÑов
-коÑоÑÑе иÑ
пÑедоÑÑавлÑÑÑ. ÐÑи ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ð¿Ð¸ÑÑваÑÑÑÑ Ð¸ÑполÑзÑÑ Ð¾Ð´Ð¸Ð½ или более
-инваÑианÑов. ÐнваÑианÑÑ - ÑÑо вÑзÑваемÑе обÑекÑÑ ÐºÐ¾ÑоÑÑе бÑдÑÑ Ð²ÑзванÑ
-Ñ Ð¾Ð±ÑекÑом пÑедоÑÑавлÑÑÑим инÑеÑÑÐµÐ¹Ñ Ð² каÑеÑÑве паÑамеÑÑа. ÐнваÑианÑ
-должен вÑкинÑÑÑ Ð¸ÑклÑÑение `Invalid` еÑли ÑÑловие не ÑоблÑдено. ÐапÑимеÑ::
-
- >>> class RangeError(zope.interface.Invalid):
- ... """A range has invalid limits"""
- ... def __repr__(self):
- ... return "RangeError(%r)" % self.args
-
- >>> def range_invariant(ob):
- ... if ob.max < ob.min:
- ... raise RangeError(ob)
-
-ÐпÑеделив ÑÑÐ¾Ñ Ð¸Ð½Ð²Ð°ÑÐ¸Ð°Ð½Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ ÐµÐ³Ð¾ в опÑеделении инÑеÑÑейÑов::
-
- >>> class IRange(zope.interface.Interface):
- ... min = zope.interface.Attribute("Lower bound")
- ... max = zope.interface.Attribute("Upper bound")
- ...
- ... zope.interface.invariant(range_invariant)
-
-ÐнÑеÑÑейÑÑ Ð¸Ð¼ÐµÑÑ Ð¼ÐµÑод Ð´Ð»Ñ Ð¿ÑовеÑки ÑвоиÑ
инваÑианÑов::
-
- >>> class Range(object):
- ... zope.interface.implements(IRange)
- ...
- ... def __init__(self, min, max):
- ... self.min, self.max = min, max
- ...
- ... def __repr__(self):
- ... return "Range(%s, %s)" % (self.min, self.max)
-
- >>> IRange.validateInvariants(Range(1,2))
- >>> IRange.validateInvariants(Range(1,1))
- >>> IRange.validateInvariants(Range(2,1))
- Traceback (most recent call last):
- ...
- RangeError: Range(2, 1)
-
-Ð ÑлÑÑае неÑколÑкиÑ
инваÑианÑов Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ заÑ
оÑеÑÑ Ð¾ÑÑановиÑÑ Ð¿ÑовеÑÐºÑ Ð¿Ð¾Ñле
-пеÑвой оÑибки. ÐÑли Ð¼Ñ Ð¿ÐµÑедадим в `validateInvariants` пÑÑÑой ÑпиÑок Ñогда
-бÑÐ´ÐµÑ Ð²ÑкинÑÑо единÑÑвенное иÑклÑÑение `Invalid` Ñо ÑпиÑком иÑклÑÑений
-как аÑгÑменÑом::
-
- >>> errors = []
- >>> IRange.validateInvariants(Range(2,1), errors)
- Traceback (most recent call last):
- ...
- Invalid: [RangeError(Range(2, 1))]
-
-Ð ÑпиÑок бÑÐ´ÐµÑ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½ индивидÑалÑнÑми иÑклÑÑениÑми::
-
- >>> errors
- [RangeError(Range(2, 1))]
-
-
-.. [#create] ÐÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð¿ÑиÑина по коÑоÑой Ð¼Ñ Ð½Ð°ÑледÑемÑÑ Ð¾Ñ `Interface` - ÑÑо
- ÑÑо Ð±Ñ Ð±ÑÑÑ ÑвеÑеннÑми в Ñом, ÑÑо клÑÑевое Ñлово class бÑдеÑ
- ÑоздаваÑÑ Ð¸Ð½ÑеÑÑейÑ, а не клаÑÑ.
-
- ÐÑÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ ÑоздаÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð²Ñзвав ÑпеÑиалÑнÑй
- клаÑÑ Ð¸Ð½ÑеÑÑейÑа напÑÑмÑÑ. ÐÐµÐ»Ð°Ñ ÑÑо, возможно (и в ÑедкиÑ
- ÑлÑÑаÑÑ
полезно) ÑоздаÑÑ Ð¸Ð½ÑеÑÑейÑÑ ÐºÐ¾ÑоÑÑе не наÑледÑÑÑÑÑ
- Ð¾Ñ `Interface`. Ðднако иÑполÑзование ÑÑой ÑеÑ
ники вÑÑ
одиÑ
- за Ñамки данного докÑменÑа.
-
-.. [#factory] ÐлаÑÑÑ - ÑÑо ÑабÑики. Ðни могÑÑ Ð±ÑÑÑ Ð²ÑÐ·Ð²Ð°Ð½Ñ Ð´Ð»Ñ ÑозданиÑ
- ÑвоиÑ
ÑкземплÑÑов. ÐÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼ ÑÑо в иÑоге Ð¼Ñ ÑаÑÑиÑим
- конÑепÑÐ¸Ñ ÑеализаÑии на дÑÑгие ÑÐ¸Ð¿Ñ ÑабÑик, Ñаким обÑазом
- Ð¼Ñ Ñможем обÑÑвлÑÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð¿ÑедоÑÑавлÑемÑе ÑозданнÑми
- ÑабÑиками обÑекÑами.
-
-.. [#compat] Ð¦ÐµÐ»Ñ - заменÑемоÑÑÑ. ÐбÑÐµÐºÑ ÐºÐ¾ÑоÑÑй пÑедоÑÑавлÑÐµÑ ÑаÑÑиÑеннÑй
- инÑеÑÑÐµÐ¹Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ Ð·Ð°Ð¼ÐµÐ½Ñем в каÑеÑÑве обÑекÑов коÑоÑÑе
- пÑедоÑÑавлÑÑÑ ÑаÑÑиÑÑемÑй инÑеÑÑейÑ. РнаÑем пÑимеÑе обÑекÑ
- коÑоÑÑй пÑедоÑÑавлÑÐµÑ IBaz должен бÑÑÑ Ð¸ÑполÑзÑемÑм и
- в ÑлÑÑае еÑли ожидаеÑÑÑ Ð¾Ð±ÑÐµÐºÑ ÐºÐ¾ÑоÑÑй пÑедоÑÑавлÑÐµÑ IBlat.
-
- РеализаÑÐ¸Ñ Ð¸Ð½ÑеÑÑейÑа не ÑÑебÑÐµÑ ÑÑого. Ðо возможно в далÑнейÑем
- она должна бÑÐ´ÐµÑ Ð´ÐµÐ»Ð°ÑÑ ÐºÐ°ÐºÐ¸Ðµ-либо пÑовеÑки.
=== removed file 'lib/zope/interface/README.txt'
--- lib/zope/interface/README.txt 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/README.txt 1970-01-01 00:00:00 +0000
@@ -1,699 +0,0 @@
-==========
-Interfaces
-==========
-
-.. contents::
-
-Interfaces are objects that specify (document) the external behavior
-of objects that "provide" them. An interface specifies behavior
-through:
-
-- Informal documentation in a doc string
-
-- Attribute definitions
-
-- Invariants, which are conditions that must hold for objects that
- provide the interface
-
-Attribute definitions specify specific attributes. They define the
-attribute name and provide documentation and constraints of attribute
-values. Attribute definitions can take a number of forms, as we'll
-see below.
-
-Defining interfaces
-===================
-
-Interfaces are defined using Python class statements:
-
- >>> import zope.interface
- >>> class IFoo(zope.interface.Interface):
- ... """Foo blah blah"""
- ...
- ... x = zope.interface.Attribute("""X blah blah""")
- ...
- ... def bar(q, r=None):
- ... """bar blah blah"""
-
-In the example above, we've created an interface, `IFoo`. We
-subclassed `zope.interface.Interface`, which is an ancestor interface for
-all interfaces, much as `object` is an ancestor of all new-style
-classes [#create]_. The interface is not a class, it's an Interface,
-an instance of `InterfaceClass`::
-
- >>> type(IFoo)
- <class 'zope.interface.interface.InterfaceClass'>
-
-We can ask for the interface's documentation::
-
- >>> IFoo.__doc__
- 'Foo blah blah'
-
-and its name::
-
- >>> IFoo.__name__
- 'IFoo'
-
-and even its module::
-
- >>> IFoo.__module__
- '__main__'
-
-The interface defined two attributes:
-
-`x`
- This is the simplest form of attribute definition. It has a name
- and a doc string. It doesn't formally specify anything else.
-
-`bar`
- This is a method. A method is defined via a function definition. A
- method is simply an attribute constrained to be a callable with a
- particular signature, as provided by the function definition.
-
- Note that `bar` doesn't take a `self` argument. Interfaces document
- how an object is *used*. When calling instance methods, you don't
- pass a `self` argument, so a `self` argument isn't included in the
- interface signature. The `self` argument in instance methods is
- really an implementation detail of Python instances. Other objects,
- besides instances can provide interfaces and their methods might not
- be instance methods. For example, modules can provide interfaces and
- their methods are usually just functions. Even instances can have
- methods that are not instance methods.
-
-You can access the attributes defined by an interface using mapping
-syntax::
-
- >>> x = IFoo['x']
- >>> type(x)
- <class 'zope.interface.interface.Attribute'>
- >>> x.__name__
- 'x'
- >>> x.__doc__
- 'X blah blah'
-
- >>> IFoo.get('x').__name__
- 'x'
-
- >>> IFoo.get('y')
-
-You can use `in` to determine if an interface defines a name::
-
- >>> 'x' in IFoo
- True
-
-You can iterate over interfaces to get the names they define::
-
- >>> names = list(IFoo)
- >>> names.sort()
- >>> names
- ['bar', 'x']
-
-Remember that interfaces aren't classes. You can't access attribute
-definitions as attributes of interfaces::
-
- >>> IFoo.x
- Traceback (most recent call last):
- File "<stdin>", line 1, in ?
- AttributeError: 'InterfaceClass' object has no attribute 'x'
-
-Methods provide access to the method signature::
-
- >>> bar = IFoo['bar']
- >>> bar.getSignatureString()
- '(q, r=None)'
-
-TODO
- Methods really should have a better API. This is something that
- needs to be improved.
-
-Declaring interfaces
-====================
-
-Having defined interfaces, we can *declare* that objects provide
-them. Before we describe the details, lets define some terms:
-
-*provide*
- We say that objects *provide* interfaces. If an object provides an
- interface, then the interface specifies the behavior of the
- object. In other words, interfaces specify the behavior of the
- objects that provide them.
-
-*implement*
- We normally say that classes *implement* interfaces. If a class
- implements an interface, then the instances of the class provide
- the interface. Objects provide interfaces that their classes
- implement [#factory]_. (Objects can provide interfaces directly,
- in addition to what their classes implement.)
-
- It is important to note that classes don't usually provide the
- interfaces that they implement.
-
- We can generalize this to factories. For any callable object we
- can declare that it produces objects that provide some interfaces
- by saying that the factory implements the interfaces.
-
-Now that we've defined these terms, we can talk about the API for
-declaring interfaces.
-
-Declaring implemented interfaces
---------------------------------
-
-The most common way to declare interfaces is using the implements
-function in a class statement::
-
- >>> class Foo:
- ... zope.interface.implements(IFoo)
- ...
- ... def __init__(self, x=None):
- ... self.x = x
- ...
- ... def bar(self, q, r=None):
- ... return q, r, self.x
- ...
- ... def __repr__(self):
- ... return "Foo(%s)" % self.x
-
-
-In this example, we declared that `Foo` implements `IFoo`. This means
-that instances of `Foo` provide `IFoo`. Having made this declaration,
-there are several ways we can introspect the declarations. First, we
-can ask an interface whether it is implemented by a class::
-
- >>> IFoo.implementedBy(Foo)
- True
-
-And we can ask whether an interface is provided by an object::
-
- >>> foo = Foo()
- >>> IFoo.providedBy(foo)
- True
-
-Of course, `Foo` doesn't provide `IFoo`, it implements it::
-
- >>> IFoo.providedBy(Foo)
- False
-
-We can also ask what interfaces are implemented by an object::
-
- >>> list(zope.interface.implementedBy(Foo))
- [<InterfaceClass __main__.IFoo>]
-
-It's an error to ask for interfaces implemented by a non-callable
-object::
-
- >>> IFoo.implementedBy(foo)
- Traceback (most recent call last):
- ...
- TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
- >>> list(zope.interface.implementedBy(foo))
- Traceback (most recent call last):
- ...
- TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-Similarly, we can ask what interfaces are provided by an object::
-
- >>> list(zope.interface.providedBy(foo))
- [<InterfaceClass __main__.IFoo>]
- >>> list(zope.interface.providedBy(Foo))
- []
-
-We can declare interfaces implemented by other factories (besides
-classes). We do this using a Python-2.4-style decorator named
-`implementer`. In versions of Python before 2.4, this looks like:
-
-
- >>> def yfoo(y):
- ... foo = Foo()
- ... foo.y = y
- ... return foo
- >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
-
- >>> list(zope.interface.implementedBy(yfoo))
- [<InterfaceClass __main__.IFoo>]
-
-Note that the implementer decorator may modify it's argument. Callers
-should not assume that a new object is created.
-
-Also note that, at least for now, implementer can't be used with
-classes:
-
- >>> zope.interface.implementer(IFoo)(Foo)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: Can't use implementer with classes.
- Use one of the class-declaration functions instead.
-
-Declaring provided interfaces
------------------------------
-
-We can declare interfaces directly provided by objects. Suppose that
-we want to document what the `__init__` method of the `Foo` class
-does. It's not *really* part of `IFoo`. You wouldn't normally call
-the `__init__` method on Foo instances. Rather, the `__init__` method
-is part of the `Foo`'s `__call__` method::
-
- >>> class IFooFactory(zope.interface.Interface):
- ... """Create foos"""
- ...
- ... def __call__(x=None):
- ... """Create a foo
- ...
- ... The argument provides the initial value for x ...
- ... """
-
-It's the class that provides this interface, so we declare the
-interface on the class::
-
- >>> zope.interface.directlyProvides(Foo, IFooFactory)
-
-And then, we'll see that Foo provides some interfaces::
-
- >>> list(zope.interface.providedBy(Foo))
- [<InterfaceClass __main__.IFooFactory>]
- >>> IFooFactory.providedBy(Foo)
- True
-
-Declaring class interfaces is common enough that there's a special
-declaration function for it, `classProvides`, that allows the
-declaration from within a class statement::
-
- >>> class Foo2:
- ... zope.interface.implements(IFoo)
- ... zope.interface.classProvides(IFooFactory)
- ...
- ... def __init__(self, x=None):
- ... self.x = x
- ...
- ... def bar(self, q, r=None):
- ... return q, r, self.x
- ...
- ... def __repr__(self):
- ... return "Foo(%s)" % self.x
-
- >>> list(zope.interface.providedBy(Foo2))
- [<InterfaceClass __main__.IFooFactory>]
- >>> IFooFactory.providedBy(Foo2)
- True
-
-There's a similar function, `moduleProvides`, that supports interface
-declarations from within module definitions. For example, see the use
-of `moduleProvides` call in `zope.interface.__init__`, which declares that
-the package `zope.interface` provides `IInterfaceDeclaration`.
-
-Sometimes, we want to declare interfaces on instances, even though
-those instances get interfaces from their classes. Suppose we create
-a new interface, `ISpecial`::
-
- >>> class ISpecial(zope.interface.Interface):
- ... reason = zope.interface.Attribute("Reason why we're special")
- ... def brag():
- ... "Brag about being special"
-
-We can make an existing foo instance special by providing `reason`
-and `brag` attributes::
-
- >>> foo.reason = 'I just am'
- >>> def brag():
- ... return "I'm special!"
- >>> foo.brag = brag
- >>> foo.reason
- 'I just am'
- >>> foo.brag()
- "I'm special!"
-
-and by declaring the interface::
-
- >>> zope.interface.directlyProvides(foo, ISpecial)
-
-then the new interface is included in the provided interfaces::
-
- >>> ISpecial.providedBy(foo)
- True
- >>> list(zope.interface.providedBy(foo))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-We can find out what interfaces are directly provided by an object::
-
- >>> list(zope.interface.directlyProvidedBy(foo))
- [<InterfaceClass __main__.ISpecial>]
-
- >>> newfoo = Foo()
- >>> list(zope.interface.directlyProvidedBy(newfoo))
- []
-
-Inherited declarations
-----------------------
-
-Normally, declarations are inherited::
-
- >>> class SpecialFoo(Foo):
- ... zope.interface.implements(ISpecial)
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
- >>> list(zope.interface.implementedBy(SpecialFoo))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
- >>> list(zope.interface.providedBy(SpecialFoo()))
- [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-Sometimes, you don't want to inherit declarations. In that case, you
-can use `implementsOnly`, instead of `implements`::
-
- >>> class Special(Foo):
- ... zope.interface.implementsOnly(ISpecial)
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
- >>> list(zope.interface.implementedBy(Special))
- [<InterfaceClass __main__.ISpecial>]
-
- >>> list(zope.interface.providedBy(Special()))
- [<InterfaceClass __main__.ISpecial>]
-
-External declarations
----------------------
-
-Normally, we make implementation declarations as part of a class
-definition. Sometimes, we may want to make declarations from outside
-the class definition. For example, we might want to declare interfaces
-for classes that we didn't write. The function `classImplements` can
-be used for this purpose::
-
- >>> class C:
- ... pass
-
- >>> zope.interface.classImplements(C, IFoo)
- >>> list(zope.interface.implementedBy(C))
- [<InterfaceClass __main__.IFoo>]
-
-We can use `classImplementsOnly` to exclude inherited interfaces::
-
- >>> class C(Foo):
- ... pass
-
- >>> zope.interface.classImplementsOnly(C, ISpecial)
- >>> list(zope.interface.implementedBy(C))
- [<InterfaceClass __main__.ISpecial>]
-
-
-
-Declaration Objects
--------------------
-
-When we declare interfaces, we create *declaration* objects. When we
-query declarations, declaration objects are returned::
-
- >>> type(zope.interface.implementedBy(Special))
- <class 'zope.interface.declarations.Implements'>
-
-Declaration objects and interface objects are similar in many ways. In
-fact, they share a common base class. The important thing to realize
-about them is that they can be used where interfaces are expected in
-declarations. Here's a silly example::
-
- >>> class Special2(Foo):
- ... zope.interface.implementsOnly(
- ... zope.interface.implementedBy(Foo),
- ... ISpecial,
- ... )
- ... reason = 'I just am'
- ... def brag(self):
- ... return "I'm special because %s" % self.reason
-
-The declaration here is almost the same as
-``zope.interface.implements(ISpecial)``, except that the order of
-interfaces in the resulting declaration is different::
-
- >>> list(zope.interface.implementedBy(Special2))
- [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
-
-
-Interface Inheritance
-=====================
-
-Interfaces can extend other interfaces. They do this simply by listing
-the other interfaces as base interfaces::
-
- >>> class IBlat(zope.interface.Interface):
- ... """Blat blah blah"""
- ...
- ... y = zope.interface.Attribute("y blah blah")
- ... def eek():
- ... """eek blah blah"""
-
- >>> IBlat.__bases__
- (<InterfaceClass zope.interface.Interface>,)
-
- >>> class IBaz(IFoo, IBlat):
- ... """Baz blah"""
- ... def eek(a=1):
- ... """eek in baz blah"""
- ...
-
- >>> IBaz.__bases__
- (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
-
- >>> names = list(IBaz)
- >>> names.sort()
- >>> names
- ['bar', 'eek', 'x', 'y']
-
-Note that `IBaz` overrides eek::
-
- >>> IBlat['eek'].__doc__
- 'eek blah blah'
- >>> IBaz['eek'].__doc__
- 'eek in baz blah'
-
-We were careful to override eek in a compatible way. When extending
-an interface, the extending interface should be compatible [#compat]_
-with the extended interfaces.
-
-We can ask whether one interface extends another::
-
- >>> IBaz.extends(IFoo)
- True
- >>> IBlat.extends(IFoo)
- False
-
-Note that interfaces don't extend themselves::
-
- >>> IBaz.extends(IBaz)
- False
-
-Sometimes we wish they did, but we can, instead use `isOrExtends`::
-
- >>> IBaz.isOrExtends(IBaz)
- True
- >>> IBaz.isOrExtends(IFoo)
- True
- >>> IFoo.isOrExtends(IBaz)
- False
-
-When we iterate over an interface, we get all of the names it defines,
-including names defined by base interfaces. Sometimes, we want *just*
-the names defined by the interface directly. We bane use the `names`
-method for that::
-
- >>> list(IBaz.names())
- ['eek']
-
-Inheritance of attribute specifications
----------------------------------------
-
-An interface may override attribute definitions from base interfaces.
-If two base interfaces define the same attribute, the attribute is
-inherited from the most specific interface. For example, with:
-
- >>> class IBase(zope.interface.Interface):
- ...
- ... def foo():
- ... "base foo doc"
-
- >>> class IBase1(IBase):
- ... pass
-
- >>> class IBase2(IBase):
- ...
- ... def foo():
- ... "base2 foo doc"
-
- >>> class ISub(IBase1, IBase2):
- ... pass
-
-ISub's definition of foo is the one from IBase2, since IBase2 is more
-specific that IBase:
-
- >>> ISub['foo'].__doc__
- 'base2 foo doc'
-
-Note that this differs from a depth-first search.
-
-Sometimes, it's useful to ask whether an interface defines an
-attribute directly. You can use the direct method to get a directly
-defined definitions:
-
- >>> IBase.direct('foo').__doc__
- 'base foo doc'
-
- >>> ISub.direct('foo')
-
-Specifications
---------------
-
-Interfaces and declarations are both special cases of specifications.
-What we described above for interface inheritance applies to both
-declarations and specifications. Declarations actually extend the
-interfaces that they declare:
-
- >>> class Baz:
- ... zope.interface.implements(IBaz)
-
- >>> baz_implements = zope.interface.implementedBy(Baz)
- >>> baz_implements.__bases__
- (<InterfaceClass __main__.IBaz>,)
-
- >>> baz_implements.extends(IFoo)
- True
-
- >>> baz_implements.isOrExtends(IFoo)
- True
- >>> baz_implements.isOrExtends(baz_implements)
- True
-
-Specifications (interfaces and declarations) provide an `__sro__`
-that lists the specification and all of it's ancestors:
-
- >>> baz_implements.__sro__
- (<implementedBy __main__.Baz>,
- <InterfaceClass __main__.IBaz>,
- <InterfaceClass __main__.IFoo>,
- <InterfaceClass __main__.IBlat>,
- <InterfaceClass zope.interface.Interface>)
-
-
-Tagged Values
-=============
-
-Interfaces and attribute descriptions support an extension mechanism,
-borrowed from UML, called "tagged values" that lets us store extra
-data::
-
- >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
- >>> IFoo.setTaggedValue('author', 'Jim Fulton')
- >>> IFoo.getTaggedValue('date-modified')
- '2004-04-01'
- >>> IFoo.queryTaggedValue('date-modified')
- '2004-04-01'
- >>> IFoo.queryTaggedValue('datemodified')
- >>> tags = list(IFoo.getTaggedValueTags())
- >>> tags.sort()
- >>> tags
- ['author', 'date-modified']
-
-Function attributes are converted to tagged values when method
-attribute definitions are created::
-
- >>> class IBazFactory(zope.interface.Interface):
- ... def __call__():
- ... "create one"
- ... __call__.return_type = IBaz
-
- >>> IBazFactory['__call__'].getTaggedValue('return_type')
- <InterfaceClass __main__.IBaz>
-
-
-Invariants
-==========
-
-Interfaces can express conditions that must hold for objects that
-provide them. These conditions are expressed using one or more
-invariants. Invariants are callable objects that will be called with
-an object that provides an interface. An invariant raises an `Invalid`
-exception if the condition doesn't hold. Here's an example::
-
- >>> class RangeError(zope.interface.Invalid):
- ... """A range has invalid limits"""
- ... def __repr__(self):
- ... return "RangeError(%r)" % self.args
-
- >>> def range_invariant(ob):
- ... if ob.max < ob.min:
- ... raise RangeError(ob)
-
-Given this invariant, we can use it in an interface definition::
-
- >>> class IRange(zope.interface.Interface):
- ... min = zope.interface.Attribute("Lower bound")
- ... max = zope.interface.Attribute("Upper bound")
- ...
- ... zope.interface.invariant(range_invariant)
-
-Interfaces have a method for checking their invariants::
-
- >>> class Range(object):
- ... zope.interface.implements(IRange)
- ...
- ... def __init__(self, min, max):
- ... self.min, self.max = min, max
- ...
- ... def __repr__(self):
- ... return "Range(%s, %s)" % (self.min, self.max)
-
- >>> IRange.validateInvariants(Range(1,2))
- >>> IRange.validateInvariants(Range(1,1))
- >>> IRange.validateInvariants(Range(2,1))
- Traceback (most recent call last):
- ...
- RangeError: Range(2, 1)
-
-If you have multiple invariants, you may not want to stop checking
-after the first error. If you pass a list to `validateInvariants`,
-then a single `Invalid` exception will be raised with the list of
-exceptions as it's argument::
-
- >>> errors = []
- >>> IRange.validateInvariants(Range(2,1), errors)
- Traceback (most recent call last):
- ...
- Invalid: [RangeError(Range(2, 1))]
-
-And the list will be filled with the individual exceptions::
-
- >>> errors
- [RangeError(Range(2, 1))]
-
-
- >>> del errors[:]
-
-
-
-
-.. [#create] The main reason we subclass `Interface` is to cause the
- Python class statement to create an interface, rather
- than a class.
-
- It's possible to create interfaces by calling a special
- interface class directly. Doing this, it's possible
- (and, on rare occasions, useful) to create interfaces
- that don't descend from `Interface`. Using this
- technique is beyond the scope of this document.
-
-.. [#factory] Classes are factories. They can be called to create
- their instances. We expect that we will eventually
- extend the concept of implementation to other kinds of
- factories, so that we can declare the interfaces
- provided by the objects created.
-
-.. [#compat] The goal is substitutability. An object that provides an
- extending interface should be substitutable for an object
- that provides the extended interface. In our example, an
- object that provides IBaz should be usable whereever an
- object that provides IBlat is expected.
-
- The interface implementation doesn't enforce this.
- but maybe it should do some checks.
=== removed file 'lib/zope/interface/SETUP.cfg'
--- lib/zope/interface/SETUP.cfg 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/SETUP.cfg 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-# Extension information for zpkg:
-
-<extension _zope_interface_coptimizations>
- source _zope_interface_coptimizations.c
-</extension>
=== removed file 'lib/zope/interface/__init__.py'
--- lib/zope/interface/__init__.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,80 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Interfaces
-
-This package implements the Python "scarecrow" proposal.
-
-The package exports two objects, `Interface` and `Attribute` directly. It also
-exports several helper methods. Interface is used to create an interface with
-a class statement, as in:
-
- class IMyInterface(Interface):
- '''Interface documentation
- '''
-
- def meth(arg1, arg2):
- '''Documentation for meth
- '''
-
- # Note that there is no self argument
-
-To find out what you can do with interfaces, see the interface
-interface, `IInterface` in the `interfaces` module.
-
-The package has several public modules:
-
- o `declarations` provides utilities to declare interfaces on objects. It
- also provides a wide range of helpful utilities that aid in managing
- declared interfaces. Most of its public names are however imported here.
-
- o `document` has a utility for documenting an interface as structured text.
-
- o `exceptions` has the interface-defined exceptions
-
- o `interfaces` contains a list of all public interfaces for this package.
-
- o `verify` has utilities for verifying implementations of interfaces.
-
-See the module doc strings for more information.
-
-$Id: __init__.py 67630 2006-04-27 00:54:03Z jim $
-"""
-__docformat__ = 'restructuredtext'
-
-from zope.interface.interface import Interface, _wire
-
-# Need to actually get the interface elements to implement the right interfaces
-_wire()
-del _wire
-
-from zope.interface.interface import Attribute, invariant
-
-from zope.interface.declarations import providedBy, implementedBy
-from zope.interface.declarations import classImplements, classImplementsOnly
-from zope.interface.declarations import directlyProvidedBy, directlyProvides
-from zope.interface.declarations import alsoProvides, implementer
-from zope.interface.declarations import implements, implementsOnly
-from zope.interface.declarations import classProvides, moduleProvides
-from zope.interface.declarations import noLongerProvides, Declaration
-from zope.interface.exceptions import Invalid
-
-# The following are to make spec pickles cleaner
-from zope.interface.declarations import Provides
-
-
-from zope.interface.interfaces import IInterfaceDeclaration
-
-moduleProvides(IInterfaceDeclaration)
-
-__all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
=== removed file 'lib/zope/interface/_flatten.py'
--- lib/zope/interface/_flatten.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/_flatten.py 1970-01-01 00:00:00 +0000
@@ -1,37 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Adapter-style interface registry
-
-See Adapter class.
-
-$Id: _flatten.py 26551 2004-07-15 07:06:37Z srichter $
-"""
-from zope.interface import Declaration
-
-def _flatten(implements, include_None=0):
-
- try:
- r = implements.flattened()
- except AttributeError:
- if implements is None:
- r=()
- else:
- r = Declaration(implements).flattened()
-
- if not include_None:
- return r
-
- r = list(r)
- r.append(None)
- return r
=== removed file 'lib/zope/interface/_zope_interface_coptimizations.c'
--- lib/zope/interface/_zope_interface_coptimizations.c 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/_zope_interface_coptimizations.c 1970-01-01 00:00:00 +0000
@@ -1,554 +0,0 @@
-/*###########################################################################
- #
- # Copyright (c) 2003 Zope Corporation 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.
- #
- ############################################################################*/
-
-#include "Python.h"
-#include "structmember.h"
-
-#define TYPE(O) ((PyTypeObject*)(O))
-#define OBJECT(O) ((PyObject*)(O))
-#define CLASSIC(O) ((PyClassObject*)(O))
-
-static PyObject *str__dict__, *str__implemented__, *strextends;
-static PyObject *BuiltinImplementationSpecifications, *str__provides__;
-static PyObject *str__class__, *str__providedBy__, *strisOrExtends;
-static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
-static PyTypeObject *Implements;
-
-static int imported_declarations = 0;
-
-static int
-import_declarations(void)
-{
- PyObject *declarations, *i;
-
- declarations = PyImport_ImportModule("zope.interface.declarations");
- if (declarations == NULL)
- return -1;
-
- BuiltinImplementationSpecifications = PyObject_GetAttrString(
- declarations, "BuiltinImplementationSpecifications");
- if (BuiltinImplementationSpecifications == NULL)
- return -1;
-
- empty = PyObject_GetAttrString(declarations, "_empty");
- if (empty == NULL)
- return -1;
-
- fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
- if (fallback == NULL)
- return -1;
-
-
-
- i = PyObject_GetAttrString(declarations, "Implements");
- if (i == NULL)
- return -1;
-
- if (! PyType_Check(i))
- {
- PyErr_SetString(PyExc_TypeError,
- "zope.declarations.Implements is not a type");
- return -1;
- }
-
- Implements = (PyTypeObject *)i;
-
- Py_DECREF(declarations);
-
- imported_declarations = 1;
- return 0;
-}
-
-static PyTypeObject SpecType; /* Forward */
-
-static PyObject *
-implementedByFallback(PyObject *cls)
-{
- if (imported_declarations == 0 && import_declarations() < 0)
- return NULL;
-
- return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
-}
-
-static PyObject *
-implementedBy(PyObject *ignored, PyObject *cls)
-{
- /* Fast retrieval of implements spec, if possible, to optimize
- common case. Use fallback code if we get stuck.
- */
-
- PyObject *dict = NULL, *spec;
-
- if (PyType_Check(cls))
- {
- dict = TYPE(cls)->tp_dict;
- Py_XINCREF(dict);
- }
-
- if (dict == NULL)
- dict = PyObject_GetAttr(cls, str__dict__);
-
- if (dict == NULL)
- {
- /* Probably a security proxied class, use more expensive fallback code */
- PyErr_Clear();
- return implementedByFallback(cls);
- }
-
- spec = PyObject_GetItem(dict, str__implemented__);
- Py_DECREF(dict);
- if (spec)
- {
- if (imported_declarations == 0 && import_declarations() < 0)
- return NULL;
-
- if (PyObject_TypeCheck(spec, Implements))
- return spec;
-
- /* Old-style declaration, use more expensive fallback code */
- Py_DECREF(spec);
- return implementedByFallback(cls);
- }
-
- PyErr_Clear();
-
- /* Maybe we have a builtin */
- if (imported_declarations == 0 && import_declarations() < 0)
- return NULL;
-
- spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
- if (spec != NULL)
- {
- Py_INCREF(spec);
- return spec;
- }
-
- /* We're stuck, use fallback */
- return implementedByFallback(cls);
-}
-
-static PyObject *
-getObjectSpecification(PyObject *ignored, PyObject *ob)
-{
- PyObject *cls, *result;
-
- result = PyObject_GetAttr(ob, str__provides__);
- if (result != NULL)
- return result;
-
- PyErr_Clear();
-
- /* We do a getattr here so as not to be defeated by proxies */
- cls = PyObject_GetAttr(ob, str__class__);
- if (cls == NULL)
- {
- PyErr_Clear();
- if (imported_declarations == 0 && import_declarations() < 0)
- return NULL;
- Py_INCREF(empty);
- return empty;
- }
-
- result = implementedBy(NULL, cls);
- Py_DECREF(cls);
-
- return result;
-}
-
-static PyObject *
-providedBy(PyObject *ignored, PyObject *ob)
-{
- PyObject *result, *cls, *cp;
-
- result = PyObject_GetAttr(ob, str__providedBy__);
- if (result == NULL)
- {
- PyErr_Clear();
- return getObjectSpecification(NULL, ob);
- }
-
-
- /* We want to make sure we have a spec. We can't do a type check
- because we may have a proxy, so we'll just try to get the
- only attribute.
- */
- if (PyObject_HasAttr(result, strextends))
- return result;
-
- /*
- The object's class doesn't understand descriptors.
- Sigh. We need to get an object descriptor, but we have to be
- careful. We want to use the instance's __provides__,l if
- there is one, but only if it didn't come from the class.
- */
- Py_DECREF(result);
-
- cls = PyObject_GetAttr(ob, str__class__);
- if (cls == NULL)
- return NULL;
-
- result = PyObject_GetAttr(ob, str__provides__);
- if (result == NULL)
- {
- /* No __provides__, so just fall back to implementedBy */
- PyErr_Clear();
- result = implementedBy(NULL, cls);
- Py_DECREF(cls);
- return result;
- }
-
- cp = PyObject_GetAttr(cls, str__provides__);
- if (cp == NULL)
- {
- /* The the class has no provides, assume we're done: */
- PyErr_Clear();
- Py_DECREF(cls);
- return result;
- }
-
- if (cp == result)
- {
- /*
- Oops, we got the provides from the class. This means
- the object doesn't have it's own. We should use implementedBy
- */
- Py_DECREF(result);
- result = implementedBy(NULL, cls);
- }
-
- Py_DECREF(cls);
- Py_DECREF(cp);
-
- return result;
-}
-
-static PyObject *
-inst_attr(PyObject *self, PyObject *name)
-{
- /* Get an attribute from an inst dict. Return a borrowed reference.
- */
-
- PyObject **dictp, *v;
-
- dictp = _PyObject_GetDictPtr(self);
- if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
- return v;
- PyErr_SetObject(PyExc_AttributeError, name);
- return NULL;
-}
-
-
-static PyObject *
-Spec_extends(PyObject *self, PyObject *other)
-{
- PyObject *implied;
-
- implied = inst_attr(self, str_implied);
- if (implied == NULL)
- return NULL;
-
-#ifdef Py_True
- if (PyDict_GetItem(implied, other) != NULL)
- {
- Py_INCREF(Py_True);
- return Py_True;
- }
- Py_INCREF(Py_False);
- return Py_False;
-#else
- return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
-#endif
-}
-
-static char Spec_extends__doc__[] =
-"Test whether a specification is or extends another"
-;
-
-static char Spec_providedBy__doc__[] =
-"Test whether an interface is implemented by the specification"
-;
-
-static PyObject *
-Spec_providedBy(PyObject *self, PyObject *ob)
-{
- PyObject *decl, *item;
-
- decl = providedBy(NULL, ob);
- if (decl == NULL)
- return NULL;
-
- if (PyObject_TypeCheck(ob, &SpecType))
- item = Spec_extends(decl, self);
- else
- /* decl is probably a security proxy. We have to go the long way
- around.
- */
- item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL);
-
- Py_DECREF(decl);
- return item;
-}
-
-
-static char Spec_implementedBy__doc__[] =
-"Test whether the specification is implemented by a class or factory.\n"
-"Raise TypeError if argument is neither a class nor a callable."
-;
-
-static PyObject *
-Spec_implementedBy(PyObject *self, PyObject *cls)
-{
- PyObject *decl, *item;
-
- decl = implementedBy(NULL, cls);
- if (decl == NULL)
- return NULL;
-
- if (PyObject_TypeCheck(decl, &SpecType))
- item = Spec_extends(decl, self);
- else
- item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL);
-
- Py_DECREF(decl);
- return item;
-}
-
-static struct PyMethodDef Spec_methods[] = {
- {"providedBy",
- (PyCFunction)Spec_providedBy, METH_O,
- Spec_providedBy__doc__},
- {"implementedBy",
- (PyCFunction)Spec_implementedBy, METH_O,
- Spec_implementedBy__doc__},
- {"isOrExtends", (PyCFunction)Spec_extends, METH_O,
- Spec_extends__doc__},
-
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject SpecType = {
- PyObject_HEAD_INIT(NULL)
- /* ob_size */ 0,
- /* tp_name */ "_interface_coptimizations."
- "SpecificationBase",
- /* tp_basicsize */ 0,
- /* tp_itemsize */ 0,
- /* tp_dealloc */ (destructor)0,
- /* tp_print */ (printfunc)0,
- /* tp_getattr */ (getattrfunc)0,
- /* tp_setattr */ (setattrfunc)0,
- /* tp_compare */ (cmpfunc)0,
- /* tp_repr */ (reprfunc)0,
- /* tp_as_number */ 0,
- /* tp_as_sequence */ 0,
- /* tp_as_mapping */ 0,
- /* tp_hash */ (hashfunc)0,
- /* tp_call */ (ternaryfunc)0,
- /* tp_str */ (reprfunc)0,
- /* tp_getattro */ (getattrofunc)0,
- /* tp_setattro */ (setattrofunc)0,
- /* tp_as_buffer */ 0,
- /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- "Base type for Specification objects",
- /* tp_traverse */ (traverseproc)0,
- /* tp_clear */ (inquiry)0,
- /* tp_richcompare */ (richcmpfunc)0,
- /* tp_weaklistoffset */ (long)0,
- /* tp_iter */ (getiterfunc)0,
- /* tp_iternext */ (iternextfunc)0,
- /* tp_methods */ Spec_methods,
-};
-
-static PyObject *
-OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
-{
- PyObject *provides;
-
- if (inst == NULL)
- return getObjectSpecification(NULL, cls);
-
- provides = PyObject_GetAttr(inst, str__provides__);
- if (provides != NULL)
- return provides;
- PyErr_Clear();
- return implementedBy(NULL, cls);
-}
-
-static PyTypeObject OSDType = {
- PyObject_HEAD_INIT(NULL)
- /* ob_size */ 0,
- /* tp_name */ "_interface_coptimizations."
- "ObjectSpecificationDescriptor",
- /* tp_basicsize */ 0,
- /* tp_itemsize */ 0,
- /* tp_dealloc */ (destructor)0,
- /* tp_print */ (printfunc)0,
- /* tp_getattr */ (getattrfunc)0,
- /* tp_setattr */ (setattrfunc)0,
- /* tp_compare */ (cmpfunc)0,
- /* tp_repr */ (reprfunc)0,
- /* tp_as_number */ 0,
- /* tp_as_sequence */ 0,
- /* tp_as_mapping */ 0,
- /* tp_hash */ (hashfunc)0,
- /* tp_call */ (ternaryfunc)0,
- /* tp_str */ (reprfunc)0,
- /* tp_getattro */ (getattrofunc)0,
- /* tp_setattro */ (setattrofunc)0,
- /* tp_as_buffer */ 0,
- /* tp_flags */ Py_TPFLAGS_DEFAULT
- | Py_TPFLAGS_BASETYPE ,
- "Object Specification Descriptor",
- /* tp_traverse */ (traverseproc)0,
- /* tp_clear */ (inquiry)0,
- /* tp_richcompare */ (richcmpfunc)0,
- /* tp_weaklistoffset */ (long)0,
- /* tp_iter */ (getiterfunc)0,
- /* tp_iternext */ (iternextfunc)0,
- /* tp_methods */ 0,
- /* tp_members */ 0,
- /* tp_getset */ 0,
- /* tp_base */ 0,
- /* tp_dict */ 0, /* internal use */
- /* tp_descr_get */ (descrgetfunc)OSD_descr_get,
-};
-
-static PyObject *
-CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
-{
- PyObject *mycls, *implements;
-
- mycls = inst_attr(self, str_cls);
- if (mycls == NULL)
- return NULL;
-
- if (cls == mycls)
- {
- if (inst == NULL)
- {
- Py_INCREF(self);
- return OBJECT(self);
- }
-
- implements = inst_attr(self, str_implements);
- Py_XINCREF(implements);
- return implements;
- }
-
- PyErr_SetObject(PyExc_AttributeError, str__provides__);
- return NULL;
-}
-
-static PyTypeObject CPBType = {
- PyObject_HEAD_INIT(NULL)
- /* ob_size */ 0,
- /* tp_name */ "_interface_coptimizations."
- "ClassProvidesBase",
- /* tp_basicsize */ 0,
- /* tp_itemsize */ 0,
- /* tp_dealloc */ (destructor)0,
- /* tp_print */ (printfunc)0,
- /* tp_getattr */ (getattrfunc)0,
- /* tp_setattr */ (setattrfunc)0,
- /* tp_compare */ (cmpfunc)0,
- /* tp_repr */ (reprfunc)0,
- /* tp_as_number */ 0,
- /* tp_as_sequence */ 0,
- /* tp_as_mapping */ 0,
- /* tp_hash */ (hashfunc)0,
- /* tp_call */ (ternaryfunc)0,
- /* tp_str */ (reprfunc)0,
- /* tp_getattro */ (getattrofunc)0,
- /* tp_setattro */ (setattrofunc)0,
- /* tp_as_buffer */ 0,
- /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- "C Base class for ClassProvides",
- /* tp_traverse */ (traverseproc)0,
- /* tp_clear */ (inquiry)0,
- /* tp_richcompare */ (richcmpfunc)0,
- /* tp_weaklistoffset */ (long)0,
- /* tp_iter */ (getiterfunc)0,
- /* tp_iternext */ (iternextfunc)0,
- /* tp_methods */ 0,
- /* tp_members */ 0,
- /* tp_getset */ 0,
- /* tp_base */ &SpecType,
- /* tp_dict */ 0, /* internal use */
- /* tp_descr_get */ (descrgetfunc)CPB_descr_get,
-};
-
-
-static struct PyMethodDef m_methods[] = {
- {"implementedBy", (PyCFunction)implementedBy, METH_O,
- "Interfaces implemented by a class or factory.\n"
- "Raises TypeError if argument is neither a class nor a callable."},
- {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
- "Get an object's interfaces (internal api)"},
- {"providedBy", (PyCFunction)providedBy, METH_O,
- "Get an object's interfaces"},
-
- {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
-};
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-init_zope_interface_coptimizations(void)
-{
- PyObject *m;
-
-#define DEFINE_STRING(S) \
- if(! (str ## S = PyString_FromString(# S))) return
-
- DEFINE_STRING(__dict__);
- DEFINE_STRING(__implemented__);
- DEFINE_STRING(__provides__);
- DEFINE_STRING(__class__);
- DEFINE_STRING(__providedBy__);
- DEFINE_STRING(isOrExtends);
- DEFINE_STRING(extends);
- DEFINE_STRING(_implied);
- DEFINE_STRING(_implements);
- DEFINE_STRING(_cls);
-#undef DEFINE_STRING
-
-
- /* Initialize types: */
- SpecType.tp_new = PyBaseObject_Type.tp_new;
- if (PyType_Ready(&SpecType) < 0)
- return;
- OSDType.tp_new = PyBaseObject_Type.tp_new;
- if (PyType_Ready(&OSDType) < 0)
- return;
- CPBType.tp_new = PyBaseObject_Type.tp_new;
- if (PyType_Ready(&CPBType) < 0)
- return;
-
- /* Create the module and add the functions */
- m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
- "C optimizations for zope.interface\n\n"
- "$Id: _zope_interface_coptimizations.c 38501 2005-09-17 10:20:09Z philikon $");
- if (m == NULL)
- return;
-
- /* Add types: */
- if (PyModule_AddObject(m, "SpecificationBase", (PyObject *)&SpecType) < 0)
- return;
- if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
- (PyObject *)&OSDType) < 0)
- return;
- if (PyModule_AddObject(m, "ClassProvidesBase", (PyObject *)&CPBType) < 0)
- return;
-}
=== removed file 'lib/zope/interface/adapter.py'
--- lib/zope/interface/adapter.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/adapter.py 1970-01-01 00:00:00 +0000
@@ -1,744 +0,0 @@
-############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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.
-#
-############################################################################
-"""Adapter-style interface registry
-
-This implementation is based on a notion of "surrogate" interfaces.
-
-$Id: adapter.py 40520 2005-12-03 15:44:57Z benji_york $
-"""
-
-# Implementation notes
-
-# We keep a collection of surrogates.
-
-# A surrogate is a surrogate for a specification (interface or
-# declaration). We use weak references in order to remove surrogates
-# if the corresponding specification goes away.
-
-# Each surrogate keeps track of:
-
-# - The adapters registered directly for that surrogate, and
-
-# - The "implied" adapters, which is the adapters that can be computed
-# from instances of that surrogate.
-
-# The later data structure takes into account adapters registered for
-# specifications that the registered surrogate extends.
-
-# The registrations are of the form:
-
-# {(subscription, with, name, specification) -> factories}
-
-# where:
-
-# 'subscription' is a flag indicating if this registration is for
-# subscription adapters.
-
-# 'with' is a tuple of specs that is non-empty only in the case
-# of multi-adapters.
-
-# 'name' is a unicode adapter name. Unnamed adapters have an empty
-# name.
-
-# 'specification' is the interface being adapted to, the provided interface.
-
-# 'factories' is normally a tuple of factories, but can be anything.
-# (See the "raw" option to the query-adapter calls.) For subscription
-# adapters, it is a tuple of tuples of factories.
-
-# The implied adapters are held in a single dictionary. The items in the
-# dictionary are of several forms:
-
-# For single adapters:
-#
-# {specification -> {name -> object}
-#
-# where object is usually a sequence of factories
-
-# For multiple adapters:
-#
-# {(specification, order) -> {name -> {with -> object}}}
-
-# For single subscription adapters:
-#
-# {('s', specification) -> tuple([object])}
-
-# For multiple-subscription adapters:
-#
-# {('s', specification, order) -> {with -> tuple([object])}}
-
-
-from __future__ import generators
-
-import weakref
-from zope.interface.ro import ro
-from zope.interface.declarations import providedBy
-from zope.interface.interface import InterfaceClass, Interface
-
-Default = InterfaceClass("Default", (), {})
-Null = InterfaceClass("Null", (), {})
-
-# 2.2 backwards compatability
-try:
- enumerate
-except NameError:
- def enumerate(l):
- i = 0
- for o in l:
- yield i, o
- i += 1
-try:
- basestring
-except NameError:
- basestring = (str, unicode)
-
-
-class ReadProperty(object):
-
- def __init__(self, func):
- self.func = func
-
- def __get__(self, inst, class_):
- if inst is None:
- return self
- return self.func(inst)
-
-class Surrogate(object):
- """Specification surrogate
-
- A specification surrogate is used to hold adapter registrations on
- behalf of a specification.
- """
-
- def __init__(self, spec, registry):
- self.spec = spec.weakref()
- self.registry = registry
- spec.subscribe(self)
- self.adapters = {}
- self.dependents = weakref.WeakKeyDictionary()
-
- self.registry = registry
- self.__bases__ = [registry.get(base) for base in spec.__bases__]
- for base in self.__bases__:
- base.subscribe(self)
-
- def dirty(self):
- if 'get' in self.__dict__:
- # Not already dirty
- del self.selfImplied
- del self.multImplied
- del self.get
-
- bases = [self.registry.get(base) for base in self.spec().__bases__]
- if bases != self.__bases__:
- # Our bases changed. unsubscribe from the old ones
- # and subscribe to the new ones
- for base in self.__bases__:
- base.unsubscribe(self)
-
- self.__bases__ = bases
- for base in bases:
- base.subscribe(self)
-
- for dependent in self.dependents.keys():
- dependent.dirty()
-
- def clean(self):
- for base in self.__bases__:
- base.unsubscribe(self)
- self.__bases__ = [self.registry.get(base)
- for base in self.spec().__bases__]
- for base in self.__bases__:
- base.subscribe(self)
-
- self.selfImplied, self.multImplied = adapterImplied(self.adapters)
-
- implied = {}
-
- ancestors = ro(self)
-
- # Collect implied data in reverse order to have more specific data
- # override less-specific data.
- ancestors.reverse()
- for ancestor in ancestors:
- ancestor_spec = ancestor.spec()
-
- for key, v in ancestor.selfImplied.iteritems():
-
- # key is specification or ('s', specification)
- subscription = isinstance(key, tuple) and key[0] == 's'
- if subscription:
- # v is tuple of subs
- implied[key] = implied.get(key, ()) + v
- else:
- oldbyname = implied.get(key)
- if not oldbyname:
- implied[key] = oldbyname = {}
-
- # v is name -> object
- oldbyname.update(v)
-
- for key, v in ancestor.multImplied.iteritems():
- # key is (specification, order)
- # or ('s', specification, order)
- subscription = key[0] == 's'
- if subscription:
- oldwithobs = implied.get(key)
- if not oldwithobs:
- oldwithobs = implied[key] = {}
-
- # v is {with -> tuple([object])}
- for with, objects in v.iteritems():
- oldwithobs[with] = oldwithobs.get(with, ()) + objects
-
- else:
- oldbyname = implied.get(key)
- if not oldbyname:
- implied[key] = oldbyname = {}
-
-
- # v is {name -> {with -> ?}}
- for name, withobs in v.iteritems():
-
- # withobs is {with -> value}
-
- # If ancestor is not the default,
- # add in ancestor so we can get ordering right
- if ancestor_spec is not Default:
- withobs = dict([
- (((ancestor_spec,) + with), value)
- for (with, value) in withobs.iteritems()
- ])
-
- oldwithobs = oldbyname.get(name)
- if not oldwithobs:
- oldwithobs = oldbyname[name] = {}
-
- # withobs is {with -> object}
- oldwithobs.update(withobs)
-
- # Now flatten with mappings to tuples
- for key, v in implied.iteritems():
- if isinstance(key, tuple):
- if key[0] == 's':
- # subscriptions
- if isinstance(v, dict):
- implied[key] = v.items()
- else:
- byname = v
- for name, value in byname.iteritems():
- if isinstance(value, dict):
- # We have {with -> value}
- # convert it to [(with, value]
- byname[name] = value.items()
-
- self.get = implied.get
-
- def get(self, key):
- """Get an implied value
-
- This is only called when the surrogate is dirty
- """
- self.clean()
- return self.__dict__['get'](key)
-
- def selfImplied(self):
- """Return selfImplied when dirty
- """
- self.clean()
- return self.__dict__['selfImplied']
- selfImplied = ReadProperty(selfImplied)
-
- def multiImplied(self):
- """Return _multiImplied when dirty
- """
- self.clean()
- return self.__dict__['multiImplied']
- multiImplied = ReadProperty(multiImplied)
-
- def subscribe(self, dependent):
- self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
-
- def unsubscribe(self, dependent):
- n = self.dependents.get(dependent, 0) - 1
- if not n:
- del self.dependents[dependent]
- elif n > 0:
- self.dependents[dependent] = n
- else:
- raise KeyError(dependent)
-
- def _adaptTo(self, specification, object, name='', with=()):
- if object is None:
- try:
- del self.adapters[False, tuple(with), name, specification]
- except KeyError:
- pass
- else:
- self.adapters[False, tuple(with), name, specification
- ] = object
-
- self.dirty()
-
- def _subscriptionAdaptTo(self, specification, object, with=()):
- if object is None:
- raise TypeError("Unregistering subscription adapters isn't "
- "implemented")
-
- key = (True, tuple(with), '', specification)
- self.adapters[key] = self.adapters.get(key, ()) + (object, )
- self.dirty()
-
- def changed(self, which=None):
- self.dirty()
-
- def __repr__(self):
- return '<%s(%s)>' % (self.__class__.__name__, self.spec())
-
-
-class AdapterLookup(object):
- # Adapter lookup support
- # We have a class here because we want to provide very
- # fast lookup support in C and making this part of the adapter
- # registry itself would provide problems if someone wanted
- # persistent adapter registries, because we want C slots for fast
- # lookup that would clash with persistence-supplied slots.
- # so this class acts a little bit like a lookup adapter for the adapter
- # registry.
-
- def __init__(self, registry, surrogates, _remove):
- self._registry = registry
- self._surrogateClass = registry._surrogateClass
- self._default = registry._default
- self._null = registry._null
- self._surrogates = surrogates
- self._remove = _remove
-
- def lookup(self, required, provided, name='', default=None):
- order = len(required)
- if order == 1:
- # Simple adapter:
- s = self.get(required[0])
- byname = s.get(provided)
- if byname:
- value = byname.get(name)
- else:
- value = None
-
- if value is None:
- byname = self._default.get(provided)
- if byname:
- value = byname.get(name, default)
- else:
- return default
-
- return value
-
- elif order == 0:
- # null adapter
- byname = self._null.get(provided)
- if byname:
- return byname.get(name, default)
- else:
- return default
-
- # Multi adapter
-
- with = required
- key = provided, order
-
- for surrogate in self.get(required[0]), self._default:
- byname = surrogate.get(key)
- if byname:
- bywith = byname.get(name)
- if bywith:
- # Selecting multi-adapters is not just a matter of
- # matching the required interfaces of the adapter
- # to the ones passed. Several adapters might
- # match, but we only want the best one. We use a
- # ranking algorithm to determine the best match.
- # `best` carries the rank and value of the best
- # found adapter.
- best = None
- for rwith, value in bywith:
- # the `rank` describes how well the found
- # adapter matches.
- rank = []
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
-
- # Determine the rank of this particular
- # specification.
- rank.append(list(spec.__sro__).index(rspec))
- else:
- # If the new rank is better than the best
- # previously recorded one, make the new
- # adapter the best one found.
- rank = tuple(rank)
- if best is None or rank < best[0]:
- best = rank, value
- # If any match was found, return the best one.
- if best:
- return best[1]
-
- with = with[1:] # on second pass through, don't use first spec
-
- return default
-
- def lookup1(self, required, provided, name='', default=None):
- return self.lookup((required,), provided, name, default)
-
- def adapter_hook(self, interface, object, name='', default=None):
- """Hook function used when calling interfaces.
-
- When called from Interface.__adapt__, only the interface and
- object parameters will be passed.
-
- If the factory produces `None`, then the default is returned. This
- allows us to prevent adaptation (if desired) and make the factory
- decide whether an adapter will be available.
- """
- factory = self.lookup1(providedBy(object), interface, name)
- if factory is not None:
- adapter = factory(object)
- if adapter is not None:
- return adapter
- return default
-
- def queryAdapter(self, object, interface, name='', default=None):
- # Note that we rarely call queryAdapter directly
- # We usually end up calling adapter_hook
- return self.adapter_hook(interface, object, name, default)
-
- def subscriptions(self, required, provided):
- if provided is None:
- provided = Null
-
- order = len(required)
- if order == 1:
- # Simple subscriptions:
- s = self.get(required[0])
- result = s.get(('s', provided))
- if result:
- result = list(result)
- else:
- result = []
-
- default = self._default.get(('s', provided))
- if default:
- result.extend(default)
-
- return result
-
- elif order == 0:
- result = self._null.get(('s', provided))
- if result:
- return list(result)
- else:
- return []
-
- # Multi
- key = 's', provided, order
- with = required[1:]
- result = []
-
- for surrogate in self.get(required[0]), self._default:
- bywith = surrogate.get(key)
- if not bywith:
- continue
-
- for rwith, values in bywith:
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
- else:
- # we didn't break, so we have a match
- result.extend(values)
-
- return result
-
- def queryMultiAdapter(self, objects, interface, name='', default=None):
- factory = self.lookup(map(providedBy, objects), interface, name)
- if factory is not None:
- return factory(*objects)
-
- return default
-
- def subscribers(self, objects, interface):
- subscriptions = self.subscriptions(map(providedBy, objects), interface)
- subscribers = [subscription(*objects)
- for subscription in subscriptions]
- # Filter None values
- return [x for x in subscribers if x is not None]
-
- def get(self, declaration):
- if declaration is None:
- return self._default
-
- ref = declaration.weakref(self._remove)
- surrogate = self._surrogates.get(ref)
- if surrogate is None:
- surrogate = self._surrogateClass(declaration, self._registry)
- self._surrogates[ref] = surrogate
-
- return surrogate
-
-
-class AdapterRegistry(object):
- """Adapter registry
- """
-
- # Implementation note:
- # We are like a weakref dict ourselves. We can't use a weakref
- # dict because we have to use spec.weakref() rather than
- # weakref.ref(spec) to get weak refs to specs.
-
- _surrogateClass = Surrogate
-
- def __init__(self):
- default = self._surrogateClass(Default, self)
- self._default = default
- null = self._surrogateClass(Null, self)
- self._null = null
-
- # Create separate lookup object and copy it's methods
- surrogates = {Default.weakref(): default, Null.weakref(): null}
- def _remove(k):
- try:
- del surrogates[k]
- except KeyError:
- pass
- lookup = AdapterLookup(self, surrogates, _remove)
-
- for name in ('lookup', 'lookup1', 'queryAdapter', 'get',
- 'adapter_hook', 'subscriptions',
- 'queryMultiAdapter', 'subscribers',
- ):
- setattr(self, name, getattr(lookup, name))
-
- def register(self, required, provided, name, value):
- if required:
- with = []
- for iface in required[1:]:
- if iface is None:
- iface = Interface
- with.append(iface)
- with = tuple(with)
- required = self.get(required[0])
- else:
- with = ()
- required = self._null
-
- if not isinstance(name, basestring):
- raise TypeError("The name provided to provideAdapter "
- "must be a string or unicode")
-
- required._adaptTo(provided, value, unicode(name), with)
-
- def lookupAll(self, required, provided):
- order = len(required)
- if order == 1:
- # Simple adapter:
- s = self.get(required[0])
- byname = s.get(provided)
- if byname:
- for item in byname.iteritems():
- yield item
-
- defbyname = self._default.get(provided)
- if defbyname:
- for name, value in defbyname.iteritems():
- if name in byname:
- continue
- yield name, value
-
- return
-
- elif order == 0:
- # null adapter
- byname = self._null.get(provided)
- if byname:
- for item in byname.iteritems():
- yield item
-
- return
-
-
- # Multi adapter
-
- with = required
- key = provided, order
- first = ()
-
- for surrogate in self.get(required[0]), self._default:
- byname = surrogate.get(key)
- if byname:
- for name, bywith in byname.iteritems():
- if not bywith or name in first:
- continue
-
- # See comments on lookup() above
- best = None
- for rwith, value in bywith:
- # the `rank` describes how well the found
- # adapter matches.
- rank = []
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
-
- # Determine the rank of this particular
- # specification.
- rank.append(list(spec.__sro__).index(rspec))
- else:
- # If the new rank is better than the best
- # previously recorded one, make the new
- # adapter the best one found.
- rank = tuple(rank)
- if best is None or rank < best[0]:
- best = rank, value
-
- # If any match was found, return the best one.
- if best:
- yield name, best[1]
-
- first = byname
-
- with = with[1:] # on second pass through, don't use first spec
-
- def subscribe(self, required, provided, value):
- if required:
- required, with = self.get(required[0]), tuple(required[1:])
- else:
- required = self._null
- with = ()
-
- if provided is None:
- provided = Null
-
- required._subscriptionAdaptTo(provided, value, with)
-
-def mextends(with, rwith):
- if len(with) == len(rwith):
- for w, r in zip(with, rwith):
- if not w.isOrExtends(r):
- break
- else:
- return True
- return False
-
-def adapterImplied(adapters):
- implied = {}
- multi = {}
-
- # This dictionary is used to catch situations specific adapters
- # override less specific adapters.
- # Because subscriptions are cumulative, registered doesn't apply.
- registered = {}
-
- # Add adapters and interfaces directly implied by same:
-
- for key, value in adapters.iteritems():
-
- # TODO: Backward compatibility
- # BBB ? Don't need to handle 3-tuples some day
- try:
- (subscription, with, name, target) = key
- except ValueError:
- (with, name, target) = key
- subscription = False
-
- if subscription:
- if with:
- _add_multi_sub_adapter(with, target, multi, value)
- else:
- _add_named_sub_adapter(target, implied, value)
- else:
- if with:
- _add_multi_adapter(with, name, target, target, multi,
- registered, value)
- else:
- _add_named_adapter(target, target, name, implied,
- registered, value)
-
- return implied, multi
-
-def _add_named_adapter(target, provided, name, implied,
- registered, value):
-
- ikey = target
- rkey = target, name
-
- byname = implied.get(ikey)
- if not byname:
- byname = implied[ikey] = {}
-
- if (name not in byname
- or
- (rkey in registered and registered[rkey].extends(provided))
- ):
-
- registered[rkey] = provided
- byname[name] = value
-
- for b in target.__bases__:
- _add_named_adapter(b, provided, name, implied,
- registered, value)
-
-def _add_multi_adapter(with, name, target, provided, implied,
- registered, object):
-
- ikey = target, (len(with) + 1)
- byname = implied.get(ikey)
- if not byname:
- byname = implied[ikey] = {}
-
- bywith = byname.get(name)
- if not bywith:
- bywith = byname[name] = {}
-
-
- rkey = ikey, name, with # The full key has all 4
- if (with not in bywith
- or
- (rkey not in registered or registered[rkey].extends(provided))
- ):
- # This is either a new entry or it is an entry for a more
- # general interface that is closer provided than what we had
- # before
- registered[rkey] = provided
- bywith[with] = object
-
- for b in target.__bases__:
- _add_multi_adapter(with, name, b, provided, implied,
- registered, object)
-
-def _add_named_sub_adapter(target, implied, objects):
- key = ('s', target)
- implied[key] = implied.get(key, ()) + objects
-
- for b in target.__bases__:
- _add_named_sub_adapter(b, implied, objects)
-
-def _add_multi_sub_adapter(with, target, implied, objects):
- key = 's', target, (len(with) + 1)
- bywith = implied.get(key)
- if not bywith:
- bywith = implied[key] = {}
-
- bywith[with] = bywith.get(with, ()) + objects
-
- for b in target.__bases__:
- _add_multi_sub_adapter(with, b, implied, objects)
=== removed file 'lib/zope/interface/adapter.txt'
--- lib/zope/interface/adapter.txt 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/adapter.txt 1970-01-01 00:00:00 +0000
@@ -1,514 +0,0 @@
-================
-Adapter Registry
-================
-
-Adapter registries provide a way to register objects that depend on
-one or more interface specifications and provide (perhaps indirectly)
-some interface. In addition, the registrations have names. (You can
-think of the names as qualifiers of the provided interfaces.)
-
-The term "interface specification" refers both to interfaces and to
-interface declarations, such as declarations of interfaces implemented
-by a class.
-
-
-Single Adapters
-===============
-
-Let's look at a simple example, using a single required specification::
-
- >>> from zope.interface.adapter import AdapterRegistry
- >>> import zope.interface
-
- >>> class IR1(zope.interface.Interface):
- ... pass
- >>> class IP1(zope.interface.Interface):
- ... pass
- >>> class IP2(IP1):
- ... pass
-
- >>> registry = AdapterRegistry()
-
-We'll register an object that depends on IR1 and "provides" IP2::
-
- >>> registry.register([IR1], IP2, '', 12)
-
-Given the registration, we can look it up again::
-
- >>> registry.lookup([IR1], IP2, '')
- 12
-
-Note that we used an integer in the example. In real applications,
-one would use some objects that actually depend on or provide
-interfaces. The registry doesn't care about what gets registered, so
-we'll use integers and strings to keep the examples simple. There is
-one exception. Registering a value of None unregisters any
-previously-registered value.
-
-If an object depends on a specification, it can be looked up with a
-specification that extends the specification that it depends on::
-
- >>> class IR2(IR1):
- ... pass
- >>> registry.lookup([IR2], IP2, '')
- 12
-
-We can use a class implementation specification to look up the object::
-
- >>> class C2:
- ... zope.interface.implements(IR2)
-
- >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
- 12
-
-
-and it can be looked up for interfaces that its provided interface
-extends::
-
- >>> registry.lookup([IR1], IP1, '')
- 12
- >>> registry.lookup([IR2], IP1, '')
- 12
-
-But if you require a specification that doesn't extend the specification the
-object depends on, you won't get anything::
-
- >>> registry.lookup([zope.interface.Interface], IP1, '')
-
-By the way, you can pass a default value to lookup::
-
- >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
- 42
-
-If you try to get an interface the object doesn't provide, you also
-won't get anything::
-
- >>> class IP3(IP2):
- ... pass
- >>> registry.lookup([IR1], IP3, '')
-
-You also won't get anything if you use the wrong name::
-
- >>> registry.lookup([IR1], IP1, 'bob')
- >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
- >>> registry.lookup([IR1], IP1, 'bob')
- "Bob's 12"
-
-You can leave the name off when doing a lookup::
-
- >>> registry.lookup([IR1], IP1)
- 12
-
-If we register an object that provides IP1::
-
- >>> registry.register([IR1], IP1, '', 11)
-
-then that object will be prefered over O(12)::
-
- >>> registry.lookup([IR1], IP1, '')
- 11
-
-Also, if we register an object for IR2, then that will be prefered
-when using IR2::
-
- >>> registry.register([IR2], IP1, '', 21)
- >>> registry.lookup([IR2], IP1, '')
- 21
-
-lookup1
--------
-
-Lookup of single adapters is common enough that there is a specialized
-version of lookup that takes a single required interface::
-
- >>> registry.lookup1(IR2, IP1, '')
- 21
- >>> registry.lookup1(IR2, IP1)
- 21
-
-Actual Adaptation
------------------
-
-The adapter registry is intended to support adaptation, where one
-object that implements an interface is adapted to another object that
-supports a different interface. The adapter registry supports the
-computation of adapters. In this case, we have to register adapter
-factories::
-
- >>> class IR(zope.interface.Interface):
- ... pass
-
- >>> class X:
- ... zope.interface.implements(IR)
-
- >>> class Y:
- ... zope.interface.implements(IP1)
- ... def __init__(self, context):
- ... self.context = context
-
- >>> registry.register([IR], IP1, '', Y)
-
-In this case, we registered a class as the factory. Now we can call
-`queryAdapter` to get the adapted object::
-
- >>> x = X()
- >>> y = registry.queryAdapter(x, IP1)
- >>> y.__class__.__name__
- 'Y'
- >>> y.context is x
- True
-
-We can register and lookup by name too::
-
- >>> class Y2(Y):
- ... pass
-
- >>> registry.register([IR], IP1, 'bob', Y2)
- >>> y = registry.queryAdapter(x, IP1, 'bob')
- >>> y.__class__.__name__
- 'Y2'
- >>> y.context is x
- True
-
-When the adapter factory produces `None`, then this is treated as if no
-adapter has been found. This allows us to prevent adaptation (when desired)
-and let the adapter factory determine whether adaptation is possible based on
-the state of the object being adapted.
-
- >>> def factory(context):
- ... if context.name == 'object':
- ... return 'adapter'
- ... return None
-
- >>> class Object(object):
- ... zope.interface.implements(IR)
- ... name = 'object'
-
- >>> registry.register([IR], IP1, 'conditional', factory)
- >>> obj = Object()
- >>> registry.queryAdapter(obj, IP1, 'conditional')
- 'adapter'
- >>> obj.name = 'no object'
- >>> registry.queryAdapter(obj, IP1, 'conditional') is None
- True
- >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
- 'default'
-
-An alternate method that provides the same function as `queryAdapter()` is
-`adapter_hook()`::
-
- >>> y = registry.adapter_hook(IP1, x)
- >>> y.__class__.__name__
- 'Y'
- >>> y.context is x
- True
- >>> y = registry.adapter_hook(IP1, x, 'bob')
- >>> y.__class__.__name__
- 'Y2'
- >>> y.context is x
- True
-
-The `adapter_hook()` simply switches the order of the object and
-interface arguments. It is used to hook into the interface call
-mechanism.
-
-
-Default Adapters
-----------------
-
-Sometimes, you want to provide an adapter that will adapt anything.
-For that, provide None as the required interface::
-
- >>> registry.register([None], IP1, '', 1)
-
-then we can use that adapter for interfaces we don't have specific
-adapters for::
-
- >>> class IQ(zope.interface.Interface):
- ... pass
- >>> registry.lookup([IQ], IP1, '')
- 1
-
-Of course, specific adapters are still used when applicable::
-
- >>> registry.lookup([IR2], IP1, '')
- 21
-
-Class adapters
---------------
-
-You can register adapters for class declarations, which is almost the
-same as registering them for a class::
-
- >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
- >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
- 'C21'
-
-Dict adapters
--------------
-
-At some point it was impossible to register dictionary-based adapters due a
-bug. Let's make sure this works now:
-
- >>> adapter = {}
- >>> registry.register((), IQ, '', adapter)
- >>> registry.lookup((), IQ, '') is adapter
- True
-
-Unregistering
--------------
-
-You can unregister by registering None, rather than an object::
-
- >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
- >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
- 21
-
-Of course, this means that None can't be registered. This is an
-exception to the statement, made earlier, that the registry doesn't
-care what gets registered.
-
-Multi-adapters
-==============
-
-You can adapt multiple specifications::
-
- >>> registry.register([IR1, IQ], IP2, '', '1q2')
- >>> registry.lookup([IR1, IQ], IP2, '')
- '1q2'
- >>> registry.lookup([IR2, IQ], IP1, '')
- '1q2'
-
- >>> class IS(zope.interface.Interface):
- ... pass
- >>> registry.lookup([IR2, IS], IP1, '')
-
- >>> class IQ2(IQ):
- ... pass
-
- >>> registry.lookup([IR2, IQ2], IP1, '')
- '1q2'
-
- >>> registry.register([IR1, IQ2], IP2, '', '1q22')
- >>> registry.lookup([IR2, IQ2], IP1, '')
- '1q22'
-
-Multi-adaptation
-----------------
-
-You can adapt multiple objects::
-
- >>> class Q:
- ... zope.interface.implements(IQ)
-
-As with single adapters, we register a factory, which is often a class::
-
- >>> class IM(zope.interface.Interface):
- ... pass
- >>> class M:
- ... zope.interface.implements(IM)
- ... def __init__(self, x, q):
- ... self.x, self.q = x, q
- >>> registry.register([IR, IQ], IM, '', M)
-
-And then we can call `queryMultiAdapter` to compute an adapter::
-
- >>> q = Q()
- >>> m = registry.queryMultiAdapter((x, q), IM)
- >>> m.__class__.__name__
- 'M'
- >>> m.x is x and m.q is q
- True
-
-and, of course, we can use names::
-
- >>> class M2(M):
- ... pass
- >>> registry.register([IR, IQ], IM, 'bob', M2)
- >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
- >>> m.__class__.__name__
- 'M2'
- >>> m.x is x and m.q is q
- True
-
-Default Adapters
-----------------
-
-As with single adapters, you can define default adapters by specifying
-None for the *first* specification::
-
- >>> registry.register([None, IQ], IP2, '', 'q2')
- >>> registry.lookup([IS, IQ], IP2, '')
- 'q2'
-
-Null Adapters
-=============
-
-You can also adapt no specification::
-
- >>> registry.register([], IP2, '', 2)
- >>> registry.lookup([], IP2, '')
- 2
- >>> registry.lookup([], IP1, '')
- 2
-
-Listing named adapters
-----------------------
-
-Adapters are named. Sometimes, it's useful to get all of the named
-adapters for given interfaces::
-
- >>> adapters = list(registry.lookupAll([IR1], IP1))
- >>> adapters.sort()
- >>> adapters
- [(u'', 11), (u'bob', "Bob's 12")]
-
-This works for multi-adapters too::
-
- >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
- >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
- >>> adapters.sort()
- >>> adapters
- [(u'', '1q22'), (u'bob', '1q2 for bob')]
-
-And even null adapters::
-
- >>> registry.register([], IP2, 'bob', 3)
- >>> adapters = list(registry.lookupAll([], IP1))
- >>> adapters.sort()
- >>> adapters
- [(u'', 2), (u'bob', 3)]
-
-Subscriptions
-=============
-
-Normally, we want to look up an object that most-closely matches a
-specification. Sometimes, we want to get all of the objects that
-match some specification. We use subscriptions for this. We
-subscribe objects against specifications and then later find all of
-the subscribed objects::
-
- >>> registry.subscribe([IR1], IP2, 'sub12 1')
- >>> registry.subscriptions([IR1], IP2)
- ['sub12 1']
-
-Note that, unlike regular adapters, subscriptions are unnamed.
-
-The order of returned subscriptions is not specified.
-
-You can have multiple subscribers for the same specification::
-
- >>> registry.subscribe([IR1], IP2, 'sub12 2')
- >>> subs = registry.subscriptions([IR1], IP2)
- >>> subs.sort()
- >>> subs
- ['sub12 1', 'sub12 2']
-
-You can register subscribers for all specifications using None::
-
- >>> registry.subscribe([None], IP1, 'sub_1')
- >>> subs = registry.subscriptions([IR2], IP1)
- >>> subs.sort()
- >>> subs
- ['sub12 1', 'sub12 2', 'sub_1']
-
-Subscriptions may be combined over multiple compatible specifications::
-
- >>> subs = registry.subscriptions([IR2], IP1)
- >>> subs.sort()
- >>> subs
- ['sub12 1', 'sub12 2', 'sub_1']
- >>> registry.subscribe([IR1], IP1, 'sub11')
- >>> subs = registry.subscriptions([IR2], IP1)
- >>> subs.sort()
- >>> subs
- ['sub11', 'sub12 1', 'sub12 2', 'sub_1']
- >>> registry.subscribe([IR2], IP2, 'sub22')
- >>> subs = registry.subscriptions([IR2], IP1)
- >>> subs.sort()
- >>> subs
- ['sub11', 'sub12 1', 'sub12 2', 'sub22', 'sub_1']
- >>> subs = registry.subscriptions([IR2], IP2)
- >>> subs.sort()
- >>> subs
- ['sub12 1', 'sub12 2', 'sub22']
-
-Subscriptions can be on multiple specifications::
-
- >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
- >>> registry.subscriptions([IR1, IQ], IP2)
- ['sub1q2']
-
-As with single subscriptions and non-subscription adapters, you can
-specify None for the first required interface, to specify a default::
-
- >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
- >>> registry.subscriptions([IS, IQ], IP2)
- ['sub_q2']
- >>> subs = registry.subscriptions([IR1, IQ], IP2)
- >>> subs.sort()
- >>> subs
- ['sub1q2', 'sub_q2']
-
-You can have subscriptions that are indepenent of any specifications::
-
- >>> registry.subscriptions([], IP1)
- []
-
- >>> registry.subscribe([], IP2, 'sub2')
- >>> registry.subscriptions([], IP1)
- ['sub2']
- >>> registry.subscribe([], IP1, 'sub1')
- >>> subs = registry.subscriptions([], IP1)
- >>> subs.sort()
- >>> subs
- ['sub1', 'sub2']
- >>> registry.subscriptions([], IP2)
- ['sub2']
-
-
-Subscription adapters
----------------------
-
-We normally register adapter factories, which then allow us to compute
-adapters, but with subscriptions, we get multiple adapters. Here's an
-example of multiple-object subscribers::
-
- >>> registry.subscribe([IR, IQ], IM, M)
- >>> registry.subscribe([IR, IQ], IM, M2)
-
- >>> subscribers = registry.subscribers((x, q), IM)
- >>> len(subscribers)
- 2
- >>> class_names = [s.__class__.__name__ for s in subscribers]
- >>> class_names.sort()
- >>> class_names
- ['M', 'M2']
- >>> [(s.x is x and s.q is q) for s in subscribers]
- [True, True]
-
-adapter factory subcribers can't return None values
-
- >>> def M3(x, y):
- ... return None
-
- >>> registry.subscribe([IR, IQ], IM, M3)
- >>> subscribers = registry.subscribers((x, q), IM)
- >>> len(subscribers)
- 2
-
-Handlers
---------
-
-A handler is a subscriber factory that doesn't produce any normal
-output. It returns None. A handler is unlike adapters in that it does
-all of its work when the factory is called.
-
-To register a handler, simply provide None as the provided interface::
-
- >>> def handler(event):
- ... print 'handler', event
-
- >>> registry.subscribe([IR1], None, handler)
- >>> registry.subscriptions([IR1], None) == [handler]
- True
=== removed file 'lib/zope/interface/advice.py'
--- lib/zope/interface/advice.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/advice.py 1970-01-01 00:00:00 +0000
@@ -1,192 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Class advice.
-
-This module was adapted from 'protocols.advice', part of the Python
-Enterprise Application Kit (PEAK). Please notify the PEAK authors
-(pje@xxxxxxxxxxxxxxxxx and tsarna@xxxxxxxxx) if bugs are found or
-Zope-specific changes are required, so that the PEAK version of this module
-can be kept in sync.
-
-PEAK is a Python application framework that interoperates with (but does
-not require) Zope 3 and Twisted. It provides tools for manipulating UML
-models, object-relational persistence, aspect-oriented programming, and more.
-Visit the PEAK home page at http://peak.telecommunity.com for more information.
-
-$Id: advice.py 25177 2004-06-02 13:17:31Z jim $
-"""
-
-from types import ClassType, FunctionType
-import sys
-
-def getFrameInfo(frame):
- """Return (kind,module,locals,globals) for a frame
-
- 'kind' is one of "exec", "module", "class", "function call", or "unknown".
- """
-
- f_locals = frame.f_locals
- f_globals = frame.f_globals
-
- sameNamespace = f_locals is f_globals
- hasModule = '__module__' in f_locals
- hasName = '__name__' in f_globals
-
- sameName = hasModule and hasName
- sameName = sameName and f_globals['__name__']==f_locals['__module__']
-
- module = hasName and sys.modules.get(f_globals['__name__']) or None
-
- namespaceIsModule = module and module.__dict__ is f_globals
-
- if not namespaceIsModule:
- # some kind of funky exec
- kind = "exec"
- elif sameNamespace and not hasModule:
- kind = "module"
- elif sameName and not sameNamespace:
- kind = "class"
- elif not sameNamespace:
- kind = "function call"
- else:
- # How can you have f_locals is f_globals, and have '__module__' set?
- # This is probably module-level code, but with a '__module__' variable.
- kind = "unknown"
- return kind, module, f_locals, f_globals
-
-
-def addClassAdvisor(callback, depth=2):
- """Set up 'callback' to be passed the containing class upon creation
-
- This function is designed to be called by an "advising" function executed
- in a class suite. The "advising" function supplies a callback that it
- wishes to have executed when the containing class is created. The
- callback will be given one argument: the newly created containing class.
- The return value of the callback will be used in place of the class, so
- the callback should return the input if it does not wish to replace the
- class.
-
- The optional 'depth' argument to this function determines the number of
- frames between this function and the targeted class suite. 'depth'
- defaults to 2, since this skips this function's frame and one calling
- function frame. If you use this function from a function called directly
- in the class suite, the default will be correct, otherwise you will need
- to determine the correct depth yourself.
-
- This function works by installing a special class factory function in
- place of the '__metaclass__' of the containing class. Therefore, only
- callbacks *after* the last '__metaclass__' assignment in the containing
- class will be executed. Be sure that classes using "advising" functions
- declare any '__metaclass__' *first*, to ensure all callbacks are run."""
-
- frame = sys._getframe(depth)
- kind, module, caller_locals, caller_globals = getFrameInfo(frame)
-
- # This causes a problem when zope interfaces are used from doctest.
- # In these cases, kind == "exec".
- #
- #if kind != "class":
- # raise SyntaxError(
- # "Advice must be in the body of a class statement"
- # )
-
- previousMetaclass = caller_locals.get('__metaclass__')
- defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
-
-
- def advise(name, bases, cdict):
-
- if '__metaclass__' in cdict:
- del cdict['__metaclass__']
-
- if previousMetaclass is None:
- if bases:
- # find best metaclass or use global __metaclass__ if no bases
- meta = determineMetaclass(bases)
- else:
- meta = defaultMetaclass
-
- elif isClassAdvisor(previousMetaclass):
- # special case: we can't compute the "true" metaclass here,
- # so we need to invoke the previous metaclass and let it
- # figure it out for us (and apply its own advice in the process)
- meta = previousMetaclass
-
- else:
- meta = determineMetaclass(bases, previousMetaclass)
-
- newClass = meta(name,bases,cdict)
-
- # this lets the callback replace the class completely, if it wants to
- return callback(newClass)
-
- # introspection data only, not used by inner function
- advise.previousMetaclass = previousMetaclass
- advise.callback = callback
-
- # install the advisor
- caller_locals['__metaclass__'] = advise
-
-
-def isClassAdvisor(ob):
- """True if 'ob' is a class advisor function"""
- return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass')
-
-
-def determineMetaclass(bases, explicit_mc=None):
- """Determine metaclass from 1+ bases and optional explicit __metaclass__"""
-
- meta = [getattr(b,'__class__',type(b)) for b in bases]
-
- if explicit_mc is not None:
- # The explicit metaclass needs to be verified for compatibility
- # as well, and allowed to resolve the incompatible bases, if any
- meta.append(explicit_mc)
-
- if len(meta)==1:
- # easy case
- return meta[0]
-
- candidates = minimalBases(meta) # minimal set of metaclasses
-
- if not candidates:
- # they're all "classic" classes
- return ClassType
-
- elif len(candidates)>1:
- # We could auto-combine, but for now we won't...
- raise TypeError("Incompatible metatypes",bases)
-
- # Just one, return it
- return candidates[0]
-
-
-def minimalBases(classes):
- """Reduce a list of base classes to its ordered minimum equivalent"""
-
- classes = [c for c in classes if c is not ClassType]
- candidates = []
-
- for m in classes:
- for n in classes:
- if issubclass(n,m) and m is not n:
- break
- else:
- # m has no subclasses in 'classes'
- if m in candidates:
- candidates.remove(m) # ensure that we're later in the list
- candidates.append(m)
-
- return candidates
-
=== removed directory 'lib/zope/interface/common'
=== removed file 'lib/zope/interface/common/__init__.py'
--- lib/zope/interface/common/__init__.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-#
-# This file is necessary to make this directory a package.
=== removed file 'lib/zope/interface/common/idatetime.py'
--- lib/zope/interface/common/idatetime.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/idatetime.py 1970-01-01 00:00:00 +0000
@@ -1,577 +0,0 @@
-##############################################################################
-# Copyright (c) 2002 Zope Corporation 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.
-##############################################################################
-"""Datetime interfaces.
-
-This module is called idatetime because if it were called datetime the import
-of the real datetime would fail.
-
-$Id: idatetime.py 25177 2004-06-02 13:17:31Z jim $
-"""
-
-from zope.interface import Interface, Attribute
-from zope.interface import classImplements, directlyProvides
-
-from datetime import timedelta, date, datetime, time, tzinfo
-
-
-class ITimeDeltaClass(Interface):
- """This is the timedelta class interface."""
-
- min = Attribute("The most negative timedelta object")
-
- max = Attribute("The most positive timedelta object")
-
- resolution = Attribute(
- "The smallest difference between non-equal timedelta objects")
-
-
-class ITimeDelta(ITimeDeltaClass):
- """Represent the difference between two datetime objects.
-
- Supported operators:
-
- - add, subtract timedelta
- - unary plus, minus, abs
- - compare to timedelta
- - multiply, divide by int/long
-
- In addition, datetime supports subtraction of two datetime objects
- returning a timedelta, and addition or subtraction of a datetime
- and a timedelta giving a datetime.
-
- Representation: (days, seconds, microseconds).
- """
-
- days = Attribute("Days between -999999999 and 999999999 inclusive")
-
- seconds = Attribute("Seconds between 0 and 86399 inclusive")
-
- microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
-
-
-class IDateClass(Interface):
- """This is the date class interface."""
-
- min = Attribute("The earliest representable date")
-
- max = Attribute("The latest representable date")
-
- resolution = Attribute(
- "The smallest difference between non-equal date objects")
-
- def today():
- """Return the current local time.
-
- This is equivalent to date.fromtimestamp(time.time())"""
-
- def fromtimestamp(timestamp):
- """Return the local date from a POSIX timestamp (like time.time())
-
- This may raise ValueError, if the timestamp is out of the range of
- values supported by the platform C localtime() function. It's common
- for this to be restricted to years from 1970 through 2038. Note that
- on non-POSIX systems that include leap seconds in their notion of a
- timestamp, leap seconds are ignored by fromtimestamp().
- """
-
- def fromordinal(ordinal):
- """Return the date corresponding to the proleptic Gregorian ordinal.
-
- January 1 of year 1 has ordinal 1. ValueError is raised unless
- 1 <= ordinal <= date.max.toordinal().
- For any date d, date.fromordinal(d.toordinal()) == d.
- """
-
-
-class IDate(IDateClass):
- """Represents a date (year, month and day) in an idealized calendar.
-
- Operators:
-
- __repr__, __str__
- __cmp__, __hash__
- __add__, __radd__, __sub__ (add/radd only with timedelta arg)
- """
-
- year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
-
- month = Attribute("Between 1 and 12 inclusive")
-
- day = Attribute(
- "Between 1 and the number of days in the given month of the given year.")
-
- def replace(year, month, day):
- """Return a date with the same value.
-
- Except for those members given new values by whichever keyword
- arguments are specified. For example, if d == date(2002, 12, 31), then
- d.replace(day=26) == date(2000, 12, 26).
- """
-
- def timetuple():
- """Return a 9-element tuple of the form returned by time.localtime().
-
- The hours, minutes and seconds are 0, and the DST flag is -1.
- d.timetuple() is equivalent to
- (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
- date(d.year, 1, 1).toordinal() + 1, -1)
- """
-
- def toordinal():
- """Return the proleptic Gregorian ordinal of the date
-
- January 1 of year 1 has ordinal 1. For any date object d,
- date.fromordinal(d.toordinal()) == d.
- """
-
- def weekday():
- """Return the day of the week as an integer.
-
- Monday is 0 and Sunday is 6. For example,
- date(2002, 12, 4).weekday() == 2, a Wednesday.
-
- See also isoweekday().
- """
-
- def isoweekday():
- """Return the day of the week as an integer.
-
- Monday is 1 and Sunday is 7. For example,
- date(2002, 12, 4).isoweekday() == 3, a Wednesday.
-
- See also weekday(), isocalendar().
- """
-
- def isocalendar():
- """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
-
- The ISO calendar is a widely used variant of the Gregorian calendar.
- See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
- explanation.
-
- The ISO year consists of 52 or 53 full weeks, and where a week starts
- on a Monday and ends on a Sunday. The first week of an ISO year is the
- first (Gregorian) calendar week of a year containing a Thursday. This
- is called week number 1, and the ISO year of that Thursday is the same
- as its Gregorian year.
-
- For example, 2004 begins on a Thursday, so the first week of ISO year
- 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
- that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
- date(2004, 1, 4).isocalendar() == (2004, 1, 7).
- """
-
- def isoformat():
- """Return a string representing the date in ISO 8601 format.
-
- This is 'YYYY-MM-DD'.
- For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
- """
-
- def __str__():
- """For a date d, str(d) is equivalent to d.isoformat()."""
-
- def ctime():
- """Return a string representing the date.
-
- For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
- d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
- on platforms where the native C ctime() function
- (which time.ctime() invokes, but which date.ctime() does not invoke)
- conforms to the C standard.
- """
-
- def strftime(format):
- """Return a string representing the date.
-
- Controlled by an explicit format string. Format codes referring to
- hours, minutes or seconds will see 0 values.
- """
-
-
-class IDateTimeClass(Interface):
- """This is the datetime class interface."""
-
- min = Attribute("The earliest representable datetime")
-
- max = Attribute("The latest representable datetime")
-
- resolution = Attribute(
- "The smallest possible difference between non-equal datetime objects")
-
- def today():
- """Return the current local datetime, with tzinfo None.
-
- This is equivalent to datetime.fromtimestamp(time.time()).
- See also now(), fromtimestamp().
- """
-
- def now(tz=None):
- """Return the current local date and time.
-
- If optional argument tz is None or not specified, this is like today(),
- but, if possible, supplies more precision than can be gotten from going
- through a time.time() timestamp (for example, this may be possible on
- platforms supplying the C gettimeofday() function).
-
- Else tz must be an instance of a class tzinfo subclass, and the current
- date and time are converted to tz's time zone. In this case the result
- is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
-
- See also today(), utcnow().
- """
-
- def utcnow():
- """Return the current UTC date and time, with tzinfo None.
-
- This is like now(), but returns the current UTC date and time, as a
- naive datetime object.
-
- See also now().
- """
-
- def fromtimestamp(timestamp, tz=None):
- """Return the local date and time corresponding to the POSIX timestamp.
-
- Same as is returned by time.time(). If optional argument tz is None or
- not specified, the timestamp is converted to the platform's local date
- and time, and the returned datetime object is naive.
-
- Else tz must be an instance of a class tzinfo subclass, and the
- timestamp is converted to tz's time zone. In this case the result is
- equivalent to
- tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
-
- fromtimestamp() may raise ValueError, if the timestamp is out of the
- range of values supported by the platform C localtime() or gmtime()
- functions. It's common for this to be restricted to years in 1970
- through 2038. Note that on non-POSIX systems that include leap seconds
- in their notion of a timestamp, leap seconds are ignored by
- fromtimestamp(), and then it's possible to have two timestamps
- differing by a second that yield identical datetime objects.
-
- See also utcfromtimestamp().
- """
-
- def utcfromtimestamp(timestamp):
- """Return the UTC datetime from the POSIX timestamp with tzinfo None.
-
- This may raise ValueError, if the timestamp is out of the range of
- values supported by the platform C gmtime() function. It's common for
- this to be restricted to years in 1970 through 2038.
-
- See also fromtimestamp().
- """
-
- def fromordinal(ordinal):
- """Return the datetime from the proleptic Gregorian ordinal.
-
- January 1 of year 1 has ordinal 1. ValueError is raised unless
- 1 <= ordinal <= datetime.max.toordinal().
- The hour, minute, second and microsecond of the result are all 0, and
- tzinfo is None.
- """
-
- def combine(date, time):
- """Return a new datetime object.
-
- Its date members are equal to the given date object's, and whose time
- and tzinfo members are equal to the given time object's. For any
- datetime object d, d == datetime.combine(d.date(), d.timetz()).
- If date is a datetime object, its time and tzinfo members are ignored.
- """
-
-
-class IDateTime(IDate, IDateTimeClass):
- """Object contains all the information from a date object and a time object.
- """
-
- year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
-
- month = Attribute("Month between 1 and 12 inclusive")
-
- day = Attribute(
- "Day between 1 and the number of days in the given month of the year")
-
- hour = Attribute("Hour in range(24)")
-
- minute = Attribute("Minute in range(60)")
-
- second = Attribute("Second in range(60)")
-
- microsecond = Attribute("Microsecond in range(1000000)")
-
- tzinfo = Attribute(
- """The object passed as the tzinfo argument to the datetime constructor
- or None if none was passed""")
-
- def date():
- """Return date object with same year, month and day."""
-
- def time():
- """Return time object with same hour, minute, second, microsecond.
-
- tzinfo is None. See also method timetz().
- """
-
- def timetz():
- """Return time object with same hour, minute, second, microsecond,
- and tzinfo.
-
- See also method time().
- """
-
- def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
- """Return a datetime with the same members, except for those members
- given new values by whichever keyword arguments are specified.
-
- Note that tzinfo=None can be specified to create a naive datetime from
- an aware datetime with no conversion of date and time members.
- """
-
- def astimezone(tz):
- """Return a datetime object with new tzinfo member tz, adjusting the
- date and time members so the result is the same UTC time as self, but
- in tz's local time.
-
- tz must be an instance of a tzinfo subclass, and its utcoffset() and
- dst() methods must not return None. self must be aware (self.tzinfo
- must not be None, and self.utcoffset() must not return None).
-
- If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
- adjustment of date or time members is performed. Else the result is
- local time in time zone tz, representing the same UTC time as self:
- after astz = dt.astimezone(tz), astz - astz.utcoffset()
- will usually have the same date and time members as dt - dt.utcoffset().
- The discussion of class tzinfo explains the cases at Daylight Saving
- Time transition boundaries where this cannot be achieved (an issue only
- if tz models both standard and daylight time).
-
- If you merely want to attach a time zone object tz to a datetime dt
- without adjustment of date and time members, use dt.replace(tzinfo=tz).
- If you merely want to remove the time zone object from an aware
- datetime dt without conversion of date and time members, use
- dt.replace(tzinfo=None).
-
- Note that the default tzinfo.fromutc() method can be overridden in a
- tzinfo subclass to effect the result returned by astimezone().
- """
-
- def utcoffset():
- """Return the timezone offset in minutes east of UTC (negative west of
- UTC)."""
-
- def dst():
- """Return 0 if DST is not in effect, or the DST offset (in minutes
- eastward) if DST is in effect.
- """
-
- def tzname():
- """Return the timezone name."""
-
- def timetuple():
- """Return a 9-element tuple of the form returned by time.localtime()."""
-
- def utctimetuple():
- """Return UTC time tuple compatilble with time.gmtimr()."""
-
- def toordinal():
- """Return the proleptic Gregorian ordinal of the date.
-
- The same as self.date().toordinal().
- """
-
- def weekday():
- """Return the day of the week as an integer.
-
- Monday is 0 and Sunday is 6. The same as self.date().weekday().
- See also isoweekday().
- """
-
- def isoweekday():
- """Return the day of the week as an integer.
-
- Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
- See also weekday(), isocalendar().
- """
-
- def isocalendar():
- """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
-
- The same as self.date().isocalendar().
- """
-
- def isoformat(sep='T'):
- """Return a string representing the date and time in ISO 8601 format.
-
- YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
-
- If utcoffset() does not return None, a 6-character string is appended,
- giving the UTC offset in (signed) hours and minutes:
-
- YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
- if microsecond is 0.
-
- The optional argument sep (default 'T') is a one-character separator,
- placed between the date and time portions of the result.
- """
-
- def __str__():
- """For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
- """
-
- def ctime():
- """Return a string representing the date and time.
-
- datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
- d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
- platforms where the native C ctime() function (which time.ctime()
- invokes, but which datetime.ctime() does not invoke) conforms to the
- C standard.
- """
-
- def strftime(format):
- """Return a string representing the date and time.
-
- This is controlled by an explicit format string.
- """
-
-
-class ITimeClass(Interface):
- """This is the time class interface."""
-
- min = Attribute("The earliest representable time")
-
- max = Attribute("The latest representable time")
-
- resolution = Attribute(
- "The smallest possible difference between non-equal time objects")
-
-
-class ITime(ITimeClass):
- """Represent time with time zone.
-
- Operators:
-
- __repr__, __str__
- __cmp__, __hash__
- """
-
- hour = Attribute("Hour in range(24)")
-
- minute = Attribute("Minute in range(60)")
-
- second = Attribute("Second in range(60)")
-
- microsecond = Attribute("Microsecond in range(1000000)")
-
- tzinfo = Attribute(
- """The object passed as the tzinfo argument to the time constructor
- or None if none was passed.""")
-
- def replace(hour, minute, second, microsecond, tzinfo):
- """Return a time with the same value.
-
- Except for those members given new values by whichever keyword
- arguments are specified. Note that tzinfo=None can be specified
- to create a naive time from an aware time, without conversion of the
- time members.
- """
-
- def isoformat():
- """Return a string representing the time in ISO 8601 format.
-
- That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
- If utcoffset() does not return None, a 6-character string is appended,
- giving the UTC offset in (signed) hours and minutes:
- HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
- """
-
- def __str__():
- """For a time t, str(t) is equivalent to t.isoformat()."""
-
- def strftime(format):
- """Return a string representing the time.
-
- This is controlled by an explicit format string.
- """
-
- def utcoffset():
- """Return the timezone offset in minutes east of UTC (negative west of
- UTC).
-
- If tzinfo is None, returns None, else returns
- self.tzinfo.utcoffset(None), and raises an exception if the latter
- doesn't return None or a timedelta object representing a whole number
- of minutes with magnitude less than one day.
- """
-
- def dst():
- """Return 0 if DST is not in effect, or the DST offset (in minutes
- eastward) if DST is in effect.
-
- If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
- and raises an exception if the latter doesn't return None, or a
- timedelta object representing a whole number of minutes with
- magnitude less than one day.
- """
-
- def tzname():
- """Return the timezone name.
-
- If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
- or raises an exception if the latter doesn't return None or a string
- object.
- """
-
-
-class ITZInfo(Interface):
- """Time zone info class.
- """
-
- def utcoffset(dt):
- """Return offset of local time from UTC, in minutes east of UTC.
-
- If local time is west of UTC, this should be negative.
- Note that this is intended to be the total offset from UTC;
- for example, if a tzinfo object represents both time zone and DST
- adjustments, utcoffset() should return their sum. If the UTC offset
- isn't known, return None. Else the value returned must be a timedelta
- object specifying a whole number of minutes in the range -1439 to 1439
- inclusive (1440 = 24*60; the magnitude of the offset must be less
- than one day).
- """
-
- def dst(dt):
- """Return the daylight saving time (DST) adjustment, in minutes east
- of UTC, or None if DST information isn't known.
- """
-
- def tzname(dt):
- """Return the time zone name corresponding to the datetime object as
- a string.
- """
-
- def fromutc(dt):
- """Return an equivalent datetime in self's local time."""
-
-
-classImplements(timedelta, ITimeDelta)
-classImplements(date, IDate)
-classImplements(datetime, IDateTime)
-classImplements(time, ITime)
-classImplements(tzinfo, ITZInfo)
-
-## directlyProvides(timedelta, ITimeDeltaClass)
-## directlyProvides(date, IDateClass)
-## directlyProvides(datetime, IDateTimeClass)
-## directlyProvides(time, ITimeClass)
=== removed file 'lib/zope/interface/common/interfaces.py'
--- lib/zope/interface/common/interfaces.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/interfaces.py 1970-01-01 00:00:00 +0000
@@ -1,98 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Interfaces for standard python exceptions
-
-$Id: interfaces.py 25177 2004-06-02 13:17:31Z jim $
-"""
-from zope.interface import Interface
-from zope.interface import classImplements
-
-class IException(Interface): pass
-class IStandardError(IException): pass
-class IWarning(IException): pass
-class ISyntaxError(IStandardError): pass
-class ILookupError(IStandardError): pass
-class IValueError(IStandardError): pass
-class IRuntimeError(IStandardError): pass
-class IArithmeticError(IStandardError): pass
-class IAssertionError(IStandardError): pass
-class IAttributeError(IStandardError): pass
-class IDeprecationWarning(IWarning): pass
-class IEOFError(IStandardError): pass
-class IEnvironmentError(IStandardError): pass
-class IFloatingPointError(IArithmeticError): pass
-class IIOError(IEnvironmentError): pass
-class IImportError(IStandardError): pass
-class IIndentationError(ISyntaxError): pass
-class IIndexError(ILookupError): pass
-class IKeyError(ILookupError): pass
-class IKeyboardInterrupt(IStandardError): pass
-class IMemoryError(IStandardError): pass
-class INameError(IStandardError): pass
-class INotImplementedError(IRuntimeError): pass
-class IOSError(IEnvironmentError): pass
-class IOverflowError(IArithmeticError): pass
-class IOverflowWarning(IWarning): pass
-class IReferenceError(IStandardError): pass
-class IRuntimeWarning(IWarning): pass
-class IStopIteration(IException): pass
-class ISyntaxWarning(IWarning): pass
-class ISystemError(IStandardError): pass
-class ISystemExit(IException): pass
-class ITabError(IIndentationError): pass
-class ITypeError(IStandardError): pass
-class IUnboundLocalError(INameError): pass
-class IUnicodeError(IValueError): pass
-class IUserWarning(IWarning): pass
-class IZeroDivisionError(IArithmeticError): pass
-
-classImplements(ArithmeticError, IArithmeticError)
-classImplements(AssertionError, IAssertionError)
-classImplements(AttributeError, IAttributeError)
-classImplements(DeprecationWarning, IDeprecationWarning)
-classImplements(EnvironmentError, IEnvironmentError)
-classImplements(EOFError, IEOFError)
-classImplements(Exception, IException)
-classImplements(FloatingPointError, IFloatingPointError)
-classImplements(ImportError, IImportError)
-classImplements(IndentationError, IIndentationError)
-classImplements(IndexError, IIndexError)
-classImplements(IOError, IIOError)
-classImplements(KeyboardInterrupt, IKeyboardInterrupt)
-classImplements(KeyError, IKeyError)
-classImplements(LookupError, ILookupError)
-classImplements(MemoryError, IMemoryError)
-classImplements(NameError, INameError)
-classImplements(NotImplementedError, INotImplementedError)
-classImplements(OSError, IOSError)
-classImplements(OverflowError, IOverflowError)
-classImplements(OverflowWarning, IOverflowWarning)
-classImplements(ReferenceError, IReferenceError)
-classImplements(RuntimeError, IRuntimeError)
-classImplements(RuntimeWarning, IRuntimeWarning)
-classImplements(StandardError, IStandardError)
-classImplements(StopIteration, IStopIteration)
-classImplements(SyntaxError, ISyntaxError)
-classImplements(SyntaxWarning, ISyntaxWarning)
-classImplements(SystemError, ISystemError)
-classImplements(SystemExit, ISystemExit)
-classImplements(TabError, ITabError)
-classImplements(TypeError, ITypeError)
-classImplements(UnboundLocalError, IUnboundLocalError)
-classImplements(UnicodeError, IUnicodeError)
-classImplements(UserWarning, IUserWarning)
-classImplements(ValueError, IValueError)
-classImplements(Warning, IWarning)
-classImplements(ZeroDivisionError, IZeroDivisionError)
-
=== removed file 'lib/zope/interface/common/mapping.py'
--- lib/zope/interface/common/mapping.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/mapping.py 1970-01-01 00:00:00 +0000
@@ -1,127 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Mapping Interfaces
-
-$Id: mapping.py 29359 2005-03-01 15:45:04Z poster $
-"""
-from zope.interface import Interface
-
-class IItemMapping(Interface):
- """Simplest readable mapping object
- """
-
- def __getitem__(key):
- """Get a value for a key
-
- A KeyError is raised if there is no value for the key.
- """
-
-
-class IReadMapping(IItemMapping):
- """Basic mapping interface
- """
-
- def get(key, default=None):
- """Get a value for a key
-
- The default is returned if there is no value for the key.
- """
-
- def __contains__(key):
- """Tell if a key exists in the mapping."""
-
-
-class IWriteMapping(Interface):
- """Mapping methods for changing data"""
-
- def __delitem__(key):
- """Delete a value from the mapping using the key."""
-
- def __setitem__(key, value):
- """Set a new item in the mapping."""
-
-
-class IEnumerableMapping(IReadMapping):
- """Mapping objects whose items can be enumerated.
- """
-
- def keys():
- """Return the keys of the mapping object.
- """
-
- def __iter__():
- """Return an iterator for the keys of the mapping object.
- """
-
- def values():
- """Return the values of the mapping object.
- """
-
- def items():
- """Return the items of the mapping object.
- """
-
- def __len__():
- """Return the number of items.
- """
-
-class IMapping(IWriteMapping, IEnumerableMapping):
- ''' Simple mapping interface '''
-
-class IIterableMapping(IEnumerableMapping):
-
- def iterkeys():
- "iterate over keys; equivalent to __iter__"
-
- def itervalues():
- "iterate over values"
-
- def iteritems():
- "iterate over items"
-
-class IClonableMapping(Interface):
-
- def copy():
- "return copy of dict"
-
-class IExtendedReadMapping(IIterableMapping):
-
- def has_key(key):
- """Tell if a key exists in the mapping; equivalent to __contains__"""
-
-class IExtendedWriteMapping(IWriteMapping):
-
- def clear():
- "delete all items"
-
- def update(d):
- " Update D from E: for k in E.keys(): D[k] = E[k]"
-
- def setdefault(key, default=None):
- "D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
-
- def pop(k, *args):
- """remove specified key and return the corresponding value
- *args may contain a single default value, or may not be supplied.
- If key is not found, default is returned if given, otherwise
- KeyError is raised"""
-
- def popitem():
- """remove and return some (key, value) pair as a
- 2-tuple; but raise KeyError if mapping is empty"""
-
-class IFullMapping(
- IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping):
- ''' Full mapping interface ''' # IMapping included so tests for IMapping
- # succeed with IFullMapping
=== removed file 'lib/zope/interface/common/sequence.py'
--- lib/zope/interface/common/sequence.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/sequence.py 1970-01-01 00:00:00 +0000
@@ -1,152 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Sequence Interfaces
-
-$Id: sequence.py 39752 2005-10-30 20:16:09Z srichter $
-"""
-__docformat__ = 'restructuredtext'
-from zope import interface
-
-class IMinimalSequence(interface.Interface):
-
- def __getitem__(index):
- """`x.__getitem__(index)` <==> `x[index]`
-
- Declaring this interface does not specify whether `__getitem__`
- supports slice objects."""
-
- def __iter__():
- """`x.__iter__()` <==> `iter(x)`"""
-
-class IFiniteSequence(IMinimalSequence):
-
- def __len__():
- """`x.__len__()` <==> `len(x)`"""
-
-class IReadSequence(IFiniteSequence):
- """read interface shared by tuple and list"""
-
- def __contains__(item):
- """`x.__contains__(item)` <==> `item in x`"""
-
- def __lt__(other):
- """`x.__lt__(other)` <==> `x < other`"""
-
- def __le__(other):
- """`x.__le__(other)` <==> `x <= other`"""
-
- def __eq__(other):
- """`x.__eq__(other)` <==> `x == other`"""
-
- def __ne__(other):
- """`x.__ne__(other)` <==> `x != other`"""
-
- def __gt__(other):
- """`x.__gt__(other)` <==> `x > other`"""
-
- def __ge__(other):
- """`x.__ge__(other)` <==> `x >= other`"""
-
- def __add__(other):
- """`x.__add__(other)` <==> `x + other`"""
-
- def __mul__(n):
- """`x.__mul__(n)` <==> `x * n`"""
-
- def __rmul__(n):
- """`x.__rmul__(n)` <==> `n * x`"""
-
- def __getslice__(i, j):
- """`x.__getslice__(i, j)` <==> `x[i:j]`
-
- Use of negative indices is not supported.
-
- Deprecated since Python 2.0 but still a part of `UserList`.
- """
-
-class IExtendedReadSequence(IReadSequence):
- """Full read interface for lists"""
-
- def count(item):
- """Return number of occurrences of value"""
-
- def index(item, *args):
- """Return first index of value
-
- `L.index(value, [start, [stop]])` -> integer"""
-
-class IUniqueMemberWriteSequence(interface.Interface):
- """The write contract for a sequence that may enforce unique members"""
-
- def __setitem__(index, item):
- """`x.__setitem__(index, item)` <==> `x[index] = item`
-
- Declaring this interface does not specify whether `__setitem__`
- supports slice objects.
- """
-
- def __delitem__(index):
- """`x.__delitem__(index)` <==> `del x[index]`
-
- Declaring this interface does not specify whether `__delitem__`
- supports slice objects.
- """
-
- def __setslice__(i, j, other):
- """`x.__setslice__(i, j, other)` <==> `x[i:j]=other`
-
- Use of negative indices is not supported.
-
- Deprecated since Python 2.0 but still a part of `UserList`.
- """
-
- def __delslice__(i, j):
- """`x.__delslice__(i, j)` <==> `del x[i:j]`
-
- Use of negative indices is not supported.
-
- Deprecated since Python 2.0 but still a part of `UserList`.
- """
- def __iadd__(y):
- """`x.__iadd__(y)` <==> `x += y`"""
-
- def append(item):
- """Append item to end"""
-
- def insert(index, item):
- """Insert item before index"""
-
- def pop(index=-1):
- """Remove and return item at index (default last)"""
-
- def remove(item):
- """Remove first occurrence of value"""
-
- def reverse():
- """Reverse *IN PLACE*"""
-
- def sort(cmpfunc=None):
- """Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
-
- def extend(iterable):
- """Extend list by appending elements from the iterable"""
-
-class IWriteSequence(IUniqueMemberWriteSequence):
- """Full write contract for sequences"""
-
- def __imul__(n):
- """`x.__imul__(n)` <==> `x *= n`"""
-
-class ISequence(IReadSequence, IWriteSequence):
- """Full sequence contract"""
=== removed directory 'lib/zope/interface/common/tests'
=== removed file 'lib/zope/interface/common/tests/__init__.py'
--- lib/zope/interface/common/tests/__init__.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/tests/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-#
-# This file is necessary to make this directory a package.
=== removed file 'lib/zope/interface/common/tests/basemapping.py'
--- lib/zope/interface/common/tests/basemapping.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/tests/basemapping.py 1970-01-01 00:00:00 +0000
@@ -1,115 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Base Mapping tests
-
-$Id: basemapping.py 26560 2004-07-15 21:38:42Z srichter $
-"""
-from operator import __getitem__
-
-def testIReadMapping(self, inst, state, absent):
- for key in state:
- self.assertEqual(inst[key], state[key])
- self.assertEqual(inst.get(key, None), state[key])
- self.failUnless(key in inst)
-
- for key in absent:
- self.assertEqual(inst.get(key, None), None)
- self.assertEqual(inst.get(key), None)
- self.assertEqual(inst.get(key, self), self)
- self.assertRaises(KeyError, __getitem__, inst, key)
-
-
-def test_keys(self, inst, state):
- # Return the keys of the mapping object
- inst_keys = list(inst.keys()); inst_keys.sort()
- state_keys = list(state.keys()) ; state_keys.sort()
- self.assertEqual(inst_keys, state_keys)
-
-def test_iter(self, inst, state):
- # Return the keys of the mapping object
- inst_keys = list(inst); inst_keys.sort()
- state_keys = list(state.keys()) ; state_keys.sort()
- self.assertEqual(inst_keys, state_keys)
-
-def test_values(self, inst, state):
- # Return the values of the mapping object
- inst_values = list(inst.values()); inst_values.sort()
- state_values = list(state.values()) ; state_values.sort()
- self.assertEqual(inst_values, state_values)
-
-def test_items(self, inst, state):
- # Return the items of the mapping object
- inst_items = list(inst.items()); inst_items.sort()
- state_items = list(state.items()) ; state_items.sort()
- self.assertEqual(inst_items, state_items)
-
-def test___len__(self, inst, state):
- # Return the number of items
- self.assertEqual(len(inst), len(state))
-
-def testIEnumerableMapping(self, inst, state):
- test_keys(self, inst, state)
- test_items(self, inst, state)
- test_values(self, inst, state)
- test___len__(self, inst, state)
-
-
-class BaseTestIReadMapping(object):
- def testIReadMapping(self):
- inst = self._IReadMapping__sample()
- state = self._IReadMapping__stateDict()
- absent = self._IReadMapping__absentKeys()
- testIReadMapping(self, inst, state, absent)
-
-
-class BaseTestIEnumerableMapping(BaseTestIReadMapping):
- # Mapping objects whose items can be enumerated
- def test_keys(self):
- # Return the keys of the mapping object
- inst = self._IEnumerableMapping__sample()
- state = self._IEnumerableMapping__stateDict()
- test_keys(self, inst, state)
-
- def test_values(self):
- # Return the values of the mapping object
- inst = self._IEnumerableMapping__sample()
- state = self._IEnumerableMapping__stateDict()
- test_values(self, inst, state)
-
- def test_values(self):
- # Return the values of the mapping object
- inst = self._IEnumerableMapping__sample()
- state = self._IEnumerableMapping__stateDict()
- test_iter(self, inst, state)
-
- def test_items(self):
- # Return the items of the mapping object
- inst = self._IEnumerableMapping__sample()
- state = self._IEnumerableMapping__stateDict()
- test_items(self, inst, state)
-
- def test___len__(self):
- # Return the number of items
- inst = self._IEnumerableMapping__sample()
- state = self._IEnumerableMapping__stateDict()
- test___len__(self, inst, state)
-
- def _IReadMapping__stateDict(self):
- return self._IEnumerableMapping__stateDict()
-
- def _IReadMapping__sample(self):
- return self._IEnumerableMapping__sample()
-
- def _IReadMapping__absentKeys(self):
- return self._IEnumerableMapping__absentKeys()
=== removed file 'lib/zope/interface/common/tests/test_idatetime.py'
--- lib/zope/interface/common/tests/test_idatetime.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/common/tests/test_idatetime.py 1970-01-01 00:00:00 +0000
@@ -1,49 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Test for datetime interfaces
-
-$Id: test_idatetime.py 25177 2004-06-02 13:17:31Z jim $
-"""
-
-import unittest
-
-from zope.interface.verify import verifyObject, verifyClass
-from zope.interface.common.idatetime import ITimeDelta, ITimeDeltaClass
-from zope.interface.common.idatetime import IDate, IDateClass
-from zope.interface.common.idatetime import IDateTime, IDateTimeClass
-from zope.interface.common.idatetime import ITime, ITimeClass, ITZInfo
-from datetime import timedelta, date, datetime, time, tzinfo
-
-class TestDateTimeInterfaces(unittest.TestCase):
-
- def test_interfaces(self):
- verifyObject(ITimeDelta, timedelta(minutes=20))
- verifyObject(IDate, date(2000, 1, 2))
- verifyObject(IDateTime, datetime(2000, 1, 2, 10, 20))
- verifyObject(ITime, time(20, 30, 15, 1234))
- verifyObject(ITZInfo, tzinfo())
- verifyClass(ITimeDeltaClass, timedelta)
- verifyClass(IDateClass, date)
- verifyClass(IDateTimeClass, datetime)
- verifyClass(ITimeClass, time)
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestDateTimeInterfaces))
- return suite
-
-
-if __name__ == '__main__':
- unittest.main()
=== removed file 'lib/zope/interface/declarations.py'
--- lib/zope/interface/declarations.py 2008-08-29 01:47:36 +0000
+++ lib/zope/interface/declarations.py 1970-01-01 00:00:00 +0000
@@ -1,1426 +0,0 @@
-##############################################################################
-# Copyright (c) 2003 Zope Corporation 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.
-##############################################################################
-"""Implementation of interface declarations
-
-There are three flavors of declarations:
-
- - Declarations are used to simply name declared interfaces.
-
- - ImplementsDeclarations are used to express the interfaces that a
- class implements (that instances of the class provides).
-
- Implements specifications support inheriting interfaces.
-
- - ProvidesDeclarations are used to express interfaces directly
- provided by objects.
-
-
-$Id: declarations.py 40184 2005-11-16 22:42:26Z srichter $
-"""
-__docformat__ = 'restructuredtext'
-
-import sys
-import types
-import weakref
-from zope.interface.interface import InterfaceClass, Specification
-from ro import mergeOrderings, ro
-import exceptions
-from types import ClassType
-from zope.interface.advice import addClassAdvisor
-from zope.interface.exceptions import InvalidInterface
-
-# Registry of class-implementation specifications
-BuiltinImplementationSpecifications = {}
-
-class Declaration(Specification):
- """Interface declarations"""
-
- def __init__(self, *interfaces):
- Specification.__init__(self, _normalizeargs(interfaces))
-
- def changed(self):
- Specification.changed(self)
- try:
- del self._v_attrs
- except AttributeError:
- pass
-
- def __contains__(self, interface):
- """Test whether an interface is in the specification
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> int(I1 in spec)
- 0
- >>> int(I2 in spec)
- 1
- >>> int(I3 in spec)
- 1
- >>> int(I4 in spec)
- 1
- """
- return self.extends(interface) and interface in self.interfaces()
-
- def __iter__(self):
- """Return an iterator for the interfaces in the specification
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> i = iter(spec)
- >>> i.next().getName()
- 'I4'
- >>> i.next().getName()
- 'I2'
- >>> i.next().getName()
- 'I3'
- >>> list(i)
- []
- """
- return self.interfaces()
-
- def flattened(self):
- """Return an iterator of all included and extended interfaces
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> i = spec.flattened()
- >>> i.next().getName()
- 'I4'
- >>> i.next().getName()
- 'I2'
- >>> i.next().getName()
- 'I1'
- >>> i.next().getName()
- 'I3'
- >>> i.next().getName()
- 'Interface'
- >>> list(i)
- []
-
- """
- return iter(self.__iro__)
-
- def __sub__(self, other):
- """Remove interfaces from a specification
-
- Examples:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> [iface.getName() for iface in spec]
- []
- >>> spec -= I1
- >>> [iface.getName() for iface in spec]
- []
- >>> spec -= Declaration(I1, I2)
- >>> [iface.getName() for iface in spec]
- []
- >>> spec = Declaration(I2, I4)
- >>> [iface.getName() for iface in spec]
- ['I2', 'I4']
- >>> [iface.getName() for iface in spec - I4]
- ['I2']
- >>> [iface.getName() for iface in spec - I1]
- ['I4']
- >>> [iface.getName() for iface
- ... in spec - Declaration(I3, I4)]
- ['I2']
-
- """
-
- return Declaration(
- *[i for i in self.interfaces()
- if not [j for j in other.interfaces()
- if i.extends(j, 0)]
- ]
- )
-
- def __add__(self, other):
- """Add two specifications or a specification and an interface
-
- Examples:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> [iface.getName() for iface in spec]
- []
- >>> [iface.getName() for iface in spec+I1]
- ['I1']
- >>> [iface.getName() for iface in I1+spec]
- ['I1']
- >>> spec2 = spec
- >>> spec += I1
- >>> [iface.getName() for iface in spec]
- ['I1']
- >>> [iface.getName() for iface in spec2]
- []
- >>> spec2 += Declaration(I3, I4)
- >>> [iface.getName() for iface in spec2]
- ['I3', 'I4']
- >>> [iface.getName() for iface in spec+spec2]
- ['I1', 'I3', 'I4']
- >>> [iface.getName() for iface in spec2+spec]
- ['I3', 'I4', 'I1']
-
- """
-
- seen = {}
- result = []
- for i in self.interfaces():
- if i not in seen:
- seen[i] = 1
- result.append(i)
- for i in other.interfaces():
- if i not in seen:
- seen[i] = 1
- result.append(i)
-
- return Declaration(*result)
-
- __radd__ = __add__
-
- def __nonzero__(self):
- """Test whether there are any interfaces in a specification.
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> spec = Declaration(I1)
- >>> int(bool(spec))
- 1
- >>> spec = Declaration()
- >>> int(bool(spec))
- 0
- """
- return bool(self.__iro__)
-
-
-##############################################################################
-#
-# Implementation specifications
-#
-# These specify interfaces implemented by instances of classes
-
-class Implements(Declaration):
-
- # class whose specification should be used as additional base
- inherit = None
-
- # interfaces actually declared for a class
- declared = ()
-
- __name__ = '?'
-
- def __repr__(self):
- return '<implementedBy %s>' % (self.__name__)
-
-
-def implementedByFallback(cls):
- """Return the interfaces implemented for a class' instances
-
- The value returned is an IDeclaration.
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> class C1(object):
- ... implements(I2)
- >>> class C2(C1):
- ... implements(I3)
- >>> [i.getName() for i in implementedBy(C2)]
- ['I3', 'I2']
-
- Really, any object should be able to receive a successful answer, even
- an instance:
-
- >>> class Callable(object):
- ... def __call__(self):
- ... return self
-
- >>> implementedBy(Callable())
- <implementedBy zope.interface.declarations.?>
-
- Note that the name of the spec ends with a '?', because the `Callable`
- instance does not have a `__name__` attribute.
- """
- # This also manages storage of implementation specifications
-
- try:
- spec = cls.__dict__.get('__implemented__')
- except AttributeError:
-
- # we can't get the class dict. This is probably due to a
- # security proxy. If this is the case, then probably no
- # descriptor was installed for the class.
-
- # We don't want to depend directly on zope.security in
- # zope.interface, but we'll try to make reasonable
- # accommodations in an indirect way.
-
- # We'll check to see if there's an implements:
-
- spec = getattr(cls, '__implemented__', None)
- if spec is None:
- # There's no spec stred in the class. Maybe its a builtin:
- spec = BuiltinImplementationSpecifications.get(cls)
- if spec is not None:
- return spec
- return _empty
-
- if spec.__class__ == Implements:
- # we defaulted to _empty or there was a spec. Good enough.
- # Return it.
- return spec
-
- # TODO: need old style __implements__ compatibility?
- # Hm, there's an __implemented__, but it's not a spec. Must be
- # an old-style declaration. Just compute a spec for it
- return Declaration(*_normalizeargs((spec, )))
-
- if isinstance(spec, Implements):
- return spec
-
- if spec is None:
- spec = BuiltinImplementationSpecifications.get(cls)
- if spec is not None:
- return spec
-
- # TODO: need old style __implements__ compatibility?
- if spec is not None:
- # old-style __implemented__ = foo declaration
- spec = (spec, ) # tuplefy, as it might be just an int
- spec = Implements(*_normalizeargs(spec))
- spec.inherit = None # old-style implies no inherit
- del cls.__implemented__ # get rid of the old-style declaration
- else:
- try:
- bases = cls.__bases__
- except AttributeError:
- if not callable(cls):
- raise TypeError("ImplementedBy called for non-factory", cls)
- bases = ()
-
- spec = Implements(*[implementedBy(c) for c in bases])
- spec.inherit = cls
-
- spec.__name__ = (getattr(cls, '__module__', '?') or '?') + \
- '.' + (getattr(cls, '__name__', '?') or '?')
-
- try:
- cls.__implemented__ = spec
- if not hasattr(cls, '__providedBy__'):
- cls.__providedBy__ = objectSpecificationDescriptor
-
- if (isinstance(cls, DescriptorAwareMetaClasses)
- and
- '__provides__' not in cls.__dict__):
- # Make sure we get a __provides__ descriptor
- cls.__provides__ = ClassProvides(
- cls,
- getattr(cls, '__class__', type(cls)),
- )
-
- except TypeError:
- if not isinstance(cls, type):
- raise TypeError("ImplementedBy called for non-type", cls)
- BuiltinImplementationSpecifications[cls] = spec
-
- return spec
-
-implementedBy = implementedByFallback
-
-def classImplementsOnly(cls, *interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- The arguments after the class are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- replace any previous declarations.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class A(object):
- ... implements(I3)
- >>> class B(object):
- ... implements(I4)
- >>> class C(A, B):
- ... pass
- >>> classImplementsOnly(C, I1, I2)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2']
-
- Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
- whatever interfaces instances of ``A`` and ``B`` implement.
- """
- spec = implementedBy(cls)
- spec.declared = ()
- spec.inherit = None
- classImplements(cls, *interfaces)
-
-def classImplements(cls, *interfaces):
- """Declare additional interfaces implemented for instances of a class
-
- The arguments after the class are one or more interfaces or
- interface specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- are added to any interfaces previously declared.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class I5(Interface): pass
- ...
- >>> class A(object):
- ... implements(I3)
- >>> class B(object):
- ... implements(I4)
- >>> class C(A, B):
- ... pass
- >>> classImplements(C, I1, I2)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2', 'I3', 'I4']
- >>> classImplements(C, I5)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2', 'I5', 'I3', 'I4']
-
- Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever
- interfaces instances of ``A`` and ``B`` provide.
- """
-
- spec = implementedBy(cls)
- spec.declared += tuple(_normalizeargs(interfaces))
-
- # compute the bases
- bases = []
- seen = {}
- for b in spec.declared:
- if b not in seen:
- seen[b] = 1
- bases.append(b)
-
- if spec.inherit is not None:
-
- for c in spec.inherit.__bases__:
- b = implementedBy(c)
- if b not in seen:
- seen[b] = 1
- bases.append(b)
-
- spec.__bases__ = tuple(bases)
-
-def _implements_advice(cls):
- interfaces, classImplements = cls.__dict__['__implements_advice_data__']
- del cls.__implements_advice_data__
- classImplements(cls, *interfaces)
- return cls
-
-
-class implementer:
-
- 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."
- )
- spec = Implements(*self.interfaces)
- try:
- ob.__implemented__ = spec
- except AttributeError:
- raise TypeError("Can't declare implements", ob)
- return ob
-
-def _implements(name, interfaces, classImplements):
- frame = sys._getframe(2)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def. In 2.2.0 we can't
- # check for __module__ since it doesn't seem to be added to the locals
- # until later on.
- if (locals is frame.f_globals) or (
- ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
- raise TypeError(name+" can be used only from a class definition.")
-
- if '__implements_advice_data__' in locals:
- raise TypeError(name+" can be used only once in a class definition.")
-
- locals['__implements_advice_data__'] = interfaces, classImplements
- addClassAdvisor(_implements_advice, depth=3)
-
-def implements(*interfaces):
- """Declare interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) are added to any interfaces previously
- declared.
-
- Previous declarations include declarations for base classes
- unless implementsOnly was used.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplements. For example::
-
- implements(I1)
-
- is equivalent to calling::
-
- classImplements(C, I1)
-
- after the class has been created.
-
- Consider the following example::
-
-
- >>> from zope.interface import Interface
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
- instances of ``A`` and ``B`` implement.
-
- """
- _implements("implements", interfaces, classImplements)
-
-def implementsOnly(*interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- Previous declarations including declarations for base classes
- are overridden.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplementsOnly. For example::
-
- implementsOnly(I1)
-
- is equivalent to calling::
-
- classImplementsOnly(I1)
-
- after the class has been created.
-
- Consider the following example::
-
- >>> from zope.interface import Interface
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implementsOnly(IC)
-
- >>> ob = C()
- >>> int(IA1 in providedBy(ob))
- 0
- >>> int(IA2 in providedBy(ob))
- 0
- >>> int(IB in providedBy(ob))
- 0
- >>> int(IC in providedBy(ob))
- 1
-
-
- Instances of ``C`` implement ``IC``, regardless of what
- instances of ``A`` and ``B`` implement.
-
- """
- _implements("implementsOnly", interfaces, classImplementsOnly)
-
-##############################################################################
-#
-# Instance declarations
-
-class Provides(Declaration): # Really named ProvidesClass
- """Implement __provides__, the instance-specific specification
-
- When an object is pickled, we pickle the interfaces that it implements.
- """
-
- def __init__(self, cls, *interfaces):
- self.__args = (cls, ) + interfaces
- self._cls = cls
- Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
-
- def __reduce__(self):
- return Provides, self.__args
-
- __module__ = 'zope.interface'
-
- def __get__(self, inst, cls):
- """Make sure that a class __provides__ doesn't leak to an instance
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFooFactory(Interface): pass
- ...
-
- >>> class C(object):
- ... pass
-
- >>> C.__provides__ = ProvidesClass(C, IFooFactory)
- >>> [i.getName() for i in C.__provides__]
- ['IFooFactory']
- >>> getattr(C(), '__provides__', 0)
- 0
-
- """
- if inst is None and cls is self._cls:
- # We were accessed through a class, so we are the class'
- # provides spec. Just return this object, but only if we are
- # being called on the same class that we were defined for:
- return self
-
- raise AttributeError('__provides__')
-
-ProvidesClass = Provides
-
-# Registry of instance declarations
-# This is a memory optimization to allow objects to share specifications.
-InstanceDeclarations = weakref.WeakValueDictionary()
-
-def Provides(*interfaces):
- """Cache instance declarations
-
- Instance declarations are shared among instances that have the same
- declaration. The declarations are cached in a weak value dictionary.
-
- (Note that, in the examples below, we are going to make assertions about
- the size of the weakvalue dictionary. For the assertions to be
- meaningful, we need to force garbage collection to make sure garbage
- objects are, indeed, removed from the system. Depending on how Python
- is run, we may need to make multiple calls to be sure. We provide a
- collect function to help with this:
-
- >>> import gc
- >>> def collect():
- ... for i in range(4):
- ... gc.collect()
-
- )
-
- >>> collect()
- >>> before = len(InstanceDeclarations)
-
- >>> class C(object):
- ... pass
-
- >>> from zope.interface import Interface
- >>> class I(Interface):
- ... pass
-
- >>> c1 = C()
- >>> c2 = C()
-
- >>> len(InstanceDeclarations) == before
- 1
-
- >>> directlyProvides(c1, I)
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> directlyProvides(c2, I)
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> del c1
- >>> collect()
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> del c2
- >>> collect()
- >>> len(InstanceDeclarations) == before
- 1
- """
-
- spec = InstanceDeclarations.get(interfaces)
- if spec is None:
- spec = ProvidesClass(*interfaces)
- InstanceDeclarations[interfaces] = spec
-
- return spec
-Provides.__safe_for_unpickling__ = True
-
-
-DescriptorAwareMetaClasses = ClassType, type
-def directlyProvides(object, *interfaces):
- """Declare interfaces declared directly for an object
-
- The arguments after the object are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- replace interfaces previously declared for the object.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> directlyProvides(ob, I1, I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 1
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
- instances have been declared for instances of ``C``.
-
- To remove directly provided interfaces, use ``directlyProvidedBy`` and
- subtract the unwanted interfaces. For example:
-
- >>> directlyProvides(ob, directlyProvidedBy(ob)-I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 0
-
- removes I2 from the interfaces directly provided by ``ob``. The object,
- ``ob`` no longer directly provides ``I2``, although it might still
- provide ``I2`` if it's class implements ``I2``.
-
- To add directly provided interfaces, use ``directlyProvidedBy`` and
- include additional interfaces. For example:
-
- >>> int(I2 in providedBy(ob))
- 0
- >>> directlyProvides(ob, directlyProvidedBy(ob), I2)
-
- adds ``I2`` to the interfaces directly provided by ob::
-
- >>> int(I2 in providedBy(ob))
- 1
-
- """
-
- # We need to avoid setting this attribute on meta classes that
- # don't support descriptors.
- # We can do away with this check when we get rid of the old EC
- cls = getattr(object, '__class__', None)
- if cls is not None and getattr(cls, '__class__', None) is cls:
- # It's a meta class (well, at least it it could be an extension class)
- if not isinstance(object, DescriptorAwareMetaClasses):
- raise TypeError("Attempt to make an interface declaration on a "
- "non-descriptor-aware class")
-
- interfaces = _normalizeargs(interfaces)
- if cls is None:
- cls = type(object)
-
- issub = False
- for damc in DescriptorAwareMetaClasses:
- if issubclass(cls, damc):
- issub = True
- break
- if issub:
- # we have a class or type. We'll use a special descriptor
- # that provides some extra caching
- object.__provides__ = ClassProvides(object, cls, *interfaces)
- else:
- object.__provides__ = Provides(cls, *interfaces)
-
-
-def alsoProvides(object, *interfaces):
- """Declare interfaces declared directly for an object
-
- The arguments after the object are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications) are
- added to the interfaces previously declared for the object.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> directlyProvides(ob, I1)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 0
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- >>> alsoProvides(ob, I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 1
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
- instances have been declared for instances of ``C``. Notice that the
- alsoProvides just extends the provided interfaces.
- """
- directlyProvides(object, directlyProvidedBy(object), *interfaces)
-
-def noLongerProvides(object, interface):
- """
- This removes a directly provided interface from an object.
- Consider the following two interfaces:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
-
- ``I1`` is provided through the class, ``I2`` is directly provided
- by the object:
-
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> alsoProvides(c, I2)
- >>> I2.providedBy(c)
- True
-
- Remove I2 from c again:
-
- >>> noLongerProvides(c, I2)
- >>> I2.providedBy(c)
- False
-
- Removing an interface that is provided through the class is not possible:
-
- >>> noLongerProvides(c, I1)
- Traceback (most recent call last):
- ...
- ValueError: Can only remove directly provided interfaces.
-
- """
- directlyProvides(object, directlyProvidedBy(object)-interface)
- if interface.providedBy(object):
- raise ValueError("Can only remove directly provided interfaces.")
-
-class ClassProvidesBasePy(object):
-
- def __get__(self, inst, cls):
- if cls is self._cls:
- # We only work if called on the class we were defined for
-
- if inst is None:
- # We were accessed through a class, so we are the class'
- # provides spec. Just return this object as is:
- return self
-
- return self._implements
-
- raise AttributeError('__provides__')
-
-ClassProvidesBase = ClassProvidesBasePy
-
-# Try to get C base:
-try:
- import _zope_interface_coptimizations
-except ImportError:
- pass
-else:
- from _zope_interface_coptimizations import ClassProvidesBase
-
-
-class ClassProvides(Declaration, ClassProvidesBase):
- """Special descriptor for class __provides__
-
- The descriptor caches the implementedBy info, so that
- we can get declarations for objects without instance-specific
- interfaces a bit quicker.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFooFactory(Interface):
- ... pass
- >>> class IFoo(Interface):
- ... pass
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__provides__]
- ['IFooFactory']
-
- >>> [i.getName() for i in C().__provides__]
- ['IFoo']
- """
-
- def __init__(self, cls, metacls, *interfaces):
- self._cls = cls
- self._implements = implementedBy(cls)
- self.__args = (cls, metacls, ) + interfaces
- Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
-
- def __reduce__(self):
- return self.__class__, self.__args
-
- # Copy base-class method for speed
- __get__ = ClassProvidesBase.__get__
-
-def directlyProvidedBy(object):
- """Return the interfaces directly provided by the given object
-
- The value returned is an ``IDeclaration``.
- """
- provides = getattr(object, "__provides__", None)
- if (provides is None # no spec
- or
- # We might have gotten the implements spec, as an
- # optimization. If so, it's like having only one base, that we
- # lop off to exclude class-supplied declarations:
- isinstance(provides, Implements)
- ):
- return _empty
-
- # Strip off the class part of the spec:
- return Declaration(provides.__bases__[:-1])
-
-def classProvides(*interfaces):
- """Declare interfaces provided directly by a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface specifications
- (``IDeclaration`` objects).
-
- The given interfaces (including the interfaces in the specifications)
- are used to create the class's direct-object interface specification.
- An error will be raised if the module class has an direct interface
- specification. In other words, it is an error to call this function more
- than once in a class definition.
-
- Note that the given interfaces have nothing to do with the interfaces
- implemented by instances of the class.
-
- This function is provided for convenience. It provides a more convenient
- way to call directlyProvidedByProvides for a class. For example::
-
- classProvides(I1)
-
- is equivalent to calling::
-
- directlyProvides(theclass, I1)
-
- after the class has been created.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
-
- if equivalent to:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- >>> directlyProvides(C, IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
- """
- frame = sys._getframe(1)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def
- if (locals is frame.f_globals) or ('__module__' not in locals):
- raise TypeError(name+" can be used only from a class definition.")
-
- if '__provides__' in locals:
- raise TypeError(
- "classProvides can only be used once in a class definition.")
-
- locals["__provides__"] = _normalizeargs(interfaces)
-
- addClassAdvisor(_classProvides_advice, depth=2)
-
-def _classProvides_advice(cls):
- interfaces = cls.__dict__['__provides__']
- del cls.__provides__
- directlyProvides(cls, *interfaces)
- return cls
-
-def moduleProvides(*interfaces):
- """Declare interfaces provided by a module
-
- This function is used in a module definition.
-
- The arguments are one or more interfaces or interface specifications
- (``IDeclaration`` objects).
-
- The given interfaces (including the interfaces in the specifications) are
- used to create the module's direct-object interface specification. An
- error will be raised if the module already has an interface specification.
- In other words, it is an error to call this function more than once in a
- module definition.
-
- This function is provided for convenience. It provides a more convenient
- way to call directlyProvides. For example::
-
- moduleImplements(I1)
-
- is equivalent to::
-
- directlyProvides(sys.modules[__name__], I1)
- """
- frame = sys._getframe(1)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def
- if (locals is not frame.f_globals) or ('__name__' not in locals):
- raise TypeError(
- "moduleProvides can only be used from a module definition.")
-
- if '__provides__' in locals:
- raise TypeError(
- "moduleProvides can only be used once in a module definition.")
-
- module = sys.modules[__name__]
-
- locals["__provides__"] = Provides(type(module),
- *_normalizeargs(interfaces))
-
-##############################################################################
-#
-# Declaration querying support
-
-def ObjectSpecification(direct, cls):
- """Provide object specifications
-
- These combine information for the object and for it's classes.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I31(I3): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class I5(Interface): pass
- ...
- >>> class A(object): implements(I1)
- ...
- >>> class B(object): __implemented__ = I2
- ...
- >>> class C(A, B): implements(I31)
- ...
- >>> c = C()
- >>> directlyProvides(c, I4)
- >>> [i.getName() for i in providedBy(c)]
- ['I4', 'I31', 'I1', 'I2']
- >>> [i.getName() for i in providedBy(c).flattened()]
- ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
- >>> int(I1 in providedBy(c))
- 1
- >>> int(I3 in providedBy(c))
- 0
- >>> int(providedBy(c).extends(I3))
- 1
- >>> int(providedBy(c).extends(I31))
- 1
- >>> int(providedBy(c).extends(I5))
- 0
- >>> class COnly(A, B): implementsOnly(I31)
- ...
- >>> class D(COnly): implements(I5)
- ...
- >>> c = D()
- >>> directlyProvides(c, I4)
- >>> [i.getName() for i in providedBy(c)]
- ['I4', 'I5', 'I31']
- >>> [i.getName() for i in providedBy(c).flattened()]
- ['I4', 'I5', 'I31', 'I3', 'Interface']
- >>> int(I1 in providedBy(c))
- 0
- >>> int(I3 in providedBy(c))
- 0
- >>> int(providedBy(c).extends(I3))
- 1
- >>> int(providedBy(c).extends(I1))
- 0
- >>> int(providedBy(c).extends(I31))
- 1
- >>> int(providedBy(c).extends(I5))
- 1
-
- nonzero:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface):
- ... pass
- >>> class I2(Interface):
- ... pass
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 1
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
- >>> class C(object):
- ... pass
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 0
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
- """
-
- return Provides(cls, direct)
-
-def getObjectSpecification(ob):
-
- provides = getattr(ob, '__provides__', None)
- if provides is not None:
- return provides
-
- try:
- cls = ob.__class__
- except AttributeError:
- # We can't get the class, so just consider provides
- return _empty
-
- return implementedBy(cls)
-
-def providedBy(ob):
-
- # Here we have either a special object, an old-style declaration
- # or a descriptor
-
- # Try to get __providedBy__
- try:
- r = ob.__providedBy__
- except AttributeError:
- # Not set yet. Fall back to lower-level thing that computes it
- return getObjectSpecification(ob)
-
- try:
- # We might have gotten a descriptor from an instance of a
- # class (like an ExtensionClass) that doesn't support
- # descriptors. We'll make sure we got one by trying to get
- # the only attribute, which all specs have.
- r.extends
-
- except AttributeError:
-
- # The object's class doesn't understand descriptors.
- # Sigh. We need to get an object descriptor, but we have to be
- # careful. We want to use the instance's __provides__, if
- # there is one, but only if it didn't come from the class.
-
- try:
- r = ob.__provides__
- except AttributeError:
- # No __provides__, so just fall back to implementedBy
- return implementedBy(ob.__class__)
-
- # We need to make sure we got the __provides__ from the
- # instance. We'll do this by making sure we don't get the same
- # thing from the class:
-
- try:
- cp = ob.__class__.__provides__
- except AttributeError:
- # The ob doesn't have a class or the class has no
- # provides, assume we're done:
- return r
-
- if r is cp:
- # Oops, we got the provides from the class. This means
- # the object doesn't have it's own. We should use implementedBy
- return implementedBy(ob.__class__)
-
- return r
-
-class ObjectSpecificationDescriptorPy(object):
- """Implement the `__providedBy__` attribute
-
- The `__providedBy__` attribute computes the interfaces peovided by
- an object.
- """
-
- def __get__(self, inst, cls):
- """Get an object specification for an object
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
-
- """
-
- # Get an ObjectSpecification bound to either an instance or a class,
- # depending on how we were accessed.
-
- if inst is None:
- return getObjectSpecification(cls)
-
- provides = getattr(inst, '__provides__', None)
- if provides is not None:
- return provides
-
- return implementedBy(cls)
-
-ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy
-
-##############################################################################
-
-def _normalizeargs(sequence, output = None):
- """Normalize declaration arguments
-
- Normalization arguments might contain Declarions, tuples, or single
- interfaces.
-
- Anything but individual interfaces or implements specs will be expanded.
- """
- if output is None:
- output = []
-
- cls = sequence.__class__
- if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
- output.append(sequence)
- else:
- try:
- for v in sequence:
- _normalizeargs(v, output)
- except TypeError:
- # this means we have already iterred the sequence yet the above if
- # statement is failing
- etype, val, tb = sys.exc_info()
- raise InvalidInterface(
- "object %s is not a valid interface (expected a class "
- "descending from Interface or Implements)" % sequence), None, tb
-
- return output
-
-_empty = Declaration()
-
-try:
- import _zope_interface_coptimizations
-except ImportError:
- pass
-else:
- from _zope_interface_coptimizations import implementedBy, providedBy
- from _zope_interface_coptimizations import getObjectSpecification
- from _zope_interface_coptimizations import ObjectSpecificationDescriptor
-
-objectSpecificationDescriptor = ObjectSpecificationDescriptor()
=== removed file 'lib/zope/interface/declarations.py.orig'
--- lib/zope/interface/declarations.py.orig 2008-08-29 01:47:36 +0000
+++ lib/zope/interface/declarations.py.orig 1970-01-01 00:00:00 +0000
@@ -1,1417 +0,0 @@
-##############################################################################
-# Copyright (c) 2003 Zope Corporation 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.
-##############################################################################
-"""Implementation of interface declarations
-
-There are three flavors of declarations:
-
- - Declarations are used to simply name declared interfaces.
-
- - ImplementsDeclarations are used to express the interfaces that a
- class implements (that instances of the class provides).
-
- Implements specifications support inheriting interfaces.
-
- - ProvidesDeclarations are used to express interfaces directly
- provided by objects.
-
-
-$Id: declarations.py 40184 2005-11-16 22:42:26Z srichter $
-"""
-__docformat__ = 'restructuredtext'
-
-import sys
-import types
-import weakref
-from zope.interface.interface import InterfaceClass, Specification
-from ro import mergeOrderings, ro
-import exceptions
-from types import ClassType
-from zope.interface.advice import addClassAdvisor
-
-# Registry of class-implementation specifications
-BuiltinImplementationSpecifications = {}
-
-class Declaration(Specification):
- """Interface declarations"""
-
- def __init__(self, *interfaces):
- Specification.__init__(self, _normalizeargs(interfaces))
-
- def changed(self):
- Specification.changed(self)
- try:
- del self._v_attrs
- except AttributeError:
- pass
-
- def __contains__(self, interface):
- """Test whether an interface is in the specification
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> int(I1 in spec)
- 0
- >>> int(I2 in spec)
- 1
- >>> int(I3 in spec)
- 1
- >>> int(I4 in spec)
- 1
- """
- return self.extends(interface) and interface in self.interfaces()
-
- def __iter__(self):
- """Return an iterator for the interfaces in the specification
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> i = iter(spec)
- >>> i.next().getName()
- 'I4'
- >>> i.next().getName()
- 'I2'
- >>> i.next().getName()
- 'I3'
- >>> list(i)
- []
- """
- return self.interfaces()
-
- def flattened(self):
- """Return an iterator of all included and extended interfaces
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration(I2, I3)
- >>> spec = Declaration(I4, spec)
- >>> i = spec.flattened()
- >>> i.next().getName()
- 'I4'
- >>> i.next().getName()
- 'I2'
- >>> i.next().getName()
- 'I1'
- >>> i.next().getName()
- 'I3'
- >>> i.next().getName()
- 'Interface'
- >>> list(i)
- []
-
- """
- return iter(self.__iro__)
-
- def __sub__(self, other):
- """Remove interfaces from a specification
-
- Examples:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> [iface.getName() for iface in spec]
- []
- >>> spec -= I1
- >>> [iface.getName() for iface in spec]
- []
- >>> spec -= Declaration(I1, I2)
- >>> [iface.getName() for iface in spec]
- []
- >>> spec = Declaration(I2, I4)
- >>> [iface.getName() for iface in spec]
- ['I2', 'I4']
- >>> [iface.getName() for iface in spec - I4]
- ['I2']
- >>> [iface.getName() for iface in spec - I1]
- ['I4']
- >>> [iface.getName() for iface
- ... in spec - Declaration(I3, I4)]
- ['I2']
-
- """
-
- return Declaration(
- *[i for i in self.interfaces()
- if not [j for j in other.interfaces()
- if i.extends(j, 0)]
- ]
- )
-
- def __add__(self, other):
- """Add two specifications or a specification and an interface
-
- Examples:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> [iface.getName() for iface in spec]
- []
- >>> [iface.getName() for iface in spec+I1]
- ['I1']
- >>> [iface.getName() for iface in I1+spec]
- ['I1']
- >>> spec2 = spec
- >>> spec += I1
- >>> [iface.getName() for iface in spec]
- ['I1']
- >>> [iface.getName() for iface in spec2]
- []
- >>> spec2 += Declaration(I3, I4)
- >>> [iface.getName() for iface in spec2]
- ['I3', 'I4']
- >>> [iface.getName() for iface in spec+spec2]
- ['I1', 'I3', 'I4']
- >>> [iface.getName() for iface in spec2+spec]
- ['I3', 'I4', 'I1']
-
- """
-
- seen = {}
- result = []
- for i in self.interfaces():
- if i not in seen:
- seen[i] = 1
- result.append(i)
- for i in other.interfaces():
- if i not in seen:
- seen[i] = 1
- result.append(i)
-
- return Declaration(*result)
-
- __radd__ = __add__
-
- def __nonzero__(self):
- """Test whether there are any interfaces in a specification.
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> spec = Declaration(I1)
- >>> int(bool(spec))
- 1
- >>> spec = Declaration()
- >>> int(bool(spec))
- 0
- """
- return bool(self.__iro__)
-
-
-##############################################################################
-#
-# Implementation specifications
-#
-# These specify interfaces implemented by instances of classes
-
-class Implements(Declaration):
-
- # class whose specification should be used as additional base
- inherit = None
-
- # interfaces actually declared for a class
- declared = ()
-
- __name__ = '?'
-
- def __repr__(self):
- return '<implementedBy %s>' % (self.__name__)
-
-
-def implementedByFallback(cls):
- """Return the interfaces implemented for a class' instances
-
- The value returned is an IDeclaration.
-
- for example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> class C1(object):
- ... implements(I2)
- >>> class C2(C1):
- ... implements(I3)
- >>> [i.getName() for i in implementedBy(C2)]
- ['I3', 'I2']
-
- Really, any object should be able to receive a successful answer, even
- an instance:
-
- >>> class Callable(object):
- ... def __call__(self):
- ... return self
-
- >>> implementedBy(Callable())
- <implementedBy zope.interface.declarations.?>
-
- Note that the name of the spec ends with a '?', because the `Callable`
- instance does not have a `__name__` attribute.
- """
- # This also manages storage of implementation specifications
-
- try:
- spec = cls.__dict__.get('__implemented__')
- except AttributeError:
-
- # we can't get the class dict. This is probably due to a
- # security proxy. If this is the case, then probably no
- # descriptor was installed for the class.
-
- # We don't want to depend directly on zope.security in
- # zope.interface, but we'll try to make reasonable
- # accommodations in an indirect way.
-
- # We'll check to see if there's an implements:
-
- spec = getattr(cls, '__implemented__', None)
- if spec is None:
- # There's no spec stred in the class. Maybe its a builtin:
- spec = BuiltinImplementationSpecifications.get(cls)
- if spec is not None:
- return spec
- return _empty
-
- if spec.__class__ == Implements:
- # we defaulted to _empty or there was a spec. Good enough.
- # Return it.
- return spec
-
- # TODO: need old style __implements__ compatibility?
- # Hm, there's an __implemented__, but it's not a spec. Must be
- # an old-style declaration. Just compute a spec for it
- return Declaration(*_normalizeargs((spec, )))
-
- if isinstance(spec, Implements):
- return spec
-
- if spec is None:
- spec = BuiltinImplementationSpecifications.get(cls)
- if spec is not None:
- return spec
-
- # TODO: need old style __implements__ compatibility?
- if spec is not None:
- # old-style __implemented__ = foo declaration
- spec = (spec, ) # tuplefy, as it might be just an int
- spec = Implements(*_normalizeargs(spec))
- spec.inherit = None # old-style implies no inherit
- del cls.__implemented__ # get rid of the old-style declaration
- else:
- try:
- bases = cls.__bases__
- except AttributeError:
- if not callable(cls):
- raise TypeError("ImplementedBy called for non-factory", cls)
- bases = ()
-
- spec = Implements(*[implementedBy(c) for c in bases])
- spec.inherit = cls
-
- spec.__name__ = (getattr(cls, '__module__', '?') or '?') + \
- '.' + (getattr(cls, '__name__', '?') or '?')
-
- try:
- cls.__implemented__ = spec
- if not hasattr(cls, '__providedBy__'):
- cls.__providedBy__ = objectSpecificationDescriptor
-
- if (isinstance(cls, DescriptorAwareMetaClasses)
- and
- '__provides__' not in cls.__dict__):
- # Make sure we get a __provides__ descriptor
- cls.__provides__ = ClassProvides(
- cls,
- getattr(cls, '__class__', type(cls)),
- )
-
- except TypeError:
- if not isinstance(cls, type):
- raise TypeError("ImplementedBy called for non-type", cls)
- BuiltinImplementationSpecifications[cls] = spec
-
- return spec
-
-implementedBy = implementedByFallback
-
-def classImplementsOnly(cls, *interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- The arguments after the class are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- replace any previous declarations.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class A(object):
- ... implements(I3)
- >>> class B(object):
- ... implements(I4)
- >>> class C(A, B):
- ... pass
- >>> classImplementsOnly(C, I1, I2)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2']
-
- Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
- whatever interfaces instances of ``A`` and ``B`` implement.
- """
- spec = implementedBy(cls)
- spec.declared = ()
- spec.inherit = None
- classImplements(cls, *interfaces)
-
-def classImplements(cls, *interfaces):
- """Declare additional interfaces implemented for instances of a class
-
- The arguments after the class are one or more interfaces or
- interface specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- are added to any interfaces previously declared.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class I5(Interface): pass
- ...
- >>> class A(object):
- ... implements(I3)
- >>> class B(object):
- ... implements(I4)
- >>> class C(A, B):
- ... pass
- >>> classImplements(C, I1, I2)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2', 'I3', 'I4']
- >>> classImplements(C, I5)
- >>> [i.getName() for i in implementedBy(C)]
- ['I1', 'I2', 'I5', 'I3', 'I4']
-
- Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever
- interfaces instances of ``A`` and ``B`` provide.
- """
-
- spec = implementedBy(cls)
- spec.declared += tuple(_normalizeargs(interfaces))
-
- # compute the bases
- bases = []
- seen = {}
- for b in spec.declared:
- if b not in seen:
- seen[b] = 1
- bases.append(b)
-
- if spec.inherit is not None:
-
- for c in spec.inherit.__bases__:
- b = implementedBy(c)
- if b not in seen:
- seen[b] = 1
- bases.append(b)
-
- spec.__bases__ = tuple(bases)
-
-def _implements_advice(cls):
- interfaces, classImplements = cls.__dict__['__implements_advice_data__']
- del cls.__implements_advice_data__
- classImplements(cls, *interfaces)
- return cls
-
-
-class implementer:
-
- 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."
- )
- spec = Implements(*self.interfaces)
- try:
- ob.__implemented__ = spec
- except AttributeError:
- raise TypeError("Can't declare implements", ob)
- return ob
-
-def _implements(name, interfaces, classImplements):
- frame = sys._getframe(2)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def. In 2.2.0 we can't
- # check for __module__ since it doesn't seem to be added to the locals
- # until later on.
- if (locals is frame.f_globals) or (
- ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
- raise TypeError(name+" can be used only from a class definition.")
-
- if '__implements_advice_data__' in locals:
- raise TypeError(name+" can be used only once in a class definition.")
-
- locals['__implements_advice_data__'] = interfaces, classImplements
- addClassAdvisor(_implements_advice, depth=3)
-
-def implements(*interfaces):
- """Declare interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) are added to any interfaces previously
- declared.
-
- Previous declarations include declarations for base classes
- unless implementsOnly was used.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplements. For example::
-
- implements(I1)
-
- is equivalent to calling::
-
- classImplements(C, I1)
-
- after the class has been created.
-
- Consider the following example::
-
-
- >>> from zope.interface import Interface
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
- instances of ``A`` and ``B`` implement.
-
- """
- _implements("implements", interfaces, classImplements)
-
-def implementsOnly(*interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- Previous declarations including declarations for base classes
- are overridden.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplementsOnly. For example::
-
- implementsOnly(I1)
-
- is equivalent to calling::
-
- classImplementsOnly(I1)
-
- after the class has been created.
-
- Consider the following example::
-
- >>> from zope.interface import Interface
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implementsOnly(IC)
-
- >>> ob = C()
- >>> int(IA1 in providedBy(ob))
- 0
- >>> int(IA2 in providedBy(ob))
- 0
- >>> int(IB in providedBy(ob))
- 0
- >>> int(IC in providedBy(ob))
- 1
-
-
- Instances of ``C`` implement ``IC``, regardless of what
- instances of ``A`` and ``B`` implement.
-
- """
- _implements("implementsOnly", interfaces, classImplementsOnly)
-
-##############################################################################
-#
-# Instance declarations
-
-class Provides(Declaration): # Really named ProvidesClass
- """Implement __provides__, the instance-specific specification
-
- When an object is pickled, we pickle the interfaces that it implements.
- """
-
- def __init__(self, cls, *interfaces):
- self.__args = (cls, ) + interfaces
- self._cls = cls
- Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
-
- def __reduce__(self):
- return Provides, self.__args
-
- __module__ = 'zope.interface'
-
- def __get__(self, inst, cls):
- """Make sure that a class __provides__ doesn't leak to an instance
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFooFactory(Interface): pass
- ...
-
- >>> class C(object):
- ... pass
-
- >>> C.__provides__ = ProvidesClass(C, IFooFactory)
- >>> [i.getName() for i in C.__provides__]
- ['IFooFactory']
- >>> getattr(C(), '__provides__', 0)
- 0
-
- """
- if inst is None and cls is self._cls:
- # We were accessed through a class, so we are the class'
- # provides spec. Just return this object, but only if we are
- # being called on the same class that we were defined for:
- return self
-
- raise AttributeError('__provides__')
-
-ProvidesClass = Provides
-
-# Registry of instance declarations
-# This is a memory optimization to allow objects to share specifications.
-InstanceDeclarations = weakref.WeakValueDictionary()
-
-def Provides(*interfaces):
- """Cache instance declarations
-
- Instance declarations are shared among instances that have the same
- declaration. The declarations are cached in a weak value dictionary.
-
- (Note that, in the examples below, we are going to make assertions about
- the size of the weakvalue dictionary. For the assertions to be
- meaningful, we need to force garbage collection to make sure garbage
- objects are, indeed, removed from the system. Depending on how Python
- is run, we may need to make multiple calls to be sure. We provide a
- collect function to help with this:
-
- >>> import gc
- >>> def collect():
- ... for i in range(4):
- ... gc.collect()
-
- )
-
- >>> collect()
- >>> before = len(InstanceDeclarations)
-
- >>> class C(object):
- ... pass
-
- >>> from zope.interface import Interface
- >>> class I(Interface):
- ... pass
-
- >>> c1 = C()
- >>> c2 = C()
-
- >>> len(InstanceDeclarations) == before
- 1
-
- >>> directlyProvides(c1, I)
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> directlyProvides(c2, I)
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> del c1
- >>> collect()
- >>> len(InstanceDeclarations) == before + 1
- 1
-
- >>> del c2
- >>> collect()
- >>> len(InstanceDeclarations) == before
- 1
- """
-
- spec = InstanceDeclarations.get(interfaces)
- if spec is None:
- spec = ProvidesClass(*interfaces)
- InstanceDeclarations[interfaces] = spec
-
- return spec
-Provides.__safe_for_unpickling__ = True
-
-
-DescriptorAwareMetaClasses = ClassType, type
-def directlyProvides(object, *interfaces):
- """Declare interfaces declared directly for an object
-
- The arguments after the object are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications)
- replace interfaces previously declared for the object.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> directlyProvides(ob, I1, I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 1
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
- instances have been declared for instances of ``C``.
-
- To remove directly provided interfaces, use ``directlyProvidedBy`` and
- subtract the unwanted interfaces. For example:
-
- >>> directlyProvides(ob, directlyProvidedBy(ob)-I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 0
-
- removes I2 from the interfaces directly provided by ``ob``. The object,
- ``ob`` no longer directly provides ``I2``, although it might still
- provide ``I2`` if it's class implements ``I2``.
-
- To add directly provided interfaces, use ``directlyProvidedBy`` and
- include additional interfaces. For example:
-
- >>> int(I2 in providedBy(ob))
- 0
- >>> directlyProvides(ob, directlyProvidedBy(ob), I2)
-
- adds ``I2`` to the interfaces directly provided by ob::
-
- >>> int(I2 in providedBy(ob))
- 1
-
- """
-
- # We need to avoid setting this attribute on meta classes that
- # don't support descriptors.
- # We can do away with this check when we get rid of the old EC
- cls = getattr(object, '__class__', None)
- if cls is not None and getattr(cls, '__class__', None) is cls:
- # It's a meta class (well, at least it it could be an extension class)
- if not isinstance(object, DescriptorAwareMetaClasses):
- raise TypeError("Attempt to make an interface declaration on a "
- "non-descriptor-aware class")
-
- interfaces = _normalizeargs(interfaces)
- if cls is None:
- cls = type(object)
-
- issub = False
- for damc in DescriptorAwareMetaClasses:
- if issubclass(cls, damc):
- issub = True
- break
- if issub:
- # we have a class or type. We'll use a special descriptor
- # that provides some extra caching
- object.__provides__ = ClassProvides(object, cls, *interfaces)
- else:
- object.__provides__ = Provides(cls, *interfaces)
-
-
-def alsoProvides(object, *interfaces):
- """Declare interfaces declared directly for an object
-
- The arguments after the object are one or more interfaces or interface
- specifications (``IDeclaration`` objects).
-
- The interfaces given (including the interfaces in the specifications) are
- added to the interfaces previously declared for the object.
-
- Consider the following example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class IA1(Interface): pass
- ...
- >>> class IA2(Interface): pass
- ...
- >>> class IB(Interface): pass
- ...
- >>> class IC(Interface): pass
- ...
- >>> class A(object): implements(IA1, IA2)
- ...
- >>> class B(object): implements(IB)
- ...
-
- >>> class C(A, B):
- ... implements(IC)
-
- >>> ob = C()
- >>> directlyProvides(ob, I1)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 0
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- >>> alsoProvides(ob, I2)
- >>> int(I1 in providedBy(ob))
- 1
- >>> int(I2 in providedBy(ob))
- 1
- >>> int(IA1 in providedBy(ob))
- 1
- >>> int(IA2 in providedBy(ob))
- 1
- >>> int(IB in providedBy(ob))
- 1
- >>> int(IC in providedBy(ob))
- 1
-
- The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
- instances have been declared for instances of ``C``. Notice that the
- alsoProvides just extends the provided interfaces.
- """
- directlyProvides(object, directlyProvidedBy(object), *interfaces)
-
-def noLongerProvides(object, interface):
- """
- This removes a directly provided interface from an object.
- Consider the following two interfaces:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
-
- ``I1`` is provided through the class, ``I2`` is directly provided
- by the object:
-
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> alsoProvides(c, I2)
- >>> I2.providedBy(c)
- True
-
- Remove I2 from c again:
-
- >>> noLongerProvides(c, I2)
- >>> I2.providedBy(c)
- False
-
- Removing an interface that is provided through the class is not possible:
-
- >>> noLongerProvides(c, I1)
- Traceback (most recent call last):
- ...
- ValueError: Can only remove directly provided interfaces.
-
- """
- directlyProvides(object, directlyProvidedBy(object)-interface)
- if interface.providedBy(object):
- raise ValueError("Can only remove directly provided interfaces.")
-
-class ClassProvidesBasePy(object):
-
- def __get__(self, inst, cls):
- if cls is self._cls:
- # We only work if called on the class we were defined for
-
- if inst is None:
- # We were accessed through a class, so we are the class'
- # provides spec. Just return this object as is:
- return self
-
- return self._implements
-
- raise AttributeError('__provides__')
-
-ClassProvidesBase = ClassProvidesBasePy
-
-# Try to get C base:
-try:
- import _zope_interface_coptimizations
-except ImportError:
- pass
-else:
- from _zope_interface_coptimizations import ClassProvidesBase
-
-
-class ClassProvides(Declaration, ClassProvidesBase):
- """Special descriptor for class __provides__
-
- The descriptor caches the implementedBy info, so that
- we can get declarations for objects without instance-specific
- interfaces a bit quicker.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFooFactory(Interface):
- ... pass
- >>> class IFoo(Interface):
- ... pass
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__provides__]
- ['IFooFactory']
-
- >>> [i.getName() for i in C().__provides__]
- ['IFoo']
- """
-
- def __init__(self, cls, metacls, *interfaces):
- self._cls = cls
- self._implements = implementedBy(cls)
- self.__args = (cls, metacls, ) + interfaces
- Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
-
- def __reduce__(self):
- return self.__class__, self.__args
-
- # Copy base-class method for speed
- __get__ = ClassProvidesBase.__get__
-
-def directlyProvidedBy(object):
- """Return the interfaces directly provided by the given object
-
- The value returned is an ``IDeclaration``.
- """
- provides = getattr(object, "__provides__", None)
- if (provides is None # no spec
- or
- # We might have gotten the implements spec, as an
- # optimization. If so, it's like having only one base, that we
- # lop off to exclude class-supplied declarations:
- isinstance(provides, Implements)
- ):
- return _empty
-
- # Strip off the class part of the spec:
- return Declaration(provides.__bases__[:-1])
-
-def classProvides(*interfaces):
- """Declare interfaces provided directly by a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface specifications
- (``IDeclaration`` objects).
-
- The given interfaces (including the interfaces in the specifications)
- are used to create the class's direct-object interface specification.
- An error will be raised if the module class has an direct interface
- specification. In other words, it is an error to call this function more
- than once in a class definition.
-
- Note that the given interfaces have nothing to do with the interfaces
- implemented by instances of the class.
-
- This function is provided for convenience. It provides a more convenient
- way to call directlyProvidedByProvides for a class. For example::
-
- classProvides(I1)
-
- is equivalent to calling::
-
- directlyProvides(theclass, I1)
-
- after the class has been created.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
-
- if equivalent to:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- >>> directlyProvides(C, IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
- """
- frame = sys._getframe(1)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def
- if (locals is frame.f_globals) or ('__module__' not in locals):
- raise TypeError(name+" can be used only from a class definition.")
-
- if '__provides__' in locals:
- raise TypeError(
- "classProvides can only be used once in a class definition.")
-
- locals["__provides__"] = _normalizeargs(interfaces)
-
- addClassAdvisor(_classProvides_advice, depth=2)
-
-def _classProvides_advice(cls):
- interfaces = cls.__dict__['__provides__']
- del cls.__provides__
- directlyProvides(cls, *interfaces)
- return cls
-
-def moduleProvides(*interfaces):
- """Declare interfaces provided by a module
-
- This function is used in a module definition.
-
- The arguments are one or more interfaces or interface specifications
- (``IDeclaration`` objects).
-
- The given interfaces (including the interfaces in the specifications) are
- used to create the module's direct-object interface specification. An
- error will be raised if the module already has an interface specification.
- In other words, it is an error to call this function more than once in a
- module definition.
-
- This function is provided for convenience. It provides a more convenient
- way to call directlyProvides. For example::
-
- moduleImplements(I1)
-
- is equivalent to::
-
- directlyProvides(sys.modules[__name__], I1)
- """
- frame = sys._getframe(1)
- locals = frame.f_locals
-
- # Try to make sure we were called from a class def
- if (locals is not frame.f_globals) or ('__name__' not in locals):
- raise TypeError(
- "moduleProvides can only be used from a module definition.")
-
- if '__provides__' in locals:
- raise TypeError(
- "moduleProvides can only be used once in a module definition.")
-
- module = sys.modules[__name__]
-
- locals["__provides__"] = Provides(type(module),
- *_normalizeargs(interfaces))
-
-##############################################################################
-#
-# Declaration querying support
-
-def ObjectSpecification(direct, cls):
- """Provide object specifications
-
- These combine information for the object and for it's classes.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(Interface): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I31(I3): pass
- ...
- >>> class I4(Interface): pass
- ...
- >>> class I5(Interface): pass
- ...
- >>> class A(object): implements(I1)
- ...
- >>> class B(object): __implemented__ = I2
- ...
- >>> class C(A, B): implements(I31)
- ...
- >>> c = C()
- >>> directlyProvides(c, I4)
- >>> [i.getName() for i in providedBy(c)]
- ['I4', 'I31', 'I1', 'I2']
- >>> [i.getName() for i in providedBy(c).flattened()]
- ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
- >>> int(I1 in providedBy(c))
- 1
- >>> int(I3 in providedBy(c))
- 0
- >>> int(providedBy(c).extends(I3))
- 1
- >>> int(providedBy(c).extends(I31))
- 1
- >>> int(providedBy(c).extends(I5))
- 0
- >>> class COnly(A, B): implementsOnly(I31)
- ...
- >>> class D(COnly): implements(I5)
- ...
- >>> c = D()
- >>> directlyProvides(c, I4)
- >>> [i.getName() for i in providedBy(c)]
- ['I4', 'I5', 'I31']
- >>> [i.getName() for i in providedBy(c).flattened()]
- ['I4', 'I5', 'I31', 'I3', 'Interface']
- >>> int(I1 in providedBy(c))
- 0
- >>> int(I3 in providedBy(c))
- 0
- >>> int(providedBy(c).extends(I3))
- 1
- >>> int(providedBy(c).extends(I1))
- 0
- >>> int(providedBy(c).extends(I31))
- 1
- >>> int(providedBy(c).extends(I5))
- 1
-
- nonzero:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface):
- ... pass
- >>> class I2(Interface):
- ... pass
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 1
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
- >>> class C(object):
- ... pass
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 0
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
- """
-
- return Provides(cls, direct)
-
-def getObjectSpecification(ob):
-
- provides = getattr(ob, '__provides__', None)
- if provides is not None:
- return provides
-
- try:
- cls = ob.__class__
- except AttributeError:
- # We can't get the class, so just consider provides
- return _empty
-
- return implementedBy(cls)
-
-def providedBy(ob):
-
- # Here we have either a special object, an old-style declaration
- # or a descriptor
-
- # Try to get __providedBy__
- try:
- r = ob.__providedBy__
- except AttributeError:
- # Not set yet. Fall back to lower-level thing that computes it
- return getObjectSpecification(ob)
-
- try:
- # We might have gotten a descriptor from an instance of a
- # class (like an ExtensionClass) that doesn't support
- # descriptors. We'll make sure we got one by trying to get
- # the only attribute, which all specs have.
- r.extends
-
- except AttributeError:
-
- # The object's class doesn't understand descriptors.
- # Sigh. We need to get an object descriptor, but we have to be
- # careful. We want to use the instance's __provides__, if
- # there is one, but only if it didn't come from the class.
-
- try:
- r = ob.__provides__
- except AttributeError:
- # No __provides__, so just fall back to implementedBy
- return implementedBy(ob.__class__)
-
- # We need to make sure we got the __provides__ from the
- # instance. We'll do this by making sure we don't get the same
- # thing from the class:
-
- try:
- cp = ob.__class__.__provides__
- except AttributeError:
- # The ob doesn't have a class or the class has no
- # provides, assume we're done:
- return r
-
- if r is cp:
- # Oops, we got the provides from the class. This means
- # the object doesn't have it's own. We should use implementedBy
- return implementedBy(ob.__class__)
-
- return r
-
-class ObjectSpecificationDescriptorPy(object):
- """Implement the `__providedBy__` attribute
-
- The `__providedBy__` attribute computes the interfaces peovided by
- an object.
- """
-
- def __get__(self, inst, cls):
- """Get an object specification for an object
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class IFoo(Interface): pass
- ...
- >>> class IFooFactory(Interface): pass
- ...
- >>> class C(object):
- ... implements(IFoo)
- ... classProvides(IFooFactory)
- >>> [i.getName() for i in C.__providedBy__]
- ['IFooFactory']
- >>> [i.getName() for i in C().__providedBy__]
- ['IFoo']
-
- """
-
- # Get an ObjectSpecification bound to either an instance or a class,
- # depending on how we were accessed.
-
- if inst is None:
- return getObjectSpecification(cls)
-
- provides = getattr(inst, '__provides__', None)
- if provides is not None:
- return provides
-
- return implementedBy(cls)
-
-ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy
-
-##############################################################################
-
-def _normalizeargs(sequence, output = None):
- """Normalize declaration arguments
-
- Normalization arguments might contain Declarions, tuples, or single
- interfaces.
-
- Anything but individial interfaces or implements specs will be expanded.
- """
- if output is None:
- output = []
-
- cls = sequence.__class__
- if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
- output.append(sequence)
- else:
- for v in sequence:
- _normalizeargs(v, output)
-
- return output
-
-_empty = Declaration()
-
-try:
- import _zope_interface_coptimizations
-except ImportError:
- pass
-else:
- from _zope_interface_coptimizations import implementedBy, providedBy
- from _zope_interface_coptimizations import getObjectSpecification
- from _zope_interface_coptimizations import ObjectSpecificationDescriptor
-
-objectSpecificationDescriptor = ObjectSpecificationDescriptor()
=== removed file 'lib/zope/interface/document.py'
--- lib/zope/interface/document.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/document.py 1970-01-01 00:00:00 +0000
@@ -1,107 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-""" Pretty-Print an Interface object as structured text (Yum)
-
-This module provides a function, asStructuredText, for rendering an
-interface as structured text.
-
-$Id: document.py 39768 2005-10-31 13:57:35Z tlotze $
-"""
-import zope.interface
-
-def asStructuredText(I, munge=0):
- """ Output structured text format. Note, this will whack any existing
- 'structured' format of the text. """
-
- r = [I.getName()]
- outp = r.append
- level = 1
-
- if I.getDoc():
- outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level))
-
- bases = [base
- for base in I.__bases__
- if base is not zope.interface.Interface
- ]
- if bases:
- outp(_justify_and_indent("This interface extends:", level, munge))
- level += 1
- for b in bases:
- item = "o %s" % b.getName()
- outp(_justify_and_indent(_trim_doc_string(item), level, munge))
- level -= 1
-
- namesAndDescriptions = I.namesAndDescriptions()
- namesAndDescriptions.sort()
-
- outp(_justify_and_indent("Attributes:", level, munge))
- level += 1
- for name, desc in namesAndDescriptions:
- if not hasattr(desc, 'getSignatureString'): # ugh...
- item = "%s -- %s" % (desc.getName(),
- desc.getDoc() or 'no documentation')
- outp(_justify_and_indent(_trim_doc_string(item), level, munge))
- level -= 1
-
- outp(_justify_and_indent("Methods:", level, munge))
- level += 1
- for name, desc in namesAndDescriptions:
- if hasattr(desc, 'getSignatureString'): # ugh...
- item = "%s%s -- %s" % (desc.getName(),
- desc.getSignatureString(),
- desc.getDoc() or 'no documentation')
- outp(_justify_and_indent(_trim_doc_string(item), level, munge))
-
- return "\n\n".join(r) + "\n\n"
-
-
-def _trim_doc_string(text):
- """ Trims a doc string to make it format
- correctly with structured text. """
-
- lines = text.replace('\r\n', '\n').split('\n')
- nlines = [lines.pop(0)]
- if lines:
- min_indent = min([len(line) - len(line.lstrip())
- for line in lines])
- for line in lines:
- nlines.append(line[min_indent:])
-
- return '\n'.join(nlines)
-
-
-def _justify_and_indent(text, level, munge=0, width=72):
- """ indent and justify text, rejustify (munge) if specified """
-
- indent = " " * level
-
- if munge:
- lines = []
- line = indent
- text = text.split()
-
- for word in text:
- line = ' '.join([line, word])
- if len(line) > width:
- lines.append(line)
- line = indent
- else:
- lines.append(line)
-
- return '\n'.join(lines)
-
- else:
- return indent + \
- text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)
=== removed file 'lib/zope/interface/exceptions.py'
--- lib/zope/interface/exceptions.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/exceptions.py 1970-01-01 00:00:00 +0000
@@ -1,69 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Interface-specific exceptions
-
-$Id: exceptions.py 26567 2004-07-16 06:58:27Z srichter $
-"""
-
-class Invalid(Exception):
- """An specification is violated
- """
-
-class DoesNotImplement(Invalid):
- """ This object does not implement """
- def __init__(self, interface):
- self.interface = interface
-
- def __str__(self):
- return """An object does not implement interface %(interface)s
-
- """ % self.__dict__
-
-class BrokenImplementation(Invalid):
- """An attribute is not completely implemented.
- """
-
- def __init__(self, interface, name):
- self.interface=interface
- self.name=name
-
- def __str__(self):
- return """An object has failed to implement interface %(interface)s
-
- The %(name)s attribute was not provided.
- """ % self.__dict__
-
-class BrokenMethodImplementation(Invalid):
- """An method is not completely implemented.
- """
-
- def __init__(self, method, mess):
- self.method=method
- self.mess=mess
-
- def __str__(self):
- return """The implementation of %(method)s violates its contract
- because %(mess)s.
- """ % self.__dict__
-
-class InvalidInterface(Exception):
- """The interface has invalid contents
- """
-
-class BadImplements(TypeError):
- """An implementation assertion is invalid
-
- because it doesn't contain an interface or a sequence of valid
- implementation assertions.
- """
=== removed file 'lib/zope/interface/human.txt'
--- lib/zope/interface/human.txt 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/human.txt 1970-01-01 00:00:00 +0000
@@ -1,152 +0,0 @@
-==========================
-Using the Adapter Registry
-==========================
-
-This is a small demonstration of the ``zope.interface`` package including its
-adapter registry. It is intended to provide a concrete but narrow example on
-how to use interfaces and adapters outside of Zope 3.
-
-First we have to import the interface package.
-
- >>> import zope.interface
-
-We now develop an interface for our object, which is a simple file in this
-case. For now we simply support one attribute, the body, which contains the
-actual file contents.
-
- >>> class IFile(zope.interface.Interface):
- ...
- ... body = zope.interface.Attribute('Contents of the file.')
- ...
-
-For statistical reasons we often want to know the size of a file. However, it
-would be clumsy to implement the size directly in the file object, since the
-size really represents meta-data. Thus we create another interface that
-provides the size of something.
-
- >>> class ISize(zope.interface.Interface):
- ...
- ... def getSize():
- ... 'Return the size of an object.'
- ...
-
-Now we need to implement the file. It is essential that the object states
-that it implements the `IFile` interface. We also provide a default body
-value (just to make things simpler for this example).
-
- >>> class File(object):
- ...
- ... zope.interface.implements(IFile)
- ... body = 'foo bar'
- ...
-
-Next we implement an adapter that can provide the `ISize` interface given any
-object providing `IFile`. By convention we use `__used_for__` to specify the
-interface that we expect the adapted object to provide, in our case
-`IFile`. However, this attribute is not used for anything. If you have
-multiple interfaces for which an adapter is used, just specify the interfaces
-via a tuple.
-
-Again by convention, the constructor of an adapter takes one argument, the
-context. The context in this case is an instance of `File` (providing `IFile`)
-that is used to extract the size from. Also by convention the context is
-stored in an attribute named `context` on the adapter. The twisted community
-refers to the context as the `original` object. However, you may feel free to
-use a specific argument name, such as `file`.
-
- >>> class FileSize(object):
- ...
- ... zope.interface.implements(ISize)
- ... __used_for__ = IFile
- ...
- ... def __init__(self, context):
- ... self.context = context
- ...
- ... def getSize(self):
- ... return len(self.context.body)
- ...
-
-Now that we have written our adapter, we have to register it with an adapter
-registry, so that it can be looked up when needed. There is no such thing as a
-global registry; thus we have to instantiate one for our example manually.
-
- >>> from zope.interface.adapter import AdapterRegistry
- >>> registry = AdapterRegistry()
-
-
-The registry keeps a map of what adapters implement based on another
-interface, the object already provides. Therefore, we next have to register an
-adapter that adapts from `IFile` to `ISize`. The first argument to
-the registry's `register()` method is a list of original interfaces.In our
-cause we have only one original interface, `IFile`. A list makes sense, since
-the interface package has the concept of multi-adapters, which are adapters
-that require multiple objects to adapt to a new interface. In these
-situations, your adapter constructor will require an argument for each
-specified interface.
-
-The second argument is the interface the adapter provides, in our case
-`ISize`. The third argument in the name of the adapter. Since we do not care
-about names, we simply leave it as an empty string. Names are commonly useful,
-if you have adapters for the same set of interfaces, but they are useful in
-different situations. The last argument is simply the adapter class.
-
- >>> registry.register([IFile], ISize, '', FileSize)
-
-You can now use the the registry to lookup the adapter.
-
- >>> registry.lookup1(IFile, ISize, '')
- <class '__main__.FileSize'>
-
-Let's get a little bit more practical. Let's create a `File` instance and
-create the adapter using a registry lookup. Then we see whether the adapter
-returns the correct size by calling `getSize()`.
-
- >>> file = File()
- >>> size = registry.lookup1(IFile, ISize, '')(file)
- >>> size.getSize()
- 7
-
-However, this is not very practical, since I have to manually pass in the
-arguments to the lookup method. There is some syntactic candy that will allow
-us to get an adapter instance by simply calling `ISize(file)`. To make use of
-this functionality, we need to add our registry to the adapter_hooks list,
-which is a member of the adapters module. This list stores a collection of
-callables that are automatically invoked when IFoo(obj) is called; their
-purpose is to locate adapters that implement an interface for a certain
-context instance.
-
-You are required to implement your own adapter hook; this example covers one
-of the simplest hooks that use the registry, but you could implement one that
-used an adapter cache or persistent adapters, for instance. The helper hook is
-required to expect as first argument the desired output interface (for us
-`ISize`) and as the second argument the context of the adapter (here
-`file`). The function returns an adapter, i.e. a `FileSize` instance.
-
- >>> def hook(provided, object):
- ... adapter = registry.lookup1(zope.interface.providedBy(object),
- ... provided, '')
- ... return adapter(object)
- ...
-
-We now just add the hook to an `adapter_hooks` list.
-
- >>> from zope.interface.interface import adapter_hooks
- >>> adapter_hooks.append(hook)
-
-Once the hook is registered, you can use the desired syntax.
-
- >>> size = ISize(file)
- >>> size.getSize()
- 7
-
-Now we have to cleanup after ourselves, so that others after us have a clean
-`adapter_hooks` list.
-
- >>> adapter_hooks.remove(hook)
-
-That's it. I have intentionally left out a discussion of named adapters and
-multi-adapters, since this text is intended as a practical and simple
-introduction to Zope 3 interfaces and adapters. You might want to read the
-`adapter.txt` in the `zope.interface` package for a more formal, referencial
-and complete treatment of the package. Warning: People have reported that
-`adapter.txt` makes their brain feel soft!
=== removed file 'lib/zope/interface/interface.py'
--- lib/zope/interface/interface.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/interface.py 1970-01-01 00:00:00 +0000
@@ -1,916 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Interface object implementation
-
-$Id: interface.py 40385 2005-11-27 21:58:28Z jim $
-"""
-
-from __future__ import generators
-
-import sys
-import warnings
-import weakref
-from types import FunctionType
-from ro import ro
-from zope.interface.exceptions import Invalid
-
-CO_VARARGS = 4
-CO_VARKEYWORDS = 8
-TAGGED_DATA = '__interface_tagged_values__'
-
-_decorator_non_return = object()
-
-def invariant(call):
- f_locals = sys._getframe(1).f_locals
- tags = f_locals.setdefault(TAGGED_DATA, {})
- invariants = tags.setdefault('invariants', [])
- invariants.append(call)
- return _decorator_non_return
-
-class Element(object):
-
- # We can't say this yet because we don't have enough
- # infrastructure in place.
- #
- #implements(IElement)
-
- def __init__(self, __name__, __doc__=''):
- """Create an 'attribute' description
- """
- if not __doc__ and __name__.find(' ') >= 0:
- __doc__ = __name__
- __name__ = None
-
- self.__name__=__name__
- self.__doc__=__doc__
- self.__tagged_values = {}
-
- def getName(self):
- """ Returns the name of the object. """
- return self.__name__
-
- def getDoc(self):
- """ Returns the documentation for the object. """
- return self.__doc__
-
- def getTaggedValue(self, tag):
- """ Returns the value associated with 'tag'. """
- return self.__tagged_values[tag]
-
- def queryTaggedValue(self, tag, default=None):
- """ Returns the value associated with 'tag'. """
- return self.__tagged_values.get(tag, default)
-
- def getTaggedValueTags(self):
- """ Returns a list of all tags. """
- return self.__tagged_values.keys()
-
- def setTaggedValue(self, tag, value):
- """ Associates 'value' with 'key'. """
- self.__tagged_values[tag] = value
-
-class SpecificationBasePy(object):
-
- def providedBy(self, ob):
- """Is the interface implemented by an object
-
- >>> from zope.interface import *
- >>> class I1(Interface):
- ... pass
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> class X(object):
- ... pass
- >>> x = X()
- >>> I1.providedBy(x)
- False
- >>> I1.providedBy(C)
- False
- >>> I1.providedBy(c)
- True
- >>> directlyProvides(x, I1)
- >>> I1.providedBy(x)
- True
- >>> directlyProvides(C, I1)
- >>> I1.providedBy(C)
- True
-
- """
- spec = providedBy(ob)
- return self in spec._implied
-
- def implementedBy(self, cls):
- """Test whether the specification is implemented by a class or factory.
- Raise TypeError if argument is neither a class nor a callable."""
- spec = implementedBy(cls)
- return self in spec._implied
-
- def isOrExtends(self, interface):
- """Is the interface the same as or extend the given interface
-
- Examples::
-
- >>> from zope.interface import Interface
- >>> from zope.interface.declarations import Declaration
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> int(spec.extends(Interface))
- 0
- >>> spec = Declaration(I2)
- >>> int(spec.extends(Interface))
- 1
- >>> int(spec.extends(I1))
- 1
- >>> int(spec.extends(I2))
- 1
- >>> int(spec.extends(I3))
- 0
- >>> int(spec.extends(I4))
- 0
-
- """
- return interface in self._implied
-
-SpecificationBase = SpecificationBasePy
-
-try:
- from _zope_interface_coptimizations import SpecificationBase
-except ImportError:
- pass
-
-class Specification(SpecificationBase):
- """Specifications
-
- An interface specification is used to track interface declarations
- and component registrations.
-
- This class is a base class for both interfaces themselves and for
- interface specifications (declarations).
-
- Specifications are mutable. If you reassign their cases, their
- relations with other specifications are adjusted accordingly.
-
- For example:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface):
- ... pass
- >>> class I2(I1):
- ... pass
- >>> class I3(I2):
- ... pass
-
- >>> [i.__name__ for i in I1.__bases__]
- ['Interface']
-
- >>> [i.__name__ for i in I2.__bases__]
- ['I1']
-
- >>> I3.extends(I1)
- 1
-
- >>> I2.__bases__ = (Interface, )
-
- >>> [i.__name__ for i in I2.__bases__]
- ['Interface']
-
- >>> I3.extends(I1)
- 0
-
- """
-
- # Copy some base class methods for speed
- isOrExtends = SpecificationBase.isOrExtends
- providedBy = SpecificationBase.providedBy
-
- #########################################################################
- # BBB 2004-07-13: Backward compatabilty. These methods have been
- # deprecated in favour of providedBy and implementedBy.
-
- def isImplementedByInstancesOf(self, cls):
- warnings.warn(
- "isImplementedByInstancesOf has been renamed to implementedBy",
- DeprecationWarning, stacklevel=2,
- )
- return self.implementedBy(cls)
-
- def isImplementedBy(self, ob):
- warnings.warn(
- "isImplementedBy has been renamed to providedBy",
- DeprecationWarning, stacklevel=2,
- )
- return self.providedBy(ob)
- #
- #########################################################################
-
- def __init__(self, bases=()):
- self._implied = {}
- self.dependents = weakref.WeakKeyDictionary()
- self.__bases__ = tuple(bases)
-
- def subscribe(self, dependent):
- self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
-
- def unsubscribe(self, dependent):
- n = self.dependents.get(dependent, 0) - 1
- if not n:
- del self.dependents[dependent]
- elif n > 0:
- self.dependents[dependent] = n
- else:
- raise KeyError(dependent)
-
- def __setBases(self, bases):
- # Register ourselves as a dependent of our old bases
- for b in self.__bases__:
- b.unsubscribe(self)
-
- # Register ourselves as a dependent of our bases
- self.__dict__['__bases__'] = bases
- for b in bases:
- b.subscribe(self)
-
- self.changed()
-
- __bases__ = property(
-
- lambda self: self.__dict__.get('__bases__', ()),
- __setBases,
- )
-
- def changed(self):
- """We, or something we depend on, have changed
- """
-
- implied = self._implied
- implied.clear()
-
- ancestors = ro(self)
- self.__sro__ = tuple(ancestors)
- self.__iro__ = tuple([ancestor for ancestor in ancestors
- if isinstance(ancestor, InterfaceClass)
- ])
-
- for ancestor in ancestors:
- # We directly imply our ancestors:
- implied[ancestor] = ()
-
- # Now, advise our dependents of change:
- for dependent in self.dependents.keys():
- dependent.changed()
-
-
- def interfaces(self):
- """Return an iterator for the interfaces in the specification
-
- for example::
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Specification((I2, I3))
- >>> spec = Specification((I4, spec))
- >>> i = spec.interfaces()
- >>> i.next().getName()
- 'I4'
- >>> i.next().getName()
- 'I2'
- >>> i.next().getName()
- 'I3'
- >>> list(i)
- []
- """
- seen = {}
- for base in self.__bases__:
- for interface in base.interfaces():
- if interface not in seen:
- seen[interface] = 1
- yield interface
-
-
- def extends(self, interface, strict=True):
- """Does the specification extend the given interface?
-
- Test whether an interface in the specification extends the
- given interface
-
- Examples::
-
- >>> from zope.interface import Interface
- >>> from zope.interface.declarations import Declaration
- >>> class I1(Interface): pass
- ...
- >>> class I2(I1): pass
- ...
- >>> class I3(Interface): pass
- ...
- >>> class I4(I3): pass
- ...
- >>> spec = Declaration()
- >>> int(spec.extends(Interface))
- 0
- >>> spec = Declaration(I2)
- >>> int(spec.extends(Interface))
- 1
- >>> int(spec.extends(I1))
- 1
- >>> int(spec.extends(I2))
- 1
- >>> int(spec.extends(I3))
- 0
- >>> int(spec.extends(I4))
- 0
- >>> I2.extends(I2)
- 0
- >>> I2.extends(I2, False)
- 1
- >>> I2.extends(I2, strict=False)
- 1
-
- """
- return ((interface in self._implied)
- and
- ((not strict) or (self != interface))
- )
-
- def weakref(self, callback=None):
- return weakref.ref(self, callback)
-
- def get(self, name, default=None):
- """Query for an attribute description
- """
- try:
- attrs = self._v_attrs
- except AttributeError:
- attrs = self._v_attrs = {}
- attr = attrs.get(name)
- if attr is None:
- for iface in self.__iro__:
- attr = iface.direct(name)
- if attr is not None:
- attrs[name] = attr
- break
-
- if attr is None:
- return default
- else:
- return attr
-
-class InterfaceClass(Element, Specification):
- """Prototype (scarecrow) Interfaces Implementation."""
-
- # We can't say this yet because we don't have enough
- # infrastructure in place.
- #
- #implements(IInterface)
-
- def __init__(self, name, bases=(), attrs=None, __doc__=None,
- __module__=None):
-
- if attrs is None:
- attrs = {}
-
- if __module__ is None:
- __module__ = attrs.get('__module__')
- if isinstance(__module__, str):
- del attrs['__module__']
- else:
- try:
- # Figure out what module defined the interface.
- # This is how cPython figures out the module of
- # a class, but of course it does it in C. :-/
- __module__ = sys._getframe(1).f_globals['__name__']
- except (AttributeError, KeyError):
- pass
-
- self.__module__ = __module__
-
- d = attrs.get('__doc__')
- if d is not None:
- if not isinstance(d, Attribute):
- if __doc__ is None:
- __doc__ = d
- del attrs['__doc__']
-
- if __doc__ is None:
- __doc__ = ''
-
- Element.__init__(self, name, __doc__)
-
- tagged_data = attrs.pop(TAGGED_DATA, None)
- if tagged_data is not None:
- for key, val in tagged_data.items():
- self.setTaggedValue(key, val)
-
- for base in bases:
- if not isinstance(base, InterfaceClass):
- raise TypeError('Expected base interfaces')
-
- Specification.__init__(self, bases)
-
- # Make sure that all recorded attributes (and methods) are of type
- # `Attribute` and `Method`
- for name, attr in attrs.items():
- if isinstance(attr, Attribute):
- attr.interface = self
- if not attr.__name__:
- attr.__name__ = name
- elif isinstance(attr, FunctionType):
- attrs[name] = fromFunction(attr, self, name=name)
- elif attr is _decorator_non_return:
- del attrs[name]
- else:
- raise InvalidInterface("Concrete attribute, " + name)
-
- self.__attrs = attrs
-
- self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
-
- def interfaces(self):
- """Return an iterator for the interfaces in the specification
-
- for example::
-
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>>
- >>> i = I1.interfaces()
- >>> i.next().getName()
- 'I1'
- >>> list(i)
- []
- """
- yield self
-
- def getBases(self):
- return self.__bases__
-
- def isEqualOrExtendedBy(self, other):
- """Same interface or extends?"""
- return self == other or other.extends(self)
-
- def names(self, all=False):
- """Return the attribute names defined by the interface."""
- if not all:
- return self.__attrs.keys()
-
- r = self.__attrs.copy()
-
- for base in self.__bases__:
- r.update(dict.fromkeys(base.names(all)))
-
- return r.keys()
-
- def __iter__(self):
- return iter(self.names(all=True))
-
- def namesAndDescriptions(self, all=False):
- """Return attribute names and descriptions defined by interface."""
- if not all:
- return self.__attrs.items()
-
- r = {}
- for base in self.__bases__[::-1]:
- r.update(dict(base.namesAndDescriptions(all)))
-
- r.update(self.__attrs)
-
- return r.items()
-
- def getDescriptionFor(self, name):
- """Return the attribute description for the given name."""
- r = self.get(name)
- if r is not None:
- return r
-
- raise KeyError(name)
-
- __getitem__ = getDescriptionFor
-
- def __contains__(self, name):
- return self.get(name) is not None
-
- def direct(self, name):
- return self.__attrs.get(name)
-
- def queryDescriptionFor(self, name, default=None):
- return self.get(name, default)
-
- def deferred(self):
- """Return a defered class corresponding to the interface."""
- if hasattr(self, "_deferred"): return self._deferred
-
- klass={}
- exec "class %s: pass" % self.__name__ in klass
- klass=klass[self.__name__]
-
- self.__d(klass.__dict__)
-
- self._deferred=klass
-
- return klass
-
- def validateInvariants(self, obj, errors=None):
- """validate object to defined invariants."""
- for call in self.queryTaggedValue('invariants', []):
- try:
- call(obj)
- except Invalid, e:
- if errors is None:
- raise
- else:
- errors.append(e)
- for base in self.__bases__:
- try:
- base.validateInvariants(obj, errors)
- except Invalid:
- if errors is None:
- raise
- if errors:
- raise Invalid(errors)
-
- def _getInterface(self, ob, name):
- """Retrieve a named interface."""
- return None
-
- def __d(self, dict):
-
- for k, v in self.__attrs.items():
- if isinstance(v, Method) and not (k in dict):
- dict[k]=v
-
- for b in self.__bases__:
- b.__d(dict)
-
- def __repr__(self):
- try:
- return self._v_repr
- except AttributeError:
- name = self.__name__
- m = self.__module__
- if m:
- name = '%s.%s' % (m, name)
- r = "<%s %s>" % (self.__class__.__name__, name)
- self._v_repr = r
- return r
-
- def __call__():
- # Mind the closure. It serves to keep a unique marker around to
- # allow for an optional argument to __call__ without resorting
- # to a global marker.
- #
- # This provides some consistency with the PEP 246 adapt method.
-
- marker = object()
-
- def __call__(self, obj, alternate=marker):
- """Adapt an object to the interface
-
- The sematics based on those of the PEP 246 adapt function.
-
- If an object cannot be adapted, then a TypeError is raised::
-
- >>> import zope.interface
- >>> class I(zope.interface.Interface):
- ... pass
-
- >>> I(0)
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt', 0, """ \
- """<InterfaceClass zope.interface.interface.I>)
-
- unless an alternate value is provided as a second
- positional argument::
-
- >>> I(0, 'bob')
- 'bob'
-
- If an object already implements the interface, then it will be
- returned::
-
- >>> class C(object):
- ... zope.interface.implements(I)
-
- >>> obj = C()
- >>> I(obj) is obj
- True
-
- If an object implements __conform__, then it will be used::
-
- >>> class C(object):
- ... zope.interface.implements(I)
- ... def __conform__(self, proto):
- ... return 0
-
- >>> I(C())
- 0
-
- Adapter hooks (see __adapt__) will also be used, if present:
-
- >>> from zope.interface.interface import adapter_hooks
- >>> def adapt_0_to_42(iface, obj):
- ... if obj == 0:
- ... return 42
-
- >>> adapter_hooks.append(adapt_0_to_42)
- >>> I(0)
- 42
-
- >>> adapter_hooks.remove(adapt_0_to_42)
- >>> I(0)
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt', 0, """ \
- """<InterfaceClass zope.interface.interface.I>)
-
- """
- conform = getattr(obj, '__conform__', None)
- if conform is not None:
- try:
- adapter = conform(self)
- except TypeError:
- # We got a TypeError. It might be an error raised by
- # the __conform__ implementation, or *we* may have
- # made the TypeError by calling an unbound method
- # (object is a class). In the later case, we behave
- # as though there is no __conform__ method. We can
- # detect this case by checking whether there is more
- # than one traceback object in the traceback chain:
- if sys.exc_info()[2].tb_next is not None:
- # There is more than one entry in the chain, so
- # reraise the error:
- raise
- # This clever trick is from Phillip Eby
- else:
- if adapter is not None:
- return adapter
-
- adapter = self.__adapt__(obj)
-
- if adapter is not None:
- return adapter
- elif alternate is not marker:
- return alternate
- else:
- raise TypeError("Could not adapt", obj, self)
-
- return __call__
-
- __call__ = __call__() # Make the closure the *real* __call__ method.
-
- def __adapt__(self, obj):
- """Adapt an object to the reciever
-
- This method is normally not called directly. It is called by
- the PEP 246 adapt framework and by the interface __call__
- operator.
-
- The adapt method is responsible for adapting an object to
- the reciever.
-
- The default version returns None::
-
- >>> import zope.interface
- >>> class I(zope.interface.Interface):
- ... pass
-
- >>> I.__adapt__(0)
-
- unless the object given provides the interface::
-
- >>> class C(object):
- ... zope.interface.implements(I)
-
- >>> obj = C()
- >>> I.__adapt__(obj) is obj
- True
-
- Adapter hooks can be provided (or removed) to provide custom
- adaptation. We'll install a silly hook that adapts 0 to 42.
- We install a hook by simply adding it to the adapter_hooks
- list::
-
- >>> from zope.interface.interface import adapter_hooks
- >>> def adapt_0_to_42(iface, obj):
- ... if obj == 0:
- ... return 42
-
- >>> adapter_hooks.append(adapt_0_to_42)
- >>> I.__adapt__(0)
- 42
-
- Hooks must either return an adapter, or None if no adapter can
- be found.
-
- Hooks can be uninstalled by removing them from the list::
-
- >>> adapter_hooks.remove(adapt_0_to_42)
- >>> I.__adapt__(0)
-
- """
- if self.providedBy(obj):
- return obj
-
- for hook in adapter_hooks:
- adapter = hook(self, obj)
- if adapter is not None:
- return adapter
-
- def __reduce__(self):
- return self.__name__
-
- def __cmp(self, o1, o2):
- # Yes, I did mean to name this __cmp, rather than __cmp__.
- # It is a private method used by __lt__ and __gt__.
- # I don't want to override __eq__ because I want the default
- # __eq__, which is really fast.
- """Make interfaces sortable
-
- TODO: It would ne nice if:
-
- More specific interfaces should sort before less specific ones.
- Otherwise, sort on name and module.
-
- But this is too complicated, and we're going to punt on it
- for now.
-
- For now, sort on interface and module name.
-
- None is treated as a pseudo interface that implies the loosest
- contact possible, no contract. For that reason, all interfaces
- sort before None.
-
- """
- if o1 == o2:
- return 0
-
- if o1 is None:
- return 1
- if o2 is None:
- return -1
-
- n1 = (getattr(o1, '__name__', ''),
- getattr(getattr(o1, '__module__', None), '__name__', ''))
- n2 = (getattr(o2, '__name__', ''),
- getattr(getattr(o2, '__module__', None), '__name__', ''))
-
- return cmp(n1, n2)
-
- def __lt__(self, other):
- c = self.__cmp(self, other)
- #print '<', self, other, c < 0, c
- return c < 0
-
- def __gt__(self, other):
- c = self.__cmp(self, other)
- #print '>', self, other, c > 0, c
- return c > 0
-
-
-adapter_hooks = []
-
-Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
-
-class Attribute(Element):
- """Attribute descriptions
- """
-
- # We can't say this yet because we don't have enough
- # infrastructure in place.
- #
- # implements(IAttribute)
-
- interface = None
-
-
-class Method(Attribute):
- """Method interfaces
-
- The idea here is that you have objects that describe methods.
- This provides an opportunity for rich meta-data.
- """
-
- # We can't say this yet because we don't have enough
- # infrastructure in place.
- #
- # implements(IMethod)
-
- def __call__(self, *args, **kw):
- raise BrokenImplementation(self.interface, self.__name__)
-
- def getSignatureInfo(self):
- return {'positional': self.positional,
- 'required': self.required,
- 'optional': self.optional,
- 'varargs': self.varargs,
- 'kwargs': self.kwargs,
- }
-
- def getSignatureString(self):
- sig = []
- for v in self.positional:
- sig.append(v)
- if v in self.optional.keys():
- sig[-1] += "=" + `self.optional[v]`
- if self.varargs:
- sig.append("*" + self.varargs)
- if self.kwargs:
- sig.append("**" + self.kwargs)
-
- return "(%s)" % ", ".join(sig)
-
-
-def fromFunction(func, interface=None, imlevel=0, name=None):
- name = name or func.__name__
- method = Method(name, func.__doc__)
- defaults = func.func_defaults or ()
- code = func.func_code
- # Number of positional arguments
- na = code.co_argcount-imlevel
- names = code.co_varnames[imlevel:]
- opt = {}
- # Number of required arguments
- nr = na-len(defaults)
- if nr < 0:
- defaults=defaults[-nr:]
- nr = 0
-
- # Determine the optional arguments.
- opt.update(dict(zip(names[nr:], defaults)))
-
- method.positional = names[:na]
- method.required = names[:nr]
- method.optional = opt
-
- argno = na
-
- # Determine the function's variable argument's name (i.e. *args)
- if code.co_flags & CO_VARARGS:
- method.varargs = names[argno]
- argno = argno + 1
- else:
- method.varargs = None
-
- # Determine the function's keyword argument's name (i.e. **kw)
- if code.co_flags & CO_VARKEYWORDS:
- method.kwargs = names[argno]
- else:
- method.kwargs = None
-
- method.interface = interface
-
- for key, value in func.__dict__.items():
- method.setTaggedValue(key, value)
-
- return method
-
-
-def fromMethod(meth, interface=None, name=None):
- func = meth.im_func
- return fromFunction(func, interface, imlevel=1, name=name)
-
-
-# Now we can create the interesting interfaces and wire them up:
-def _wire():
- from zope.interface.declarations import classImplements
-
- from zope.interface.interfaces import IAttribute
- classImplements(Attribute, IAttribute)
-
- from zope.interface.interfaces import IMethod
- classImplements(Method, IMethod)
-
- from zope.interface.interfaces import IInterface
- classImplements(InterfaceClass, IInterface)
-
-# We import this here to deal with module dependencies.
-from zope.interface.declarations import providedBy, implementedBy
-from zope.interface.exceptions import InvalidInterface
-from zope.interface.exceptions import BrokenImplementation
=== removed file 'lib/zope/interface/interfaces.py'
--- lib/zope/interface/interfaces.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/interfaces.py 1970-01-01 00:00:00 +0000
@@ -1,695 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Interface Package Interfaces
-
-$Id: interfaces.py 39752 2005-10-30 20:16:09Z srichter $
-"""
-__docformat__ = 'restructuredtext'
-
-
-from zope.interface import Interface
-from zope.interface.interface import Attribute
-
-class IElement(Interface):
- """Objects that have basic documentation and tagged values.
- """
-
- __name__ = Attribute('__name__', 'The object name')
- __doc__ = Attribute('__doc__', 'The object doc string')
-
- def getTaggedValue(tag):
- """Returns the value associated with `tag`.
-
- Raise a `KeyError` of the tag isn't set.
- """
-
- def queryTaggedValue(tag, default=None):
- """Returns the value associated with `tag`.
-
- Return the default value of the tag isn't set.
- """
-
- def getTaggedValueTags():
- """Returns a list of all tags."""
-
- def setTaggedValue(tag, value):
- """Associates `value` with `key`."""
-
-
-class IAttribute(IElement):
- """Attribute descriptors"""
-
- interface = Attribute('interface',
- 'Stores the interface instance in which the '
- 'attribute is located.')
-
-
-class IMethod(IAttribute):
- """Method attributes"""
-
- def getSignatureInfo():
- """Returns the signature information.
-
- This method returns a dictionary with the following keys:
-
- o `positional` - All positional arguments.
-
- o `required` - A list of all required arguments.
-
- o `optional` - A list of all optional arguments.
-
- o `varargs` - The name of the varargs argument.
-
- o `kwargs` - The name of the kwargs argument.
- """
-
- def getSignatureString():
- """Return a signature string suitable for inclusion in documentation.
-
- This method returns the function signature string. For example, if you
- have `func(a, b, c=1, d='f')`, then the signature string is `(a, b,
- c=1, d='f')`.
- """
-
-class ISpecification(Interface):
- """Object Behavioral specifications"""
-
- def extends(other, strict=True):
- """Test whether a specification extends another
-
- The specification extends other if it has other as a base
- interface or if one of it's bases extends other.
-
- If strict is false, then the specification extends itself.
- """
-
- def isOrExtends(other):
- """Test whether the specification is or extends another
- """
-
- def weakref(callback=None):
- """Return a weakref to the specification
-
- This method is, regrettably, needed to allow weakrefs to be
- computed to security-proxied specifications. While the
- zope.interface package does not require zope.security or
- zope.proxy, it has to be able to coexist with it.
-
- """
-
- __bases__ = Attribute("""Base specifications
-
- A tuple if specifications from which this specification is
- directly derived.
-
- """)
-
- __sro__ = Attribute("""Specification-resolution order
-
- A tuple of the specification and all of it's ancestor
- specifications from most specific to least specific.
-
- (This is similar to the method-resolution order for new-style classes.)
- """)
-
- def get(name, default=None):
- """Look up the description for a name
-
- If the named attribute is not defined, the default is
- returned.
- """
-
-
-class IInterface(ISpecification, IElement):
- """Interface objects
-
- Interface objects describe the behavior of an object by containing
- useful information about the object. This information includes:
-
- o Prose documentation about the object. In Python terms, this
- is called the "doc string" of the interface. In this element,
- you describe how the object works in prose language and any
- other useful information about the object.
-
- o Descriptions of attributes. Attribute descriptions include
- the name of the attribute and prose documentation describing
- the attributes usage.
-
- o Descriptions of methods. Method descriptions can include:
-
- - Prose "doc string" documentation about the method and its
- usage.
-
- - A description of the methods arguments; how many arguments
- are expected, optional arguments and their default values,
- the position or arguments in the signature, whether the
- method accepts arbitrary arguments and whether the method
- accepts arbitrary keyword arguments.
-
- o Optional tagged data. Interface objects (and their attributes and
- methods) can have optional, application specific tagged data
- associated with them. Examples uses for this are examples,
- security assertions, pre/post conditions, and other possible
- information you may want to associate with an Interface or its
- attributes.
-
- Not all of this information is mandatory. For example, you may
- only want the methods of your interface to have prose
- documentation and not describe the arguments of the method in
- exact detail. Interface objects are flexible and let you give or
- take any of these components.
-
- Interfaces are created with the Python class statement using
- either Interface.Interface or another interface, as in::
-
- from zope.interface import Interface
-
- class IMyInterface(Interface):
- '''Interface documentation'''
-
- def meth(arg1, arg2):
- '''Documentation for meth'''
-
- # Note that there is no self argument
-
- class IMySubInterface(IMyInterface):
- '''Interface documentation'''
-
- def meth2():
- '''Documentation for meth2'''
-
- You use interfaces in two ways:
-
- o You assert that your object implement the interfaces.
-
- There are several ways that you can assert that an object
- implements an interface:
-
- 1. Call zope.interface.implements in your class definition.
-
- 2. Call zope.interfaces.directlyProvides on your object.
-
- 3. Call 'zope.interface.classImplements' to assert that instances
- of a class implement an interface.
-
- For example::
-
- from zope.interface import classImplements
-
- classImplements(some_class, some_interface)
-
- This approach is useful when it is not an option to modify
- the class source. Note that this doesn't affect what the
- class itself implements, but only what its instances
- implement.
-
- o You query interface meta-data. See the IInterface methods and
- attributes for details.
-
- """
-
- def providedBy(object):
- """Test whether the interface is implemented by the object
-
- Return true of the object asserts that it implements the
- interface, including asserting that it implements an extended
- interface.
- """
-
- def implementedBy(class_):
- """Test whether the interface is implemented by instances of the class
-
- Return true of the class asserts that its instances implement the
- interface, including asserting that they implement an extended
- interface.
- """
-
- def names(all=False):
- """Get the interface attribute names
-
- Return a sequence of the names of the attributes, including
- methods, included in the interface definition.
-
- Normally, only directly defined attributes are included. If
- a true positional or keyword argument is given, then
- attributes defined by base classes will be included.
- """
-
- def namesAndDescriptions(all=False):
- """Get the interface attribute names and descriptions
-
- Return a sequence of the names and descriptions of the
- attributes, including methods, as name-value pairs, included
- in the interface definition.
-
- Normally, only directly defined attributes are included. If
- a true positional or keyword argument is given, then
- attributes defined by base classes will be included.
- """
-
- def __getitem__(name):
- """Get the description for a name
-
- If the named attribute is not defined, a KeyError is raised.
- """
-
- def direct(name):
- """Get the description for the name if it was defined by the interface
-
- If the interface doesn't define the name, returns None.
- """
-
- def validateInvariants(obj, errors=None):
- """Validate invariants
-
- Validate object to defined invariants. If errors is None,
- raises first Invalid error; if errors is a list, appends all errors
- to list, then raises Invalid with the errors as the first element
- of the "args" tuple."""
-
- def __contains__(name):
- """Test whether the name is defined by the interface"""
-
- def __iter__():
- """Return an iterator over the names defined by the interface
-
- The names iterated include all of the names defined by the
- interface directly and indirectly by base interfaces.
- """
-
- __module__ = Attribute("""The name of the module defining the interface""")
-
-class IDeclaration(ISpecification):
- """Interface declaration
-
- Declarations are used to express the interfaces implemented by
- classes or provided by objects.
- """
-
- def __contains__(interface):
- """Test whether an interface is in the specification
-
- Return true if the given interface is one of the interfaces in
- the specification and false otherwise.
- """
-
- def __iter__():
- """Return an iterator for the interfaces in the specification
- """
-
- def flattened():
- """Return an iterator of all included and extended interfaces
-
- An iterator is returned for all interfaces either included in
- or extended by interfaces included in the specifications
- without duplicates. The interfaces are in "interface
- resolution order". The interface resolution order is such that
- base interfaces are listed after interfaces that extend them
- and, otherwise, interfaces are included in the order that they
- were defined in the specification.
- """
-
- def __sub__(interfaces):
- """Create an interface specification with some interfaces excluded
-
- The argument can be an interface or an interface
- specifications. The interface or interfaces given in a
- specification are subtracted from the interface specification.
-
- Removing an interface that is not in the specification does
- not raise an error. Doing so has no effect.
-
- Removing an interface also removes sub-interfaces of the interface.
-
- """
-
- def __add__(interfaces):
- """Create an interface specification with some interfaces added
-
- The argument can be an interface or an interface
- specifications. The interface or interfaces given in a
- specification are added to the interface specification.
-
- Adding an interface that is already in the specification does
- not raise an error. Doing so has no effect.
- """
-
- def __nonzero__():
- """Return a true value of the interface specification is non-empty
- """
-
-class IInterfaceDeclaration(Interface):
- """Declare and check the interfaces of objects
-
- The functions defined in this interface are used to declare the
- interfaces that objects provide and to query the interfaces that have
- been declared.
-
- Interfaces can be declared for objects in two ways:
-
- - Interfaces are declared for instances of the object's class
-
- - Interfaces are declared for the object directly.
-
- The interfaces declared for an object are, therefore, the union of
- interfaces declared for the object directly and the interfaces
- declared for instances of the object's class.
-
- Note that we say that a class implements the interfaces provided
- by it's instances. An instance can also provide interfaces
- directly. The interfaces provided by an object are the union of
- the interfaces provided directly and the interfaces implemented by
- the class.
- """
-
- def providedBy(ob):
- """Return the interfaces provided by an object
-
- This is the union of the interfaces directly provided by an
- object and interfaces implemented by it's class.
-
- The value returned is an IDeclaration.
- """
-
- def implementedBy(class_):
- """Return the interfaces implemented for a class' instances
-
- The value returned is an IDeclaration.
- """
-
- def classImplements(class_, *interfaces):
- """Declare additional interfaces implemented for instances of a class
-
- The arguments after the class are one or more interfaces or
- interface specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) are added to any interfaces previously
- declared.
-
- Consider the following example::
-
- class C(A, B):
- ...
-
- classImplements(C, I1, I2)
-
-
- Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
- instances of ``A`` and ``B`` provide.
- """
-
- def implementer(*interfaces):
- """Create a decorator for declaring interfaces implemented by a facory
-
- A callable is returned that makes an implements declaration on
- objects passed to it.
- """
-
- def classImplementsOnly(class_, *interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- The arguments after the class are one or more interfaces or
- interface specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) replace any previous declarations.
-
- Consider the following example::
-
- class C(A, B):
- ...
-
- classImplements(C, IA, IB. IC)
- classImplementsOnly(C. I1, I2)
-
- Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
- whatever interfaces instances of ``A`` and ``B`` implement.
- """
-
- def directlyProvidedBy(object):
- """Return the interfaces directly provided by the given object
-
- The value returned is an IDeclaration.
- """
-
- def directlyProvides(object, *interfaces):
- """Declare interfaces declared directly for an object
-
- The arguments after the object are one or more interfaces or
- interface specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) replace interfaces previously
- declared for the object.
-
- Consider the following example::
-
- class C(A, B):
- ...
-
- ob = C()
- directlyProvides(ob, I1, I2)
-
- The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
- instances have been declared for instances of ``C``.
-
- To remove directly provided interfaces, use ``directlyProvidedBy`` and
- subtract the unwanted interfaces. For example::
-
- directlyProvides(ob, directlyProvidedBy(ob)-I2)
-
- removes I2 from the interfaces directly provided by
- ``ob``. The object, ``ob`` no longer directly provides ``I2``,
- although it might still provide ``I2`` if it's class
- implements ``I2``.
-
- To add directly provided interfaces, use ``directlyProvidedBy`` and
- include additional interfaces. For example::
-
- directlyProvides(ob, directlyProvidedBy(ob), I2)
-
- adds I2 to the interfaces directly provided by ob.
- """
-
- def alsoProvides(object, *interfaces):
- """Declare additional interfaces directly for an object::
-
- alsoProvides(ob, I1)
-
- is equivalent to::
-
- directivelyProvides(ob, directlyProvidedBy(ob), I1)
- """
-
- def noLongerProvides(object, interface):
- """Remove an interface from the list of an object's directly
- provided interfaces::
-
- noLongerProvides(ob, I1)
-
- is equivalent to::
-
- directlyProvides(ob, directlyProvidedBy(ob)-I1)
-
- with the exception that if ``I1`` is an interface that is
- provided by ``ob`` through the class's implementation,
- ValueError is raised.
- """
-
- def implements(*interfaces):
- """Declare interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- The interfaces given (including the interfaces in the
- specifications) are added to any interfaces previously
- declared.
-
- Previous declarations include declarations for base classes
- unless implementsOnly was used.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplements. For example::
-
- implements(I1)
-
- is equivalent to calling::
-
- classImplements(C, I1)
-
- after the class has been created.
-
- Consider the following example::
-
- class C(A, B):
- implements(I1, I2)
-
-
- Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
- instances of ``A`` and ``B`` implement.
- """
-
- def implementsOnly(*interfaces):
- """Declare the only interfaces implemented by instances of a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- Previous declarations including declarations for base classes
- are overridden.
-
- This function is provided for convenience. It provides a more
- convenient way to call classImplementsOnly. For example::
-
- implementsOnly(I1)
-
- is equivalent to calling::
-
- classImplementsOnly(I1)
-
- after the class has been created.
-
- Consider the following example::
-
- class C(A, B):
- implementsOnly(I1, I2)
-
-
- Instances of ``C`` implement ``I1``, ``I2``, regardless of what
- instances of ``A`` and ``B`` implement.
- """
-
- def classProvides(*interfaces):
- """Declare interfaces provided directly by a class
-
- This function is called in a class definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- The given interfaces (including the interfaces in the
- specifications) are used to create the class's direct-object
- interface specification. An error will be raised if the module
- class has an direct interface specification. In other words, it is
- an error to call this function more than once in a class
- definition.
-
- Note that the given interfaces have nothing to do with the
- interfaces implemented by instances of the class.
-
- This function is provided for convenience. It provides a more
- convenient way to call directlyProvides for a class. For example::
-
- classProvides(I1)
-
- is equivalent to calling::
-
- directlyProvides(theclass, I1)
-
- after the class has been created.
- """
-
- def moduleProvides(*interfaces):
- """Declare interfaces provided by a module
-
- This function is used in a module definition.
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- The given interfaces (including the interfaces in the
- specifications) are used to create the module's direct-object
- interface specification. An error will be raised if the module
- already has an interface specification. In other words, it is
- an error to call this function more than once in a module
- definition.
-
- This function is provided for convenience. It provides a more
- convenient way to call directlyProvides for a module. For example::
-
- moduleImplements(I1)
-
- is equivalent to::
-
- directlyProvides(sys.modules[__name__], I1)
- """
-
- def Declaration(*interfaces):
- """Create an interface specification
-
- The arguments are one or more interfaces or interface
- specifications (IDeclaration objects).
-
- A new interface specification (IDeclaration) with
- the given interfaces is returned.
- """
-
-class IAdapterRegistry(Interface):
- """Provide an interface-based registry for adapters
-
- This registry registers objects that are in some sense "from" a
- sequence of specification to an interface and a name.
-
- No specific semantics are assumed for the registered objects,
- however, the most common application will be to register factories
- that adapt objects providing required specifications to a provided
- interface.
- """
-
- def register(required, provided, name, value):
- """Register a value
-
- A value is registered for a *sequence* of required specifications, a
- provided interface, and a name.
- """
-
- def lookup(required, provided, name, default=None):
- """Lookup a value
-
- A value is looked up based on a *sequence* of required
- specifications, a provided interface, and a name.
- """
-
- def lookupAll(required, provided):
- """Find all adapters from the required to the provided interfaces
-
- An iterable object is returned that provides name-value two-tuples.
- """
-
- def names(required, provided):
- """Return the names for which there are registered objects
- """
-
- def subscribe(required, provided, subscriber):
- """Register a subscriber
-
- A subscriber is registered for a *sequence* of required
- specifications, a provided interface, and a name.
-
- Multiple subscribers may be registered for the same (or
- equivalent) interfaces.
- """
-
- def subscriptions(required, provided):
- """Get a sequence of subscribers
-
- Subscribers for a *sequence* of required interfaces, and a provided
- interface are returned.
- """
=== removed file 'lib/zope/interface/ro.py'
--- lib/zope/interface/ro.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/ro.py 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Compute a resolution order for an object and it's bases
-
-$Id: ro.py 25177 2004-06-02 13:17:31Z jim $
-"""
-
-def ro(object):
- """Compute a "resolution order" for an object
- """
- return mergeOrderings([_flatten(object, [])])
-
-def mergeOrderings(orderings, seen=None):
- """Merge multiple orderings so that within-ordering order is preserved
-
- Orderings are constrained in such a way that if an object appears
- in two or more orderings, then the suffix that begins with the
- object must be in both orderings.
-
- For example:
-
- >>> _mergeOrderings([
- ... ['x', 'y', 'z'],
- ... ['q', 'z'],
- ... [1, 3, 5],
- ... ['z']
- ... ])
- ['x', 'y', 'q', 1, 3, 5, 'z']
-
- """
-
- if seen is None:
- seen = {}
- result = []
- orderings.reverse()
- for ordering in orderings:
- ordering = list(ordering)
- ordering.reverse()
- for o in ordering:
- if o not in seen:
- seen[o] = 1
- result.append(o)
-
- result.reverse()
- return result
-
-def _flatten(ob, result):
- result.append(ob)
- for base in ob.__bases__:
- _flatten(base, result)
-
- return result
=== removed directory 'lib/zope/interface/tests'
=== removed file 'lib/zope/interface/tests/__init__.py'
--- lib/zope/interface/tests/__init__.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-#
-# This file is necessary to make this directory a package.
=== removed file 'lib/zope/interface/tests/dummy.py'
--- lib/zope/interface/tests/dummy.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/dummy.py 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Dummy Module
-
-$Id$
-"""
-from zope.interface import moduleProvides
-from zope.interface.tests.ifoo import IFoo
-from zope.interface import moduleProvides
-
-moduleProvides(IFoo)
-
-def bar(baz):
- pass
=== removed file 'lib/zope/interface/tests/foodforthought.txt'
--- lib/zope/interface/tests/foodforthought.txt 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/foodforthought.txt 1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-================================
-Food-based subscription examples
-================================
-
-
-This file gives more subscription examples using a cooking-based example::
-
- >>> from zope.interface.adapter import AdapterRegistry
- >>> registry = AdapterRegistry()
-
- >>> import zope.interface
- >>> class IAnimal(zope.interface.Interface):
- ... pass
- >>> class IPoultry(IAnimal):
- ... pass
- >>> class IChicken(IPoultry):
- ... pass
- >>> class ISeafood(IAnimal):
- ... pass
-
-Adapting to some other interface for which there is no
-subscription adapter returns an empty sequence::
-
- >>> class IRecipe(zope.interface.Interface):
- ... pass
- >>> class ISausages(IRecipe):
- ... pass
- >>> class INoodles(IRecipe):
- ... pass
- >>> class IKFC(IRecipe):
- ... pass
-
- >>> list(registry.subscriptions([IPoultry], IRecipe))
- []
-
-unless we define a subscription::
-
- >>> registry.subscribe([IAnimal], ISausages, 'sausages')
- >>> list(registry.subscriptions([IPoultry], ISausages))
- ['sausages']
-
-And define another subscription adapter::
-
- >>> registry.subscribe([IPoultry], INoodles, 'noodles')
- >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
- >>> meals.sort()
- >>> meals
- ['noodles', 'sausages']
-
- >>> registry.subscribe([IChicken], IKFC, 'kfc')
- >>> meals = list(registry.subscriptions([IChicken], IRecipe))
- >>> meals.sort()
- >>> meals
- ['kfc', 'noodles', 'sausages']
-
-And the answer for poultry hasn't changed::
-
- >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
- >>> meals.sort()
- >>> meals
- ['noodles', 'sausages']
=== removed file 'lib/zope/interface/tests/ifoo.py'
--- lib/zope/interface/tests/ifoo.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/ifoo.py 1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""IFoo test module
-
-$Id$
-"""
-from zope.interface import Interface
-
-class IFoo(Interface):
- """
- Dummy interface for unit tests.
- """
-
- def bar(baz):
- """
- Just a note.
- """
=== removed file 'lib/zope/interface/tests/m1.py'
--- lib/zope/interface/tests/m1.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/m1.py 1970-01-01 00:00:00 +0000
@@ -1,23 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""Test module that declares an interface
-
-$Id$
-"""
-from zope.interface import Interface, moduleProvides
-
-class I1(Interface): pass
-class I2(Interface): pass
-
-moduleProvides(I1, I2)
=== removed file 'lib/zope/interface/tests/m2.py'
--- lib/zope/interface/tests/m2.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/m2.py 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""Test module that doesn't declare an interface
-
-$Id$
-"""
=== removed file 'lib/zope/interface/tests/odd.py'
--- lib/zope/interface/tests/odd.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/odd.py 1970-01-01 00:00:00 +0000
@@ -1,129 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Odd meta class that doesn't subclass type.
-
-This is used for testing support for ExtensionClass in new interfaces.
-
- >>> class A(object):
- ... __metaclass__ = MetaClass
- ... a = 1
- ...
- >>> A.__name__
- 'A'
- >>> A.__bases__
- ()
- >>> class B(object):
- ... __metaclass__ = MetaClass
- ... b = 1
- ...
- >>> class C(A, B): pass
- ...
- >>> C.__name__
- 'C'
- >>> int(C.__bases__ == (A, B))
- 1
- >>> a = A()
- >>> aa = A()
- >>> a.a
- 1
- >>> aa.a
- 1
- >>> aa.a = 2
- >>> a.a
- 1
- >>> aa.a
- 2
- >>> c = C()
- >>> c.a
- 1
- >>> c.b
- 1
- >>> c.b = 2
- >>> c.b
- 2
- >>> C.c = 1
- >>> c.c
- 1
- >>> from types import ClassType
- >>> int(isinstance(C, (type, ClassType)))
- 0
- >>> int(C.__class__.__class__ is C.__class__)
- 1
-
-$Id: odd.py 38178 2005-08-30 21:50:19Z mj $
-"""
-
-# class OddClass is an odd meta class
-
-class MetaMetaClass(type):
-
- def __getattribute__(self, name):
- if name == '__class__':
- return self
- return type.__getattribute__(self, name)
-
-
-class MetaClass(object):
- """Odd classes
- """
- __metaclass__ = MetaMetaClass
-
- def __init__(self, name, bases, dict):
- self.__name__ = name
- self.__bases__ = bases
- self.__dict__.update(dict)
-
- def __call__(self):
- return OddInstance(self)
-
- def __getattr__(self, name):
- for b in self.__bases__:
- v = getattr(b, name, self)
- if v is not self:
- return v
- raise AttributeError(name)
-
- def __repr__(self):
- return "<odd class %s at %s>" % (self.__name__, hex(id(self)))
-
-class OddInstance(object):
-
- def __init__(self, cls):
- self.__dict__['__class__'] = cls
-
- def __getattribute__(self, name):
- dict = object.__getattribute__(self, '__dict__')
- if name == '__dict__':
- return dict
- v = dict.get(name, self)
- if v is not self:
- return v
- return getattr(dict['__class__'], name)
-
- def __setattr__(self, name, v):
- self.__dict__[name] = v
-
- def __delattr__(self, name):
- del self.__dict__[name]
-
- def __repr__(self):
- return "<odd %s instance at %s>" % (
- self.__class__.__name__, hex(id(self)))
-
-
-
-# DocTest:
-if __name__ == "__main__":
- import doctest, __main__
- doctest.testmod(__main__, isprivate=lambda *a: False)
=== removed file 'lib/zope/interface/tests/test_adapter.py'
--- lib/zope/interface/tests/test_adapter.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_adapter.py 1970-01-01 00:00:00 +0000
@@ -1,336 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Adapter registry tests
-
-$Id: test_adapter.py 40385 2005-11-27 21:58:28Z jim $
-"""
-import unittest
-import zope.interface
-from zope.interface.adapter import AdapterRegistry
-import zope.interface
-
-class IF0(zope.interface.Interface):
- pass
-class IF1(IF0):
- pass
-
-class IB0(zope.interface.Interface):
- pass
-class IB1(IB0):
- pass
-
-class IR0(zope.interface.Interface):
- pass
-class IR1(IR0):
- pass
-
-def test_multi_adapter_get_best_match():
- """
- >>> registry = AdapterRegistry()
-
- >>> class IB2(IB0):
- ... pass
- >>> class IB3(IB2, IB1):
- ... pass
- >>> class IB4(IB1, IB2):
- ... pass
-
- >>> registry.register([None, IB1], IR0, '', 'A1')
- >>> registry.register([None, IB0], IR0, '', 'A0')
- >>> registry.register([None, IB2], IR0, '', 'A2')
-
- >>> registry.lookup((IF1, IB1), IR0, '')
- 'A1'
- >>> registry.lookup((IF1, IB2), IR0, '')
- 'A2'
- >>> registry.lookup((IF1, IB0), IR0, '')
- 'A0'
- >>> registry.lookup((IF1, IB3), IR0, '')
- 'A2'
- >>> registry.lookup((IF1, IB4), IR0, '')
- 'A1'
- """
-
-def test_multi_adapter_lookupAll_get_best_matches():
- """
- >>> registry = AdapterRegistry()
-
- >>> class IB2(IB0):
- ... pass
- >>> class IB3(IB2, IB1):
- ... pass
- >>> class IB4(IB1, IB2):
- ... pass
-
- >>> registry.register([None, IB1], IR0, '', 'A1')
- >>> registry.register([None, IB0], IR0, '', 'A0')
- >>> registry.register([None, IB2], IR0, '', 'A2')
-
- >>> registry.lookupAll((IF1, IB1), IR0).next()[1]
- 'A1'
- >>> registry.lookupAll((IF1, IB2), IR0).next()[1]
- 'A2'
- >>> registry.lookupAll((IF1, IB0), IR0).next()[1]
- 'A0'
- >>> registry.lookupAll((IF1, IB3), IR0).next()[1]
- 'A2'
- >>> registry.lookupAll((IF1, IB4), IR0).next()[1]
- 'A1'
- """
-
-
-def test_multi_adapter_w_default():
- """
- >>> registry = AdapterRegistry()
-
- >>> registry.register([None, None], IB1, 'bob', 'A0')
-
- >>> registry.lookup((IF1, IR1), IB0, 'bob')
- 'A0'
-
- >>> registry.register([None, IR0], IB1, 'bob', 'A1')
-
- >>> registry.lookup((IF1, IR1), IB0, 'bob')
- 'A1'
-
- >>> registry.lookup((IF1, IR1), IB0, 'bruce')
-
- >>> registry.register([None, IR1], IB1, 'bob', 'A2')
- >>> registry.lookup((IF1, IR1), IB0, 'bob')
- 'A2'
- """
-
-def test_multi_adapter_w_inherited_and_multiple_registrations():
- """
- >>> registry = AdapterRegistry()
-
- >>> class IX(zope.interface.Interface):
- ... pass
-
- >>> registry.register([IF0, IR0], IB1, 'bob', 'A1')
- >>> registry.register([IF1, IX], IB1, 'bob', 'AX')
-
- >>> registry.lookup((IF1, IR1), IB0, 'bob')
- 'A1'
- """
-
-def test_named_adapter_with_default():
- """Query a named simple adapter
-
- >>> registry = AdapterRegistry()
-
- If we ask for a named adapter, we won't get a result unless there
- is a named adapter, even if the object implements the interface:
-
- >>> registry.lookup([IF1], IF0, 'bob')
-
- >>> registry.register([None], IB1, 'bob', 'A1')
- >>> registry.lookup([IF1], IB0, 'bob')
- 'A1'
-
- >>> registry.lookup([IF1], IB0, 'bruce')
-
- >>> registry.register([None], IB0, 'bob', 'A2')
- >>> registry.lookup([IF1], IB0, 'bob')
- 'A2'
- """
-
-def test_multi_adapter_gets_closest_provided():
- """
- >>> registry = AdapterRegistry()
- >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
- >>> registry.register((IF1, IR0), IB1, 'bob', 'A2')
- >>> registry.lookup((IF1, IR1), IB0, 'bob')
- 'A1'
-
- >>> registry = AdapterRegistry()
- >>> registry.register([IF1, IR0], IB1, 'bob', 'A2')
- >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
- >>> registry.lookup([IF1, IR0], IB0, 'bob')
- 'A1'
-
- >>> registry = AdapterRegistry()
- >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
- >>> registry.register([IF1, IR1], IB1, 'bob', 'A2')
- >>> registry.lookup([IF1, IR1], IB0, 'bob')
- 'A2'
-
- >>> registry = AdapterRegistry()
- >>> registry.register([IF1, IR1], IB1, 'bob', 2)
- >>> registry.register([IF1, IR0], IB0, 'bob', 1)
- >>> registry.lookup([IF1, IR1], IB0, 'bob')
- 2
- """
-
-def test_multi_adapter_check_non_default_dont_hide_default():
- """
- >>> registry = AdapterRegistry()
-
- >>> class IX(zope.interface.Interface):
- ... pass
-
-
- >>> registry.register([None, IR0], IB0, 'bob', 1)
- >>> registry.register([IF1, IX], IB0, 'bob', 2)
- >>> registry.lookup([IF1, IR1], IB0, 'bob')
- 1
- """
-
-def test_adapter_hook_with_factory_producing_None():
- """
- >>> registry = AdapterRegistry()
- >>> default = object()
-
- >>> class Object1(object):
- ... zope.interface.implements(IF0)
- >>> class Object2(object):
- ... zope.interface.implements(IF0)
-
- >>> def factory(context):
- ... if isinstance(context, Object1):
- ... return 'adapter'
- ... return None
-
- >>> registry.register([IF0], IB0, '', factory)
-
- >>> registry.adapter_hook(IB0, Object1())
- 'adapter'
- >>> registry.adapter_hook(IB0, Object2()) is None
- True
- >>> registry.adapter_hook(IB0, Object2(), default=default) is default
- True
- """
-
-def test_adapter_registry_update_upon_interface_bases_change():
- """
- Let's first create a adapter registry and a simple adaptation hook:
-
- >>> globalRegistry = AdapterRegistry()
-
- >>> def _hook(iface, ob, lookup=globalRegistry.lookup1):
- ... factory = lookup(zope.interface.providedBy(ob), iface)
- ... if factory is None:
- ... return None
- ... else:
- ... return factory(ob)
-
- >>> zope.interface.interface.adapter_hooks.append(_hook)
-
- Now we create some interfaces and an implementation:
-
- >>> class IX(zope.interface.Interface):
- ... pass
-
- >>> class IY(zope.interface.Interface):
- ... pass
-
- >>> class X(object):
- ... pass
-
- >>> class Y(object):
- ... zope.interface.implements(IY)
- ... def __init__(self, original):
- ... self.original=original
-
- and register an adapter:
-
- >>> globalRegistry.register((IX,), IY, '', Y)
-
- at first, we still expect the adapter lookup from `X` to `IY` to fail:
-
- >>> IY(X()) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt',
- <zope.interface.tests.test_adapter.X object at ...>,
- <InterfaceClass zope.interface.tests.test_adapter.IY>)
-
- But after we declare an interface on the class `X`, it should pass:
-
- >>> zope.interface.classImplementsOnly(X, IX)
-
- >>> IY(X()) #doctest: +ELLIPSIS
- <zope.interface.tests.test_adapter.Y object at ...>
-
- >>> hook = zope.interface.interface.adapter_hooks.pop()
- """
-
-
-def test_changing_declarations():
- """
-
- If we change declarations for a class, those adapter lookup should
- eflect the changes:
-
- >>> class I1(zope.interface.Interface):
- ... pass
- >>> class I2(zope.interface.Interface):
- ... pass
-
- >>> registry = AdapterRegistry()
- >>> registry.register([I1], I2, '', 42)
-
- >>> class C:
- ... pass
-
- >>> registry.lookup([zope.interface.implementedBy(C)], I2, '')
-
- >>> zope.interface.classImplements(C, I1)
-
- >>> registry.lookup([zope.interface.implementedBy(C)], I2, '')
- 42
- """
-
-def test_correct_multi_adapter_lookup():
- """
- >>> registry = AdapterRegistry()
- >>> registry.register([IF0, IB1], IR0, '', 'A01')
- >>> registry.register([IF1, IB0], IR0, '', 'A10')
- >>> registry.lookup((IF1, IB1), IR0, '')
- 'A10'
- """
-
-def test_duplicate_bases():
- """
-There was a bug that caused problems if a spec had multiple bases:
-
- >>> class I(zope.interface.Interface):
- ... pass
- >>> class I2(I, I):
- ... pass
- >>> registry = AdapterRegistry()
- >>> registry.register([I2], IR0, 'x', 'X')
- >>> registry.lookup((I2, ), IR0, 'x')
- 'X'
- >>> registry.register([I2], IR0, 'y', 'Y')
- >>> registry.lookup((I2, ), IR0, 'x')
- 'X'
- >>> registry.lookup((I2, ), IR0, 'y')
- 'Y'
-
-
-
-"""
-
-def test_suite():
- from zope.testing import doctest, doctestunit
- return unittest.TestSuite((
- doctestunit.DocFileSuite('../adapter.txt', '../human.txt',
- 'foodforthought.txt',
- globs={'__name__': '__main__'}),
- doctest.DocTestSuite(),
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
=== removed file 'lib/zope/interface/tests/test_advice.py'
--- lib/zope/interface/tests/test_advice.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_advice.py 1970-01-01 00:00:00 +0000
@@ -1,178 +0,0 @@
-
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Tests for advice
-
-This module was adapted from 'protocols.tests.advice', part of the Python
-Enterprise Application Kit (PEAK). Please notify the PEAK authors
-(pje@xxxxxxxxxxxxxxxxx and tsarna@xxxxxxxxx) if bugs are found or
-Zope-specific changes are required, so that the PEAK version of this module
-can be kept in sync.
-
-PEAK is a Python application framework that interoperates with (but does
-not require) Zope 3 and Twisted. It provides tools for manipulating UML
-models, object-relational persistence, aspect-oriented programming, and more.
-Visit the PEAK home page at http://peak.telecommunity.com for more information.
-
-$Id: test_advice.py 40833 2005-12-16 21:32:26Z benji_york $
-"""
-
-import unittest
-from unittest import TestCase, makeSuite, TestSuite
-from zope.interface.advice import *
-from types import ClassType
-import sys
-
-def ping(log, value):
-
- def pong(klass):
- log.append((value,klass))
- return [klass]
-
- addClassAdvisor(pong)
-
-class ClassicClass:
- __metaclass__ = ClassType
- classLevelFrameInfo = getFrameInfo(sys._getframe())
-
-class NewStyleClass:
- __metaclass__ = type
- classLevelFrameInfo = getFrameInfo(sys._getframe())
-
-moduleLevelFrameInfo = getFrameInfo(sys._getframe())
-
-class FrameInfoTest(TestCase):
-
- classLevelFrameInfo = getFrameInfo(sys._getframe())
-
- def checkModuleInfo(self):
- kind, module, f_locals, f_globals = moduleLevelFrameInfo
- self.assertEquals(kind, "module")
- for d in module.__dict__, f_locals, f_globals:
- self.assert_(d is globals())
-
- def checkClassicClassInfo(self):
- kind, module, f_locals, f_globals = ClassicClass.classLevelFrameInfo
- self.assertEquals(kind, "class")
-
- self.assert_(f_locals is ClassicClass.__dict__) # ???
- for d in module.__dict__, f_globals:
- self.assert_(d is globals())
-
- def checkNewStyleClassInfo(self):
- kind, module, f_locals, f_globals = NewStyleClass.classLevelFrameInfo
- self.assertEquals(kind, "class")
-
- for d in module.__dict__, f_globals:
- self.assert_(d is globals())
-
- def checkCallInfo(self):
- kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
- self.assertEquals(kind, "function call")
- self.assert_(f_locals is locals()) # ???
- for d in module.__dict__, f_globals:
- self.assert_(d is globals())
-
-
-class AdviceTests(TestCase):
-
- def checkOrder(self):
- log = []
- class Foo(object):
- ping(log, 1)
- ping(log, 2)
- ping(log, 3)
-
- # Strip the list nesting
- for i in 1,2,3:
- self.assert_(isinstance(Foo, list))
- Foo, = Foo
-
- self.assertEquals(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])])
-
- def TODOcheckOutside(self):
- # Disabled because the check does not work with doctest tests.
- try:
- ping([], 1)
- except SyntaxError:
- pass
- else:
- raise AssertionError(
- "Should have detected advice outside class body"
- )
-
- def checkDoubleType(self):
- if sys.hexversion >= 0x02030000:
- return # you can't duplicate bases in 2.3
- class aType(type,type):
- ping([],1)
- aType, = aType
- self.assert_(aType.__class__ is type)
-
- def checkSingleExplicitMeta(self):
-
- class M(type):
- pass
-
- class C(M):
- __metaclass__ = M
- ping([],1)
-
- C, = C
- self.assert_(C.__class__ is M)
-
-
- def checkMixedMetas(self):
-
- class M1(type): pass
- class M2(type): pass
-
- class B1: __metaclass__ = M1
- class B2: __metaclass__ = M2
-
- try:
- class C(B1,B2):
- ping([],1)
- except TypeError:
- pass
- else:
- raise AssertionError("Should have gotten incompatibility error")
-
- class M3(M1,M2): pass
-
- class C(B1,B2):
- __metaclass__ = M3
- ping([],1)
-
- self.assert_(isinstance(C,list))
- C, = C
- self.assert_(isinstance(C,M3))
-
- def checkMetaOfClass(self):
-
- class metameta(type):
- pass
-
- class meta(type):
- __metaclass__ = metameta
-
- self.assertEquals(determineMetaclass((meta, type)), metameta)
-
-TestClasses = (AdviceTests, FrameInfoTest)
-
-def test_suite():
- return TestSuite([makeSuite(t,'check') for t in TestClasses])
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
=== removed file 'lib/zope/interface/tests/test_declarations.py'
--- lib/zope/interface/tests/test_declarations.py 2008-08-29 01:47:36 +0000
+++ lib/zope/interface/tests/test_declarations.py 1970-01-01 00:00:00 +0000
@@ -1,417 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Test the new API for making and checking interface declarations
-
-$Id: test_declarations.py 40082 2005-11-13 17:11:09Z jim $
-"""
-import unittest
-from zope.interface import *
-from zope.testing.doctestunit import DocTestSuite
-from zope.interface import Interface
-
-class I1(Interface): pass
-class I2(Interface): pass
-class I3(Interface): pass
-class I4(Interface): pass
-class I5(Interface): pass
-
-class A(object):
- implements(I1)
-class B(object):
- implements(I2)
-class C(A, B):
- implements(I3)
-
-class COnly(A, B):
- implementsOnly(I3)
-
-class COnly_old(A, B):
- __implemented__ = I3
-
-class D(COnly):
- implements(I5)
-
-def test_ObjectSpecification_Simple():
- """
- >>> c = C()
- >>> directlyProvides(c, I4)
- >>> [i.__name__ for i in providedBy(c)]
- ['I4', 'I3', 'I1', 'I2']
- """
-
-def test_ObjectSpecification_Simple_w_only():
- """
- >>> c = COnly()
- >>> directlyProvides(c, I4)
- >>> [i.__name__ for i in providedBy(c)]
- ['I4', 'I3']
- """
-
-def test_ObjectSpecification_Simple_old_style():
- """
- >>> c = COnly_old()
- >>> directlyProvides(c, I4)
- >>> [i.__name__ for i in providedBy(c)]
- ['I4', 'I3']
- """
-
-
-class Test(unittest.TestCase):
-
- # Note that most of the tests are in the doc strings of the
- # declarations module.
-
- def test_backward_compat(self):
-
- class C1(object): __implemented__ = I1
- class C2(C1): __implemented__ = I2, I5
- class C3(C2): __implemented__ = I3, C2.__implemented__
-
- self.assert_(C3.__implemented__.__class__ is tuple)
-
- self.assertEqual(
- [i.getName() for i in providedBy(C3())],
- ['I3', 'I2', 'I5'],
- )
-
- class C4(C3):
- implements(I4)
-
- self.assertEqual(
- [i.getName() for i in providedBy(C4())],
- ['I4', 'I3', 'I2', 'I5'],
- )
-
- self.assertEqual(
- [i.getName() for i in C4.__implemented__],
- ['I4', 'I3', 'I2', 'I5'],
- )
-
- # Note that C3.__implemented__ should now be a sequence of interfaces
- self.assertEqual(
- [i.getName() for i in C3.__implemented__],
- ['I3', 'I2', 'I5'],
- )
- self.failIf(C3.__implemented__.__class__ is tuple)
-
- def test_module(self):
- import zope.interface.tests.m1
- import zope.interface.tests.m2
- directlyProvides(zope.interface.tests.m2,
- zope.interface.tests.m1.I1,
- zope.interface.tests.m1.I2,
- )
- self.assertEqual(list(providedBy(zope.interface.tests.m1)),
- list(providedBy(zope.interface.tests.m2)),
- )
-
- def test_builtins(self):
- # Setup
-
- intspec = implementedBy(int)
- olddeclared = intspec.declared
-
- classImplements(int, I1)
- class myint(int):
- implements(I2)
-
- x = 42
- self.assertEqual([i.getName() for i in providedBy(x)],
- ['I1'])
-
- x = myint(42)
- directlyProvides(x, I3)
- self.assertEqual([i.getName() for i in providedBy(x)],
- ['I3', 'I2', 'I1'])
-
- # cleanup
- intspec.declared = olddeclared
- classImplements(int)
-
- x = 42
- self.assertEqual([i.getName() for i in providedBy(x)],
- [])
-
-
-def test_invalid_interface_raises_useful_error():
- """
- >>> from zope import interface
- >>> class NotAnInterface(object):
- ... pass
- ...
- >>> class MyObject(object): # doctest: +ELLIPSIS
- ... interface.implements(NotAnInterface)
- ...
- Traceback (most recent call last):
- ...
- InvalidInterface: object <class '...NotAnInterface'> is not a valid interface (expected a class descending from Interface or Implements)
- """
-
-def test_signature_w_no_class_interfaces():
- """
- >>> from zope.interface import *
- >>> class C(object):
- ... pass
- >>> c = C()
- >>> list(providedBy(c))
- []
-
- >>> class I(Interface):
- ... pass
- >>> directlyProvides(c, I)
- >>> list(providedBy(c)) == list(directlyProvidedBy(c))
- 1
- """
-
-def test_classImplement_on_deeply_nested_classes():
- """This test is in response to a bug found, which is why it's a bit
- contrived
-
- >>> from zope.interface import *
- >>> class B1(object):
- ... pass
- >>> class B2(B1):
- ... pass
- >>> class B3(B2):
- ... pass
- >>> class D(object):
- ... implements()
- >>> class S(B3, D):
- ... implements()
-
- This failed due to a bug in the code for finding __providedBy__
- descriptors for old-style classes.
-
- """
-
-def test_pickle_provides_specs():
- """
- >>> from pickle import dumps, loads
- >>> a = A()
- >>> I2.providedBy(a)
- 0
- >>> directlyProvides(a, I2)
- >>> I2.providedBy(a)
- 1
- >>> a2 = loads(dumps(a))
- >>> I2.providedBy(a2)
- 1
-
- """
-
-def test_that_we_dont_inherit_class_provides():
- """
- >>> class X(object):
- ... classProvides(I1)
- >>> class Y(X):
- ... pass
- >>> [i.__name__ for i in X.__provides__]
- ['I1']
- >>> Y.__provides__
- Traceback (most recent call last):
- ...
- AttributeError: __provides__
-
- """
-
-def test_that_we_dont_inherit_provides_optimizations():
- """
-
- When we make a declaration for a class, we install a __provides__
- descriptors that provides a default for instances that don't have
- instance-specific declarations:
-
- >>> class A(object):
- ... implements(I1)
-
- >>> class B(object):
- ... implements(I2)
-
- >>> [i.__name__ for i in A().__provides__]
- ['I1']
- >>> [i.__name__ for i in B().__provides__]
- ['I2']
-
- But it's important that we don't use this for subclasses without
- declarations. This would cause incorrect results:
-
- >>> class X(A, B):
- ... pass
-
- >>> X().__provides__
- Traceback (most recent call last):
- ...
- AttributeError: __provides__
-
- However, if we "induce" a declaration, by calling implementedBy
- (even indirectly through providedBy):
-
- >>> [i.__name__ for i in providedBy(X())]
- ['I1', 'I2']
-
-
- then the optimization will work:
-
- >>> [i.__name__ for i in X().__provides__]
- ['I1', 'I2']
-
- """
-
-def test_classProvides_before_implements():
- """Special descriptor for class __provides__
-
- The descriptor caches the implementedBy info, so that
- we can get declarations for objects without instance-specific
- interfaces a bit quicker.
-
- For example::
-
- >>> from zope.interface import Interface
- >>> class IFooFactory(Interface):
- ... pass
- >>> class IFoo(Interface):
- ... pass
- >>> class C(object):
- ... classProvides(IFooFactory)
- ... implements(IFoo)
- >>> [i.getName() for i in C.__provides__]
- ['IFooFactory']
-
- >>> [i.getName() for i in C().__provides__]
- ['IFoo']
- """
-
-def test_getting_spec_for_proxied_builtin_class():
- """
-
- In general, we should be able to get a spec
- for a proxied class if someone has declared or
- asked for a spec before.
-
- We don't want to depend on proxies in this (zope.interface)
- package, but we do want to work with proxies. Proxies have the
- effect that a class's __dict__ cannot be gotten. Further, for
- built-in classes, we can't save, and thus, cannot get, any class
- attributes. We'll emulate this by treating a plain object as a class:
-
- >>> cls = object()
-
- We'll create an implements specification:
-
- >>> import zope.interface.declarations
- >>> impl = zope.interface.declarations.Implements(I1, I2)
-
- Now, we'll emulate a declaration for a built-in type by putting
- it in BuiltinImplementationSpecifications:
-
- >>> zope.interface.declarations.BuiltinImplementationSpecifications[
- ... cls] = impl
-
- Now, we should be able to get it back:
-
- >>> implementedBy(cls) is impl
- True
-
- Of course, we don't want to leave it there. :)
-
- >>> del zope.interface.declarations.BuiltinImplementationSpecifications[
- ... cls]
-
- """
-
-def test_declaration_get():
- """
- We can get definitions from a declaration:
-
- >>> import zope.interface
- >>> class I1(zope.interface.Interface):
- ... a11 = zope.interface.Attribute('a11')
- ... a12 = zope.interface.Attribute('a12')
- >>> class I2(zope.interface.Interface):
- ... a21 = zope.interface.Attribute('a21')
- ... a22 = zope.interface.Attribute('a22')
- ... a12 = zope.interface.Attribute('a212')
- >>> class I11(I1):
- ... a11 = zope.interface.Attribute('a111')
-
- >>> decl = Declaration(I11, I2)
- >>> decl.get('a11') is I11.get('a11')
- True
- >>> decl.get('a12') is I1.get('a12')
- True
- >>> decl.get('a21') is I2.get('a21')
- True
- >>> decl.get('a22') is I2.get('a22')
- True
- >>> decl.get('a')
- >>> decl.get('a', 42)
- 42
-
- We get None even with no interfaces:
-
- >>> decl = Declaration()
- >>> decl.get('a11')
- >>> decl.get('a11', 42)
- 42
-
- We get new data if e change interface bases:
-
- >>> decl.__bases__ = I11, I2
- >>> decl.get('a11') is I11.get('a11')
- True
- """
-
-def test_classImplements_after_classImplementsOnly_issue_402():
- """http://www.zope.org/Collectors/Zope3-dev/402
-
->>> from zope.interface import *
->>> class I1(Interface):
-... pass
->>> class I2(Interface):
-... pass
->>> class C:
-... implements(I1)
->>> class C2:
-... implementsOnly(I2)
->>> class I3(Interface):
-... pass
-
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'Interface']
-
->>> classImplements(C2, I3)
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'I3', 'Interface']
-
->>> class I4(Interface):
-... pass
->>> classImplements(C2, I4)
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'I3', 'I4', 'Interface']
-
-
-"""
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test))
- suite.addTest(DocTestSuite("zope.interface.declarations"))
- suite.addTest(DocTestSuite())
-
- return suite
-
-
-if __name__ == '__main__':
- unittest.main()
=== removed file 'lib/zope/interface/tests/test_document.py'
--- lib/zope/interface/tests/test_document.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_document.py 1970-01-01 00:00:00 +0000
@@ -1,71 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Documentation tests.
-
-$Id: test_document.py 26560 2004-07-15 21:38:42Z srichter $
-"""
-from unittest import TestCase, main, makeSuite
-
-from zope.interface import Interface, Attribute
-
-class Test(TestCase):
-
- def testBlech(self):
- from zope.interface.document import asStructuredText
-
- self.assertEqual(asStructuredText(I2), '''\
-I2
-
- I2 doc
-
- This interface extends:
-
- o _I1
-
- Attributes:
-
- a1 -- no documentation
-
- a2 -- a2 doc
-
- Methods:
-
- f21() -- f21 doc
-
- f22() -- no documentation
-
- f23() -- f23 doc
-
-''')
-
-
-def test_suite():
- return makeSuite(Test)
-
-class _I1(Interface):
- def f11(): pass
- def f12(): pass
-
-class I2(_I1):
- "I2 doc"
-
- a1 = Attribute('a1')
- a2 = Attribute('a2', 'a2 doc')
-
- def f21(): "f21 doc"
- def f22(): pass
- def f23(): "f23 doc"
-
-if __name__=='__main__':
- main(defaultTest='test_suite')
=== removed file 'lib/zope/interface/tests/test_element.py'
--- lib/zope/interface/tests/test_element.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_element.py 1970-01-01 00:00:00 +0000
@@ -1,43 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Test Element meta-class.
-
-$Id: test_element.py 39768 2005-10-31 13:57:35Z tlotze $
-"""
-
-import unittest
-from zope.interface.interface import Element
-
-class TestElement(unittest.TestCase):
-
- def test_taggedValues(self):
- """Test that we can update tagged values of more than one element
- """
-
- e1 = Element("foo")
- e2 = Element("bar")
- e1.setTaggedValue("x", 1)
- e2.setTaggedValue("x", 2)
- self.assertEqual(e1.getTaggedValue("x"), 1)
- self.assertEqual(e2.getTaggedValue("x"), 2)
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestElement))
- return suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
=== removed file 'lib/zope/interface/tests/test_interface.py'
--- lib/zope/interface/tests/test_interface.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_interface.py 1970-01-01 00:00:00 +0000
@@ -1,353 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Test Interface implementation
-
-$Id: test_interface.py 40385 2005-11-27 21:58:28Z jim $
-"""
-import sys
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-from zope.interface.tests.unitfixtures import * # hehehe
-from zope.interface.exceptions import BrokenImplementation, Invalid
-from zope.interface import implementedBy, providedBy
-from zope.interface import Interface, directlyProvides, Attribute
-from zope import interface
-
-class InterfaceTests(unittest.TestCase):
-
- def testInterfaceSetOnAttributes(self):
- self.assertEqual(FooInterface['foobar'].interface,
- FooInterface)
- self.assertEqual(FooInterface['aMethod'].interface,
- FooInterface)
-
- def testClassImplements(self):
- self.assert_(IC.implementedBy(C))
-
- self.assert_(I1.implementedBy(A))
- self.assert_(I1.implementedBy(B))
- self.assert_(not I1.implementedBy(C))
- self.assert_(I1.implementedBy(D))
- self.assert_(I1.implementedBy(E))
-
- self.assert_(not I2.implementedBy(A))
- self.assert_(I2.implementedBy(B))
- self.assert_(not I2.implementedBy(C))
-
- # No longer after interfacegeddon
- # self.assert_(not I2.implementedBy(D))
-
- self.assert_(not I2.implementedBy(E))
-
- def testUtil(self):
- self.assert_(IC in implementedBy(C))
- self.assert_(I1 in implementedBy(A))
- self.assert_(not I1 in implementedBy(C))
- self.assert_(I2 in implementedBy(B))
- self.assert_(not I2 in implementedBy(C))
-
- self.assert_(IC in providedBy(C()))
- self.assert_(I1 in providedBy(A()))
- self.assert_(not I1 in providedBy(C()))
- self.assert_(I2 in providedBy(B()))
- self.assert_(not I2 in providedBy(C()))
-
-
- def testObjectImplements(self):
- self.assert_(IC.providedBy(C()))
-
- self.assert_(I1.providedBy(A()))
- self.assert_(I1.providedBy(B()))
- self.assert_(not I1.providedBy(C()))
- self.assert_(I1.providedBy(D()))
- self.assert_(I1.providedBy(E()))
-
- self.assert_(not I2.providedBy(A()))
- self.assert_(I2.providedBy(B()))
- self.assert_(not I2.providedBy(C()))
-
- # Not after interface geddon
- # self.assert_(not I2.providedBy(D()))
-
- self.assert_(not I2.providedBy(E()))
-
- def testDeferredClass(self):
- a = A()
- self.assertRaises(BrokenImplementation, a.ma)
-
-
- def testInterfaceExtendsInterface(self):
- self.assert_(BazInterface.extends(BobInterface))
- self.assert_(BazInterface.extends(BarInterface))
- self.assert_(BazInterface.extends(FunInterface))
- self.assert_(not BobInterface.extends(FunInterface))
- self.assert_(not BobInterface.extends(BarInterface))
- self.assert_(BarInterface.extends(FunInterface))
- self.assert_(not BarInterface.extends(BazInterface))
-
- def testVerifyImplementation(self):
- from zope.interface.verify import verifyClass
- self.assert_(verifyClass(FooInterface, Foo))
- self.assert_(Interface.providedBy(I1))
-
- def test_names(self):
- names = list(_I2.names()); names.sort()
- self.assertEqual(names, ['f21', 'f22', 'f23'])
- names = list(_I2.names(all=True)); names.sort()
- self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
-
- def test_namesAndDescriptions(self):
- names = [nd[0] for nd in _I2.namesAndDescriptions()]; names.sort()
- self.assertEqual(names, ['f21', 'f22', 'f23'])
- names = [nd[0] for nd in _I2.namesAndDescriptions(1)]; names.sort()
- self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
-
- for name, d in _I2.namesAndDescriptions(1):
- self.assertEqual(name, d.__name__)
-
- def test_getDescriptionFor(self):
- self.assertEqual(_I2.getDescriptionFor('f11').__name__, 'f11')
- self.assertEqual(_I2.getDescriptionFor('f22').__name__, 'f22')
- self.assertEqual(_I2.queryDescriptionFor('f33', self), self)
- self.assertRaises(KeyError, _I2.getDescriptionFor, 'f33')
-
- def test___getitem__(self):
- self.assertEqual(_I2['f11'].__name__, 'f11')
- self.assertEqual(_I2['f22'].__name__, 'f22')
- self.assertEqual(_I2.get('f33', self), self)
- self.assertRaises(KeyError, _I2.__getitem__, 'f33')
-
- def test___contains__(self):
- self.failUnless('f11' in _I2)
- self.failIf('f33' in _I2)
-
- def test___iter__(self):
- names = list(iter(_I2))
- names.sort()
- self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
-
- def testAttr(self):
- description = _I2.getDescriptionFor('a1')
- self.assertEqual(description.__name__, 'a1')
- self.assertEqual(description.__doc__, 'This is an attribute')
-
- def testFunctionAttributes(self):
- # Make sure function attributes become tagged values.
- meth = _I1['f12']
- self.assertEqual(meth.getTaggedValue('optional'), 1)
-
- def testInvariant(self):
- # set up
- o = InvariantC()
- directlyProvides(o, IInvariant)
- # a helper
- def errorsEqual(self, o, error_len, error_msgs, interface=None):
- if interface is None:
- interface = IInvariant
- self.assertRaises(Invalid, interface.validateInvariants, o)
- e = []
- try:
- interface.validateInvariants(o, e)
- except Invalid, error:
- self.assertEquals(error.args[0], e)
- else:
- self._assert(0) # validateInvariants should always raise
- # Invalid
- self.assertEquals(len(e), error_len)
- msgs = [error.args[0] for error in e]
- msgs.sort()
- for msg in msgs:
- self.assertEquals(msg, error_msgs.pop(0))
- # the tests
- self.assertEquals(IInvariant.getTaggedValue('invariants'),
- [ifFooThenBar])
- self.assertEquals(IInvariant.validateInvariants(o), None)
- o.bar = 27
- self.assertEquals(IInvariant.validateInvariants(o), None)
- o.foo = 42
- self.assertEquals(IInvariant.validateInvariants(o), None)
- del o.bar
- errorsEqual(self, o, 1, ['If Foo, then Bar!'])
- # nested interfaces with invariants:
- self.assertEquals(ISubInvariant.getTaggedValue('invariants'),
- [BarGreaterThanFoo])
- o = InvariantC()
- directlyProvides(o, ISubInvariant)
- o.foo = 42
- # even though the interface has changed, we should still only have one
- # error.
- errorsEqual(self, o, 1, ['If Foo, then Bar!'], ISubInvariant)
- # however, if we set foo to 0 (Boolean False) and bar to a negative
- # number then we'll get the new error
- o.foo = 2
- o.bar = 1
- errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'],
- ISubInvariant)
- # and if we set foo to a positive number and boo to 0, we'll
- # get both errors!
- o.foo = 1
- o.bar = 0
- errorsEqual(self, o, 2, ['If Foo, then Bar!',
- 'Please, Boo MUST be greater than Foo!'],
- ISubInvariant)
- # for a happy ending, we'll make the invariants happy
- o.foo = 1
- o.bar = 2
- self.assertEquals(IInvariant.validateInvariants(o), None) # woohoo
- # now we'll do two invariants on the same interface,
- # just to make sure that a small
- # multi-invariant interface is at least minimally tested.
- o = InvariantC()
- directlyProvides(o, IInvariant)
- o.foo = 42
- old_invariants = IInvariant.getTaggedValue('invariants')
- invariants = old_invariants[:]
- invariants.append(BarGreaterThanFoo) # if you really need to mutate,
- # then this would be the way to do it. Probably a bad idea, though. :-)
- IInvariant.setTaggedValue('invariants', invariants)
- #
- # even though the interface has changed, we should still only have one
- # error.
- errorsEqual(self, o, 1, ['If Foo, then Bar!'])
- # however, if we set foo to 0 (Boolean False) and bar to a negative
- # number then we'll get the new error
- o.foo = 2
- o.bar = 1
- errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'])
- # and if we set foo to a positive number and boo to 0, we'll
- # get both errors!
- o.foo = 1
- o.bar = 0
- errorsEqual(self, o, 2, ['If Foo, then Bar!',
- 'Please, Boo MUST be greater than Foo!'])
- # for another happy ending, we'll make the invariants happy again
- o.foo = 1
- o.bar = 2
- self.assertEquals(IInvariant.validateInvariants(o), None) # bliss
- # clean up
- IInvariant.setTaggedValue('invariants', old_invariants)
-
- def test___doc___element(self):
- class I(Interface):
- "xxx"
-
- self.assertEqual(I.__doc__, "xxx")
- self.assertEqual(list(I), [])
-
- class I(Interface):
- "xxx"
-
- __doc__ = Attribute('the doc')
-
- self.assertEqual(I.__doc__, "")
- self.assertEqual(list(I), ['__doc__'])
-
- def testIssue228(self):
- # Test for http://collector.zope.org/Zope3-dev/228
- class I(Interface):
- "xxx"
- class Bad:
- __providedBy__ = None
- # Old style classes don't have a '__class__' attribute
- self.failUnlessRaises(AttributeError, I.providedBy, Bad)
-
-
-class _I1(Interface):
-
- a1 = Attribute("This is an attribute")
-
- def f11(): pass
- def f12(): pass
- f12.optional = 1
-
-class _I1_(_I1): pass
-class _I1__(_I1_): pass
-
-class _I2(_I1__):
- def f21(): pass
- def f22(): pass
- f23 = f22
-
-
-
-if sys.version_info >= (2, 4):
- def test_invariant_as_decorator():
- """Invaiants can be deined in line
-
- >>> class IRange(interface.Interface):
- ... min = interface.Attribute("Lower bound")
- ... max = interface.Attribute("Upper bound")
- ...
- ... @interface.invariant
- ... def range_invariant(ob):
- ... if ob.max < ob.min:
- ... raise Invalid('max < min')
-
-
- >>> class Range(object):
- ... interface.implements(IRange)
- ...
- ... def __init__(self, min, max):
- ... self.min, self.max = min, max
-
- >>> IRange.validateInvariants(Range(1,2))
- >>> IRange.validateInvariants(Range(1,1))
- >>> IRange.validateInvariants(Range(2,1))
- Traceback (most recent call last):
- ...
- Invalid: max < min
-
-
- """
-
-def duplicate_bases_management():
- """
-There was a bug that surfaced when an interface was repeated in
-a set of bases and the bases were changed:
-
- >>> class I(interface.Interface):
- ... pass
-
- >>> class I2(I, I):
- ... pass
-
- >>> I2.__bases__ = (I,)
-
-
-"""
-
-
-def test_suite():
- from zope.testing import doctest
- suite = unittest.makeSuite(InterfaceTests)
- suite.addTest(doctest.DocTestSuite("zope.interface.interface"))
- if sys.version_info >= (2, 4):
- suite.addTest(doctest.DocTestSuite())
- suite.addTest(doctest.DocFileSuite(
- '../README.txt',
- globs={'__name__': '__main__'},
- optionflags=doctest.NORMALIZE_WHITESPACE,
- ))
- suite.addTest(doctest.DocFileSuite(
- '../README.ru.txt',
- globs={'__name__': '__main__'},
- optionflags=doctest.NORMALIZE_WHITESPACE,
- ))
- return suite
-
-def main():
- unittest.TextTestRunner().run(test_suite())
-
-if __name__=="__main__":
- main()
=== removed file 'lib/zope/interface/tests/test_odd_declarations.py'
--- lib/zope/interface/tests/test_odd_declarations.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_odd_declarations.py 1970-01-01 00:00:00 +0000
@@ -1,204 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Test interface declarations against ExtensionClass-like classes.
-
-These tests are to make sure we do something sane in the presense of
-classic ExtensionClass classes and instances.
-
-$Id: test_odd_declarations.py 40833 2005-12-16 21:32:26Z benji_york $
-"""
-import unittest, odd
-from zope.interface import Interface, implements, implementsOnly
-from zope.interface import directlyProvides, providedBy, directlyProvidedBy
-from zope.interface import classImplements, classImplementsOnly, implementedBy
-
-class I1(Interface): pass
-class I2(Interface): pass
-class I3(Interface): pass
-class I31(I3): pass
-class I4(Interface): pass
-class I5(Interface): pass
-
-class Odd(object): __metaclass__ = odd.MetaClass
-
-class B(Odd): __implemented__ = I2
-
-
-# TODO: We are going to need more magic to make classProvides work with odd
-# classes. This will work in the next iteration. For now, we'll use
-# a different mechanism.
-
-# from zope.interface import classProvides
-
-class A(Odd):
- implements(I1)
-
-class C(A, B):
- implements(I31)
-
-
-class Test(unittest.TestCase):
-
- def test_ObjectSpecification(self):
- c = C()
- directlyProvides(c, I4)
- self.assertEqual([i.getName() for i in providedBy(c)],
- ['I4', 'I31', 'I1', 'I2']
- )
- self.assertEqual([i.getName() for i in providedBy(c).flattened()],
- ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
- )
- self.assert_(I1 in providedBy(c))
- self.failIf(I3 in providedBy(c))
- self.assert_(providedBy(c).extends(I3))
- self.assert_(providedBy(c).extends(I31))
- self.failIf(providedBy(c).extends(I5))
-
- class COnly(A, B):
- implementsOnly(I31)
-
- class D(COnly):
- implements(I5)
-
- classImplements(D, I5)
-
- c = D()
- directlyProvides(c, I4)
- self.assertEqual([i.getName() for i in providedBy(c)],
- ['I4', 'I5', 'I31'])
- self.assertEqual([i.getName() for i in providedBy(c).flattened()],
- ['I4', 'I5', 'I31', 'I3', 'Interface'])
- self.failIf(I1 in providedBy(c))
- self.failIf(I3 in providedBy(c))
- self.assert_(providedBy(c).extends(I3))
- self.failIf(providedBy(c).extends(I1))
- self.assert_(providedBy(c).extends(I31))
- self.assert_(providedBy(c).extends(I5))
-
- class COnly(A, B): __implemented__ = I31
- class D(COnly):
- implements(I5)
-
- classImplements(D, I5)
- c = D()
- directlyProvides(c, I4)
- self.assertEqual([i.getName() for i in providedBy(c)],
- ['I4', 'I5', 'I31'])
- self.assertEqual([i.getName() for i in providedBy(c).flattened()],
- ['I4', 'I5', 'I31', 'I3', 'Interface'])
- self.failIf(I1 in providedBy(c))
- self.failIf(I3 in providedBy(c))
- self.assert_(providedBy(c).extends(I3))
- self.failIf(providedBy(c).extends(I1))
- self.assert_(providedBy(c).extends(I31))
- self.assert_(providedBy(c).extends(I5))
-
- def test_classImplements(self):
- class A(Odd):
- implements(I3)
-
- class B(Odd):
- implements(I4)
-
- class C(A, B):
- pass
- classImplements(C, I1, I2)
- self.assertEqual([i.getName() for i in implementedBy(C)],
- ['I1', 'I2', 'I3', 'I4'])
- classImplements(C, I5)
- self.assertEqual([i.getName() for i in implementedBy(C)],
- ['I1', 'I2', 'I5', 'I3', 'I4'])
-
- def test_classImplementsOnly(self):
- class A(Odd):
- implements(I3)
-
- class B(Odd):
- implements(I4)
-
- class C(A, B):
- pass
- classImplementsOnly(C, I1, I2)
- self.assertEqual([i.__name__ for i in implementedBy(C)],
- ['I1', 'I2'])
-
-
- def test_directlyProvides(self):
- class IA1(Interface): pass
- class IA2(Interface): pass
- class IB(Interface): pass
- class IC(Interface): pass
- class A(Odd):
- implements(IA1, IA2)
-
- class B(Odd):
- implements(IB)
-
- class C(A, B):
- implements(IC)
-
-
- ob = C()
- directlyProvides(ob, I1, I2)
- self.assert_(I1 in providedBy(ob))
- self.assert_(I2 in providedBy(ob))
- self.assert_(IA1 in providedBy(ob))
- self.assert_(IA2 in providedBy(ob))
- self.assert_(IB in providedBy(ob))
- self.assert_(IC in providedBy(ob))
-
- directlyProvides(ob, directlyProvidedBy(ob)-I2)
- self.assert_(I1 in providedBy(ob))
- self.failIf(I2 in providedBy(ob))
- self.failIf(I2 in providedBy(ob))
- directlyProvides(ob, directlyProvidedBy(ob), I2)
- self.assert_(I2 in providedBy(ob))
-
- def test_directlyProvides_fails_for_odd_class(self):
- self.assertRaises(TypeError, directlyProvides, C, I5)
-
- # see above
- def TODO_test_classProvides_fails_for_odd_class(self):
- try:
- class A(Odd):
- classProvides(I1)
- except TypeError:
- pass # Sucess
- self.assert_(False,
- "Shouldn't be able to use directlyProvides on odd class."
- )
-
- def test_implementedBy(self):
- class I2(I1): pass
-
- class C1(Odd):
- implements(I2)
-
- class C2(C1):
- implements(I3)
-
- self.assertEqual([i.getName() for i in implementedBy(C2)],
- ['I3', 'I2'])
-
-
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(Test))
- return suite
-
-
-if __name__ == '__main__':
- unittest.main()
=== removed file 'lib/zope/interface/tests/test_sorting.py'
--- lib/zope/interface/tests/test_sorting.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_sorting.py 1970-01-01 00:00:00 +0000
@@ -1,49 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Test interface sorting
-
-$Id: test_sorting.py 25177 2004-06-02 13:17:31Z jim $
-"""
-
-from unittest import TestCase, TestSuite, main, makeSuite
-
-from zope.interface import Interface
-
-class I1(Interface): pass
-class I2(I1): pass
-class I3(I1): pass
-class I4(Interface): pass
-class I5(I4): pass
-class I6(I2): pass
-
-
-class Test(TestCase):
-
- def test(self):
- l = [I1, I3, I5, I6, I4, I2]
- l.sort()
- self.assertEqual(l, [I1, I2, I3, I4, I5, I6])
-
- def test_w_None(self):
- l = [I1, None, I3, I5, None, I6, I4, I2]
- l.sort()
- self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None, None])
-
-def test_suite():
- return TestSuite((
- makeSuite(Test),
- ))
-
-if __name__=='__main__':
- main(defaultTest='test_suite')
=== removed file 'lib/zope/interface/tests/test_verify.py'
--- lib/zope/interface/tests/test_verify.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/test_verify.py 1970-01-01 00:00:00 +0000
@@ -1,196 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Interface Verify tests
-
-$Id: test_verify.py 26866 2004-08-02 20:57:00Z jim $
-"""
-from zope.interface import Interface, implements, classImplements, Attribute
-from zope.interface.verify import verifyClass, verifyObject
-from zope.interface.exceptions import DoesNotImplement, BrokenImplementation
-from zope.interface.exceptions import BrokenMethodImplementation
-
-import unittest
-
-class Test(unittest.TestCase):
-
- def testNotImplemented(self):
-
- class C(object): pass
-
- class I(Interface): pass
-
- self.assertRaises(DoesNotImplement, verifyClass, I, C)
-
- classImplements(C, I)
-
- verifyClass(I, C)
-
- def testMissingAttr(self):
-
- class I(Interface):
- def f(): pass
-
- class C(object):
- implements(I)
-
- self.assertRaises(BrokenImplementation, verifyClass, I, C)
-
- C.f=lambda self: None
-
- verifyClass(I, C)
-
- def testMissingAttr_with_Extended_Interface(self):
-
- class II(Interface):
- def f():
- pass
-
- class I(II):
- pass
-
- class C(object):
- implements(I)
-
- self.assertRaises(BrokenImplementation, verifyClass, I, C)
-
- C.f=lambda self: None
-
- verifyClass(I, C)
-
- def testWrongArgs(self):
-
- class I(Interface):
- def f(a): pass
-
- class C(object):
- def f(self, b): pass
-
- implements(I)
-
- # We no longer require names to match.
- #self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
-
- C.f=lambda self, a: None
-
- verifyClass(I, C)
-
- C.f=lambda self, **kw: None
-
- self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
-
- C.f=lambda self, a, *args: None
-
- verifyClass(I, C)
-
- C.f=lambda self, a, *args, **kw: None
-
- verifyClass(I, C)
-
- C.f=lambda self, *args: None
-
- verifyClass(I, C)
-
- def testExtraArgs(self):
-
- class I(Interface):
- def f(a): pass
-
- class C(object):
- def f(self, a, b): pass
-
- implements(I)
-
- self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
-
- C.f=lambda self, a: None
-
- verifyClass(I, C)
-
- C.f=lambda self, a, b=None: None
-
- verifyClass(I, C)
-
- def testNoVar(self):
-
- class I(Interface):
- def f(a, *args): pass
-
- class C(object):
- def f(self, a): pass
-
- implements(I)
-
- self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
-
- C.f=lambda self, a, *foo: None
-
- verifyClass(I, C)
-
- def testNoKW(self):
-
- class I(Interface):
- def f(a, **args): pass
-
- class C(object):
- def f(self, a): pass
-
- implements(I)
-
- self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
-
- C.f=lambda self, a, **foo: None
-
- verifyClass(I, C)
-
- def testModule(self):
-
- from zope.interface.tests.ifoo import IFoo
- from zope.interface.tests import dummy
-
- verifyObject(IFoo, dummy)
-
- def testMethodForAttr(self):
-
- class IFoo(Interface):
- foo = Attribute("The foo Attribute")
-
-
- class Foo:
- implements(IFoo)
-
- def foo(self):
- pass
-
- verifyClass(IFoo, Foo)
-
- def testNonMethodForMethod(self):
-
- class IBar(Interface):
- def foo():
- pass
-
- class Bar:
- implements(IBar)
-
- foo = 1
-
- self.assertRaises(BrokenMethodImplementation, verifyClass, IBar, Bar)
-
-
-def test_suite():
- loader=unittest.TestLoader()
- return loader.loadTestsFromTestCase(Test)
-
-if __name__=='__main__':
- unittest.TextTestRunner().run(test_suite())
=== removed file 'lib/zope/interface/tests/unitfixtures.py'
--- lib/zope/interface/tests/unitfixtures.py 2008-08-27 05:59:29 +0000
+++ lib/zope/interface/tests/unitfixtures.py 1970-01-01 00:00:00 +0000
@@ -1,142 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Unit Test Fixtures
-
-$Id: unitfixtures.py 26898 2004-08-04 09:38:12Z hdima $
-"""
-from zope.interface import Interface, invariant
-from zope.interface.interface import Attribute
-from zope.interface.exceptions import Invalid
-
-class mytest(Interface):
- pass
-
-class C(object):
- def m1(self, a, b):
- "return 1"
- return 1
-
- def m2(self, a, b):
- "return 2"
- return 2
-
-# testInstancesOfClassImplements
-
-# YAGNI IC=Interface.impliedInterface(C)
-class IC(Interface):
-