From jinty at codespeak.net Mon Apr 3 00:17:17 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Mon Apr 3 00:17:19 2006
Subject: [z3-checkins] r25241 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060402221717.298A3100E1@code0.codespeak.net>
Author: jinty
Date: Mon Apr 3 00:17:15 2006
New Revision: 25241
Modified:
z3/sqlos/trunk/src/sqlos/configure.zcml
Log:
Oops, didnt run the tests properly, removing the zcml refernce to the removed sybase adapter.
Modified: z3/sqlos/trunk/src/sqlos/configure.zcml
==============================================================================
--- z3/sqlos/trunk/src/sqlos/configure.zcml (original)
+++ z3/sqlos/trunk/src/sqlos/configure.zcml Mon Apr 3 00:17:15 2006
@@ -90,13 +90,6 @@
/>
-
-
-
-
Author: jinty
Date: Mon Apr 3 00:21:40 2006
New Revision: 25242
Added:
z3/sqlos/trunk/patch-test.py (contents, props changed)
Modified:
z3/sqlos/trunk/makefile
Log:
You should now just be able to download the source and run "make test". if I havnt forgotten somethign that is.
Modified: z3/sqlos/trunk/makefile
==============================================================================
--- z3/sqlos/trunk/makefile (original)
+++ z3/sqlos/trunk/makefile Mon Apr 3 00:21:40 2006
@@ -2,7 +2,8 @@
CSV=${HERE}/csv
ZP=${HERE}/../
ZH=${HERE}/../../
-PYTHON=python
+PYTHON=python2.4
+z3includes=Zope3/zopeskel/etc/package-includes
all : test clean
@@ -17,11 +18,16 @@
coverage_sorted : coverage sorted
-test :
- export PYTHONPATH=${ZP} && cd ${ZH} && $(PYTHON) test.py -vpf --all sqlos
-
-clean :
+.PHONY: clean
+clean:
find . \( -name '*~' -o -name '*.py[co]' -o -name '*.bak' -o -name '#*#' -o -name '\.#*' \) -exec rm {} \; -print
+ $(PYTHON) setup.py clean
+
+.PHONY: realclean
+realclean: clean
+ rm -rf dist
+ rm -rf build
+ rm -rf Zope3
reindent :
~/src/reindent.py -r -v .
@@ -39,22 +45,26 @@
Zope3:
$(MAKE) z3-checkout
-Zope3/package-includes/sqlos-meta.zcml: Zope3 includes/sqlos-meta.zcml
- cp includes/sqlos-meta.zcml Zope3/package-includes
-
-Zope3/package-includes/sqlos-configure.zcml: Zope3 includes/sqlos-configure.zcml
- cp includes/sqlos-configure.zcml Zope3/package-includes
+$(z3includes)/sqlos-%.zcml: includes/sqlos-%.zcml Zope3
+ cp $< $@
-Zope3/package-includes/sqlos-ftesting.zcml: Zope3 includes/sqlos-ftesting.zcml
- cp includes/sqlos-ftesting.zcml Zope3/package-includes
+.PHONY: sqlos-meta
+sqlos-meta: $(z3includes)/sqlos-meta.zcml $(z3includes)/sqlos-configure.zcml $(z3includes)/sqlos-ftesting.zcml
-.PHONY: z3-build
-z3-build: Zope3
+.PHONY: develop
+develop: Zope3 sqlos-meta
cd Zope3 && $(MAKE) PYTHON=$(PYTHON) inplace
+ touch Zope3/src/easy-install.pth
+ PYTHONPATH=Zope3/src $(PYTHON) setup.py develop -S Zope3/src --install-dir Zope3/src
-.PHONY: test-dist
-test-dist: z3-update z3-build \
- Zope3/package-includes/sqlos-meta.zcml\
- Zope3/package-includes/sqlos-configure.zcml\
- Zope3/package-includes/sqlos-ftesting.zcml
- cd releases && $(PYTHON) SQLOS-test.py
+.PHONY: patch
+patch:
+ # This is butttt ugly pul hopefully temporary
+ set - e;\
+ if [ `grep 'site.addsitedir(src)' Zope3/test.py -c` == 0 ]; then\
+ cat patch-test.py | patch -p0;\
+ fi
+
+.PHONY: testall
+test: develop patch
+ cd Zope3 && $(PYTHON) test.py --test-path=../src -s sqlos
Added: z3/sqlos/trunk/patch-test.py
==============================================================================
--- (empty file)
+++ z3/sqlos/trunk/patch-test.py Mon Apr 3 00:21:40 2006
@@ -0,0 +1,13 @@
+Index: Zope3/test.py
+===================================================================
+--- Zope3/test.py (revision 65897)
++++ Zope3/test.py (working copy)
+@@ -26,6 +26,8 @@
+ # add src to path
+ src = os.path.join(here, 'src')
+ sys.path.insert(0, src) # put at beginning to avoid one in site_packages
++import site
++site.addsitedir(src)
+
+ from zope.testing import testrunner
+
From reebalazs at codespeak.net Mon Apr 3 09:44:25 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Mon Apr 3 09:44:26 2006
Subject: [z3-checkins] r25244 -
z3/jsonserver/branch/merge/concatresource/compression
Message-ID: <20060403074425.44185100E9@code0.codespeak.net>
Author: reebalazs
Date: Mon Apr 3 09:44:23 2006
New Revision: 25244
Modified:
z3/jsonserver/branch/merge/concatresource/compression/css.py
z3/jsonserver/branch/merge/concatresource/compression/javascript.py
Log:
Has to use safe option for compression
Modified: z3/jsonserver/branch/merge/concatresource/compression/css.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/css.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/css.py Mon Apr 3 09:44:23 2006
@@ -5,7 +5,7 @@
from thirdparty.packer import CSSPacker
-csspacker_full = CSSPacker('full')
+csspacker_full = CSSPacker('safe')
def compress(data):
return csspacker_full.pack(data)
Modified: z3/jsonserver/branch/merge/concatresource/compression/javascript.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/javascript.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/javascript.py Mon Apr 3 09:44:23 2006
@@ -4,7 +4,7 @@
from thirdparty.packer import JavascriptPacker
-jspacker_full = JavascriptPacker('full')
+jspacker_full = JavascriptPacker('safe')
def compress(data):
return jspacker_full.pack(data)
From reebalazs at codespeak.net Mon Apr 3 15:59:37 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Mon Apr 3 15:59:38 2006
Subject: [z3-checkins] r25255 - z3/jsonserver/branch/merge/concatresource
Message-ID: <20060403135937.83A0C100FB@code0.codespeak.net>
Author: reebalazs
Date: Mon Apr 3 15:59:35 2006
New Revision: 25255
Modified:
z3/jsonserver/branch/merge/concatresource/__init__.py
z3/jsonserver/branch/merge/concatresource/concatfileresource.py
z3/jsonserver/branch/merge/concatresource/configure.zcml
z3/jsonserver/branch/merge/concatresource/interfaces.py
Log:
Allow utility mechanism to extend list of files
- Check if files exist on configuration, to report unexistant resource files
on startup.
- add the utility hook to allow extend filelist by other components
- hack the module to be aliased to under "Products", this allows the product
to be imported multiple times.
Modified: z3/jsonserver/branch/merge/concatresource/__init__.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/__init__.py (original)
+++ z3/jsonserver/branch/merge/concatresource/__init__.py Mon Apr 3 15:59:35 2006
@@ -2,3 +2,8 @@
Product init
'''
+# alias myself to Products, directly
+import sys, Products
+if not hasattr(Products, 'concatresource'):
+ # only 1st import is aliased.
+ Products.concatresource = sys.modules['Products.concatresource'] = sys.modules[globals()['__name__']]
Modified: z3/jsonserver/branch/merge/concatresource/concatfileresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatfileresource.py (original)
+++ z3/jsonserver/branch/merge/concatresource/concatfileresource.py Mon Apr 3 15:59:35 2006
@@ -8,30 +8,81 @@
from zope.interface import implements
from interfaces import IContextFile
+# we are aliased to Products, hence the following absolute import
+from Products.concatresource.interfaces import IConcatResourceAddon
from fileresource import File
from compression import compress
+import time
+import zope.component
+from zope.component.exceptions import ComponentLookupError
class ConcatFiles(object):
- 'A resource that concatenates files and compresses the result'
+ '''A resource that concatenates files and compresses the result
+
+ It is also possible to extend the statically given list via
+ a utility.
+ '''
implements(IContextFile)
def __init__(self, pathlist, name):
# Path is now a list.
assert isinstance(pathlist, (list, tuple))
- self.pathlist = pathlist
+ # check all files, just to raise error if don't exist
+ for path in pathlist:
+ file(path, 'rb').close()
+ #
+ self.pathlist_base = pathlist
self.__name__ = name
- # Init a list of files.
- self.content = [File(path, name) for path in pathlist]
+ # markers for pathlist modification
+ self.pathlist = []
+ self.fileslist_changed = None
+ self.fileslist = []
+ def getPathList(self):
+ 'Gets the extended pathlist'
+ # we allow the list to be extended via an utility
+ try:
+ registry = zope.component.getUtility(IConcatResourceAddon, self.__name__)
+ except ComponentLookupError:
+ extend = []
+ else:
+ extend = registry.getAddonFiles()
+ pathlist = self.pathlist_base + extend
+ return pathlist
+
+ def getFilesList(self):
+ 'Gets the list of files'
+ ## # XXX We have two choices:
+ ## # 1. We only calculate the list once, on startup
+ ## # that is, we suppose that the file resource is
+ ## # called up after the extension reg has been finished
+ ## # and that it never changes later.
+ ## # 2. but it also could be like this to allow changes later:
+ pathlist = self.getPathList()
+ if pathlist != self.pathlist:
+ ##if not self.pathlist:
+ ##pathlist = self.getPathList()
+ # mark pathlist modification
+ self.pathlist = pathlist
+ self.fileslist_changed = time.time()
+ fileslist = self.fileslist = [File(path, self.__name__) for path in pathlist]
+ else:
+ fileslist = self.fileslist
+ return fileslist
+
def getLastMod(self):
- return max([f.getLastMod() for f in self.content])
+ # We take in consideration that the pathlist
+ # itself could have changed too.
+ return max([f.getLastMod() for f in self.getFilesList()] +
+ [self.fileslist_changed])
def getContents(self):
- assert self.content, 'Must contain at least one resource.'
- result = self.content[0].getContents()
+ fileslist = self.getFilesList()
+ assert fileslist, 'Must contain at least one resource.'
+ result = fileslist[0].getContents()
content_type = result['content_type']
data = [result['data']]
- for subres in self.content[1:]:
+ for subres in fileslist[1:]:
d = subres.getContents()
# all elements must have the same content type.
assert d['content_type'] == content_type
Modified: z3/jsonserver/branch/merge/concatresource/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/configure.zcml (original)
+++ z3/jsonserver/branch/merge/concatresource/configure.zcml Mon Apr 3 15:59:35 2006
@@ -7,6 +7,6 @@
/>
-
+
Modified: z3/jsonserver/branch/merge/concatresource/interfaces.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/interfaces.py (original)
+++ z3/jsonserver/branch/merge/concatresource/interfaces.py Mon Apr 3 15:59:35 2006
@@ -22,3 +22,20 @@
def purgeData(self):
'Purges the cached data'
+
+class IConcatResourceAddon(Interface):
+ '''Utility to register addons
+
+ This can be used to dynamically extend components for a given resource.
+ We don't provide implementation for this here, but other
+ components can implement this to provide dynamic add-ons.
+
+ The name of the utility should be the name of the resource.
+ '''
+
+ def getAddonFiles(request):
+ '''Returns a list of addon files.
+ This will be concatenated to the end of the static list.
+ '''
+
+
From jinty at codespeak.net Wed Apr 5 14:48:34 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed Apr 5 14:48:36 2006
Subject: [z3-checkins] r25377 - z3/sqlos/trunk
Message-ID: <20060405124834.C3851101DB@code0.codespeak.net>
Author: jinty
Date: Wed Apr 5 14:48:32 2006
New Revision: 25377
Added:
z3/sqlos/trunk/sampleapp.py (contents, props changed)
Modified:
z3/sqlos/trunk/makefile
Log:
Add a sampleapp script that allows people to run the functional testing suite as a sample application. Not quite thoroughly tested yet...
Modified: z3/sqlos/trunk/makefile
==============================================================================
--- z3/sqlos/trunk/makefile (original)
+++ z3/sqlos/trunk/makefile Wed Apr 5 14:48:32 2006
@@ -4,6 +4,7 @@
ZH=${HERE}/../../
PYTHON=python2.4
z3includes=Zope3/zopeskel/etc/package-includes
+Z3BRANCH=trunk
all : test clean
@@ -36,7 +37,7 @@
.PHONY: z3-checkout
z3-checkout:
- -test -d Zope3 || svn co svn://svn.zope.org/repos/main/Zope3/trunk Zope3
+ -test -d Zope3 || svn co svn://svn.zope.org/repos/main/Zope3/$(Z3BRANCH) Zope3
.PHONY: z3-update
z3-update: z3-checkout
@@ -51,9 +52,12 @@
.PHONY: sqlos-meta
sqlos-meta: $(z3includes)/sqlos-meta.zcml $(z3includes)/sqlos-configure.zcml $(z3includes)/sqlos-ftesting.zcml
-.PHONY: develop
-develop: Zope3 sqlos-meta
+.PHONY: Zope3-build
+Zope3-build: Zope3
cd Zope3 && $(MAKE) PYTHON=$(PYTHON) inplace
+
+.PHONY: develop
+develop: Zope3-build sqlos-meta
touch Zope3/src/easy-install.pth
PYTHONPATH=Zope3/src $(PYTHON) setup.py develop -S Zope3/src --install-dir Zope3/src
@@ -68,3 +72,11 @@
.PHONY: testall
test: develop patch
cd Zope3 && $(PYTHON) test.py --test-path=../src -s sqlos
+
+Zope3/principals.zcml: Zope3 Zope3/sample_principals.zcml
+ cp Zope3/sample_principals.zcml $@
+
+.PHONY: run-sample
+run-sample: develop Zope3/principals.zcml
+ cp includes/sqlos-ftesting.zcml $(z3includes)/sqlos.testing-configure.zcml
+ sampleapp.py ; rm $(z3includes)/sqlos.testing-configure.zcml
Added: z3/sqlos/trunk/sampleapp.py
==============================================================================
--- (empty file)
+++ z3/sqlos/trunk/sampleapp.py Wed Apr 5 14:48:32 2006
@@ -0,0 +1,79 @@
+#!/usr/bin/env python2.4
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Start script for Zope3: loads configuration and starts the server.
+
+$Id: z3.py 40235 2005-11-18 21:30:31Z srichter $
+"""
+import os
+import sys
+
+basepath = filter(None, sys.path)
+
+def run(argv=list(sys.argv)):
+
+ if sys.version_info < ( 2,3,5 ):
+ print """\
+ ERROR: Your python version is not supported by Zope3.
+ Zope3 needs Python 2.3.5 or greater. You are running:""" + sys.version
+ sys.exit(1)
+
+ # Refuse to run without principals.zcml
+ if not os.path.exists('principals.zcml'):
+ print """\
+ ERROR: You need to create principals.zcml
+
+ The file principals.zcml contains your "bootstrap" user
+ database. You aren't going to get very far without it. Start
+ by copying sample_principals.zcml and then modify the
+ example principal and role settings.
+ """
+ sys.exit(1)
+
+ # setting python paths
+ program = argv[0]
+ if "--build" in argv:
+ argv.remove("--build")
+ from distutils.util import get_platform
+ PLAT_SPEC = "%s-%s" % (get_platform(), sys.version[0:3])
+ src = os.path.join("build", "lib.%s" % PLAT_SPEC)
+ else:
+ src = 'src'
+
+ here = os.path.dirname(os.path.abspath(program))
+ srcdir = os.path.abspath(src)
+ sys.path = [srcdir] + basepath
+ sys.path[:] = [p for p in sys.path if os.path.abspath(p) != here]
+
+ # Register the paths
+ import site
+ site.addsitedir(srcdir)
+
+ # setup a subscriber to create the sampleperson tables
+ def setupTestingTables(event):
+ from sqlos.testing import sampleperson
+ sampleperson.createTestingTables()
+
+ from zope.app.appsetup.interfaces import IDatabaseOpenedEvent
+ from zope.component import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ gsm.subscribe([IDatabaseOpenedEvent], None, setupTestingTables)
+
+ from zope.app.twisted.main import main
+ main(argv[1:])
+
+
+if __name__ == '__main__':
+ os.chdir('Zope3')
+ run()
From jinty at codespeak.net Wed Apr 5 23:09:42 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed Apr 5 23:09:44 2006
Subject: [z3-checkins] r25418 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060405210942.D4A8410238@code0.codespeak.net>
Author: jinty
Date: Wed Apr 5 23:09:40 2006
New Revision: 25418
Modified:
z3/sqlos/trunk/src/sqlos/configure.zcml
Log:
Remove the option to add a SQLObject container. It is really useless as it can contain nothing.
Modified: z3/sqlos/trunk/src/sqlos/configure.zcml
==============================================================================
--- z3/sqlos/trunk/src/sqlos/configure.zcml (original)
+++ z3/sqlos/trunk/src/sqlos/configure.zcml Wed Apr 5 23:09:40 2006
@@ -5,13 +5,6 @@
-
-
@@ -47,6 +40,8 @@
factory=".container.SQLObjectNameChooser"
/>
+
+
Author: jinty
Date: Wed Apr 5 23:26:55 2006
New Revision: 25420
Modified:
z3/sqlos/trunk/src/sqlos/container.py
z3/sqlos/trunk/src/sqlos/ftests/adding.txt
z3/sqlos/trunk/src/sqlos/testing/sampleperson.py
Log:
Proibit the sample people (almost like flower people) from being added to any container but a IPersonContainer. Also, unrelatedly, make an event subscriber that will create the testing tables.
Modified: z3/sqlos/trunk/src/sqlos/container.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/container.py (original)
+++ z3/sqlos/trunk/src/sqlos/container.py Wed Apr 5 23:26:55 2006
@@ -59,13 +59,14 @@
class SQLObjectNameChooser(NameChooser):
-
+ # XXX: This needs unit tests...
+
def chooseName(self, name, obj):
if ISQLObject.providedBy(obj):
# Look for the SQLObject class our object is from, so get all
# allowed factories
for name, factory in zapi.getFactoriesFor(ISQLObject):
- if checkFactory(self, None, factory):
+ if checkFactory(self.context, None, factory):
# get the sqlobject class
utility = zapi.queryUtility(IISQLObject, name)
if utility is None:
Modified: z3/sqlos/trunk/src/sqlos/ftests/adding.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/ftests/adding.txt (original)
+++ z3/sqlos/trunk/src/sqlos/ftests/adding.txt Wed Apr 5 23:26:55 2006
@@ -19,6 +19,8 @@
Go to the main interface and add a SQLObject MultiContainer
>>> browser.open('http://localhost/manage')
+ >>> 'SamplePerson' not in str(browser.contents)
+ True
>>> browser.getLink('SQLObject Multi Container').click()
>>> browser.getControl(name='new_value').value = 'multicontainer1'
>>> browser.getControl('Apply').click()
Modified: z3/sqlos/trunk/src/sqlos/testing/sampleperson.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/testing/sampleperson.py (original)
+++ z3/sqlos/trunk/src/sqlos/testing/sampleperson.py Wed Apr 5 23:26:55 2006
@@ -1,6 +1,6 @@
from sqlobject import *
import transaction
-from zope.interface import implements, classProvides
+from zope.interface import implements, classProvides, Interface
from zope.schema import TextLine, Text, Datetime
from zope.app.container import constraints
@@ -9,6 +9,10 @@
from sqlos.interfaces.container import ISQLObjectContainer
from sqlos.container import SQLObjectContainer, SQLIsolatedContainer
+def createTestingTablesSubscriber(obj):
+ # An event subscriber that can be used to create the testing tables
+ createTestingTables()
+
def createTestingTables():
"""Creates the tables of the SQLObject calsses defined here."""
transaction.get().commit()
@@ -36,18 +40,14 @@
description=u"The user's password")
-class SamplePerson(SQLOS):
-
- implements(IPerson)
+class IPersonContainer(ISQLObjectContainer):
- fullname = StringCol(length=50, notNull=1)
- username = StringCol(length=20, notNull=1)
- password = StringCol(length=20, notNull=1)
+ constraints.contains(IPerson)
-class IPersonContainer(ISQLObjectContainer):
+class IPersonContained(Interface):
- constraints.contains(IPerson)
+ constraints.containers(IPersonContainer)
class SamplePersonContainer(SQLObjectContainer):
@@ -55,6 +55,15 @@
implements(IPersonContainer)
+class SamplePerson(SQLOS):
+
+ implements(IPerson, IPersonContained)
+
+ fullname = StringCol(length=50, notNull=1)
+ username = StringCol(length=20, notNull=1)
+ password = StringCol(length=20, notNull=1)
+
+
class SampleIsolatedPerson(SQLOS):
classProvides(IISQLObjectIsolated)
@@ -119,7 +128,7 @@
owner = StringCol(length=20, notNull=1)
-class IMultiContainer(ISQLObjectContainer):
+class IMultiContainer(IPersonContainer):
constraints.contains(IDog, IPerson)
From jinty at codespeak.net Wed Apr 5 23:28:49 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed Apr 5 23:28:50 2006
Subject: [z3-checkins] r25422 - in z3/sqlos/trunk: . includes src/sqlos
Message-ID: <20060405212849.0F21D10238@code0.codespeak.net>
Author: jinty
Date: Wed Apr 5 23:28:44 2006
New Revision: 25422
Added:
z3/sqlos/trunk/includes/sqlos.ftesting-configure.zcml
- copied, changed from r25354, z3/sqlos/trunk/includes/sqlos-ftesting.zcml
z3/sqlos/trunk/src/sqlos/sampleapp.zcml (contents, props changed)
Removed:
z3/sqlos/trunk/patch-test.py
z3/sqlos/trunk/sampleapp.py
Modified:
z3/sqlos/trunk/makefile
z3/sqlos/trunk/src/sqlos/README.txt
Log:
Re-do the sample application in a better way and actually document it.
Copied: z3/sqlos/trunk/includes/sqlos.ftesting-configure.zcml (from r25354, z3/sqlos/trunk/includes/sqlos-ftesting.zcml)
==============================================================================
--- z3/sqlos/trunk/includes/sqlos-ftesting.zcml (original)
+++ z3/sqlos/trunk/includes/sqlos.ftesting-configure.zcml Wed Apr 5 23:28:44 2006
@@ -1 +1 @@
-
+
Modified: z3/sqlos/trunk/makefile
==============================================================================
--- z3/sqlos/trunk/makefile (original)
+++ z3/sqlos/trunk/makefile Wed Apr 5 23:28:44 2006
@@ -30,11 +30,6 @@
rm -rf build
rm -rf Zope3
-reindent :
- ~/src/reindent.py -r -v .
-
-reindent_clean : reindent clean
-
.PHONY: z3-checkout
z3-checkout:
-test -d Zope3 || svn co svn://svn.zope.org/repos/main/Zope3/$(Z3BRANCH) Zope3
@@ -46,7 +41,7 @@
Zope3:
$(MAKE) z3-checkout
-$(z3includes)/sqlos-%.zcml: includes/sqlos-%.zcml Zope3
+$(z3includes)/%.zcml: includes/%.zcml Zope3
cp $< $@
.PHONY: sqlos-meta
@@ -61,22 +56,13 @@
touch Zope3/src/easy-install.pth
PYTHONPATH=Zope3/src $(PYTHON) setup.py develop -S Zope3/src --install-dir Zope3/src
-.PHONY: patch
-patch:
- # This is butttt ugly pul hopefully temporary
- set - e;\
- if [ `grep 'site.addsitedir(src)' Zope3/test.py -c` == 0 ]; then\
- cat patch-test.py | patch -p0;\
- fi
-
.PHONY: testall
-test: develop patch
+test: develop
cd Zope3 && $(PYTHON) test.py --test-path=../src -s sqlos
Zope3/principals.zcml: Zope3 Zope3/sample_principals.zcml
cp Zope3/sample_principals.zcml $@
-.PHONY: run-sample
-run-sample: develop Zope3/principals.zcml
- cp includes/sqlos-ftesting.zcml $(z3includes)/sqlos.testing-configure.zcml
- sampleapp.py ; rm $(z3includes)/sqlos.testing-configure.zcml
+.PHONY: run-sampleapp
+run-sampleapp: develop Zope3/principals.zcml $(z3includes)/sqlos.ftesting-configure.zcml
+ cd Zope3; ./z3.py
Deleted: /z3/sqlos/trunk/patch-test.py
==============================================================================
--- /z3/sqlos/trunk/patch-test.py Wed Apr 5 23:28:44 2006
+++ (empty file)
@@ -1,13 +0,0 @@
-Index: Zope3/test.py
-===================================================================
---- Zope3/test.py (revision 65897)
-+++ Zope3/test.py (working copy)
-@@ -26,6 +26,8 @@
- # add src to path
- src = os.path.join(here, 'src')
- sys.path.insert(0, src) # put at beginning to avoid one in site_packages
-+import site
-+site.addsitedir(src)
-
- from zope.testing import testrunner
-
Deleted: /z3/sqlos/trunk/sampleapp.py
==============================================================================
--- /z3/sqlos/trunk/sampleapp.py Wed Apr 5 23:28:44 2006
+++ (empty file)
@@ -1,79 +0,0 @@
-#!/usr/bin/env python2.4
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Start script for Zope3: loads configuration and starts the server.
-
-$Id: z3.py 40235 2005-11-18 21:30:31Z srichter $
-"""
-import os
-import sys
-
-basepath = filter(None, sys.path)
-
-def run(argv=list(sys.argv)):
-
- if sys.version_info < ( 2,3,5 ):
- print """\
- ERROR: Your python version is not supported by Zope3.
- Zope3 needs Python 2.3.5 or greater. You are running:""" + sys.version
- sys.exit(1)
-
- # Refuse to run without principals.zcml
- if not os.path.exists('principals.zcml'):
- print """\
- ERROR: You need to create principals.zcml
-
- The file principals.zcml contains your "bootstrap" user
- database. You aren't going to get very far without it. Start
- by copying sample_principals.zcml and then modify the
- example principal and role settings.
- """
- sys.exit(1)
-
- # setting python paths
- program = argv[0]
- if "--build" in argv:
- argv.remove("--build")
- from distutils.util import get_platform
- PLAT_SPEC = "%s-%s" % (get_platform(), sys.version[0:3])
- src = os.path.join("build", "lib.%s" % PLAT_SPEC)
- else:
- src = 'src'
-
- here = os.path.dirname(os.path.abspath(program))
- srcdir = os.path.abspath(src)
- sys.path = [srcdir] + basepath
- sys.path[:] = [p for p in sys.path if os.path.abspath(p) != here]
-
- # Register the paths
- import site
- site.addsitedir(srcdir)
-
- # setup a subscriber to create the sampleperson tables
- def setupTestingTables(event):
- from sqlos.testing import sampleperson
- sampleperson.createTestingTables()
-
- from zope.app.appsetup.interfaces import IDatabaseOpenedEvent
- from zope.component import getGlobalSiteManager
- gsm = getGlobalSiteManager()
- gsm.subscribe([IDatabaseOpenedEvent], None, setupTestingTables)
-
- from zope.app.twisted.main import main
- main(argv[1:])
-
-
-if __name__ == '__main__':
- os.chdir('Zope3')
- run()
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Wed Apr 5 23:28:44 2006
@@ -48,6 +48,8 @@
Dependencies
------------
+ + setuptools >= 0.6a11
+
+ SQLObject >= 0.7
Place the sqlobject package somewhere in python's sys.path
@@ -107,6 +109,32 @@
connection and any registered class you wish.
+A Sample Application
+--------------------
+
+The functional test setup for sqlos is really a sample application. You can
+run and play with this to see how sqlos works.
+
+First install a Z3 database adapter, create a database, edit
+src/sqlos/ftesting.zcml to change the connection settings as
+described below in "Setting up a connection for SQLObject".
+
+NOTE: This currently does not work with the default testing database
+ (memory based SQLite) due to threading issues.
+
+Then, from a checkout of sqlos run:
+
+ $ make run-sampleapp
+
+This should download Zope3 install sqlos and set up the functional
+test suite as a sample application. You can then log into zope3 on
+http://localhost:8080 with gandalf:123.
+
+Try adding a "SQLObject MultiContainer" and then some people.
+
+NOTE: changing debug=1 in src/sqlos/adapter.py will cause the SQL
+ executed to be printed on the terminal
+
Setting up a connection for SQLObject
-------------------------------------
Added: z3/sqlos/trunk/src/sqlos/sampleapp.zcml
==============================================================================
--- (empty file)
+++ z3/sqlos/trunk/src/sqlos/sampleapp.zcml Wed Apr 5 23:28:44 2006
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
From jinty at codespeak.net Thu Apr 6 12:04:09 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 6 12:04:10 2006
Subject: [z3-checkins] r25435 - z3/sqlos/trunk/Zope2/FiveSQLOS
Message-ID: <20060406100409.22ADE10223@code0.codespeak.net>
Author: jinty
Date: Thu Apr 6 12:04:07 2006
New Revision: 25435
Modified:
z3/sqlos/trunk/Zope2/FiveSQLOS/wrapper.py
Log:
Fix an important bug that was uncovered by the changes to the testing harness in sqlos.
Modified: z3/sqlos/trunk/Zope2/FiveSQLOS/wrapper.py
==============================================================================
--- z3/sqlos/trunk/Zope2/FiveSQLOS/wrapper.py (original)
+++ z3/sqlos/trunk/Zope2/FiveSQLOS/wrapper.py Thu Apr 6 12:04:07 2006
@@ -25,6 +25,7 @@
from zope.app.container.constraints import checkFactory
from zope.interface import implements, providedBy, directlyProvides
from sqlos.interfaces import ISQLObject, IISQLObject
+from zope.app.exception.interfaces import UserError
from Products.FiveSQLOS.interfaces import IFiveSQLObject
@@ -80,10 +81,12 @@
# Look for the SQLObject class our object is from, so get all
# allowed factories
for name, factory in zapi.getFactoriesFor(ISQLObject):
- if checkFactory(self, None, factory):
+ if checkFactory(self.aq_parent, None, factory):
# get the sqlobject class
- factory = zapi.getUtility(IISQLObject, name)
- if obj.sqlmeta.table == factory.sqlmeta.table:
+ utility = zapi.queryUtility(IISQLObject, name)
+ if utility is None:
+ continue
+ if obj.sqlmeta.table == utility.sqlmeta.table:
# if the tables names are the same, we assume that the
# sqlobject is an instance of that class, perhaps that
# is wrong
From jinty at codespeak.net Thu Apr 6 21:38:45 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 6 21:38:46 2006
Subject: [z3-checkins] r25463 - in z3/sqlos/trunk: doc/examples src/sqlos
Message-ID: <20060406193845.46DA71024C@code0.codespeak.net>
Author: jinty
Date: Thu Apr 6 21:38:38 2006
New Revision: 25463
Removed:
z3/sqlos/trunk/doc/examples/
Modified:
z3/sqlos/trunk/src/sqlos/README.txt
Log:
Rip out the example because it broke and was frustrating first time users. Being untested it is just too much maintainence to fix. Anyway, now we use our functional test setup as an example application and, well, that is tested.
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Thu Apr 6 21:38:38 2006
@@ -138,9 +138,6 @@
Setting up a connection for SQLObject
-------------------------------------
-NOTE: There is a fully worked out example package in the
- doc/examples/sqlos_sample directory.
-
This example is not complete yet (XXX), but should give you an idea::
Author: jinty
Date: Fri Apr 7 02:01:23 2006
New Revision: 25467
Modified:
z3/sqlos/trunk/src/sqlos/__init__.py
z3/sqlos/trunk/src/sqlos/interfaces/__init__.py
Log:
Move some strange, untested and probably un-necessary class implements closer to where the interfaces are defined.
Modified: z3/sqlos/trunk/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/__init__.py Fri Apr 7 02:01:23 2006
@@ -13,27 +13,8 @@
__metaclass__ = type
from datetime import datetime, date
-from zope.interface import classImplements
from zope.app import zapi
-from zope.security.checker import NamesChecker, NoProxy, defineChecker
-
-from sqlobject.dbconnection import DBConnection, DBAPI
-from sqlobject import _mysql, _postgres, _sybase
-from sqlobject.main import SQLObject, SelectResults
-from sqlobject.sqlbuilder import registerConverter, \
- SQLObjectTable
-from sqlos.interfaces import IDBConnection, IDBAPI, ISQLConnection
-from sqlos.interfaces import IISQLObject, ISQLObject, ISelectResults
-
-defineChecker(SQLObjectTable, NoProxy)
-
-classImplements(DBConnection, IDBConnection)
-classImplements(DBAPI, IDBAPI)
-classImplements(_mysql.builder(), ISQLConnection)
-classImplements(_postgres.builder(), ISQLConnection)
-classImplements(_sybase.builder(), ISQLConnection)
-classImplements(SQLObject, ISQLObject)
-classImplements(SelectResults, ISelectResults)
+from sqlobject.sqlbuilder import registerConverter
from _sqlos import SQLOS
Modified: z3/sqlos/trunk/src/sqlos/interfaces/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/interfaces/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/interfaces/__init__.py Fri Apr 7 02:01:23 2006
@@ -11,11 +11,17 @@
"""
from zope.schema import TextLine
from zope.interface import Interface, Attribute
-from sqlobject import NoDefault
from zope.component import getService, ComponentLookupError
+from zope.interface import classImplements
+from zope.security.checker import NamesChecker, NoProxy, defineChecker
from zope.schema.vocabulary import SimpleVocabulary
from zope.schema import Choice, List
from zope.app.annotation.interfaces import IAttributeAnnotatable
+from sqlobject import NoDefault
+from sqlobject.dbconnection import DBConnection, DBAPI
+from sqlobject import _mysql, _postgres, _sybase
+from sqlobject.main import SQLObject, SelectResults
+from sqlobject.sqlbuilder import SQLObjectTable
class IConnectionName(Interface):
"""A marker interface for providing a connection name"""
@@ -248,7 +254,7 @@
class IISQLObjectIsolated(IISQLObject):
"""Support for using this class in isolated containers.
-
+
This interface is necessary to move the SQL query logic to the SQLOS class
as it can be implemented in various ways in the class.
"""
@@ -335,3 +341,17 @@
def next():
""" Iterator """
+
+# XXX: Why do we need these????
+
+defineChecker(SQLObjectTable, NoProxy)
+
+classImplements(DBConnection, IDBConnection)
+classImplements(DBAPI, IDBAPI)
+classImplements(_mysql.builder(), ISQLConnection)
+classImplements(_postgres.builder(), ISQLConnection)
+classImplements(_sybase.builder(), ISQLConnection)
+classImplements(SQLObject, ISQLObject)
+classImplements(SelectResults, ISelectResults)
+
+
From jinty at codespeak.net Fri Apr 7 02:03:50 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri Apr 7 02:03:58 2006
Subject: [z3-checkins] r25468 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060407000350.2629910249@code0.codespeak.net>
Author: jinty
Date: Fri Apr 7 02:03:40 2006
New Revision: 25468
Modified:
z3/sqlos/trunk/src/sqlos/__init__.py
Log:
Deprecate the unused (in sqlos) sqlos.caller
Modified: z3/sqlos/trunk/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/__init__.py Fri Apr 7 02:03:40 2006
@@ -52,3 +52,4 @@
factory."
deprecated("getFactory", msg)
+deprecated("caller", "sqlos.caller is deprecated and will be removed after sqlos 0.2")
From jinty at codespeak.net Fri Apr 7 02:17:11 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri Apr 7 02:17:13 2006
Subject: [z3-checkins] r25469 - in z3/sqlos/trunk/src/sqlos: . auth ftests
Message-ID: <20060407001711.8666010251@code0.codespeak.net>
Author: jinty
Date: Fri Apr 7 02:17:08 2006
New Revision: 25469
Modified:
z3/sqlos/trunk/src/sqlos/__init__.py
z3/sqlos/trunk/src/sqlos/auth/__init__.py
z3/sqlos/trunk/src/sqlos/connection.py
z3/sqlos/trunk/src/sqlos/container.py
z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py
Log:
Remove users of zapi.
Modified: z3/sqlos/trunk/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/__init__.py Fri Apr 7 02:17:08 2006
@@ -13,7 +13,7 @@
__metaclass__ = type
from datetime import datetime, date
-from zope.app import zapi
+import zope.component
from sqlobject.sqlbuilder import registerConverter
from _sqlos import SQLOS
@@ -41,14 +41,14 @@
def getFactory(name, context=None, default=None):
# XXX - deprecated, goes away after sqlos 0.2
- return zapi.queryUtility(IISQLObject, name, default=default, context=context)
+ return zope.component.queryUtility(IISQLObject, name, default=default, context=context)
from zope.deprecation import deprecated
msg = "getFactory is depreciated and will go away after sqlos 0.2 you should \
replace this with a direct call to \
-zapi.getUtility(IISQLObject, name, context=context) if you need the \
+zope.component.getUtility(IISQLObject, name, context=context) if you need the \
functionailty of a SQLObject class, or \
-zapi.getUtility(IFactory, name, context=context) if you want to use it as a \
+zope.component.getUtility(IFactory, name, context=context) if you want to use it as a \
factory."
deprecated("getFactory", msg)
Modified: z3/sqlos/trunk/src/sqlos/auth/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/auth/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/auth/__init__.py Fri Apr 7 02:17:08 2006
@@ -13,7 +13,7 @@
from zope.interface import implements
-from zope.app import zapi
+import zope.component
from zope.app.pluggableauth.interfaces import ILoginPasswordPrincipalSource
from zope.app.pluggableauth import SimplePrincipal
Modified: z3/sqlos/trunk/src/sqlos/connection.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/connection.py (original)
+++ z3/sqlos/trunk/src/sqlos/connection.py Fri Apr 7 02:17:08 2006
@@ -15,7 +15,7 @@
import warnings
from zope.component import ComponentLookupError
-from zope.app import zapi
+import zope.component
from zope.app.rdb.interfaces import IZopeDatabaseAdapter
from zope.thread import local
@@ -79,7 +79,7 @@
name = self.name
if name is None:
try:
- ut = zapi.getUtility(IConnectionName)
+ ut = zope.component.getUtility(IConnectionName)
except ComponentLookupError:
return self
if ut is None:
@@ -91,7 +91,7 @@
# try get the connection from the cache, or make a new one
conn = conn_cache.queryConnection(name)
if conn is None:
- zda = zapi.getUtility(IZopeDatabaseAdapter, name)
+ zda = zope.component.getUtility(IZopeDatabaseAdapter, name)
try:
conn = IZopeSQLConnection(zda())
except ComponentLookupError:
Modified: z3/sqlos/trunk/src/sqlos/container.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/container.py (original)
+++ z3/sqlos/trunk/src/sqlos/container.py Fri Apr 7 02:17:08 2006
@@ -18,7 +18,7 @@
from zope.interface import implements
from zope.component import IFactory
from zope import deprecation
-from zope.app import zapi
+import zope.component
from zope.app.container.interfaces import IContained
from zope.app.container.contained import ContainedProxy
from zope.app.container.contained import Contained
@@ -65,10 +65,10 @@
if ISQLObject.providedBy(obj):
# Look for the SQLObject class our object is from, so get all
# allowed factories
- for name, factory in zapi.getFactoriesFor(ISQLObject):
+ for name, factory in zope.component.getFactoriesFor(ISQLObject):
if checkFactory(self.context, None, factory):
# get the sqlobject class
- utility = zapi.queryUtility(IISQLObject, name)
+ utility = zope.component.queryUtility(IISQLObject, name)
if utility is None:
continue
if obj.sqlmeta.table == utility.sqlmeta.table:
@@ -87,7 +87,7 @@
pass
def _allowedFactories(self):
- for name, factory in zapi.getFactoriesFor(ISQLObject):
+ for name, factory in zope.component.getFactoriesFor(ISQLObject):
if checkFactory(self, None, factory):
yield name
allowedFactories = deprecation.deprecated(_allowedFactories,
@@ -95,9 +95,9 @@
' please use _getAllowedIISQLObjectUtilities instead.')
def _getAllowedIISQLObjectUtilities(self):
- for name, factory in zapi.getFactoriesFor(ISQLObject):
+ for name, factory in zope.component.getFactoriesFor(ISQLObject):
if checkFactory(self, None, factory):
- utility = zapi.queryUtility(IISQLObject, name)
+ utility = zope.component.queryUtility(IISQLObject, name)
# Someone might have registered a factory implementing
# IISQLObject using for whatever reason.
# in this case queryUtility returns None and we can just
@@ -212,7 +212,7 @@
def allowedFactories(self):
# Ignore all factories not implementing ISQLObjectIsolated
for f in SQLObjectContainer._allowedFactories(self):
- implemented = zapi.getFactoryInterfaces(f)
+ implemented = zope.component.getFactoryInterfaces(f)
if implemented.isOrExtends(ISQLObjectIsolated):
yield f
allowedFactories = deprecation.deprecated(allowedFactories,
Modified: z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py (original)
+++ z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py Fri Apr 7 02:17:08 2006
@@ -16,7 +16,7 @@
from transaction import get, begin
from zope.app.testing.functional import BrowserTestCase
-from zope.app import zapi
+import zope.component
from zope.app.rdb.interfaces import IZopeDatabaseAdapter
from sqlos.interfaces import IConnectionName
@@ -98,8 +98,8 @@
This is a regression test for if the cache makes breaks the isolation
between threads.
"""
- ut = zapi.getUtility(IConnectionName)
- adapter = zapi.queryUtility(IZopeDatabaseAdapter, ut.name)
+ ut = zope.component.getUtility(IConnectionName)
+ adapter = zope.component.queryUtility(IZopeDatabaseAdapter, ut.name)
if adapter.getDSN() == 'dbi://:memory:':
import warnings
warnings.warn('Warning, not testing Cache Isolation')
@@ -130,8 +130,8 @@
happen even if the thread is not the main thread. (Just in case some
dodo only registers the cache clearer in the main thread.)
"""
- ut = zapi.getUtility(IConnectionName)
- adapter = zapi.queryUtility(IZopeDatabaseAdapter, ut.name)
+ ut = zope.component.getUtility(IConnectionName)
+ adapter = zope.component.queryUtility(IZopeDatabaseAdapter, ut.name)
if adapter.getDSN() == 'dbi://:memory:':
import warnings
warnings.warn('Warning, not testing Cache Isolation')
From reebalazs at codespeak.net Sun Apr 9 21:37:11 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sun Apr 9 21:37:11 2006
Subject: [z3-checkins] r25638 - z3/jsonserver/branch/zope2_test
Message-ID: <20060409193711.0F0F310169@code0.codespeak.net>
Author: reebalazs
Date: Sun Apr 9 21:37:09 2006
New Revision: 25638
Modified:
z3/jsonserver/branch/zope2_test/configure.zcml
Log:
include browser package was missing
Modified: z3/jsonserver/branch/zope2_test/configure.zcml
==============================================================================
--- z3/jsonserver/branch/zope2_test/configure.zcml (original)
+++ z3/jsonserver/branch/zope2_test/configure.zcml Sun Apr 9 21:37:09 2006
@@ -8,6 +8,7 @@
+
-
-
-
-
From regebro at codespeak.net Tue Apr 11 20:25:57 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Tue Apr 11 20:25:58 2006
Subject: [z3-checkins] r25706 - z3/CMFonFive/trunk
Message-ID: <20060411182557.9581510177@code0.codespeak.net>
Author: regebro
Date: Tue Apr 11 20:25:57 2006
New Revision: 25706
Modified:
z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/trunk/fiveactionstool.py
z3/CMFonFive/trunk/version.txt
Log:
The generated id of the icons is now consistent.
Modified: z3/CMFonFive/trunk/CHANGES.txt
==============================================================================
--- z3/CMFonFive/trunk/CHANGES.txt (original)
+++ z3/CMFonFive/trunk/CHANGES.txt Tue Apr 11 20:25:57 2006
@@ -1,7 +1,17 @@
CMFonFive Product Changelog
+ CMFonFive 1.3.3 (2005-04-11)
+
+ - The id of the action is now generated from the last part of the interface
+ the menu item is defined for, and the last part of the action. This should
+ generate enough uniqueness so that action id's does not clash too much, while
+ never generating two different ids.
+
+ The reason for this change is that it enables you to add icons with the CMF
+ ActionIconsTool.
+
CMFonFive 1.3.2 (2005-02-22)
-
+
- GenericSetup calls all action providers with both object and info
as None, which resulted in an attribute error.
Modified: z3/CMFonFive/trunk/fiveactionstool.py
==============================================================================
--- z3/CMFonFive/trunk/fiveactionstool.py (original)
+++ z3/CMFonFive/trunk/fiveactionstool.py Tue Apr 11 20:25:57 2006
@@ -21,13 +21,52 @@
from Products.CMFCore.Expression import Expression
from Products.CMFCore.utils import UniqueObject
+from zope.interface import providedBy
from zope.app import zapi
from zope.app.publisher.interfaces.browser import IBrowserMenu
-from zope.app.publisher.browser.menu import getMenu
-
+from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
+from zope.security.proxy import removeSecurityProxy
+
def _listMenuIds():
return [id for id, utility in zapi.getUtilitiesFor(IBrowserMenu)]
+def getMenu(id, object, request):
+ """Return menu item entries in a TAL-friendly form."""
+ menu = zapi.getUtility(IBrowserMenu, id)
+
+ result = []
+ for name, item in zapi.getAdapters((object, request),
+ menu.getMenuItemType()):
+ if item.available():
+ result.append(item)
+
+ # Now order the result. This is not as easy as it seems.
+ #
+ # (1) Look at the interfaces and put the more specific menu entries
+ # to the front.
+ # (2) Sort unabigious entries by order and then by title.
+ ifaces = list(providedBy(removeSecurityProxy(object)).__iro__)
+ result = [(ifaces.index(item._for or Interface),
+ item.order, item.title, item) for item in result]
+ result.sort()
+
+ res = []
+ for index, order, title, item in result:
+ identifier = '%s_%s' % (item._for.__identifier__.split('.')[-1],
+ item.action.split('/')[-1])
+ identifier = identifier.replace(' ', '_').lower()
+ res.append({'title': item.title,
+ 'description': item.description,
+ 'action': item.action,
+ 'selected': (item.selected() and u'selected') or u'',
+ 'icon': item.icon,
+ 'extra': item.extra,
+ 'submenu': (IBrowserSubMenuItem.providedBy(item) and
+ getMenu(item.submenuId, object, request)) or None,
+ 'identifier': identifier,
+ })
+ return res
+
from Products.Five import security
import zope.thread
@@ -61,10 +100,8 @@
# from the object_id and the action url. That is sure
# to be unique.
action = str(entry['action'])
- if object is None:
- act_id = 'action_%s' % action
- else:
- act_id = 'action_%s_%s' % (object.getId(), action)
+ meta_type = getattr(object, 'meta_type', '')
+ act_id = entry['identifier']
if entry.get('filter') is None:
filter = None
Modified: z3/CMFonFive/trunk/version.txt
==============================================================================
--- z3/CMFonFive/trunk/version.txt (original)
+++ z3/CMFonFive/trunk/version.txt Tue Apr 11 20:25:57 2006
@@ -1 +1 @@
-CMFonFive-1.3.2
+CMFonFive-1.3.3
From regebro at codespeak.net Wed Apr 12 12:01:34 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Wed Apr 12 12:01:35 2006
Subject: [z3-checkins] r25714 - z3/CMFonFive/trunk
Message-ID: <20060412100134.7A74910149@code0.codespeak.net>
Author: regebro
Date: Wed Apr 12 12:01:34 2006
New Revision: 25714
Modified:
z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/trunk/version.txt
Log:
Decided not to release it now, but before CPS 3.4.1 (or if somebody asks me too).
Modified: z3/CMFonFive/trunk/CHANGES.txt
==============================================================================
--- z3/CMFonFive/trunk/CHANGES.txt (original)
+++ z3/CMFonFive/trunk/CHANGES.txt Wed Apr 12 12:01:34 2006
@@ -1,6 +1,6 @@
CMFonFive Product Changelog
- CMFonFive 1.3.3 (2005-04-11)
+ CMFonFive 1.3.3 (unreleased)
- The id of the action is now generated from the last part of the interface
the menu item is defined for, and the last part of the action. This should
Modified: z3/CMFonFive/trunk/version.txt
==============================================================================
--- z3/CMFonFive/trunk/version.txt (original)
+++ z3/CMFonFive/trunk/version.txt Wed Apr 12 12:01:34 2006
@@ -1 +1 @@
-CMFonFive-1.3.3
+CMFonFive-1.3.2+
From jinty at codespeak.net Thu Apr 13 00:15:54 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 00:15:56 2006
Subject: [z3-checkins] r25747 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060412221554.C8161101A9@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 00:15:53 2006
New Revision: 25747
Modified:
z3/sqlos/trunk/src/sqlos/README.txt
Log:
Be consistent
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Thu Apr 13 00:15:53 2006
@@ -13,21 +13,21 @@
``sqlos`` is a toolkit for using SQLObject_ (an Object Relational
Mapper) inside Zope 3 or Zope 2. It tries to take care of many of the
fiddly details that always seem to take a lot of time. The major ways
-it helps are::
+it helps are:
- * Integrates the Zope transaction system and SQLObject, allowing
- SQLObject to be used in lazyUpdate mode.
+ + Integrates the Zope transaction system and SQLObject, allowing
+ SQLObject to be used in lazyUpdate mode.
+
+ + Uses Zope Database adapters in SQLObject.
- * Uses Zope Database adapters in SQLObject.
+ + Provide zcml configuration directives.
- * Provide zcml configuration directives.
+ + Provide ZODB persistent objects that can act as a "window" into
+ the database.
- * Provide ZODB persistent objects that can act as a "window" into
- the database.
+ + A testing infrastructure for testing SQLObject based applications.
- * A testing infrastructure for testing SQLObject based applications.
-
- * Caches SQLObjects and database connections to improve performance.
+ + Caches SQLObjects and database connections to improve performance.
.. _SQLObject: http://sqlobject.org
From jinty at codespeak.net Thu Apr 13 01:05:58 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:05:59 2006
Subject: [z3-checkins] r25751 - in z3/sqlos/trunk/src/sqlos: . auth
Message-ID: <20060412230558.84476101AF@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:05:56 2006
New Revision: 25751
Removed:
z3/sqlos/trunk/src/sqlos/annotations.py
z3/sqlos/trunk/src/sqlos/attributeannotations.py
z3/sqlos/trunk/src/sqlos/auth/
Modified:
z3/sqlos/trunk/src/sqlos/configure.zcml
Log:
Rip out sqlos.auth, sqlos.annotations and sqlos.attributeannotations as they were competely untested, prbably broken and nobody stepped up to do anything about it.
Deleted: /z3/sqlos/trunk/src/sqlos/annotations.py
==============================================================================
--- /z3/sqlos/trunk/src/sqlos/annotations.py Thu Apr 13 01:05:56 2006
+++ (empty file)
@@ -1,18 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Enfold Systems LLC. All rights reserved.
-#
-# This software is distributed under the terms of the Zope Public
-# License (ZPL) v2.1. See COPYING.txt for more information.
-#
-##############################################################################
-"""
-$Id: adapter.py 5212 2004-06-21 18:09:05Z philikon $
-"""
-from sqlobject import *
-
-class Annotations(SQLObject):
-
- location = StringCol('location', length=255, notNull=1)
- key = StringCol('key', length=255, notNull=1)
- value = StringCol('value', notNull=0)
Deleted: /z3/sqlos/trunk/src/sqlos/attributeannotations.py
==============================================================================
--- /z3/sqlos/trunk/src/sqlos/attributeannotations.py Thu Apr 13 01:05:56 2006
+++ (empty file)
@@ -1,135 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Enfold Systems LLC. All rights reserved.
-#
-# This software is distributed under the terms of the Zope Public
-# License (ZPL) v2.1. See COPYING.txt for more information.
-#
-##############################################################################
-"""
-$Id: adapter.py 5212 2004-06-21 18:09:05Z philikon $
-"""
-
-import pickle
-
-from sqlobject import *
-from zope.app.interfaces.annotation import IAnnotations
-from zope.app import zapi
-from zope.proxy import removeAllProxies
-from zope.interface import implements
-from zope.app.interfaces.location import ILocation
-from zope.app.location import Location
-
-from sqlos import getFactory
-
-
-class AnnotationProxy(object):
-
- def __init__(self, parent, key, context):
- self.__parent = parent
- self.__key = key
- self.__context = context
-
- def __getattr__(self, name):
- if name in ('_AnnotationProxy__parent',
- '_AnnotationProxy__key',
- '_AnnotationProxy__context'):
- return object.__getattribute__(self, name)
- return getattr(self.__context, name)
-
- def __setattr__(self, name, value):
- if name in ('_AnnotationProxy__parent',
- '_AnnotationProxy__key',
- '_AnnotationProxy__context'):
- object.__setattr__(self, name, value)
- else:
- setattr(self.__context, name, value)
- self.__parent[self.__key] = self.__context
-
- def __setitem__(self, name, value):
- if name in ('_AnnotationProxy__parent',
- '_AnnotationProxy__key',
- '_AnnotationProxy__context'):
- object.__setattr__(self, name, value)
- else:
- self.__context[name] = value
- self.__parent[self.__key] = self.__context
-
-
-class AnnotationSource(Location):
-
- def __init__(self, context):
- self.context = context
- self.location = "%s/%s" % (zapi.getName(zapi.getParent(context)),
- zapi.getName(context))
- self.__parent__ = context
- self.__name__ = '__annotations_source__'
- self.className = 'Annotations'
-
- def __getitem__(self, name):
- factory = getFactory(self.className)
- clause = "location = %r and key = %r" % (str(self.location),
- str(name))
- result = factory.select(clause = clause)
- if not len(result):
- raise KeyError, name
- return AnnotationProxy(self, name, pickle.loads(result[0].value))
-
- def get(self, name, default):
- try:
- item = self[name]
- except KeyError:
- return default
- return item
-
- def __setitem__(self, name, value):
- factory = getFactory(self.className)
- clause = "location = %r and key = %r" % (str(self.location),
- str(name))
- result = factory.select(clause = clause)
- if not len(result):
- item = factory.new(location=self.location,
- key=name,
- value=None)
- else:
- item = result[0]
-
- assert pickle.loads(pickle.dumps(value)) == value
- value = pickle.dumps(value)
- item.value = value
-
-
-class SQLAttributeAnnotations:
- """
- Store annotations in the annotations table, keyed by
- table_name/id on a IAttributeAnnotatable object.
- """
-
- implements(IAnnotations)
-
- def __init__(self, obj):
- self.wrapped_obj = obj
- self.unwrapped_obj = removeAllProxies(obj)
-
- def __getitem__(self, key):
- annotations = AnnotationSource(self.wrapped_obj)
- if annotations is None:
- raise KeyError, key
- return annotations[key]
-
- def __setitem__(self, key, value):
- if ILocation.providedBy(value):
- value.__parent__ = self.unwrapped_obj
-
- annotations = AnnotationSource(self.wrapped_obj)
- annotations[key] = value
-
- def get(self, key, default=None):
- annotations = AnnotationSource(self.wrapped_obj)
- return annotations.get(key, default)
-
- def __getattr__(self, name):
- # this method is for getting methods and attributes of the
- # mapping object used to store annotations.
- annotations = AnnotationSource(self.wrapped_obj)
- return getattr(annotations, name)
Modified: z3/sqlos/trunk/src/sqlos/configure.zcml
==============================================================================
--- z3/sqlos/trunk/src/sqlos/configure.zcml (original)
+++ z3/sqlos/trunk/src/sqlos/configure.zcml Thu Apr 13 01:05:56 2006
@@ -3,8 +3,6 @@
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="sqlos">
-
-
@@ -56,21 +54,6 @@
attribute="contents"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Author: jinty
Date: Thu Apr 13 01:27:53 2006
New Revision: 25753
Modified:
z3/sqlos/trunk/src/sqlos/README.txt
Log:
Steal the compatibilty matrix from Five
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Thu Apr 13 01:27:53 2006
@@ -17,7 +17,7 @@
+ Integrates the Zope transaction system and SQLObject, allowing
SQLObject to be used in lazyUpdate mode.
-
+
+ Uses Zope Database adapters in SQLObject.
+ Provide zcml configuration directives.
@@ -42,6 +42,17 @@
but it can be used with Zope 2. Heavily leveraging the work by the Five
project, a Zope 2 product (FiveSQLOS) was created to enable this.
+The following table shows which sqlos version can and should be used
+with which Zope 2 and Zope 3 versions.
+
+============ ========
+. Zope 2.9
+------------ --------
+. Zope 3.2
+============ ========
+sqlos 0.2 X
+============ ========
+
.. _FiveSQLOS: http://codespeak.net/svn/z3/sqlos/trunk/Zope2/FiveSQLOS/
From jinty at codespeak.net Thu Apr 13 01:33:49 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:33:50 2006
Subject: [z3-checkins] r25754 - z3/www/trunk
Message-ID: <20060412233349.00FF5101B3@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:33:47 2006
New Revision: 25754
Modified:
z3/www/trunk/mkwebsite.py
Log:
Remove the Five 1.0.3 release which isnt in the zope.org repository.
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Thu Apr 13 01:33:47 2006
@@ -152,8 +152,6 @@
site.registerReleases([
Z3ReleaseResource(
- 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.0.3'),
- Z3ReleaseResource(
'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.1'),
Z3ReleaseResource(
'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.2.2'),
From jinty at codespeak.net Thu Apr 13 01:37:59 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:38:00 2006
Subject: [z3-checkins] r25755 - z3/sqlos/branch/0.2
Message-ID: <20060412233759.3FB25101B3@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:37:56 2006
New Revision: 25755
Added:
z3/sqlos/branch/0.2/
- copied from r25754, z3/sqlos/trunk/
Log:
Make a 0.2 maintainence branch.
From jinty at codespeak.net Thu Apr 13 01:42:01 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:42:02 2006
Subject: [z3-checkins] r25756 - z3/sqlos/branch/0.2
Message-ID: <20060412234201.44D5C101B3@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:41:59 2006
New Revision: 25756
Removed:
z3/sqlos/branch/0.2/setup.cfg
Modified:
z3/sqlos/branch/0.2/makefile
z3/sqlos/branch/0.2/setup.py
Log:
Mark 0.2 as a release.
Modified: z3/sqlos/branch/0.2/makefile
==============================================================================
--- z3/sqlos/branch/0.2/makefile (original)
+++ z3/sqlos/branch/0.2/makefile Thu Apr 13 01:41:59 2006
@@ -4,7 +4,7 @@
ZH=${HERE}/../../
PYTHON=python2.4
z3includes=Zope3/zopeskel/etc/package-includes
-Z3BRANCH=trunk
+Z3BRANCH=branches/0,2
all : test clean
Deleted: /z3/sqlos/branch/0.2/setup.cfg
==============================================================================
--- /z3/sqlos/branch/0.2/setup.cfg Thu Apr 13 01:41:59 2006
+++ (empty file)
@@ -1,2 +0,0 @@
-[egg-info]
-tag_svn_revision = 1
Modified: z3/sqlos/branch/0.2/setup.py
==============================================================================
--- z3/sqlos/branch/0.2/setup.py (original)
+++ z3/sqlos/branch/0.2/setup.py Thu Apr 13 01:41:59 2006
@@ -3,7 +3,7 @@
setup(
name="sqlos",
description="an integration package for Zope3 and SQLObject",
- version="0.1",
+ version="0.2",
license="ZPL",
package_dir={'':'src'},
packages=find_packages('src'),
From jinty at codespeak.net Thu Apr 13 01:50:27 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:50:28 2006
Subject: [z3-checkins] r25757 - z3/sqlos/trunk
Message-ID: <20060412235027.604D6101B3@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:50:24 2006
New Revision: 25757
Modified:
z3/sqlos/trunk/setup.py
Log:
Add some more metadata to the setup.py
Modified: z3/sqlos/trunk/setup.py
==============================================================================
--- z3/sqlos/trunk/setup.py (original)
+++ z3/sqlos/trunk/setup.py Thu Apr 13 01:50:24 2006
@@ -3,8 +3,17 @@
setup(
name="sqlos",
description="an integration package for Zope3 and SQLObject",
+ long_description="""
+sqlos is a toolkit for using SQLObject (an Object Relational
+Mapper) inside Zope 3 or Zope 2. It tries to take care of many of the
+fiddly details that always seem to take a lot of time.
+""",
+ url='http://codespeak.net/z3/sqlos/',
version="0.1",
license="ZPL",
+ maintainer="SQLOS development team",
+ maintainer_email="z3-sqlos@codespeak.net",
+ platforms=["any"],
package_dir={'':'src'},
packages=find_packages('src'),
zip_safe=False,
From jinty at codespeak.net Thu Apr 13 01:51:48 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 01:51:49 2006
Subject: [z3-checkins] r25758 - z3/sqlos/branch/0.2
Message-ID: <20060412235148.3D75B101B3@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 01:51:46 2006
New Revision: 25758
Modified:
z3/sqlos/branch/0.2/setup.py
Log:
Merge 25757 from trunk.
Modified: z3/sqlos/branch/0.2/setup.py
==============================================================================
--- z3/sqlos/branch/0.2/setup.py (original)
+++ z3/sqlos/branch/0.2/setup.py Thu Apr 13 01:51:46 2006
@@ -3,8 +3,17 @@
setup(
name="sqlos",
description="an integration package for Zope3 and SQLObject",
+ long_description="""
+sqlos is a toolkit for using SQLObject (an Object Relational
+Mapper) inside Zope 3 or Zope 2. It tries to take care of many of the
+fiddly details that always seem to take a lot of time.
+""",
+ url='http://codespeak.net/z3/sqlos/',
version="0.2",
license="ZPL",
+ maintainer="SQLOS development team",
+ maintainer_email="z3-sqlos@codespeak.net",
+ platforms=["any"],
package_dir={'':'src'},
packages=find_packages('src'),
zip_safe=False,
From jinty at codespeak.net Thu Apr 13 20:42:13 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 20:42:15 2006
Subject: [z3-checkins] r25812 - z3/sqlos/branch/0.2
Message-ID: <20060413184213.A6A1D1007D@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 20:42:11 2006
New Revision: 25812
Modified:
z3/sqlos/branch/0.2/makefile
z3/sqlos/branch/0.2/setup.py
Log:
Fix the version no and makefile.
Modified: z3/sqlos/branch/0.2/makefile
==============================================================================
--- z3/sqlos/branch/0.2/makefile (original)
+++ z3/sqlos/branch/0.2/makefile Thu Apr 13 20:42:11 2006
@@ -4,7 +4,7 @@
ZH=${HERE}/../../
PYTHON=python2.4
z3includes=Zope3/zopeskel/etc/package-includes
-Z3BRANCH=branches/0,2
+Z3BRANCH=branches/3.2
all : test clean
Modified: z3/sqlos/branch/0.2/setup.py
==============================================================================
--- z3/sqlos/branch/0.2/setup.py (original)
+++ z3/sqlos/branch/0.2/setup.py Thu Apr 13 20:42:11 2006
@@ -9,7 +9,7 @@
fiddly details that always seem to take a lot of time.
""",
url='http://codespeak.net/z3/sqlos/',
- version="0.2",
+ version="0.2.0",
license="ZPL",
maintainer="SQLOS development team",
maintainer_email="z3-sqlos@codespeak.net",
From jinty at codespeak.net Thu Apr 13 20:46:45 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 20:46:46 2006
Subject: [z3-checkins] r25813 - z3/sqlos/tag/0.2.0
Message-ID: <20060413184645.42FCC10081@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 20:46:41 2006
New Revision: 25813
Added:
z3/sqlos/tag/0.2.0/
- copied from r25812, z3/sqlos/branch/0.2/
Log:
Tag 0.2.0
From jinty at codespeak.net Thu Apr 13 20:54:34 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 20:54:35 2006
Subject: [z3-checkins] r25814 - z3/sqlos/trunk/doc
Message-ID: <20060413185434.6CB3810081@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 20:54:31 2006
New Revision: 25814
Added:
z3/sqlos/trunk/doc/HowToMakeARealease.rst
Log:
Make a release howto.
Added: z3/sqlos/trunk/doc/HowToMakeARealease.rst
==============================================================================
--- (empty file)
+++ z3/sqlos/trunk/doc/HowToMakeARealease.rst Thu Apr 13 20:54:31 2006
@@ -0,0 +1,60 @@
+How to make a SQLOS release
+===========================
+
+Firstly, this document is only a guide, feel free to correct/add to it.
+
+
+Major release
++++++++++++++
+
+Step 1 - Update Documentation
+-----------------------------
+
+Update the documents in the source:
+ 1. trunk/src/sqlos/README.txt - Th compatibility matrix.
+
+
+Step 2 - Make a maintenance branch for the release
+--------------------------------------------------
+
+Copy the branch:
+ 1. `svn cp https://codespeak.net/svn/z3/sqlos/trunk https://codespeak.net/svn/z3/sqlos/branch/x.y`
+
+Check it out:
+ 1. `svn co https://codespeak.net/svn/z3/sqlos/branch/x.y x.y`
+ 2. `cd x.y`
+
+Mark as a release as follows:
+ 1. svn rm setup.cfg
+ 2. update the version number in setup.py
+ 3. set the Z3BRANCH makefile variable so that the makefile points at the
+ compatible zope release branch
+
+Test the branch against Zope3 and Zope2:
+ 1. use `make test` to test the branch against the compatible version of Zope3
+ 2. TODO - develop a procedure for testing against Zope2
+
+
+Step 3 - Tag the branch as a release
+------------------------------------
+
+Copy the branch:
+ 1. `svn cp https://codespeak.net/svn/z3/sqlos/branch/x.y https://codespeak.net/svn/z3/sqlos/tag/x.y.z`
+
+Step 4 - Upload to the python cheese shop
+-----------------------------------------
+
+Simple:
+ 1. `svn co https://codespeak.net/svn/z3/sqlos/tag/x.y.z`
+ 2. cd x.y.z
+ 3. pythonX.X setup.py register sdist bdist_egg upload
+
+Step 5 - Send announcements
+---------------------------
+
+To:
+ z3-sqlos@codespeak.net
+ TODO: More?
+
+Template:
+ TODO
From jinty at codespeak.net Thu Apr 13 21:04:54 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 21:04:55 2006
Subject: [z3-checkins] r25815 - z3/www/trunk
Message-ID: <20060413190454.A110A10080@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 21:04:53 2006
New Revision: 25815
Modified:
z3/www/trunk/mkwebsite.py
Log:
Add a quick link to the sqlos 0.2.0 release.
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Thu Apr 13 21:04:53 2006
@@ -225,6 +225,8 @@
('sqlos main', 'index.html'),
]
quick_links = [
+ ('sqlos 0.2.0 release (compatible with SQLObject 0.7)',
+ 'http://cheeseshop.python.org/pypi/sqlos/0.2.0'),
('sqlos 0.1 release (compatible with SQLObject 0.6)',
'release/sqlos-0.1.tgz'),
('svn (the code)',
From jinty at codespeak.net Thu Apr 13 21:16:24 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Thu Apr 13 21:16:25 2006
Subject: [z3-checkins] r25816 - z3/www/trunk
Message-ID: <20060413191624.50EBE1007C@code0.codespeak.net>
Author: jinty
Date: Thu Apr 13 21:16:22 2006
New Revision: 25816
Modified:
z3/www/trunk/mkwebsite.py
Log:
Add a link to the sqlos mailing list.
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Thu Apr 13 21:16:22 2006
@@ -223,6 +223,7 @@
def sqlos_site(site, project):
nav_links = [
('sqlos main', 'index.html'),
+ ('mailing list', '/mailman/listinfo/z3-sqlos'),
]
quick_links = [
('sqlos 0.2.0 release (compatible with SQLObject 0.7)',
From jinty at codespeak.net Mon Apr 17 01:46:27 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Mon Apr 17 01:46:30 2006
Subject: [z3-checkins] r25876 - in z3/sqlos/trunk: . src/sqlos
Message-ID: <20060416234627.36781100A3@code0.codespeak.net>
Author: jinty
Date: Mon Apr 17 01:46:21 2006
New Revision: 25876
Modified:
z3/sqlos/trunk/TODO.txt
z3/sqlos/trunk/src/sqlos/README.txt
z3/sqlos/trunk/src/sqlos/_transaction.py
z3/sqlos/trunk/src/sqlos/adapter.py
z3/sqlos/trunk/src/sqlos/connection.py
Log:
Add some documntation
Modified: z3/sqlos/trunk/TODO.txt
==============================================================================
--- z3/sqlos/trunk/TODO.txt (original)
+++ z3/sqlos/trunk/TODO.txt Mon Apr 17 01:46:21 2006
@@ -4,9 +4,6 @@
Features
--------
-* Continuing quest to make sqlos containers more like zope persistent
- containers.
-
* Make it un-necessary to register the db adapter class in zcml. This is
required right now as there is no 'correct' way to tell which database a
IZopeConnection is for.
@@ -15,6 +12,3 @@
Bugs
----
-
-* the sqlos.auth, sqlos.annotations and sqlos.attributeannotations modules
- are completely un-tested and wait for someone to love them.
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Mon Apr 17 01:46:21 2006
@@ -59,9 +59,9 @@
Dependencies
------------
- + setuptools >= 0.6a11
+ + setuptools_ >= 0.6a11
- + SQLObject >= 0.7
+ + SQLObject_ >= 0.7
Place the sqlobject package somewhere in python's sys.path
($ZOPEHOME/lib/python is a good location).
@@ -74,6 +74,7 @@
repository.
.. _zopeproducts: http://cvs.zope.org/zopeproducts/
+.. _setuptools: http://www.python.org/pypi/setuptools
Background
Modified: z3/sqlos/trunk/src/sqlos/_transaction.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/_transaction.py (original)
+++ z3/sqlos/trunk/src/sqlos/_transaction.py Mon Apr 17 01:46:21 2006
@@ -7,7 +7,21 @@
# License (ZPL) v2.1. See COPYING.txt for more information.
#
##############################################################################
-"""
+"""Transaction management.
+
+This module integrates Zope and SQLObject's transaction management. It does 3
+things:
+
+ * Creates a thread local cache of SQLObjects so that cached objects do not
+ leak into other threads as they would in pure SQLObject.
+ * Clears the thread local cache at the start of each new transaction.
+ * When an object is modified, it registers itself with the data manager
+ which, in turn, registers a pre-commit hook. This hook sync's the object
+ sending all the SQL down the line before the two phase commit starts.
+
+XXX - There was a reason why we couldn't do this without a data manager, but I
+ cannot remember it now. -jinty
+
$Id$
"""
Modified: z3/sqlos/trunk/src/sqlos/adapter.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/adapter.py (original)
+++ z3/sqlos/trunk/src/sqlos/adapter.py Mon Apr 17 01:46:21 2006
@@ -7,14 +7,18 @@
# License (ZPL) v2.1. See COPYING.txt for more information.
#
##############################################################################
-"""
+"""Connection adapters for sqlos.
+
+These adapters adapt Zope RDB Connections to SQLObject connections by
+sub-classing the SQLObject connection classes.
+
$Id$
"""
__metaclass__ = type
from sqlobject.dbconnection import DBAPI
-from sqlobject import _mysql, _postgres, _sybase, _sqlite
+from sqlobject import _mysql, _postgres, _sqlite
from sqlobject.converters import registerConverter
from sqlobject.mysql import mysqlconnection
from zope.app.rdb.interfaces import DatabaseException
Modified: z3/sqlos/trunk/src/sqlos/connection.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/connection.py (original)
+++ z3/sqlos/trunk/src/sqlos/connection.py Mon Apr 17 01:46:21 2006
@@ -8,6 +8,15 @@
#
##############################################################################
"""
+Connection management.
+
+This module defines the connection descriptor used as the connection in a
+a sqlos SQLObject. This is responsible for getting the Zope connection and
+adapting it to look like a SQLObject connection.
+
+Connections are cached as experience has shown that all the utility and
+adapter utilities have a significant effect on speed.
+
$Id: factory.py 5216 2004-06-21 18:33:07Z dreamcatcher $
"""
__metaclass__ = type
From reebalazs at codespeak.net Tue Apr 18 08:31:59 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Tue Apr 18 08:32:00 2006
Subject: [z3-checkins] r25926 - z3/jsonserver/branch/merge/browser
Message-ID: <20060418063159.8D8A31008F@code0.codespeak.net>
Author: reebalazs
Date: Tue Apr 18 08:31:58 2006
New Revision: 25926
Modified:
z3/jsonserver/branch/merge/browser/json.js
z3/jsonserver/branch/merge/browser/xmlhttp.js
Log:
Critical: in XMLHttp change parameters and headers to Object from Array!
Because it is handled with for(xx in obj), they must be created
as Object. Problem is, that Sarissa puts extra functions in the
Array prototype, and these would come up in the iteration:
- causing an exception at setHeader,
- and snapping a &xxx=xxx...etc part to the end of the json
variable, causing a decode error on the server side.
The problem only instantiated (strangely) when we were logged
in as a plone user, in the kukitportlets demo.
Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js (original)
+++ z3/jsonserver/branch/merge/browser/json.js Tue Apr 18 08:31:58 2006
@@ -164,7 +164,7 @@
JSONRPCMethod.prototype.postData = function(url, user, pass, data, timeout, callback) {
var xmlhttp = new XMLHttp(url);
- var header = new Array()
+ var header = new Object()
header["Content-Type"] = "application/json-rpc";
xmlhttp.setHeaders(header);
xmlhttp.user = user;
@@ -291,7 +291,7 @@
var v = [];
for(attr in o) {
if(o[attr] == null) v.push("\"" + attr + "\": null");
- else if(typeof o[attr] == "function"); // skip
+ else if(typeof(o[attr]) == "function"); // skip
else v.push(escapeJSONString(attr) + ": " + toJSON(o[attr]));
}
return "{" + v.join(", ") + "}";
Modified: z3/jsonserver/branch/merge/browser/xmlhttp.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/xmlhttp.js (original)
+++ z3/jsonserver/branch/merge/browser/xmlhttp.js Tue Apr 18 08:31:58 2006
@@ -27,8 +27,8 @@
this.password = null;
this.timeout = null;
this.argString = "";
- this.parameters = new Array();
- this.headers = new Array();
+ this.parameters = new Object();
+ this.headers = new Object();
this.headers['Content-Type'] = 'application/x-www-form-urlencoded'
/* internal status flags */
From reebalazs at codespeak.net Tue Apr 18 17:11:19 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Tue Apr 18 17:11:20 2006
Subject: [z3-checkins] r25954 - z3/jsonserver/branch/merge/browser
Message-ID: <20060418151119.4EC851008E@code0.codespeak.net>
Author: reebalazs
Date: Tue Apr 18 17:11:16 2006
New Revision: 25954
Added:
z3/jsonserver/branch/merge/browser/logging.js
z3/jsonserver/branch/merge/browser/requestmanager.js
Modified:
z3/jsonserver/branch/merge/browser/configure.zcml
z3/jsonserver/branch/merge/browser/json.js
Log:
Add logging and simple support for simple request queue management
Modified: z3/jsonserver/branch/merge/browser/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/browser/configure.zcml (original)
+++ z3/jsonserver/branch/merge/browser/configure.zcml Tue Apr 18 17:11:16 2006
@@ -4,9 +4,11 @@
-
\ No newline at end of file
+
Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js (original)
+++ z3/jsonserver/branch/merge/browser/json.js Tue Apr 18 17:11:16 2006
@@ -51,6 +51,21 @@
function JSONSupplement(data, id) {
return new json.SupplementWrapper(data, id);
}
+
+// Direct method creation, by creating an implicit proxy
+// if methodName == '' then the url is taken as full url
+function makeJSONRPCMethod(url, methodName, callback, error, timeout, supplementData,
+ requestId, requestManager, user, pass) {
+ if (typeof(methodName) == 'undefined' || methodName == null || methodName == '') {
+ var pieces = url.split('/');
+ methodName = pieces.pop();
+ url = pieces.join('/');
+ }
+ var proxy = new JSONRPC(url);
+ proxy.addMethod(methodName, callback, error, timeout, supplementData,
+ requestId, requestManager, user, pass);
+ return proxy[methodName];
+}
function JSONRPC(url) {
this._url = url;
@@ -63,7 +78,7 @@
return new JSONRPC(url);
}
-JSONRPC.prototype.addMethod = function(name, callback, errHandler, timeout, supplementData, requestId) {
+JSONRPC.prototype.addMethod = function(name, callback, errHandler, timeout, supplementData, requestId, requestManager) {
if (typeof(errHandler) == 'undefined') {
errHandler = null;
}
@@ -76,9 +91,13 @@
if (typeof(requestId) == 'undefined' || requestId == null) {
requestId = "jsonRequest";
}
+ if (typeof(requestManager) == 'undefined' || requestManager == null) {
+ requestManager = _dummyRequestManager;
+ }
var self = this;
if(!self[name]){
- var method = new JSONRPCMethod(this._url, name, callback, errHandler, timeout, supplementData, requestId, this._user, this._password);
+ var method = new JSONRPCMethod(this._url, name, callback, errHandler, timeout, supplementData, requestId,
+ requestManager, this._user, this._password);
self[name] = method;
this._methods.push(method);
}
@@ -92,12 +111,26 @@
}
}
-function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId, user, pass) {
+function _DummyRequestManager() {
+ }
+
+_DummyRequestManager.prototype.notifyServer = function(method_with_parms, url) {
+ method_with_parms();
+ }
+
+_DummyRequestManager.prototype.receivedResult = function() {
+ }
+
+var _dummyRequestManager = _DummyRequestManager();
+
+function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId,
+ requestManager, user, pass) {
this.methodName = methodName;
this.callback = callback;
this.errHandler = errHandler;
this.supplementData = supplementData;
this.requestId = requestId;
+ this.requestManager = requestManager;
this.url = url;
this.user = user;
this.password = pass;
@@ -132,26 +165,30 @@
}
if(self.callback) {
var data = self.jsonRequest(requestId, self.methodName, args);
- self.postData(self.url, self.user, self.password, data, timeout, function(resp){
- var res = null;
- var exc = null;
- try {
- res = self.handleResponse(resp);
- } catch(e) {
- if (e.name == 'JSONRPCError' && self.errHandler) {
- exc = e;
+ var do_postdata = function() {
+ self.postData(self.url, self.user, self.password, data, timeout, function(resp){
+ var res = null;
+ var exc = null;
+ try {
+ res = self.handleResponse(resp);
+ } catch(e) {
+ if (e.name == 'JSONRPCError' && self.errHandler) {
+ exc = e;
+ } else {
+ throw(e);
+ }
+ }
+ self.requestManager.receivedResult();
+ if (exc == null) {
+ self.callback(res, supplementData, requestId);
} else {
- throw(e);
+ self.errHandler(exc, supplementData, requestId);
}
- }
- if (exc == null) {
- self.callback(res, supplementData, requestId);
- } else {
- self.errHandler(exc, supplementData, requestId);
- }
- args = null;
- resp = null;
- });
+ args = null;
+ resp = null;
+ });
+ }
+ self.requestManager.notifyServer(do_postdata, self.url + '/' + self.methodName);
} else {
var data = self.jsonRequest(requestId, self.methodName, args);
var resp = self.postData(self.url, self.user, self.password, data, timeout);
@@ -159,7 +196,6 @@
}
}
return fn;
-
}
JSONRPCMethod.prototype.postData = function(url, user, pass, data, timeout, callback) {
Added: z3/jsonserver/branch/merge/browser/logging.js
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/browser/logging.js Tue Apr 18 17:11:16 2006
@@ -0,0 +1,23 @@
+/* Set up logging with Mochikit, if that is installed */
+
+/* Create jsonrpc namespace */
+
+if (typeof(jsonrpc) == 'undefined') {
+ var jsonrpc = {};
+}
+
+/* check whether the logging stuff of MochiKit is available */
+try {
+ MochiKit.Logging.log('Initializing jsonrpc');
+ jsonrpc.log = MochiKit.Logging.log;
+ jsonrpc.logError = MochiKit.Logging.logError;
+ jsonrpc.logDebug = MochiKit.Logging.logDebug;
+ jsonrpc.logFatal = MochiKit.Logging.logFatal;
+ jsonrpc.logWarning = MochiKit.Logging.logWarning;
+} catch(e) {
+ jsonrpc.log = function(str){};
+ jsonrpc.logError = jsonrpc.log;
+ jsonrpc.logDebug = jsonrpc.log;
+ jsonrpc.logFatal = jsonrpc.log;
+ jsonrpc.logWarning = jsonrpc.log;
+}
Added: z3/jsonserver/branch/merge/browser/requestmanager.js
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/browser/requestmanager.js Tue Apr 18 17:11:16 2006
@@ -0,0 +1,141 @@
+/* Request manager
+
+This limits the number of outgoing requests. Extra
+requests are stored and sent out on demand.
+
+XXX Requests never, at the moment, time out from the queue
+TODO should take care of this.
+
+It is possible to have more instances and have different methods
+queue up in different queues.
+
+Usage:
+
+- instantiate a queue
+- use it as a parameter for addMethod
+- it will only queue async requests.
+
+Usage manually:
+
+- notifyServer(func, url) , where func is a partial containing
+ all parameters,
+- receivedResult() when result is received or an error is signalled.
+
+*/
+
+jsonrpc.RequestManager = function (name, maxNr) {
+ this.waitingQueue = new jsonrpc.FifoQueue();
+ this.sentNr = 0;
+ if (typeof(name) == undefined) {
+ name = null;
+ }
+ this.name = name;
+ var namestr = '';
+ if (name != null) {
+ namestr = '[' + name + '] '
+ }
+ this.namestr = namestr;
+ if (typeof(maxNr) != undefined && maxNr != null) {
+ this.maxNr = maxNr;
+ }
+}
+
+// max request nr
+jsonrpc.RequestManager.prototype.maxNr = 4;
+
+jsonrpc.RequestManager.prototype.getInfo = function() {
+ return '(RQ: ' + this.sentNr + ' OUT, ' + this.waitingQueue.size() + ' WAI)';
+}
+
+jsonrpc.RequestManager.prototype.log = function(txt) {
+ jsonrpc.logDebug('RequestManager ' + this.namestr + txt + ' ' + this.getInfo());
+}
+
+jsonrpc.RequestManager.prototype.pushWaitingRequest = function(func, url) {
+ this.waitingQueue.push([func, url]);
+}
+
+jsonrpc.RequestManager.prototype.popWaitingRequest = function() {
+ return this.waitingQueue.pop();
+}
+
+jsonrpc.RequestManager.prototype.isWaitingRequestQueueEmpty = function() {
+ return this.waitingQueue.empty();
+}
+
+jsonrpc.RequestManager.prototype.pushSentRequest = function(func, url) {
+ // we do not store the elems, since they are not needed now
+ this.sentNr = this.sentNr + 1;
+}
+
+jsonrpc.RequestManager.prototype.popSentRequest = function() {
+ this.sentNr = this.sentNr - 1;
+}
+
+jsonrpc.RequestManager.prototype.isSentRequestQueueFull = function() {
+ return (this.sentNr >= this.maxNr)
+}
+
+/* request manager notification API */
+
+jsonrpc.RequestManager.prototype.notifyServer = function(func, url) {
+ // func must be a partial (e.g. use Mochikit or wrap up)
+ // here url is only for the logging
+ if (! jsonrpc.requestManager.isSentRequestQueueFull()) {
+ // can be sent if we are not over the limit.
+ this.pushSentRequest(func, url);
+ this.log('Notify server at ' + url);
+ func();
+ } else {
+ this.pushWaitingRequest(func, url);
+ this.log('Queue server notification at ' + url);
+ }
+}
+
+jsonrpc.RequestManager.prototype.receivedResult = function() {
+ // must be called when one result arrived
+ // Mark that we have one less request out.
+ jsonrpc.requestManager.popSentRequest();
+ if (! jsonrpc.requestManager.isWaitingRequestQueueEmpty()) {
+ // see if we can send another request in place of the received one
+ // request is waiting, send it.
+ var waiting = jsonrpc.requestManager.popWaitingRequest();
+ var func = waiting[0];
+ var url = waiting[1];
+ jsonrpc.requestManager.pushSentRequest(func, url);
+ this.log("Send queued notification to server at " + url);
+ func();
+ } else {
+ this.log("Request queue empty.");
+ }
+}
+
+/* simple FIFO queue */
+
+jsonrpc.FifoQueue = function () {
+ this.reset();
+}
+
+jsonrpc.FifoQueue.prototype.reset = function() {
+ this.elements = new Array();
+}
+
+jsonrpc.FifoQueue.prototype.push = function(obj) {
+ this.elements.push(obj);
+}
+
+jsonrpc.FifoQueue.prototype.pop = function() {
+ return this.elements.shift();
+}
+
+jsonrpc.FifoQueue.prototype.empty = function() {
+ return ! this.elements.length;
+}
+
+jsonrpc.FifoQueue.prototype.size = function() {
+ return this.elements.length;
+}
+
+jsonrpc.FifoQueue.prototype.front = function() {
+ return this.elements[0];
+}
From reebalazs at codespeak.net Tue Apr 18 17:24:58 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Tue Apr 18 17:24:59 2006
Subject: [z3-checkins] r25957 - z3/jsonserver/branch/merge/browser
Message-ID: <20060418152458.4EE041009C@code0.codespeak.net>
Author: reebalazs
Date: Tue Apr 18 17:24:57 2006
New Revision: 25957
Modified:
z3/jsonserver/branch/merge/browser/requestmanager.js
Log:
Fix request manager
Modified: z3/jsonserver/branch/merge/browser/requestmanager.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/requestmanager.js (original)
+++ z3/jsonserver/branch/merge/browser/requestmanager.js Tue Apr 18 17:24:57 2006
@@ -81,7 +81,7 @@
jsonrpc.RequestManager.prototype.notifyServer = function(func, url) {
// func must be a partial (e.g. use Mochikit or wrap up)
// here url is only for the logging
- if (! jsonrpc.requestManager.isSentRequestQueueFull()) {
+ if (! this.isSentRequestQueueFull()) {
// can be sent if we are not over the limit.
this.pushSentRequest(func, url);
this.log('Notify server at ' + url);
@@ -95,14 +95,14 @@
jsonrpc.RequestManager.prototype.receivedResult = function() {
// must be called when one result arrived
// Mark that we have one less request out.
- jsonrpc.requestManager.popSentRequest();
- if (! jsonrpc.requestManager.isWaitingRequestQueueEmpty()) {
+ this.popSentRequest();
+ if (! this.isWaitingRequestQueueEmpty()) {
// see if we can send another request in place of the received one
// request is waiting, send it.
- var waiting = jsonrpc.requestManager.popWaitingRequest();
+ var waiting = this.popWaitingRequest();
var func = waiting[0];
var url = waiting[1];
- jsonrpc.requestManager.pushSentRequest(func, url);
+ this.pushSentRequest(func, url);
this.log("Send queued notification to server at " + url);
func();
} else {
From reebalazs at codespeak.net Thu Apr 20 08:24:18 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Thu Apr 20 08:24:21 2006
Subject: [z3-checkins] r26014 - z3/jsonserver/branch/merge/concatresource
Message-ID: <20060420062418.9E24E100C6@code0.codespeak.net>
Author: reebalazs
Date: Thu Apr 20 08:24:15 2006
New Revision: 26014
Modified:
z3/jsonserver/branch/merge/concatresource/concatresource.py
Log:
Adjust Five import to Zope 2.9 / Five 1.3
Modified: z3/jsonserver/branch/merge/concatresource/concatresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatresource.py (original)
+++ z3/jsonserver/branch/merge/concatresource/concatresource.py Thu Apr 20 08:24:15 2006
@@ -13,7 +13,14 @@
from zope.app.publisher.browser.resource import Resource
else:
__five__ = True
- from Products.Five.resource import Resource
+ try:
+ # Zope 2.8 / Five 1.0.2
+ from Products.Five.resource import Resource
+ __five_pre_1_3_ = True
+ except ImportError:
+ # Zope 2.9 / Five 1.3
+ from Products.Five.browser.resource import Resource
+ __five_pre_1_3__ = False
class GenericResource(BrowserView, Resource):
"""A publishable resource"""
From reebalazs at codespeak.net Thu Apr 20 10:53:49 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Thu Apr 20 10:53:50 2006
Subject: [z3-checkins] r26020 - z3/jsonserver/branch/merge/browser
Message-ID: <20060420085349.DE93410087@code0.codespeak.net>
Author: reebalazs
Date: Thu Apr 20 10:53:48 2006
New Revision: 26020
Modified:
z3/jsonserver/branch/merge/browser/json.js
Log:
Critical fix (self.requestManager has no properties)
Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js (original)
+++ z3/jsonserver/branch/merge/browser/json.js Thu Apr 20 10:53:48 2006
@@ -121,7 +121,7 @@
_DummyRequestManager.prototype.receivedResult = function() {
}
-var _dummyRequestManager = _DummyRequestManager();
+var _dummyRequestManager = new _DummyRequestManager();
function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId,
requestManager, user, pass) {
From reebalazs at codespeak.net Thu Apr 20 12:08:26 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Thu Apr 20 12:08:28 2006
Subject: [z3-checkins] r26026 - z3/jsonserver/branch/zope2_test
Message-ID: <20060420100826.D51C31008D@code0.codespeak.net>
Author: reebalazs
Date: Thu Apr 20 12:08:25 2006
New Revision: 26026
Modified:
z3/jsonserver/branch/zope2_test/jsonrpc.py
Log:
Make the IJsonRequest interface bound in Zope 2.9
In 2.9 I realized that the interface binding does not work
somehow directlyProvides attaches the interfact but it disappears
later where I want to use it for an adapter lookup.
Now we provide the interface in the class level and
override __class__ of the request object on the run.
Modified: z3/jsonserver/branch/zope2_test/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/zope2_test/jsonrpc.py (original)
+++ z3/jsonserver/branch/zope2_test/jsonrpc.py Thu Apr 20 12:08:25 2006
@@ -21,8 +21,10 @@
from zLOG import LOG, INFO, DEBUG, WARNING, ERROR
from cgi import FieldStorage
import ZPublisher.HTTPResponse
-from zope.interface import directlyProvides, directlyProvidedBy
+##from zope.interface import directlyProvides, directlyProvidedBy
+from zope.interface import implements
from interfaces import IJsonRequest
+from ZPublisher.HTTPRequest import HTTPRequest
# this is used to identify incoming requests
request_content_type = 'application/json-rpc'
@@ -198,6 +200,11 @@
# Patching processInputs of ZPublisher.HTTPRequest
# --
+class JsonRpcRequest(HTTPRequest):
+ 'JSON-RPC HTTP request'
+ # this is just used to force the interface on the object
+ implements(IJsonRequest)
+
re_content_type= re.compile(r'charset\s*=\s*([^;]+)')
def processInputs(self, **kw):
@@ -245,9 +252,13 @@
# set the marker that can be used to check if we are in json mode
other['JSON_MODE'] = self.json_mode = True
# also set the request interface
- interfaces = directlyProvidedBy(self)
- interfaces += IJsonRequest
- directlyProvides(self, interfaces)
+ # XXX this would be good but for some reason gets "swallowed"
+ # by the time we get there, so we override the class instead.
+ # This error first manifested in Zope2.9, it was ok. till 2.8.
+ ##interfaces = directlyProvidedBy(self)
+ ##interfaces += IJsonRequest
+ ##directlyProvides(self, interfaces)
+ self.__class__ = JsonRpcRequest
#
response = Response(response, jsonID)
other['RESPONSE'] = self.response = response
@@ -264,7 +275,6 @@
self.stdin.seek(0)
return self._processInputs_jsonrc_patched(**kw)
-from ZPublisher.HTTPRequest import HTTPRequest
def patch_HTTPRequest():
'This will patch HTTPRequest to enable json-rpc handling'
HTTPRequest._processInputs_jsonrc_patched, HTTPRequest.processInputs = \
From reebalazs at codespeak.net Fri Apr 21 09:32:09 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri Apr 21 09:32:12 2006
Subject: [z3-checkins] r26075 - in
z3/jsonserver/branch/merge/concatresource: . compression test
Message-ID: <20060421073209.DC6DB1007D@code0.codespeak.net>
Author: reebalazs
Date: Fri Apr 21 09:32:05 2006
New Revision: 26075
Added:
z3/jsonserver/branch/merge/concatresource/README
Modified:
z3/jsonserver/branch/merge/concatresource/compression/__init__.py
z3/jsonserver/branch/merge/concatresource/compression/css.py
z3/jsonserver/branch/merge/concatresource/compression/javascript.py
z3/jsonserver/branch/merge/concatresource/concatfileresource.py
z3/jsonserver/branch/merge/concatresource/concatresource.py
z3/jsonserver/branch/merge/concatresource/directives.py
z3/jsonserver/branch/merge/concatresource/meta.py
z3/jsonserver/branch/merge/concatresource/test/configure.zcml
Log:
Adding compress_level as attribute, choices are "none", "safe", "full"
Added: z3/jsonserver/branch/merge/concatresource/README
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/concatresource/README Fri Apr 21 09:32:05 2006
@@ -0,0 +1,72 @@
+
+Objectives
+----------
+
+I made this utility for the works in the jsonserver integration and
+AZAX/kukit. This was meant to be a temporary, lightweight solution but it
+has long term merits too. I needed this because I wanted a solution that
+works right now, works on zope3 and zope 2.8 even (so zc.resourcelibraries
+was not a choice), does not depend on Plone (so ResourceRegistries is out
+too).
+
+The interesting point of the utility is: instead of building registries to
+emit include tags in the HTML, it simply makes one resource that needs to
+be imported in a single line::
+
+
+
+Also:
+
+- it compresses the JS or CSS files with Florian Schulze's compressor
+ from ResourceRegistries
+
+- it contains an utility interface that another component can implement
+ to dynamically extend the list of files (like I did with AZAX). So the
+ "registry" is not really implemented but can be plugged in.
+
+- it is tested (although not much) to work with Zope 2.8, 2.9, 3.1, 3.2
+
+Meanwhile I implemented the cache headers for the resources correctly
+here, the current implementation of caching is broken in Five and I
+believe in Z3 resources as well; beware that I considered the original
+Zope3 code only and did not look at additional utilities. According to my
+observation: in Z3 the original resources attempt to handle the cache
+headers correctly but never really check if the file gets changed on the
+filesystem (only on restart). If this is really a problem and not just I
+believe, then it is fixed in my code.
+
+More information on this issue:
+
+http://article.gmane.org/gmane.comp.web.zope.z3base.general/53
+
+Compression
+-----------
+
+You can use more levels of compressions with the compress_level attribute.
+
+
+
+Some explanation:
+
+- compression is only implemented for JavaScript and CSS
+
+- The default level is "safe", this is useable with all scripts
+
+- The "full" level gives even better compression by taking out all newlines
+ and mangling private variable names, but some preparation must be made
+ in the scripts for that (like putting a ; after }-s I think, and
+ also maybe more).
+
+- Specifying "none" will leave your resource uncompressed. This
+ can be useful for debugging.
+
+
Modified: z3/jsonserver/branch/merge/concatresource/compression/__init__.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/__init__.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/__init__.py Fri Apr 21 09:32:05 2006
@@ -14,7 +14,7 @@
default_compress_method = lambda text: text
-def compress(data, content_type):
+def compress(data, content_type, compress_level):
'Returns compressed text for a given content type'
method = compress_methods.get(content_type, default_compress_method)
- return method(data)
+ return method(data, compress_level)
Modified: z3/jsonserver/branch/merge/concatresource/compression/css.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/css.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/css.py Fri Apr 21 09:32:05 2006
@@ -5,7 +5,14 @@
from thirdparty.packer import CSSPacker
-csspacker_full = CSSPacker('safe')
+csspacker_safe = CSSPacker('safe')
+csspacker_full = CSSPacker('full')
-def compress(data):
- return csspacker_full.pack(data)
+def compress(data, compress_level):
+ if compress_level == "safe":
+ return csspacker_safe.pack(data)
+ elif compress_level == "full":
+ return csspacker_full.pack(data)
+ else:
+ # none
+ return data
Modified: z3/jsonserver/branch/merge/concatresource/compression/javascript.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/javascript.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/javascript.py Fri Apr 21 09:32:05 2006
@@ -4,7 +4,14 @@
from thirdparty.packer import JavascriptPacker
-jspacker_full = JavascriptPacker('safe')
+jspacker_safe = JavascriptPacker('safe')
+jspacker_full = JavascriptPacker('full')
-def compress(data):
- return jspacker_full.pack(data)
+def compress(data, compress_level):
+ if compress_level == "safe":
+ return jspacker_safe.pack(data)
+ elif compress_level == "full":
+ return jspacker_full.pack(data)
+ else:
+ # none
+ return data
Modified: z3/jsonserver/branch/merge/concatresource/concatfileresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatfileresource.py (original)
+++ z3/jsonserver/branch/merge/concatresource/concatfileresource.py Fri Apr 21 09:32:05 2006
@@ -24,7 +24,7 @@
'''
implements(IContextFile)
- def __init__(self, pathlist, name):
+ def __init__(self, pathlist, name, compress_level):
# Path is now a list.
assert isinstance(pathlist, (list, tuple))
# check all files, just to raise error if don't exist
@@ -33,6 +33,7 @@
#
self.pathlist_base = pathlist
self.__name__ = name
+ self.compress_level = compress_level
# markers for pathlist modification
self.pathlist = []
self.fileslist_changed = None
@@ -88,6 +89,7 @@
assert d['content_type'] == content_type
data.append(d['data'])
result['data'] = '\n'.join(data)
+ result['compress_level'] = self.compress_level
# Do compression on the result
result['data'] = compress(**result)
return result
Modified: z3/jsonserver/branch/merge/concatresource/concatresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatresource.py (original)
+++ z3/jsonserver/branch/merge/concatresource/concatresource.py Fri Apr 21 09:32:05 2006
@@ -104,9 +104,10 @@
factory = None
resource = None
- def __init__(self, path, name, resource_factory=None, checker=None):
+ def __init__(self, path, name, compress_level, resource_factory=None, checker=None):
self.__name = name
self.__path = path
+ self.__compress_level = compress_level
if resource_factory is not None:
self.resource = resource_factory
# z3 only
@@ -117,7 +118,7 @@
rsrc = self.__rsrc
except AttributeError:
# Delayed creation. That assures that registry is set up by this time.
- rsrc = self.__rsrc = ICachedResource(self.factory(self.__path, self.__name))
+ rsrc = self.__rsrc = ICachedResource(self.factory(self.__path, self.__name, self.__compress_level))
resource = self.resource(rsrc, request)
# z3 only
resource.__name__ = self.__name
Modified: z3/jsonserver/branch/merge/concatresource/directives.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/directives.py (original)
+++ z3/jsonserver/branch/merge/concatresource/directives.py Fri Apr 21 09:32:05 2006
@@ -1,7 +1,7 @@
from zope.interface import Interface
from zope.configuration.fields import GlobalObject, Tokens, Path, \
PythonIdentifier, MessageID
-from zope.schema import TextLine, Text, Id
+from zope.schema import TextLine, Text, Id, Choice
from zope.app.security.fields import Permission
from fields import PathList
from zope.app.component.metadirectives import IBasicViewInformation
@@ -29,3 +29,10 @@
description=u"A space separated list of resource files",
required=True
)
+
+ compress_level = Choice(
+ title=u"Compress level",
+ description=u"Level of compression applied, by default 'safe'.",
+ values=(u'none', u'safe', u'full'),
+ required=False,
+ )
Modified: z3/jsonserver/branch/merge/concatresource/meta.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/meta.py (original)
+++ z3/jsonserver/branch/merge/concatresource/meta.py Fri Apr 21 09:32:05 2006
@@ -39,7 +39,7 @@
},
}
-def concatresource(_context, name, files=None, layer=_layer, permission='zope.Public'):
+def concatresource(_context, name, files=None, compress_level='safe', layer=_layer, permission='zope.Public'):
if not files:
raise ConfigurationError(
@@ -78,7 +78,7 @@
checker = NamesChecker(allowed_names, permission)
- factory = res_factory(res, name, resource_factory=new_class, checker=checker)
+ factory = res_factory(res, name, compress_level, resource_factory=new_class, checker=checker)
if __pre_3_2__:
_context.action(
Modified: z3/jsonserver/branch/merge/concatresource/test/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/test/configure.zcml (original)
+++ z3/jsonserver/branch/merge/concatresource/test/configure.zcml Fri Apr 21 09:32:05 2006
@@ -8,4 +8,11 @@
test2.js"
/>
+
+
From jinty at codespeak.net Fri Apr 21 15:15:08 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri Apr 21 15:15:11 2006
Subject: [z3-checkins] r26099 - in z3/sqlos/trunk/src/sqlos: . testing tests
Message-ID: <20060421131508.B733310084@code0.codespeak.net>
Author: jinty
Date: Fri Apr 21 15:14:55 2006
New Revision: 26099
Modified:
z3/sqlos/trunk/src/sqlos/README.txt
z3/sqlos/trunk/src/sqlos/__init__.py
z3/sqlos/trunk/src/sqlos/testing/sampleperson.py
z3/sqlos/trunk/src/sqlos/tests/test_doctests.py
Log:
move sqlos._sqlos to sqlos.zsqlobject and softly deprecate the import of SQLOS from sqlos.
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Fri Apr 21 15:14:55 2006
@@ -198,7 +198,7 @@
>>> from zope.interface import implements
>>> from sqlobject import *
- >>> from sqlos import SQLOS
+ >>> from sqlos.zsqlobject import SQLOS
>>> class Person(SQLOS):
... implements(IPerson)
Modified: z3/sqlos/trunk/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/__init__.py Fri Apr 21 15:14:55 2006
@@ -16,7 +16,10 @@
import zope.component
from sqlobject.sqlbuilder import registerConverter
-from _sqlos import SQLOS
+# sqlos.SQLOS is softly deprecated, will go away sometime
+# (after at least one major release with deprecation warnings)
+# import directly from sqlos.zsqlobject
+from sqlos.zsqlobject import SQLOS
def caller(n=1):
"""Return the name of the calling function n levels up in the frame stack.
Modified: z3/sqlos/trunk/src/sqlos/testing/sampleperson.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/testing/sampleperson.py (original)
+++ z3/sqlos/trunk/src/sqlos/testing/sampleperson.py Fri Apr 21 15:14:55 2006
@@ -4,7 +4,7 @@
from zope.schema import TextLine, Text, Datetime
from zope.app.container import constraints
-from sqlos import SQLOS
+from sqlos.zsqlobject import SQLOS
from sqlos.interfaces import ISQLSchema, IISQLObjectIsolated, ISQLObjectIsolated
from sqlos.interfaces.container import ISQLObjectContainer
from sqlos.container import SQLObjectContainer, SQLIsolatedContainer
Modified: z3/sqlos/trunk/src/sqlos/tests/test_doctests.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/tests/test_doctests.py (original)
+++ z3/sqlos/trunk/src/sqlos/tests/test_doctests.py Fri Apr 21 15:14:55 2006
@@ -26,5 +26,5 @@
DocTestSuite('sqlos.container', optionflags=doctest.ELLIPSIS),
DocTestSuite('sqlos.connection'),
DocTestSuite('sqlos._transaction'),
- DocTestSuite('sqlos._sqlos')
+ DocTestSuite('sqlos.zsqlobject')
])
From jinty at codespeak.net Fri Apr 21 15:23:02 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri Apr 21 15:23:03 2006
Subject: [z3-checkins] r26100 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060421132302.83ADD10084@code0.codespeak.net>
Author: jinty
Date: Fri Apr 21 15:22:59 2006
New Revision: 26100
Modified:
z3/sqlos/trunk/src/sqlos/__init__.py
Log:
Remove cruft and deprecated code. Also drop an XXX for untested code.
Modified: z3/sqlos/trunk/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/__init__.py (original)
+++ z3/sqlos/trunk/src/sqlos/__init__.py Fri Apr 21 15:22:59 2006
@@ -10,10 +10,7 @@
$Id$
"""
-__metaclass__ = type
-
from datetime import datetime, date
-import zope.component
from sqlobject.sqlbuilder import registerConverter
# sqlos.SQLOS is softly deprecated, will go away sometime
@@ -21,14 +18,8 @@
# import directly from sqlos.zsqlobject
from sqlos.zsqlobject import SQLOS
-def caller(n=1):
- """Return the name of the calling function n levels up in the frame stack.
- Ex: caller(0) ==> 'caller'; def f(): return caller(); f() ==> 'f'
- """
- import inspect
- return inspect.getouterframes(inspect.currentframe())[n][3]
-
+## XXX: What are these?? I am sure there are no tests for them. - jinty
def DateTimeConverter(value, db=None):
return repr(value.isoformat())
@@ -40,19 +31,3 @@
return repr(value.isoformat())
registerConverter(date, DateConverter)
-
-
-def getFactory(name, context=None, default=None):
- # XXX - deprecated, goes away after sqlos 0.2
- return zope.component.queryUtility(IISQLObject, name, default=default, context=context)
-
-from zope.deprecation import deprecated
-msg = "getFactory is depreciated and will go away after sqlos 0.2 you should \
-replace this with a direct call to \
-zope.component.getUtility(IISQLObject, name, context=context) if you need the \
-functionailty of a SQLObject class, or \
-zope.component.getUtility(IFactory, name, context=context) if you want to use it as a \
-factory."
-
-deprecated("getFactory", msg)
-deprecated("caller", "sqlos.caller is deprecated and will be removed after sqlos 0.2")
From jinty at codespeak.net Fri Apr 21 15:28:47 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri Apr 21 15:28:48 2006
Subject: [z3-checkins] r26101 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060421132847.95ACE10084@code0.codespeak.net>
Author: jinty
Date: Fri Apr 21 15:28:44 2006
New Revision: 26101
Modified:
z3/sqlos/trunk/src/sqlos/container.py
Log:
Remove the deprecated allowedFactories method.
Modified: z3/sqlos/trunk/src/sqlos/container.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/container.py (original)
+++ z3/sqlos/trunk/src/sqlos/container.py Fri Apr 21 15:28:44 2006
@@ -17,7 +17,6 @@
from persistent import Persistent
from zope.interface import implements
from zope.component import IFactory
-from zope import deprecation
import zope.component
from zope.app.container.interfaces import IContained
from zope.app.container.contained import ContainedProxy
@@ -86,14 +85,6 @@
def __init__(self):
pass
- def _allowedFactories(self):
- for name, factory in zope.component.getFactoriesFor(ISQLObject):
- if checkFactory(self, None, factory):
- yield name
- allowedFactories = deprecation.deprecated(_allowedFactories,
- 'allowedFactories is deprecated and will be removed after sqlos 0.2'
- ' please use _getAllowedIISQLObjectUtilities instead.')
-
def _getAllowedIISQLObjectUtilities(self):
for name, factory in zope.component.getFactoriesFor(ISQLObject):
if checkFactory(self, None, factory):
@@ -209,16 +200,6 @@
_container_id = None
- def allowedFactories(self):
- # Ignore all factories not implementing ISQLObjectIsolated
- for f in SQLObjectContainer._allowedFactories(self):
- implemented = zope.component.getFactoryInterfaces(f)
- if implemented.isOrExtends(ISQLObjectIsolated):
- yield f
- allowedFactories = deprecation.deprecated(allowedFactories,
- 'allowedFactories is deprecated and will be removed after sqlos 0.2'
- ' please use _getAllowedIISQLObjectUtilities instead.')
-
def _getAllowedIISQLObjectUtilities(self):
# Ignore all utilities not implementing ISQLObjectIsolated
for name, utility in SQLObjectContainer._getAllowedIISQLObjectUtilities(self):
From reebalazs at codespeak.net Sat Apr 22 11:38:13 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:38:14 2006
Subject: [z3-checkins] r26122 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422093813.22ACE1008D@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:38:12 2006
New Revision: 26122
Added:
z3/jsonserver/branch/merge/utils/
Log:
create utils subdir
From reebalazs at codespeak.net Sat Apr 22 11:38:20 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:38:21 2006
Subject: [z3-checkins] r26123 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422093820.6EC4310097@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:38:18 2006
New Revision: 26123
Added:
z3/jsonserver/branch/merge/utils/pyclient
- copied unchanged from r26122, z3/jsonserver/branch/zope2_test/pyclient.py
Log:
move file to utils
From reebalazs at codespeak.net Sat Apr 22 11:42:03 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:42:05 2006
Subject: [z3-checkins] r26125 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422094203.DE93710098@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:42:02 2006
New Revision: 26125
Modified:
z3/jsonserver/branch/merge/utils/pyclient
Log:
Add comment to pyclient
Modified: z3/jsonserver/branch/merge/utils/pyclient
==============================================================================
--- z3/jsonserver/branch/merge/utils/pyclient (original)
+++ z3/jsonserver/branch/merge/utils/pyclient Sat Apr 22 11:42:02 2006
@@ -1,15 +1,25 @@
+#! /usr/bin/python
'''\
A python client for jsonserver.
-This is a separate file that is not needed for jsonserver to work.
+This is a separate utility that is not needed for jsonserver to work.
It can be used to
- test json components from the command line
- create a standalone python json-rpc client.
-This file needs to import minjson.py, it uses nothing else
-from the server.
+This utility will only work if the following packages are
+importable from python:
+
+ minjson
+ zope.component
+ zope.interface
+
+Since neither minjson nor the zope component architecture
+are distributed as standalone at the moment,
+you have to arrange this yourself (e.g. symlinking to
+site-packages)
'''
import urllib2
From reebalazs at codespeak.net Sat Apr 22 11:47:05 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:47:08 2006
Subject: [z3-checkins] r26126 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422094705.EDBAD1009B@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:47:04 2006
New Revision: 26126
Added:
z3/jsonserver/branch/merge/utils/tcpwatch (contents, props changed)
Log:
Include tcpwatch original version
Added: z3/jsonserver/branch/merge/utils/tcpwatch
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/utils/tcpwatch Sat Apr 22 11:47:04 2006
@@ -0,0 +1,1485 @@
+#!/usr/bin/python
+
+#############################################################################
+#
+# Zope Public License (ZPL) Version 2.0
+# -----------------------------------------------
+#
+# This software is Copyright (c) Zope Corporation (tm) and
+# Contributors. All rights reserved.
+#
+# 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 above
+# copyright notice, this list of conditions, and the following
+# disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions, and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# 3. The name Zope Corporation (tm) must not be used to
+# endorse or promote products derived from this software
+# without prior written permission from Zope Corporation.
+#
+# 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 Zope Corporation. Use of them is
+# covered in a separate agreement (see
+# http://www.zope.com/Marks).
+#
+# 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 ZOPE CORPORATION ``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 ZOPE CORPORATION OR ITS CONTRIBUTORS 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.
+#
+#
+# This software consists of contributions made by Zope
+# Corporation and many individuals on behalf of Zope
+# Corporation. Specific attributions are listed in the
+# accompanying credits file.
+#
+#############################################################################
+"""TCPWatch, a connection forwarder and HTTP proxy for monitoring connections.
+
+Requires Python 2.1 or above.
+
+Revision information:
+$Id: tcpwatch.py,v 1.9 2004/06/17 00:03:46 shane Exp $
+"""
+
+from __future__ import nested_scopes
+
+VERSION = '1.3'
+COPYRIGHT = (
+ 'TCPWatch %s Copyright 2001 Shane Hathaway, Zope Corporation'
+ % VERSION)
+
+import sys
+import os
+import socket
+import asyncore
+import getopt
+from time import time, localtime
+
+
+RECV_BUFFER_SIZE = 8192
+show_cr = 0
+
+
+#############################################################################
+#
+# Connection forwarder
+#
+#############################################################################
+
+
+class ForwardingEndpoint (asyncore.dispatcher):
+ """A socket wrapper that accepts and generates stream messages.
+ """
+ _dests = ()
+
+ def __init__(self, conn=None):
+ self._outbuf = []
+ asyncore.dispatcher.__init__(self, conn)
+
+ def set_dests(self, dests):
+ """Sets the destination streams.
+ """
+ self._dests = dests
+
+ def write(self, data):
+ if data:
+ self._outbuf.append(data)
+ self.handle_write()
+
+ def readable(self):
+ return 1
+
+ def writable(self):
+ return not self.connected or len(self._outbuf) > 0
+
+ def handle_connect(self):
+ for d in self._dests:
+ d.write('') # A blank string means the socket just connected.
+
+ def received(self, data):
+ if data:
+ for d in self._dests:
+ d.write(data)
+
+ def handle_read(self):
+ data = self.recv(RECV_BUFFER_SIZE)
+ self.received(data)
+
+ def handle_write(self):
+ if not self.connected:
+ # Wait for a connection.
+ return
+ buf = self._outbuf
+ while buf:
+ data = buf.pop(0)
+ if data:
+ sent = self.send(data)
+ if sent < len(data):
+ buf.insert(0, data[sent:])
+ break
+
+ def handle_close (self):
+ dests = self._dests
+ self._dests = ()
+ for d in dests:
+ d.close()
+ self.close()
+
+ def handle_error(self):
+ t, v = sys.exc_info()[:2]
+ for d in self._dests:
+ if hasattr(d, 'error'):
+ d.error(t, v)
+ self.handle_close()
+
+
+
+class EndpointObserver:
+ """Sends stream events to a ConnectionObserver.
+
+ Streams don't distinguish sources, while ConnectionObservers do.
+ This adapter adds source information to stream events.
+ """
+
+ def __init__(self, obs, from_client):
+ self.obs = obs
+ self.from_client = from_client
+
+ def write(self, data):
+ if data:
+ self.obs.received(data, self.from_client)
+ else:
+ self.obs.connected(self.from_client)
+
+ def close(self):
+ self.obs.closed(self.from_client)
+
+ def error(self, t, v):
+ self.obs.error(self.from_client, t, v)
+
+
+
+class ForwardedConnectionInfo:
+ transaction = 1
+
+ def __init__(self, connection_number, client_addr, server_addr=None):
+ self.opened = time()
+ self.connection_number = connection_number
+ self.client_addr = client_addr
+ self.server_addr = server_addr
+
+ def dup(self):
+ return ForwardedConnectionInfo(self.connection_number,
+ self.client_addr,
+ self.server_addr)
+
+
+
+class ForwardingService (asyncore.dispatcher):
+
+ _counter = 0
+
+ def __init__(self, listen_host, listen_port, dest_host, dest_port,
+ observer_factory=None):
+ self._obs_factory = observer_factory
+ self._dest = (dest_host, dest_port)
+ asyncore.dispatcher.__init__(self)
+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.set_reuse_addr()
+ self.bind((listen_host, listen_port))
+ self.listen(5)
+
+ def handle_accept(self):
+ info = self.accept()
+ if info:
+ # Got a connection.
+ conn, addr = info
+ conn.setblocking(0)
+
+ ep1 = ForwardingEndpoint() # connects client to self
+ ep2 = ForwardingEndpoint() # connects self to server
+
+ counter = self._counter + 1
+ self._counter = counter
+ factory = self._obs_factory
+ if factory is not None:
+ fci = ForwardedConnectionInfo(counter, addr, self._dest)
+ obs = factory(fci)
+ dests1 = (ep2, EndpointObserver(obs, 1))
+ dests2 = (ep1, EndpointObserver(obs, 0))
+ else:
+ dests1 = (ep2,)
+ dests2 = (ep1,)
+
+ ep1.set_dests(dests1)
+ ep2.set_dests(dests2)
+
+ # Now everything is hooked up. Let data pass.
+ ep2.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ ep1.set_socket(conn)
+ ep1.connected = 1 # We already know the client connected.
+ ep2.connect(self._dest)
+
+ def handle_error(self):
+ # Don't stop the server.
+ import traceback
+ traceback.print_exc()
+
+
+
+class IConnectionObserver:
+
+ def connected(from_client):
+ """Called when the client or the server connects.
+ """
+
+ def received(data, from_client):
+ """Called when the client or the server sends data.
+ """
+
+ def closed(from_client):
+ """Called when the client or the server closes the channel.
+ """
+
+ def error(from_client, type, value):
+ """Called when an error occurs in the client or the server channel.
+ """
+
+
+#############################################################################
+#
+# Basic abstract connection observer and stdout observer
+#
+#############################################################################
+
+
+def escape(s):
+ # XXX This might be a brittle trick. :-(
+ return repr('"\'' + str(s))[4:-1]
+
+
+class BasicObserver:
+
+ continuing_line = -1 # Tracks when a line isn't finished.
+ arrows = ('<==', '==>')
+
+ def __init__(self):
+ self._start = time()
+
+ def _output_message(self, m, from_client):
+ if self.continuing_line >= 0:
+ self.write('\n')
+ self.continuing_line = -1
+ if from_client:
+ who = 'client'
+ else:
+ who = 'server'
+
+ t = time() - self._start
+ min, sec = divmod(t, 60)
+ self.write('[%02d:%06.3f - %s %s]\n' % (min, sec, who, m))
+ self.flush()
+
+ def connection_from(self, fci):
+ if fci.server_addr is not None:
+ self._output_message(
+ '%s:%s forwarded to %s:%s' %
+ (tuple(fci.client_addr) + tuple(fci.server_addr)), 1)
+ else:
+ self._output_message(
+ 'connection from %s:%s' %
+ (tuple(fci.client_addr)), 1)
+
+ if fci.transaction > 1:
+ self._output_message(
+ ('HTTP transaction #%d' % fci.transaction), 1)
+
+ def connected(self, from_client):
+ self._output_message('connected', from_client)
+
+ def received(self, data, from_client):
+ arrow = self.arrows[from_client]
+ cl = self.continuing_line
+ if cl >= 0:
+ if cl != from_client:
+ # Switching directions.
+ self.write('\n%s' % arrow)
+ else:
+ self.write(arrow)
+
+ if data.endswith('\n'):
+ data = data[:-1]
+ newline = 1
+ else:
+ newline = 0
+
+ if not show_cr:
+ data = data.replace('\r', '')
+ lines = data.split('\n')
+ lines = map(escape, lines)
+ s = ('\n%s' % arrow).join(lines)
+ self.write(s)
+
+ if newline:
+ self.write('\n')
+ self.continuing_line = -1
+ else:
+ self.continuing_line = from_client
+ self.flush()
+
+ def closed(self, from_client):
+ self._output_message('closed', from_client)
+
+ def error(self, from_client, type, value):
+ self._output_message(
+ 'connection error %s: %s' % (type, value), from_client)
+
+ def write(self, s):
+ raise NotImplementedError
+
+ def flush(self):
+ raise NotImplementedError
+
+
+class StdoutObserver (BasicObserver):
+
+ # __implements__ = IConnectionObserver
+
+ def __init__(self, fci):
+ BasicObserver.__init__(self)
+ self.connection_from(fci)
+
+ def write(self, s):
+ sys.stdout.write(s)
+
+ def flush(self):
+ sys.stdout.flush()
+
+
+# 'log_number' is a log file counter used for naming log files.
+log_number = 0
+
+def nextLogNumber():
+ global log_number
+ log_number = log_number + 1
+ return log_number
+
+
+class RecordingObserver (BasicObserver):
+ """Log request to a file.
+
+ o Filenames mangle connection and transaction numbers from the
+ ForwardedConnectionInfo passed as 'fci'.
+
+ o Decorates an underlying observer, created via the passed 'sub_factory'.
+
+ o Files are created in the supplied 'record_directory'.
+
+ o Unless suppressed, log response and error to corresponding files.
+ """
+ _ERROR_SOURCES = ('Server', 'Client')
+
+ # __implements__ = IConnectionObserver
+
+ def __init__(self, fci, sub_factory, record_directory,
+ record_prefix='watch', record_responses=1, record_errors=1):
+ self._log_number = nextLogNumber()
+ self._decorated = sub_factory(fci)
+ self._directory = record_directory
+ self._prefix = record_prefix
+ self._response = record_responses
+ self._errors = record_errors
+
+ def connected(self, from_client):
+ """See IConnectionObserver.
+ """
+ self._decorated.connected(from_client)
+
+ def received(self, data, from_client):
+ """See IConnectionObserver.
+ """
+ if from_client or self._response:
+ extension = from_client and 'request' or 'response'
+ file = self._openForAppend(extension=extension)
+ file.write(data)
+ file.close()
+ self._decorated.received(data, from_client)
+
+ def closed(self, from_client):
+ """See IConnectionObserver.
+ """
+ self._decorated.closed(from_client)
+
+ def error(self, from_client, type, value):
+ """See IConnectionObserver.
+ """
+ if self._errors:
+ file = self._openForAppend(extension='errors')
+ file.write('(%s) %s: %s\n' % (self._ERROR_SOURCES[from_client],
+ type, value))
+ self._decorated.error(from_client, type, value)
+
+ def _openForAppend(self, extension):
+ """Open a file with the given extension for appending.
+
+ o File should be in the directory indicated by self._directory.
+
+ o File should have a filename '_.'.
+ """
+ filename = '%s%04d.%s' % (self._prefix, self._log_number, extension)
+ fqpath = os.path.join(self._directory, filename)
+ return open(fqpath, 'a')
+
+
+#############################################################################
+#
+# Tkinter GUI
+#
+#############################################################################
+
+
+def setupTk(titlepart, config_info, colorized=1):
+ """Starts the Tk application and returns an observer factory.
+ """
+
+ import Tkinter
+ from ScrolledText import ScrolledText
+ from Queue import Queue, Empty
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+ from StringIO import StringIO
+
+ startup_text = COPYRIGHT + ("""
+
+Use your client to connect to the proxied port(s) then click
+the list on the left to see the data transferred.
+
+%s
+""" % config_info)
+
+
+ class TkTCPWatch (Tkinter.Frame):
+ '''The tcpwatch top-level window.
+ '''
+ def __init__(self, master):
+ Tkinter.Frame.__init__(self, master)
+ self.createWidgets()
+ # connections maps ids to TkConnectionObservers.
+ self.connections = {}
+ self.showingid = ''
+ self.queue = Queue()
+ self.processQueue()
+
+ def createWidgets(self):
+ listframe = Tkinter.Frame(self)
+ listframe.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
+ scrollbar = Tkinter.Scrollbar(listframe, orient=Tkinter.VERTICAL)
+ self.connectlist = Tkinter.Listbox(
+ listframe, yscrollcommand=scrollbar.set, exportselection=0)
+ scrollbar.config(command=self.connectlist.yview)
+ scrollbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y)
+ self.connectlist.pack(
+ side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
+ self.connectlist.bind('', self.mouseListSelect)
+ self.textbox = ScrolledText(self, background="#ffffff")
+ self.textbox.tag_config("message", foreground="#000000")
+ self.textbox.tag_config("client", foreground="#007700")
+ self.textbox.tag_config(
+ "clientesc", foreground="#007700", background="#dddddd")
+ self.textbox.tag_config("server", foreground="#770000")
+ self.textbox.tag_config(
+ "serveresc", foreground="#770000", background="#dddddd")
+ self.textbox.insert(Tkinter.END, startup_text, "message")
+ self.textbox.pack(side='right', fill=Tkinter.BOTH, expand=1)
+ self.pack(fill=Tkinter.BOTH, expand=1)
+
+ def addConnection(self, id, conn):
+ self.connections[id] = conn
+ connectlist = self.connectlist
+ connectlist.insert(Tkinter.END, id)
+
+ def updateConnection(self, id, output):
+ if id == self.showingid:
+ textbox = self.textbox
+ for data, style in output:
+ textbox.insert(Tkinter.END, data, style)
+
+ def mouseListSelect(self, event=None):
+ connectlist = self.connectlist
+ idx = connectlist.nearest(event.y)
+ sel = connectlist.get(idx)
+ connections = self.connections
+ if connections.has_key(sel):
+ self.showingid = ''
+ output = connections[sel].getOutput()
+ self.textbox.delete(1.0, Tkinter.END)
+ for data, style in output:
+ self.textbox.insert(Tkinter.END, data, style)
+ self.showingid = sel
+
+ def processQueue(self):
+ try:
+ if not self.queue.empty():
+ # Process messages for up to 1/4 second
+ from time import time
+ limit = time() + 0.25
+ while time() < limit:
+ try:
+ f, args = self.queue.get_nowait()
+ except Empty:
+ break
+ f(*args)
+ finally:
+ self.master.after(50, self.processQueue)
+
+
+ class TkConnectionObserver (BasicObserver):
+ '''A connection observer which shows captured data in a TCPWatch
+ frame. The data is mangled for presentation.
+ '''
+ # __implements__ = IConnectionObserver
+
+ def __init__(self, frame, fci, colorized=1):
+ BasicObserver.__init__(self)
+ self._output = [] # list of tuples containing (text, style)
+ self._frame = frame
+ self._colorized = colorized
+ t = localtime(fci.opened)
+ if fci.transaction > 1:
+ base_id = '%03d-%02d' % (
+ fci.connection_number, fci.transaction)
+ else:
+ base_id = '%03d' % fci.connection_number
+ id = '%s (%02d:%02d:%02d)' % (base_id, t[3], t[4], t[5])
+ self._id = id
+ frame.queue.put((frame.addConnection, (id, self)))
+ self.connection_from(fci)
+
+ def write(self, s):
+ output = [(s, "message")]
+ self._output.extend(output)
+ self._frame.queue.put(
+ (self._frame.updateConnection, (self._id, output)))
+
+ def flush(self):
+ pass
+
+ def received(self, data, from_client):
+ if not self._colorized:
+ BasicObserver.received(self, data, from_client)
+ return
+
+ if not show_cr:
+ data = data.replace('\r', '')
+
+ output = []
+
+ extra_color = (self._colorized == 2)
+
+ if extra_color:
+ # 4 colors: Change the color client/server and escaped chars
+ def append(ss, escaped, output=output,
+ from_client=from_client, escape=escape):
+ if escaped:
+ output.append((escape(ss), from_client
+ and 'clientesc' or 'serveresc'))
+ else:
+ output.append((ss, from_client
+ and 'client' or 'server'))
+ else:
+ # 2 colors: Only change color for client/server
+ segments = []
+ def append(ss, escaped, segments=segments,
+ escape=escape):
+ if escaped:
+ segments.append(escape(ss))
+ else:
+ segments.append(ss)
+
+ # Escape the input data.
+ was_escaped = 0
+ start_idx = 0
+ for idx in xrange(len(data)):
+ c = data[idx]
+ escaped = (c < ' ' and c != '\n') or c >= '\x80'
+ if was_escaped != escaped:
+ ss = data[start_idx:idx]
+ if ss:
+ append(ss, was_escaped)
+ was_escaped = escaped
+ start_idx = idx
+ ss = data[start_idx:]
+ if ss:
+ append(ss, was_escaped)
+
+ if not extra_color:
+ output.append((''.join(segments),
+ from_client and 'client' or 'server'))
+
+ # Send output to the frame.
+ self._output.extend(output)
+ self._frame.queue.put(
+ (self._frame.updateConnection, (self._id, output)))
+ if data.endswith('\n'):
+ self.continuing_line = -1
+ else:
+ self.continuing_line = from_client
+
+ def getOutput(self):
+ return self._output
+
+
+ def createApp(titlepart):
+ master = Tkinter.Tk()
+ app = TkTCPWatch(master)
+ try:
+ wm_title = app.master.wm_title
+ except AttributeError:
+ pass # No wm_title method available.
+ else:
+ wm_title('TCPWatch [%s]' % titlepart)
+ return app
+
+ app = createApp(titlepart)
+
+ def tkObserverFactory(fci, app=app, colorized=colorized):
+ return TkConnectionObserver(app, fci, colorized)
+
+ return tkObserverFactory, app.mainloop
+
+
+
+#############################################################################
+#
+# The HTTP splitter
+#
+# Derived from Zope.Server.HTTPServer.
+#
+#############################################################################
+
+
+def find_double_newline(s):
+ """Returns the position just after the double newline."""
+ pos1 = s.find('\n\r\n') # One kind of double newline
+ if pos1 >= 0:
+ pos1 += 3
+ pos2 = s.find('\n\n') # Another kind of double newline
+ if pos2 >= 0:
+ pos2 += 2
+
+ if pos1 >= 0:
+ if pos2 >= 0:
+ return min(pos1, pos2)
+ else:
+ return pos1
+ else:
+ return pos2
+
+
+
+class StreamedReceiver:
+ """Accepts data up to a specific limit."""
+
+ completed = 0
+
+ def __init__(self, cl, buf=None):
+ self.remain = cl
+ self.buf = buf
+ if cl < 1:
+ self.completed = 1
+
+ def received(self, data):
+ rm = self.remain
+ if rm < 1:
+ self.completed = 1 # Avoid any chance of spinning
+ return 0
+ buf = self.buf
+ datalen = len(data)
+ if rm <= datalen:
+ if buf is not None:
+ buf.append(data[:rm])
+ self.remain = 0
+ self.completed = 1
+ return rm
+ else:
+ if buf is not None:
+ buf.append(data)
+ self.remain -= datalen
+ return datalen
+
+
+
+class UnlimitedReceiver:
+ """Accepts data without limits."""
+
+ completed = 0
+
+ def received(self, data):
+ # always consume everything
+ return len(data)
+
+
+
+class ChunkedReceiver:
+ """Accepts all chunks."""
+
+ chunk_remainder = 0
+ control_line = ''
+ all_chunks_received = 0
+ trailer = ''
+ completed = 0
+
+
+ def __init__(self, buf=None):
+ self.buf = buf
+
+ def received(self, s):
+ # Returns the number of bytes consumed.
+ if self.completed:
+ return 0
+ orig_size = len(s)
+ while s:
+ rm = self.chunk_remainder
+ if rm > 0:
+ # Receive the remainder of a chunk.
+ to_write = s[:rm]
+ if self.buf is not None:
+ self.buf.append(to_write)
+ written = len(to_write)
+ s = s[written:]
+ self.chunk_remainder -= written
+ elif not self.all_chunks_received:
+ # Receive a control line.
+ s = self.control_line + s
+ pos = s.find('\n')
+ if pos < 0:
+ # Control line not finished.
+ self.control_line = s
+ s = ''
+ else:
+ # Control line finished.
+ line = s[:pos]
+ s = s[pos + 1:]
+ self.control_line = ''
+ line = line.strip()
+ if line:
+ # Begin a new chunk.
+ semi = line.find(';')
+ if semi >= 0:
+ # discard extension info.
+ line = line[:semi]
+ sz = int(line.strip(), 16) # hexadecimal
+ if sz > 0:
+ # Start a new chunk.
+ self.chunk_remainder = sz
+ else:
+ # Finished chunks.
+ self.all_chunks_received = 1
+ # else expect a control line.
+ else:
+ # Receive the trailer.
+ trailer = self.trailer + s
+ if trailer[:2] == '\r\n':
+ # No trailer.
+ self.completed = 1
+ return orig_size - (len(trailer) - 2)
+ elif trailer[:1] == '\n':
+ # No trailer.
+ self.completed = 1
+ return orig_size - (len(trailer) - 1)
+ pos = find_double_newline(trailer)
+ if pos < 0:
+ # Trailer not finished.
+ self.trailer = trailer
+ s = ''
+ else:
+ # Finished the trailer.
+ self.completed = 1
+ self.trailer = trailer[:pos]
+ return orig_size - (len(trailer) - pos)
+ return orig_size
+
+
+
+class HTTPStreamParser:
+ """A structure that parses the HTTP stream.
+ """
+
+ completed = 0 # Set once request is completed.
+ empty = 0 # Set if no request was made.
+ header_plus = ''
+ chunked = 0
+ content_length = 0
+ body_rcv = None
+
+ # headers is a mapping containing keys translated to uppercase
+ # with dashes turned into underscores.
+
+ def __init__(self, is_a_request):
+ self.headers = {}
+ self.is_a_request = is_a_request
+ self.body_data = []
+
+ def received(self, data):
+ """Receives the HTTP stream for one request.
+
+ Returns the number of bytes consumed.
+ Sets the completed flag once both the header and the
+ body have been received.
+ """
+ if self.completed:
+ return 0 # Can't consume any more.
+ datalen = len(data)
+ br = self.body_rcv
+ if br is None:
+ # In header.
+ s = self.header_plus + data
+ index = find_double_newline(s)
+ if index >= 0:
+ # Header finished.
+ header_plus = s[:index]
+ consumed = len(data) - (len(s) - index)
+ self.in_header = 0
+ # Remove preceeding blank lines.
+ header_plus = header_plus.lstrip()
+ if not header_plus:
+ self.empty = 1
+ self.completed = 1
+ else:
+ self.parse_header(header_plus)
+ if self.body_rcv is None or self.body_rcv.completed:
+ self.completed = 1
+ return consumed
+ else:
+ # Header not finished yet.
+ self.header_plus = s
+ return datalen
+ else:
+ # In body.
+ consumed = br.received(data)
+ self.body_data.append(data[:consumed])
+ if br.completed:
+ self.completed = 1
+ return consumed
+
+
+ def parse_header(self, header_plus):
+ """Parses the header_plus block of text.
+
+ (header_plus is the headers plus the first line of the request).
+ """
+ index = header_plus.find('\n')
+ if index >= 0:
+ first_line = header_plus[:index]
+ header = header_plus[index + 1:]
+ else:
+ first_line = header_plus
+ header = ''
+ self.first_line = first_line
+ self.header = header
+
+ lines = self.get_header_lines()
+ headers = self.headers
+ for line in lines:
+ index = line.find(':')
+ if index > 0:
+ key = line[:index]
+ value = line[index + 1:].strip()
+ key1 = key.upper().replace('-', '_')
+ headers[key1] = value
+ # else there's garbage in the headers?
+
+ if not self.is_a_request:
+ # Check for a 304 response.
+ parts = first_line.split()
+ if len(parts) >= 2 and parts[1] == '304':
+ # Expect no body.
+ self.body_rcv = StreamedReceiver(0)
+
+ if self.body_rcv is None:
+ # Ignore the HTTP version and just assume
+ # that the Transfer-Encoding header, when supplied, is valid.
+ te = headers.get('TRANSFER_ENCODING', '')
+ if te == 'chunked':
+ self.chunked = 1
+ self.body_rcv = ChunkedReceiver()
+ if not self.chunked:
+ cl = int(headers.get('CONTENT_LENGTH', -1))
+ self.content_length = cl
+ if cl >= 0 or self.is_a_request:
+ self.body_rcv = StreamedReceiver(cl)
+ else:
+ # No content length and this is a response.
+ # We have to assume unlimited content length.
+ self.body_rcv = UnlimitedReceiver()
+
+
+ def get_header_lines(self):
+ """Splits the header into lines, putting multi-line headers together.
+ """
+ r = []
+ lines = self.header.split('\n')
+ for line in lines:
+ if line.endswith('\r'):
+ line = line[:-1]
+ if line and line[0] in ' \t':
+ r[-1] = r[-1] + line[1:]
+ else:
+ r.append(line)
+ return r
+
+
+
+class HTTPConnectionSplitter:
+ """Makes a new observer for each HTTP subconnection and forwards events.
+ """
+
+ # __implements__ = IConnectionObserver
+ req_index = 0
+ resp_index = 0
+
+ def __init__(self, sub_factory, fci):
+ self.sub_factory = sub_factory
+ self.transactions = [] # (observer, request_data, response_data)
+ self.fci = fci
+ self._newTransaction()
+
+ def _newTransaction(self):
+ fci = self.fci.dup()
+ fci.transaction = len(self.transactions) + 1
+ obs = self.sub_factory(fci)
+ req = HTTPStreamParser(1)
+ resp = HTTPStreamParser(0)
+ self.transactions.append((obs, req, resp))
+
+ def _mostRecentObs(self):
+ return self.transactions[-1][0]
+
+ def connected(self, from_client):
+ self._mostRecentObs().connected(from_client)
+
+ def closed(self, from_client):
+ self._mostRecentObs().closed(from_client)
+
+ def error(self, from_client, type, value):
+ self._mostRecentObs().error(from_client, type, value)
+
+ def received(self, data, from_client):
+ transactions = self.transactions
+ while data:
+ if from_client:
+ index = self.req_index
+ else:
+ index = self.resp_index
+ if index >= len(transactions):
+ self._newTransaction()
+
+ obs, req, resp = transactions[index]
+ if from_client:
+ parser = req
+ else:
+ parser = resp
+
+ consumed = parser.received(data)
+ obs.received(data[:consumed], from_client)
+ data = data[consumed:]
+ if parser.completed:
+ new_index = index + 1
+ if from_client:
+ self.req_index = new_index
+ else:
+ self.resp_index = new_index
+
+
+#############################################################################
+#
+# HTTP proxy
+#
+#############################################################################
+
+
+class HTTPProxyToServerConnection (ForwardingEndpoint):
+ """Ensures that responses to a persistent HTTP connection occur
+ in the correct order."""
+
+ finished = 0
+
+ def __init__(self, proxy_conn, dests=()):
+ ForwardingEndpoint.__init__(self)
+ self.response_parser = HTTPStreamParser(0)
+ self.proxy_conn = proxy_conn
+ self.set_dests(dests)
+
+ # Data for the client held until previous responses are sent
+ self.held = []
+
+ def _isMyTurn(self):
+ """Returns a true value if it's time for this response
+ to respond to the client."""
+ order = self.proxy_conn._response_order
+ if order:
+ return (order[0] is self)
+ return 1
+
+ def received(self, data):
+ """Receives data from the HTTP server to be sent back to the client."""
+ while 1:
+ parser = self.response_parser
+ if parser.completed:
+ self.finished = 1
+ self.flush()
+ # Note that any extra data returned from the server is
+ # ignored. Should it be? :-(
+ return
+ if not data:
+ break
+ consumed = parser.received(data)
+ fragment = data[:consumed]
+ data = data[consumed:]
+ ForwardingEndpoint.received(self, fragment)
+ self.held.append(fragment)
+ self.flush()
+
+ def flush(self):
+ """Flushes buffers and, if the response has been sent, allows
+ the next response to take over.
+ """
+ if self.held and self._isMyTurn():
+ data = ''.join(self.held)
+ del self.held[:]
+ self.proxy_conn.write(data)
+ if self.finished:
+ order = self.proxy_conn._response_order
+ if order and order[0] is self:
+ del order[0]
+ if order:
+ order[0].flush() # kick!
+
+ def handle_close(self):
+ """The HTTP server closed the connection.
+ """
+ ForwardingEndpoint.handle_close(self)
+ if not self.finished:
+ # Cancel the proxy connection, even if there are responses
+ # pending, since the HTTP spec provides no way to recover
+ # from an unfinished response.
+ self.proxy_conn.close()
+
+ def close(self):
+ """Close the connection to the server.
+
+ If there is unsent response data, an error is generated.
+ """
+ self.flush()
+ if not self.finished:
+ t = IOError
+ v = 'Closed without finishing response to client'
+ for d in self._dests:
+ if hasattr(d, 'error'):
+ d.error(t, v)
+ ForwardingEndpoint.close(self)
+
+
+
+class HTTPProxyToClientConnection (ForwardingEndpoint):
+ """A connection from a client to the proxy server"""
+
+ _req_parser = None
+ _transaction = 0
+ _obs = None
+
+ def __init__(self, conn, factory, counter, addr):
+ ForwardingEndpoint.__init__(self, conn)
+ self._obs_factory = factory
+ self._counter = counter
+ self._client_addr = addr
+ self._response_order = []
+ self._newRequest()
+
+ def _newRequest(self):
+ """Starts a new request on a persistent connection."""
+ if self._req_parser is None:
+ self._req_parser = HTTPStreamParser(1)
+ factory = self._obs_factory
+ if factory is not None:
+ fci = ForwardedConnectionInfo(self._counter, self._client_addr)
+ self._transaction = self._transaction + 1
+ fci.transaction = self._transaction
+ obs = factory(fci)
+ self._obs = obs
+ self.set_dests((EndpointObserver(obs, 1),))
+
+ def received(self, data):
+ """Accepts data received from the client."""
+ while data:
+ parser = self._req_parser
+ if parser is None:
+ # Begin another request.
+ self._newRequest()
+ parser = self._req_parser
+ if not parser.completed:
+ # Waiting for a complete request.
+ consumed = parser.received(data)
+ ForwardingEndpoint.received(self, data[:consumed])
+ data = data[consumed:]
+ if parser.completed:
+ # Connect to a server.
+ self.openProxyConnection(parser)
+ # Expect a new request or a closed connection.
+ self._req_parser = None
+
+ def openProxyConnection(self, request):
+ """Parses the client connection and opens a connection to an
+ HTTP server.
+ """
+ first_line = request.first_line.strip()
+ if not ' ' in first_line:
+ raise ValueError, ('Malformed request: %s' % first_line)
+ command, url = first_line.split(' ', 1)
+ pos = url.rfind(' HTTP/')
+ if pos >= 0:
+ protocol = url[pos + 1:]
+ url = url[:pos].rstrip()
+ else:
+ protocol = 'HTTP/1.0'
+ if url.startswith('http://'):
+ # Standard proxy
+ urlpart = url[7:]
+ if '/' in urlpart:
+ host, path = url[7:].split('/', 1)
+ path = '/' + path
+ else:
+ host = urlpart
+ path = '/'
+ else:
+ # Transparent proxy
+ host = request.headers.get('HOST')
+ path = url
+ if not host:
+ raise ValueError, ('Request type not supported: %s' % url)
+
+ if ':' in host:
+ host, port = host.split(':')
+ port = int(port)
+ else:
+ port = 80
+
+ if '@' in host:
+ username, host = host.split('@')
+
+ obs = self._obs
+ if obs is not None:
+ eo = EndpointObserver(obs, 0)
+ ptos = HTTPProxyToServerConnection(self, (eo,))
+ else:
+ ptos = HTTPProxyToServerConnection(self)
+
+ self._response_order.append(ptos)
+
+ ptos.write('%s %s %s\r\n' % (command, path, protocol))
+ # Duplicate the headers sent by the client.
+ if request.header:
+ ptos.write(request.header)
+ else:
+ ptos.write('\r\n')
+ if request.body_data:
+ ptos.write(''.join(request.body_data))
+ ptos.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ ptos.connect((host, port))
+
+ def close(self):
+ """Closes the connection to the client.
+
+ If there are open connections to proxy servers, the server
+ connections are also closed.
+ """
+ ForwardingEndpoint.close(self)
+ for ptos in self._response_order:
+ ptos.close()
+ del self._response_order[:]
+
+
+class HTTPProxyService (asyncore.dispatcher):
+ """A minimal HTTP proxy server"""
+
+ connection_class = HTTPProxyToClientConnection
+
+ _counter = 0
+
+ def __init__(self, listen_host, listen_port, observer_factory=None):
+ self._obs_factory = observer_factory
+ asyncore.dispatcher.__init__(self)
+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.set_reuse_addr()
+ self.bind((listen_host, listen_port))
+ self.listen(5)
+
+ def handle_accept(self):
+ info = self.accept()
+ if info:
+ # Got a connection.
+ conn, addr = info
+ conn.setblocking(0)
+ counter = self._counter + 1
+ self._counter = counter
+ self.connection_class(conn, self._obs_factory, counter, addr)
+
+ def handle_error(self):
+ # Don't stop the server.
+ import traceback
+ traceback.print_exc()
+
+
+#############################################################################
+#
+# Command-line interface
+#
+#############################################################################
+
+def usage():
+ sys.stderr.write(COPYRIGHT + '\n')
+ sys.stderr.write(
+ """TCP monitoring and logging tool with support for HTTP 1.1
+Simple usage: tcpwatch.py -L listen_port:dest_hostname:dest_port
+
+TCP forwarded connection setup:
+ -L :
+ Set up a local forwarded connection
+ -L ::
+ Set up a forwarded connection to a specified host
+ -L :::
+ Set up a forwarded connection to a specified host, bound to an interface
+
+HTTP setup:
+ -h (or --http) Split forwarded HTTP persistent connections
+ -p [:] Run an HTTP proxy
+
+Output options:
+ -s Output to stdout instead of a Tkinter window
+ -n No color in GUI (faster and consumes less RAM)
+ -c Extra color (colorizes escaped characters)
+ --cr Show carriage returns (ASCII 13)
+ --help Show usage information
+
+Recording options:
+ -r (synonyms: -R, --record-directory)
+ Write recorded data to . By default, creates request and
+ response files for each request, and writes a corresponding error file
+ for any error detected by tcpwatch.
+ --record-prefix=
+ Use as the file prefix for logged request / response / error
+ files (defaults to 'watch').
+ --no-record-responses
+ Suppress writing '.response' files.
+ --no-record-errors
+ Suppress writing '.error' files.
+""")
+ sys.exit()
+
+
+def usageError(s):
+ sys.stderr.write(str(s) + '\n\n')
+ usage()
+
+
+def main(args):
+ global show_cr
+
+ try:
+ optlist, extra = getopt.getopt(args, 'chL:np:r:R:s',
+ ['help', 'http', 'cr',
+ 'record-directory=',
+ 'record-prefix=',
+ 'no-record-responses',
+ 'no-record-errors',
+ ])
+ except getopt.GetoptError, msg:
+ usageError(msg)
+
+ fwd_params = []
+ proxy_params = []
+ obs_factory = None
+ show_config = 0
+ split_http = 0
+ colorized = 1
+ record_directory = None
+ record_prefix = 'watch'
+ record_responses = 1
+ record_errors = 1
+ recording = {}
+
+ for option, value in optlist:
+ if option == '--help':
+ usage()
+ elif option == '--http' or option == '-h':
+ split_http = 1
+ elif option == '-n':
+ colorized = 0
+ elif option == '-c':
+ colorized = 2
+ elif option == '--cr':
+ show_cr = 1
+ elif option == '-s':
+ show_config = 1
+ obs_factory = StdoutObserver
+ elif option == '-p':
+ # HTTP proxy
+ info = value.split(':')
+ listen_host = ''
+ if len(info) == 1:
+ listen_port = int(info[0])
+ elif len(info) == 2:
+ listen_host = info[0]
+ listen_port = int(info[1])
+ else:
+ usageError('-p requires a port or a host:port parameter')
+ proxy_params.append((listen_host, listen_port))
+ elif option == '-L':
+ # TCP forwarder
+ info = value.split(':')
+ listen_host = ''
+ dest_host = ''
+ if len(info) == 2:
+ listen_port = int(info[0])
+ dest_port = int(info[1])
+ elif len(info) == 3:
+ listen_port = int(info[0])
+ dest_host = info[1]
+ dest_port = int(info[2])
+ elif len(info) == 4:
+ listen_host = info[0]
+ listen_port = int(info[1])
+ dest_host = info[2]
+ dest_port = int(info[3])
+ else:
+ usageError('-L requires 2, 3, or 4 colon-separated parameters')
+ fwd_params.append(
+ (listen_host, listen_port, dest_host, dest_port))
+ elif (option == '-r'
+ or option == '-R'
+ or option == '--record-directory'):
+ record_directory = value
+ elif option == '--record-prefix':
+ record_prefix = value
+ elif option == '--no-record-responses':
+ record_responses = 0
+ elif option == '--no-record-errors':
+ record_errors = 0
+
+ if not fwd_params and not proxy_params:
+ usageError("At least one -L or -p option is required.")
+
+ # Prepare the configuration display.
+ config_info_lines = []
+ title_lst = []
+ if fwd_params:
+ config_info_lines.extend(map(
+ lambda args: 'Forwarding %s:%d -> %s:%d' % args, fwd_params))
+ title_lst.extend(map(
+ lambda args: '%s:%d -> %s:%d' % args, fwd_params))
+ if proxy_params:
+ config_info_lines.extend(map(
+ lambda args: 'HTTP proxy listening on %s:%d' % args, proxy_params))
+ title_lst.extend(map(
+ lambda args: '%s:%d -> proxy' % args, proxy_params))
+ if split_http:
+ config_info_lines.append('HTTP connection splitting enabled.')
+ if record_directory:
+ config_info_lines.append(
+ 'Recording to directory %s.' % record_directory)
+ config_info = '\n'.join(config_info_lines)
+ titlepart = ', '.join(title_lst)
+ mainloop = None
+
+ if obs_factory is None:
+ # If no observer factory has been specified, use Tkinter.
+ obs_factory, mainloop = setupTk(titlepart, config_info, colorized)
+
+ if record_directory:
+ def _decorateRecorder(fci, sub_factory=obs_factory,
+ record_directory=record_directory,
+ record_prefix=record_prefix,
+ record_responses=record_responses,
+ record_errors=record_errors):
+ return RecordingObserver(fci, sub_factory, record_directory,
+ record_prefix, record_responses,
+ record_errors)
+ obs_factory = _decorateRecorder
+
+ chosen_factory = obs_factory
+ if split_http:
+ # Put an HTTPConnectionSplitter between the events and the output.
+ def _factory(fci, sub_factory=obs_factory):
+ return HTTPConnectionSplitter(sub_factory, fci)
+ chosen_factory = _factory
+ # obs_factory is the connection observer factory without HTTP
+ # connection splitting, while chosen_factory may have connection
+ # splitting. Proxy services use obs_factory rather than the full
+ # chosen_factory because proxy services perform connection
+ # splitting internally.
+
+ services = []
+ try:
+ # Start forwarding services.
+ for params in fwd_params:
+ args = params + (chosen_factory,)
+ s = ForwardingService(*args)
+ services.append(s)
+
+ # Start proxy services.
+ for params in proxy_params:
+ args = params + (obs_factory,)
+ s = HTTPProxyService(*args)
+ services.append(s)
+
+ if show_config:
+ sys.stderr.write(config_info + '\n')
+
+ # Run the main loop.
+ try:
+ if mainloop is not None:
+ import thread
+ thread.start_new_thread(asyncore.loop, (), {'timeout': 1.0})
+ mainloop()
+ else:
+ asyncore.loop(timeout=1.0)
+ except KeyboardInterrupt:
+ sys.stderr.write('TCPWatch finished.\n')
+ finally:
+ for s in services:
+ s.close()
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
From reebalazs at codespeak.net Sat Apr 22 11:48:10 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:48:11 2006
Subject: [z3-checkins] r26127 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422094810.DC5771009F@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:48:09 2006
New Revision: 26127
Modified:
z3/jsonserver/branch/merge/utils/tcpwatch
Log:
Add json support to tcpwatch
Modified: z3/jsonserver/branch/merge/utils/tcpwatch
==============================================================================
--- z3/jsonserver/branch/merge/utils/tcpwatch (original)
+++ z3/jsonserver/branch/merge/utils/tcpwatch Sat Apr 22 11:48:09 2006
@@ -89,6 +89,134 @@
RECV_BUFFER_SIZE = 8192
show_cr = 0
+# Support for jsonic read
+# To use the json_read, minjson, zope.component and zope.interface
+# must be installable from the python level. If this does not happen,
+# we provide a simple conversion that however will not always work.
+try:
+ from minjson import read as json_read
+ # best to try these imports too, right away
+ import zope.component
+ import zope.interface
+except ImportError:
+ print "Could not import minjson, applying fallback function."
+ def json_read(txt):
+ class Null:
+ def __repr__(self):
+ return 'null'
+ class True:
+ def __repr__(self):
+ return 'true'
+ class False:
+ def __repr__(self):
+ return 'false'
+ return eval(txt, {'null': Null(), 'true': True(), 'false': False()}, {})
+
+def json_prettify(line):
+ # Try to prettify JSON output
+ # return None if unsuccesful
+ try:
+ ob = json_read(line)
+ except:
+ pass
+ else:
+ stream = StringIO()
+ writer = Writer(stream)
+ prettify(writer, ob)
+ return stream.getvalue()
+
+# --
+# Prettifyer
+# --
+
+import re
+from textwrap import dedent
+from cStringIO import StringIO
+
+class Writer:
+
+ def __init__(self, stream, baseindent=4):
+ self.stream = stream
+ self.indent = 0
+ self.baseindent = baseindent
+ self.isnewline = True
+ self.nrnewlines = 0
+
+ re_multi = re.compile(r'(\n)')
+
+ def write(self, txt, keepindents=False):
+ if self.isnewline:
+ self.stream.write('\n' * self.nrnewlines)
+ self.stream.write(' ' * self.indent)
+ self.isnewline = False
+ self.nrnewlines = 0
+ else:
+ # if a continuation line, then we always keep indents.
+ keepindents = True
+ if not keepindents:
+ # (new lines are getting dedented, continuations not.)
+ txt = dedent(txt)
+ # see if there are more lines
+ lines = self.re_multi.split(txt)
+ if len(lines) > 1:
+ # more lines
+ for line in lines:
+ if line == '\n':
+ self.newline()
+ else:
+ self.write(line, keepindents=True)
+ else:
+ # single line
+ self.stream.write(txt)
+
+ def newline(self):
+ self.isnewline = True
+ self.nrnewlines += 1
+
+ def indenton(self, levels=1):
+ self.indent += self.baseindent * levels
+
+ def indentoff(self, levels=1):
+ self.indent -= self.baseindent * levels
+
+ def add_remark(self, text, remark, pos=65):
+ if remark is not None:
+ # remark will be indented to position, or later if text is longer.
+ return text.ljust(pos - 2 - self.indent) + ' # ' + remark
+ else:
+ return text
+
+def prettify(writer, value):
+ if isinstance(value, (list, tuple)):
+ writer.indenton()
+ if isinstance(value, list):
+ writer.write('[')
+ else:
+ writer.write('(')
+ writer.newline()
+ for elem in value:
+ prettify(writer, elem)
+ writer.write(',')
+ writer.newline()
+ if isinstance(value, list):
+ writer.write(']')
+ else:
+ writer.write(')')
+ writer.indentoff()
+ elif isinstance(value, dict):
+ writer.indenton()
+ writer.write('{')
+ writer.newline()
+ for k, v in value.iteritems():
+ prettify(writer, k)
+ writer.write(': ')
+ prettify(writer, v)
+ writer.write(',')
+ writer.newline()
+ writer.write('}')
+ writer.indentoff()
+ else:
+ writer.write(repr(value))
#############################################################################
#
@@ -347,6 +475,18 @@
data = data.replace('\r', '')
lines = data.split('\n')
lines = map(escape, lines)
+ # Try to prettify JSON output
+ if lines:
+ result = json_prettify(lines[-1])
+ if result:
+ if getattr(self, '_colorized', True):
+ if from_client:
+ result = '\x1b[0;32m' + result + '\x1b[0m'
+ else:
+ result = '\x1b[0;31m' + result + '\x1b[0m'
+ del lines[-1]
+ lines.extend(result.splitlines())
+
s = ('\n%s' % arrow).join(lines)
self.write(s)
@@ -520,6 +660,8 @@
self.textbox.tag_config("server", foreground="#770000")
self.textbox.tag_config(
"serveresc", foreground="#770000", background="#dddddd")
+ self.textbox.tag_config("clientjson", foreground="#00dd00")
+ self.textbox.tag_config("serverjson", foreground="#dd0000")
self.textbox.insert(Tkinter.END, startup_text, "message")
self.textbox.pack(side='right', fill=Tkinter.BOTH, expand=1)
self.pack(fill=Tkinter.BOTH, expand=1)
@@ -627,6 +769,17 @@
else:
segments.append(ss)
+
+ # Try to prettify JSON output
+ jsondata = None
+ if data:
+ lines = data.splitlines()
+ result = json_prettify(lines[-1])
+ if result:
+ data = '\n'.join(lines[:-1]) + '\n'
+ jsondata = result + '\n'
+ print data
+
# Escape the input data.
was_escaped = 0
start_idx = 0
@@ -646,6 +799,10 @@
if not extra_color:
output.append((''.join(segments),
from_client and 'client' or 'server'))
+
+ # Append the json data
+ if jsondata:
+ output.append((jsondata, from_client and 'clientjson' or 'serverjson'))
# Send output to the frame.
self._output.extend(output)
From reebalazs at codespeak.net Sat Apr 22 11:52:47 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:52:47 2006
Subject: [z3-checkins] r26129 - z3/jsonserver/branch/zope2_test
Message-ID: <20060422095247.0EF41100AC@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:52:45 2006
New Revision: 26129
Removed:
z3/jsonserver/branch/zope2_test/pyclient.py
Modified:
z3/jsonserver/branch/zope2_test/ (props changed)
z3/jsonserver/branch/zope2_test/EXTERNALS.TXT
Log:
external link to utils in the merge branch
Modified: z3/jsonserver/branch/zope2_test/EXTERNALS.TXT
==============================================================================
--- z3/jsonserver/branch/zope2_test/EXTERNALS.TXT (original)
+++ z3/jsonserver/branch/zope2_test/EXTERNALS.TXT Sat Apr 22 11:52:45 2006
@@ -7,3 +7,5 @@
#
browser http://codespeak.net/svn/z3/jsonserver/branch/merge/browser
concatresource http://codespeak.net/svn/z3/jsonserver/branch/merge/concatresource
+utils http://codespeak.net/svn/z3/jsonserver/branch/merge/utils
+
Deleted: /z3/jsonserver/branch/zope2_test/pyclient.py
==============================================================================
--- /z3/jsonserver/branch/zope2_test/pyclient.py Sat Apr 22 11:52:45 2006
+++ (empty file)
@@ -1,84 +0,0 @@
-'''\
-A python client for jsonserver.
-
-This is a separate file that is not needed for jsonserver to work.
-
-It can be used to
-
-- test json components from the command line
-- create a standalone python json-rpc client.
-
-This file needs to import minjson.py, it uses nothing else
-from the server.
-'''
-
-import urllib2
-from minjson import read, write
-
-request_content_type = 'application/json-rpc'
-pythonkwmarker = 'pythonKwMaRkEr'
-
-class JsonRpcError(Exception):
- pass
-
-class JsonserverClient(object):
- '''A Jsonserver client.
-
- On creation it is bound to an url and you
- can call up methods on it.
-
- Example::
-
- c = JsonserverClient('http://localhost:9777/xx1/edit_title_content')
- result = c.title_widget(widget_mode=1)
-
- '''
-
- class Opener(object):
-
- def __init__(self, baseurl, method):
- self.baseurl = baseurl
- self.method = method
-
- def __call__(self, *args, **kw):
- # build the data
- if kw:
- args += ({pythonkwmarker: kw}, )
- data = {
- 'id': 'httpReq',
- 'method': self.method,
- 'params': args,
- }
- raw_data = write(data, 'utf-8', 'utf-8')
- #
- headers={'Content-Type': request_content_type}
- r = urllib2.Request(self.baseurl, raw_data, headers=headers)
- f = urllib2.urlopen(r)
- #
- raw_response = f.read()
- response = read(raw_response, 'utf-8')
- if response['error']:
- raise JsonRpcError, 'Error: %s' % (response['error'], )
- result = response['result']
- return result
-
- def __init__(self, baseurl):
- '''Create a Jsonserver client class
-
- Then you can call methods on this class
- '''
- self._baseurl = baseurl
-
- def __getattr__(self, name):
- # If a new method is called up, a descriptor is created for it
- # and it is stored in the class.
- if not name or name[0] == '_':
- raise JsonRpcError('Method names cannot start with "_". (%s)' % (name, ))
- method = self.Opener(self._baseurl, name)
- setattr(self, name, method)
- return method
-
-if __name__ == '__main__':
- c = JsonserverClient('http://localhost:9676/xx1/edit_title_content')
- result = c.title_widget(widget_mode=1)
- print result
From reebalazs at codespeak.net Sat Apr 22 11:54:26 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 11:54:26 2006
Subject: [z3-checkins] r26130 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422095426.24FEA100B5@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 11:54:25 2006
New Revision: 26130
Modified:
z3/jsonserver/branch/merge/utils/pyclient (props changed)
Log:
Setting up utils
From reebalazs at codespeak.net Sat Apr 22 12:31:48 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 12:31:50 2006
Subject: [z3-checkins] r26131 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422103148.EDD8F100B7@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 12:31:48 2006
New Revision: 26131
Modified:
z3/jsonserver/branch/merge/utils/tcpwatch
Log:
Fix tcpwatch
Modified: z3/jsonserver/branch/merge/utils/tcpwatch
==============================================================================
--- z3/jsonserver/branch/merge/utils/tcpwatch (original)
+++ z3/jsonserver/branch/merge/utils/tcpwatch Sat Apr 22 12:31:48 2006
@@ -93,6 +93,9 @@
# To use the json_read, minjson, zope.component and zope.interface
# must be installable from the python level. If this does not happen,
# we provide a simple conversion that however will not always work.
+#
+# XXX other problem:
+# longer streams can be split. That destroys conversion.
try:
from minjson import read as json_read
# best to try these imports too, right away
@@ -215,6 +218,8 @@
writer.newline()
writer.write('}')
writer.indentoff()
+ elif isinstance(value, unicode):
+ writer.write('"%s"' % (value.encode('utf8', ))
else:
writer.write(repr(value))
@@ -477,14 +482,18 @@
lines = map(escape, lines)
# Try to prettify JSON output
if lines:
- result = json_prettify(lines[-1])
+ # find where to start from
+ for i, line in enumerate(lines):
+ if not line:
+ break
+ result = json_prettify('\n'.join(lines[i+1:]))
if result:
if getattr(self, '_colorized', True):
if from_client:
result = '\x1b[0;32m' + result + '\x1b[0m'
else:
result = '\x1b[0;31m' + result + '\x1b[0m'
- del lines[-1]
+ del lines[i+1:]
lines.extend(result.splitlines())
s = ('\n%s' % arrow).join(lines)
From reebalazs at codespeak.net Sat Apr 22 12:52:05 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 12:52:06 2006
Subject: [z3-checkins] r26133 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422105205.246D9100C2@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 12:52:03 2006
New Revision: 26133
Modified:
z3/jsonserver/branch/merge/utils/tcpwatch
Log:
fix
Modified: z3/jsonserver/branch/merge/utils/tcpwatch
==============================================================================
--- z3/jsonserver/branch/merge/utils/tcpwatch (original)
+++ z3/jsonserver/branch/merge/utils/tcpwatch Sat Apr 22 12:52:03 2006
@@ -219,7 +219,7 @@
writer.write('}')
writer.indentoff()
elif isinstance(value, unicode):
- writer.write('"%s"' % (value.encode('utf8', ))
+ writer.write('"%s"' % (value.encode('utf8', )))
else:
writer.write(repr(value))
From reebalazs at codespeak.net Sat Apr 22 13:41:40 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat Apr 22 13:41:42 2006
Subject: [z3-checkins] r26140 - z3/jsonserver/branch/merge/utils
Message-ID: <20060422114140.92D3110087@code0.codespeak.net>
Author: reebalazs
Date: Sat Apr 22 13:41:39 2006
New Revision: 26140
Modified:
z3/jsonserver/branch/merge/utils/tcpwatch
Log:
fix
Modified: z3/jsonserver/branch/merge/utils/tcpwatch
==============================================================================
--- z3/jsonserver/branch/merge/utils/tcpwatch (original)
+++ z3/jsonserver/branch/merge/utils/tcpwatch Sat Apr 22 13:41:39 2006
@@ -218,8 +218,6 @@
writer.newline()
writer.write('}')
writer.indentoff()
- elif isinstance(value, unicode):
- writer.write('"%s"' % (value.encode('utf8', )))
else:
writer.write(repr(value))
@@ -486,6 +484,9 @@
for i, line in enumerate(lines):
if not line:
break
+ else:
+ # no line found - take the whole buffer
+ i = -1
result = json_prettify('\n'.join(lines[i+1:]))
if result:
if getattr(self, '_colorized', True):
From rocky at codespeak.net Sat Apr 22 16:56:56 2006
From: rocky at codespeak.net (rocky@codespeak.net)
Date: Sat Apr 22 16:56:58 2006
Subject: [z3-checkins] r26143 - z3/pythonproducts/trunk
Message-ID: <20060422145656.02B3E10076@code0.codespeak.net>
Author: rocky
Date: Sat Apr 22 16:37:03 2006
New Revision: 26143
Modified:
z3/pythonproducts/trunk/ (props changed)
z3/pythonproducts/trunk/README.txt
z3/pythonproducts/trunk/setup.py
Log:
Preparing for 1.0beta1 release.
Modified: z3/pythonproducts/trunk/README.txt
==============================================================================
--- z3/pythonproducts/trunk/README.txt (original)
+++ z3/pythonproducts/trunk/README.txt Sat Apr 22 16:37:03 2006
@@ -17,7 +17,7 @@
Requirements
- Python 2.3.5 or higher in 2.3.x series
- - Zope 2.8.4 or higher in 2.8.x series
+ - Zope 2.8 or 2.9
- Five 1.2 or higher
Installing
@@ -55,4 +55,3 @@
Step 3: The standard way of registering a package with Zope 3 is to create
a ZCML "slug" in the $INSTANCE_HOME/etc/package-includes directory. This
file can be called anything as long as it ends with "-configure.zcml".
-
\ No newline at end of file
Modified: z3/pythonproducts/trunk/setup.py
==============================================================================
--- z3/pythonproducts/trunk/setup.py (original)
+++ z3/pythonproducts/trunk/setup.py Sat Apr 22 16:37:03 2006
@@ -96,7 +96,7 @@
setup(cmdclass={'install': Installer},
name='pythonproducts',
- version='1.0alpha1',
+ version='1.0beta1',
description='A mechanism to construct Zope 2 products as regular '
'python packages',
author='Rocky Burt',
From jinty at codespeak.net Mon Apr 24 01:31:40 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Mon Apr 24 01:31:44 2006
Subject: [z3-checkins] r26204 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060423233140.67FB810081@code0.codespeak.net>
Author: jinty
Date: Mon Apr 24 01:31:35 2006
New Revision: 26204
Added:
z3/sqlos/trunk/src/sqlos/zsqlobject.py
- copied unchanged from r26203, z3/sqlos/trunk/src/sqlos/_sqlos.py
Removed:
z3/sqlos/trunk/src/sqlos/_sqlos.py
Log:
Forgotten in the last commit
Deleted: /z3/sqlos/trunk/src/sqlos/_sqlos.py
==============================================================================
--- /z3/sqlos/trunk/src/sqlos/_sqlos.py Mon Apr 24 01:31:35 2006
+++ (empty file)
@@ -1,85 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Enfold Systems LLC. All rights reserved.
-#
-# This software is distributed under the terms of the Zope Public
-# License (ZPL) v2.1. See COPYING.txt for more information.
-#
-##############################################################################
-"""
-$Id: __init__.py 5216 2004-06-21 18:33:07Z dreamcatcher $
-"""
-
-from zope.interface import implements
-from sqlobject.main import SQLObject
-from sqlobject import StringCol
-
-from sqlos.connection import ConnectionDescriptor
-from sqlos.interfaces import ISQLObject
-
-class SQLOS(SQLObject):
- """Subclass SQLObject to enable ``lazy updates`` by default,
- as well as adding knowledge to register ``dirty`` objects
- with SQLObjectTransactionManager so they get sync'd on transaction
- boundaries.
-
- First, make a test data base:
-
- >>> from sqlos import testing
- >>> testdb = testing.TestDB([SQLOS])
-
- Test the interface:
-
- >>> s = SQLOS()
- >>> from zope.interface.verify import verifyObject
- >>> verifyObject(ISQLObject, s)
- True
-
- And finally call tearDown and cleanup:
-
- >>> testdb.tearDown()
- """
- implements(ISQLObject)
- _connection = ConnectionDescriptor()
-
- class sqlmeta:
- lazyUpdate = True
-
- def _set_dirty(self, value):
- if value:
- self._connection._dm.register(self)
- # This breaks the transaction functional tests and seems to be an
- # optimization only. So I've commented it out. - jinty 2005-10-5
- #else:
- # # XXX: 'objects' shouldn't really be fiddled directly like this.
- # # Probably there should be an unregister function.
- # # - Andrew Bennetts, 2005-01-05
- # self._connection._dm.objects.discard(self)
- self._dirty = value
-
- def _get_dirty(self):
- return self._dirty
-
- dirty = property(_get_dirty, _set_dirty)
-
- def get(self, id, connection=None, selectResults=None):
- # While interacting with zope, we may end up having
- # objects in the cache that have a __parent__ set.
- # This may be confusing when expect to get a object
- # which has no __parent__ and thats not what you get.
- val = super(SQLOS, self).get(id, connection=connection,
- selectResults=selectResults)
- if getattr(val, '__parent__', None) is not None:
- val.__parent__ = None
- val.__name__ = None
- return val
- get = classmethod(get)
-
- def __repr__(self):
- return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
-
- def setConnection(self, connection):
- if connection is not None:
- self._connection = connection
-
- setConnection = classmethod(setConnection)
From jinty at codespeak.net Mon Apr 24 03:18:57 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Mon Apr 24 03:19:00 2006
Subject: [z3-checkins] r26206 - in z3/sqlos/trunk/src/sqlos: . ftests
Message-ID: <20060424011857.D051D10084@code0.codespeak.net>
Author: jinty
Date: Mon Apr 24 03:18:48 2006
New Revision: 26206
Modified:
z3/sqlos/trunk/src/sqlos/_transaction.py
z3/sqlos/trunk/src/sqlos/adapter.py
z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py
z3/sqlos/trunk/src/sqlos/zsqlobject.py
Log:
Implement a dirty object registry that keeps track of dirty SQLOS objects and registers a beforeCommitHook. This allows us to expose a syncUpdateAll function which can be used to send all outstanding SQL to the database in mid-transaction.
Modified: z3/sqlos/trunk/src/sqlos/_transaction.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/_transaction.py (original)
+++ z3/sqlos/trunk/src/sqlos/_transaction.py Mon Apr 24 03:18:48 2006
@@ -15,48 +15,25 @@
* Creates a thread local cache of SQLObjects so that cached objects do not
leak into other threads as they would in pure SQLObject.
* Clears the thread local cache at the start of each new transaction.
- * When an object is modified, it registers itself with the data manager
- which, in turn, registers a pre-commit hook. This hook sync's the object
- sending all the SQL down the line before the two phase commit starts.
-
-XXX - There was a reason why we couldn't do this without a data manager, but I
- cannot remember it now. -jinty
+ * When an object is modified, it registers itself with the dirty object
+ registry which, in turn, registers a pre-commit hook. This hook
+ syncUpdates's the object sending all the SQL down the line before the
+ commit starts.
$Id$
"""
__metaclass__ = type
-import sets
-
import transaction
-from transaction import get
-from transaction.interfaces import IDataManager, ISynchronizer
+from transaction.interfaces import ISynchronizer
from zope.interface import implements
-from zope.app.event.objectevent import modified
-from sqlobject import SQLObjectNotFound
from sqlobject.cache import CacheSet
-from zope.security.proxy import removeSecurityProxy
from zope.thread import local
from sqlos.interfaces import ISQLObject
-def beforeCommitHook(obj):
- """Called before transactions are started.
-
- obj is a SQLObject
-
- This normally generates the database activity that pulls the zope.app.rdb
- data manager into the transaction, thus must be called before the
- transaction commits.
-
- Note that it is only called on commit.
- """
- if not obj.sqlmeta._obsolete:
- obj.sync()
-
-
class CacheSynchronizer:
"""Synchronizer to expire the Global per thread cache at transaction start.
@@ -126,144 +103,190 @@
# there must be a dead simple way.
-class SQLObjectTransactionManager:
- """
- This is a very simple Data Manager that just takes registrations
- of ``ISQLObject`` objects and calls their ``sync()`` method when
- needed.
-
- In addition to that, when the transaction is aborted, all modified
- objects will be expired.
+class DirtyObjectRegistry(local):
+ """A thread local registry of dirty SQLObjects.
- Let's see how it works.
+ StubPeople:
- First of all, setup the environment:
-
- >>> from zope.app.testing.placelesssetup import setUp, tearDown
- >>> setUp()
-
- First, register the subscribers and make a test data base:
-
- >>> from sqlos import testing
- >>> from sqlos.testing.sampleperson import SamplePerson
- >>> testdb = testing.TestDB([SamplePerson])
+ >>> synced = []
+ >>> class StubPerson:
+ ... implements(ISQLObject)
+ ... class sqlmeta:
+ ... _obsolete = False
+ ... def __init__(self, name):
+ ... self.name = name
+ ... def syncUpdate(self):
+ ... synced.append(self.name)
+ ... synced.sort()
+
+ Lets get some sample people:
+
+ >>> jhon = StubPerson('jhon')
+ >>> jane = StubPerson('jane')
+
+ Stub out some methods and make a registry:
+
+ >>> oldhook = DirtyObjectRegistry._addBeforeCommitHook
+ >>> def hook(self):
+ ... print 'adding before commit hook'
+ ... assert transaction.get() is self._txn
+ ... oldhook(self)
+ >>> DirtyObjectRegistry._addBeforeCommitHook = hook
+ >>> reg = DirtyObjectRegistry()
+
+ Objects not implementing ISQLObject fail to register:
+
+ >>> reg.register(object()) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: ...
+
+ Register some people and check the internal state:
+
+ >>> reg.register(jhon)
+ adding before commit hook
+ >>> len(reg._objects)
+ 1
+ >>> reg._txn is transaction.get()
+ True
- Now create some SamplePeople for testing:
+ >>> reg.register(jhon)
+ >>> len(reg._objects)
+ 1
+
+ >>> reg.register(jane)
+ >>> len(reg._objects)
+ 2
+
+ Test the thread localness of the registry:
+
+ >>> log = []
+ >>> import threading
+ >>> def logRegisterState():
+ ... log.append(reg._txn)
+ ... log.append(reg._objects)
+ ... log.append(reg._registered)
+ >>> thread = threading.Thread(target=logRegisterState)
+ >>> thread.start()
+ >>> thread.join()
+ >>> log
+ [None, set([]), False]
- >>> person = SamplePerson(fullname='Sidnei', username='sidnei',
- ... password='123')
- >>> person1 = SamplePerson(fullname='Brian', username='jinty',
- ... password='456')
- And commit everything:
+ After a commit we should be able to do it again:
- >>> get().commit()
+ >>> transaction.get().commit()
+ >>> synced
+ ['jane', 'jhon']
- Monkeypatch some methods to ease testing:
+ Register some people and check the internal state:
>>> synced = []
-
- >>> oldsync = SamplePerson.sync
- >>> def sync(self):
- ... synced.append(self.username)
- ... synced.sort()
- ... oldsync(self)
- >>> SamplePerson.sync = sync
-
- Now, we check the initial DataManager state:
-
- >>> person.dirty
- False
- >>> dm = SamplePerson._connection._dm
- >>> dm._objects == sets.Set([])
+ >>> reg.register(jhon)
+ adding before commit hook
+ >>> len(reg._objects)
+ 1
+ >>> reg._txn is transaction.get()
True
- Change something on the people and make sure that they register:
+ >>> reg.register(jhon)
+ >>> len(reg._objects)
+ 1
- >>> person.set(fullname='Sidnei da Silva')
- >>> person.dirty
- True
- >>> dm._objects == sets.Set([person])
- True
-
- >>> person1.set(fullname='Brian Sutherland')
- >>> person1.dirty
- True
- >>> dm._objects == sets.Set([person, person1])
- True
+ >>> reg.register(jane)
+ >>> len(reg._objects)
+ 2
- Commit the transaction:
+ Test that after an abort everything works as expected:
+ >>> transaction.get().abort()
>>> synced
[]
- >>> get().commit()
- >>> synced
- ['jinty', 'sidnei']
-
- >>> synced[:] = []
- Check the state:
+ Register some people and check the internal state:
- >>> person.dirty
- False
- >>> dm._objects == sets.Set([])
+ >>> reg.register(jhon)
+ adding before commit hook
+ >>> len(reg._objects)
+ 1
+ >>> reg._txn is transaction.get()
True
- Now, we change something again to test abort():
+ >>> reg.register(jhon)
+ >>> len(reg._objects)
+ 1
- >>> person.set(fullname='Alan Runyan')
- >>> person.dirty
- True
- >>> dm._objects == sets.Set([person])
- True
+ >>> reg.register(jane)
+ >>> len(reg._objects)
+ 2
- Lets abort the current transaction:
+ We can manually sync all the objects:
+ >>> reg.syncUpdateAll()
>>> synced
- []
- >>> get().abort()
+ ['jane', 'jhon']
+ >>> len(reg._objects)
+ 0
+
+ We will not re-register after a manual sync, but new objects can be
+ registered. A committed transaction will sync them:
+
+ >>> synced = []
+ >>> reg.register(jhon)
+ >>> len(reg._objects)
+ 1
+ >>> transaction.get().commit()
>>> synced
- []
+ ['jhon']
- And then cleanup the monkeypatched method:
+ After an abort, nothing can be synced:
- >>> SamplePerson.sync = oldsync
+ >>> synced = []
+ >>> reg.register(jhon)
+ adding before commit hook
+ >>> len(reg._objects)
+ 1
+ >>> transaction.get().abort()
+ >>> reg.syncUpdateAll()
+ >>> synced
+ []
- And finally call tearDown and cleanup:
+ TearDown:
- >>> testdb.tearDown()
- >>> tearDown()
+ >>> DirtyObjectRegistry._addBeforeCommitHook = oldhook
"""
- implements(IDataManager)
-
def __init__(self):
- self._objects = sets.Set()
- self._joined_txn = False
-
- def prepare(self, txn):
- return True
+ self._txn = None
+ self._objects = set([])
+ self._registered = False
+
+ def syncUpdateAll(self):
+ self._ensureCurrentTxn()
+ while self._objects:
+ obj = self._objects.pop()
+ if not obj.sqlmeta._obsolete:
+ obj.syncUpdate()
- def abort(self, txn):
- self._objects.clear()
- self._joined_txn = False
-
- def commit(self, txn):
- self._objects.clear()
- self._joined_txn = False
+ def _addBeforeCommitHook(self):
+ self._txn.addBeforeCommitHook(self.syncUpdateAll, ())
def register(self, obj):
if not ISQLObject.providedBy(obj):
raise ValueError, ("Only objects that implement ISQLObject "
- "can be registered with this transaction "
- "manager")
- if obj not in self._objects:
- self._objects.add(obj)
- txn = get()
- txn.addBeforeCommitHook(beforeCommitHook, (obj, ))
- if not self._joined_txn:
- txn.join(self)
- self._joined_txn = True
+ "can be registered with this registry.")
+ self._ensureCurrentTxn()
+ if not self._registered:
+ self._addBeforeCommitHook()
+ self._registered = True
+ self._objects.add(obj)
+
+ def _ensureCurrentTxn(self):
+ txn = transaction.get()
+ if self._txn is not txn:
+ # clean up after the last transaction
+ self._objects.clear()
+ self._txn = txn
+ self._registered = False
- def sortKey(self):
- return str(id(self))
+dirty_object_registry = DirtyObjectRegistry()
Modified: z3/sqlos/trunk/src/sqlos/adapter.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/adapter.py (original)
+++ z3/sqlos/trunk/src/sqlos/adapter.py Mon Apr 24 03:18:48 2006
@@ -26,7 +26,6 @@
from zope.interface import implements
from sqlos.interfaces import ISQLObject
-from sqlos._transaction import SQLObjectTransactionManager
from sqlos._transaction import cache_manager
# TODO: it is probably possible to optimize this by not creating a
@@ -43,7 +42,6 @@
self.autoCommit = None
self.debug = 0
self.supportTransactions = False
- self._dm = SQLObjectTransactionManager()
def _get_cache(self):
return cache_manager.cache
Modified: z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py (original)
+++ z3/sqlos/trunk/src/sqlos/ftests/test_transaction.py Mon Apr 24 03:18:48 2006
@@ -78,7 +78,8 @@
person.fullname = 'Sidnei Silva'
person.username = 'dreamcatcher'
person.password = 'pass'
- person.sync() # Sunc to make sure that the DB is sent the statements
+ assert person.dirty is True
+ person.sync() # Sync to ensure that the DB is sent the SQL statements
get().abort()
begin()
person = SamplePerson.get(self.personid)
@@ -86,12 +87,62 @@
self.assertEqual(person.fullname, 'Sidnei da Silva')
self.assertEqual(person.username, 'sidnei')
self.assertEqual(person.password, 'test')
+ # commit the next transaction so we can paranoically check
+ get().commit()
+ begin()
+ person = SamplePerson.get(self.personid)
+ self.assertEqual(person.fullname, 'Sidnei da Silva')
else:
# ya well no fine
+ import warnings
+ warnings.warn('SQLObject connections for this database do not '
+ 'support transactions. Not testing if transaction '
+ 'abort works.')
self.assertEqual(person.fullname, 'Sidnei Silva')
self.assertEqual(person.username, 'dreamcatcher')
self.assertEqual(person.password, 'pass')
+ def testAbortAndCommitDirty(self):
+ """Test the commit after an abort in the presence of dirty SQLObjects.
+
+ Here we commit the next transaction with another dirty object
+ just to make sure that remnants from the previous transaction are
+ not committed.
+ Yeah, this is paranoid, but sometimes it pays to be paranoid.
+ """
+ if self.supportTransactions():
+ # make a dirty object
+ person = SamplePerson.get(self.personid)
+ self.assertEqual(person.fullname, 'Sidnei da Silva')
+ person.fullname = 'Sidnei Silva'
+ assert person.dirty is True
+ person.sync() # Sync to ensure that the DB is sent the SQL
+ # abort transaction and start a new one
+ get().abort()
+ begin()
+ # make another dirty object
+ person = SamplePerson.get(self.personid)
+ self.assertEqual(person.fullname, 'Sidnei da Silva')
+ brian = SamplePerson(fullname='Brian Sutherland',
+ username='brian',
+ password='test')
+ brian.fullname = "B. Sutherland" # make the object dirty
+ assert brian.dirty is True
+ brianid = brian.id
+ # commit the second transaction
+ get().commit()
+ begin()
+ person = SamplePerson.get(self.personid)
+ brian = SamplePerson.get(brianid)
+ self.assertEqual(person.fullname, 'Sidnei da Silva')
+ self.assertEqual(brian.fullname, 'B. Sutherland')
+ else:
+ # ya well no fine
+ import warnings
+ warnings.warn('SQLObject connections for this database do not '
+ 'support transactions. Not testing if transaction '
+ 'abort works.')
+
def testCacheThreadIsolation(self):
"""Tests that the changes we make in one thread don't appear in another.
Modified: z3/sqlos/trunk/src/sqlos/zsqlobject.py
==============================================================================
--- z3/sqlos/trunk/src/sqlos/zsqlobject.py (original)
+++ z3/sqlos/trunk/src/sqlos/zsqlobject.py Mon Apr 24 03:18:48 2006
@@ -16,6 +16,15 @@
from sqlos.connection import ConnectionDescriptor
from sqlos.interfaces import ISQLObject
+from sqlos import _transaction
+
+def syncUpdateAll():
+ """Calls syncUpdate on all dirty SQLOS objects, sending all SQL to the DB.
+
+ >>> syncUpdateAll()
+ """
+ _transaction.dirty_object_registry.syncUpdateAll()
+
class SQLOS(SQLObject):
"""Subclass SQLObject to enable ``lazy updates`` by default,
@@ -47,14 +56,7 @@
def _set_dirty(self, value):
if value:
- self._connection._dm.register(self)
- # This breaks the transaction functional tests and seems to be an
- # optimization only. So I've commented it out. - jinty 2005-10-5
- #else:
- # # XXX: 'objects' shouldn't really be fiddled directly like this.
- # # Probably there should be an unregister function.
- # # - Andrew Bennetts, 2005-01-05
- # self._connection._dm.objects.discard(self)
+ _transaction.dirty_object_registry.register(self)
self._dirty = value
def _get_dirty(self):
From jwashin at codespeak.net Thu Apr 27 15:06:51 2006
From: jwashin at codespeak.net (jwashin@codespeak.net)
Date: Thu Apr 27 15:06:51 2006
Subject: [z3-checkins] r26445 - in z3/jsonserver/trunk: . tests
Message-ID: <20060427130651.56863100B7@code0.codespeak.net>
Author: jwashin
Date: Thu Apr 27 15:06:47 2006
New Revision: 26445
Modified:
z3/jsonserver/trunk/jsonrpc.py
z3/jsonserver/trunk/metaconfigure.py
z3/jsonserver/trunk/tests/test_directives.py
z3/jsonserver/trunk/tests/test_httpfactory.py
Log:
update for z3 trunk changes
Modified: z3/jsonserver/trunk/jsonrpc.py
==============================================================================
--- z3/jsonserver/trunk/jsonrpc.py (original)
+++ z3/jsonserver/trunk/jsonrpc.py Thu Apr 27 15:06:47 2006
@@ -20,6 +20,7 @@
#2005-09-08 updated to work with the new IResult idea (wsgi)
#2005-10-09 unicode handling update
#2006-03-09 enabled gzip compression for large responses
+#2006-04-27 updated to sync with z3 trunk changes jmw
__docformat__ = 'restructuredtext'
@@ -28,7 +29,11 @@
IJSONRPCRequest, IJSONReader, IJSONWriter
from zope.interface import implements
#from zope.publisher.http import IResult
-from zope.app.location.location import Location
+try:
+ from zope.location.location import Location
+except ImportError:
+ #deprecate this for 3.5
+ from zope.app.location.location import Location
from zope.publisher.http import HTTPRequest, HTTPResponse, \
getCharsetUsingRequest, DirectResult
from zope.publisher.browser import BrowserRequest
Modified: z3/jsonserver/trunk/metaconfigure.py
==============================================================================
--- z3/jsonserver/trunk/metaconfigure.py (original)
+++ z3/jsonserver/trunk/metaconfigure.py Thu Apr 27 15:06:47 2006
@@ -1,7 +1,7 @@
############################################################################
##
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -17,6 +17,7 @@
like zope.app.publisher.xmlrpc.metaconfigure
+Updated 2006-04-27 to sync with zope3 trunk jmw
updated 2005-12-03 Roger Ineichen
jwashin 2005-06-06
"""
@@ -26,8 +27,8 @@
from zope.configuration.exceptions import ConfigurationError
from interfaces import IJSONRPCRequest
-from zope.app.component.interface import provideInterface
-from zope.app.component.metaconfigure import handler
+from zope.component.interface import provideInterface
+from zope.component.zcml import handler
from jsonrpc import MethodPublisher
def view(_context, for_=None, interface=None, methods=None,
@@ -57,8 +58,7 @@
# Make sure that the class inherits MethodPublisher, so that the views
# have a location
if class_ is None:
- class_ = MethodPublisher
- original_class = class_
+ class_ = original_class = MethodPublisher
else:
original_class = class_
class_ = type(class_.__name__, (class_, MethodPublisher), {})
@@ -83,8 +83,8 @@
_context.action(
discriminator = ('view', for_, name, IJSONRPCRequest),
callable = handler,
- args = ('provideAdapter',
- (for_, IJSONRPCRequest), Interface, name, class_,
+ args = ('registerAdapter',
+ class_, (for_, IJSONRPCRequest), Interface, name,
_context.info)
)
else:
@@ -101,8 +101,8 @@
_context.action(
discriminator = ('view', for_, name, IJSONRPCRequest),
callable = handler,
- args = ('provideAdapter',
- (for_, IJSONRPCRequest), Interface, name, new_class,
+ args = ('registerAdapter',
+ new_class, (for_, IJSONRPCRequest), Interface, name,
_context.info)
)
Modified: z3/jsonserver/trunk/tests/test_directives.py
==============================================================================
--- z3/jsonserver/trunk/tests/test_directives.py (original)
+++ z3/jsonserver/trunk/tests/test_directives.py Thu Apr 27 15:06:47 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -19,11 +19,11 @@
from zope.configuration import xmlconfig
from zope.configuration.exceptions import ConfigurationError
-from zope.app.component.tests.views import IC, V1
+from zope.app.component.tests.views import IC, V1, Request
from zope.app.testing.placelesssetup import PlacelessSetup
from zope.security.proxy import ProxyFactory
-from zope.component.tests.request import Request
+#from zope.component.tests.request import Request
from jsonserver.interfaces import IJSONRPCRequest
Modified: z3/jsonserver/trunk/tests/test_httpfactory.py
==============================================================================
--- z3/jsonserver/trunk/tests/test_httpfactory.py (original)
+++ z3/jsonserver/trunk/tests/test_httpfactory.py Thu Apr 27 15:06:47 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2003 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2003 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -23,7 +23,7 @@
from zope.publisher.browser import BrowserRequest
from zope.publisher.http import HTTPRequest
from jsonserver.jsonrpc import JSONRPCRequest
-from zope.component.tests.placelesssetup import PlacelessSetup
+from zope.component.testing import PlacelessSetup
from jsonserver.interfaces import IJSONRPCRequestFactory
from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
from zope.app.publication.browser import BrowserPublication
From faassen at codespeak.net Mon May 1 18:29:55 2006
From: faassen at codespeak.net (faassen@codespeak.net)
Date: Mon May 1 18:29:57 2006
Subject: [z3-checkins] r26637 - z3/hurry/trunk
Message-ID: <20060501162955.47EA8100AD@code0.codespeak.net>
Author: faassen
Date: Mon May 1 18:29:54 2006
New Revision: 26637
Added:
z3/hurry/trunk/CHANGES.txt
Log:
Add changelog.
Added: z3/hurry/trunk/CHANGES.txt
==============================================================================
--- (empty file)
+++ z3/hurry/trunk/CHANGES.txt Mon May 1 18:29:54 2006
@@ -0,0 +1,7 @@
+hurry changes
+=============
+
+0.8 (2006-05-01)
+----------------
+
+Initial public release.
From faassen at codespeak.net Mon May 1 18:50:29 2006
From: faassen at codespeak.net (faassen@codespeak.net)
Date: Mon May 1 18:50:31 2006
Subject: [z3-checkins] r26638 - z3/hurry/trunk
Message-ID: <20060501165029.DCFFF100AD@code0.codespeak.net>
Author: faassen
Date: Mon May 1 18:50:29 2006
New Revision: 26638
Modified:
z3/hurry/trunk/INSTALL.txt
Log:
Intermediate checkin, needs more information.
Modified: z3/hurry/trunk/INSTALL.txt
==============================================================================
--- z3/hurry/trunk/INSTALL.txt (original)
+++ z3/hurry/trunk/INSTALL.txt Mon May 1 18:50:29 2006
@@ -1,9 +1,13 @@
Installation
------------
-Hurry needs Zope 3.1. Install it in a Zope install's lib/python
+Hurry needs Zope 3.1. It can work with Zope 3.2 too. Make sure hurry's
+src directory is on the Python path somehow, and then copy
+hurry-configure.zcml into your Zope's `etc/package-includes`
directory.
hurry.query also has support for zc.catalog SetIndexes in
-hurry.query.set. zc.catalog can be found here in the Zope 3
-SVN repository, in Sandbox/zc/catalog/
+hurry.query.set. zc.catalog can be found here in the Zope 3 SVN
+repository, in Sandbox/zc/catalog/. You also need to copy
+`zc.catalog-configure.zcml` into your Zope's `etc/package-includes`
+directory.
From reebalazs at codespeak.net Tue May 2 15:55:07 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Tue May 2 15:55:08 2006
Subject: [z3-checkins] r26670 - z3/jsonserver/branch/zope2_test
Message-ID: <20060502135507.7049C100A0@code0.codespeak.net>
Author: reebalazs
Date: Tue May 2 15:55:06 2006
New Revision: 26670
Modified:
z3/jsonserver/branch/zope2_test/jsonrpc.py
Log:
Fix IJsonRequest interface providing problem earlier addressed in r26026
The problem is triggered from the traverse hook set up by Five
on traversable objects. This calls setDefaultSkin in zope and this
in effect sets the IBrowserLayer on the request but also purges
all other interfaces. Which may not be a bug from a zope3 point
of view, but it screws things in this combination
XXX Workaround. We call setDefaultSkin ourselves, so later it
does not touch the interface any more.
Modified: z3/jsonserver/branch/zope2_test/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/zope2_test/jsonrpc.py (original)
+++ z3/jsonserver/branch/zope2_test/jsonrpc.py Tue May 2 15:55:06 2006
@@ -21,10 +21,10 @@
from zLOG import LOG, INFO, DEBUG, WARNING, ERROR
from cgi import FieldStorage
import ZPublisher.HTTPResponse
-##from zope.interface import directlyProvides, directlyProvidedBy
-from zope.interface import implements
+from zope.interface import directlyProvides, directlyProvidedBy
from interfaces import IJsonRequest
from ZPublisher.HTTPRequest import HTTPRequest
+from zope.app.publication.browser import setDefaultSkin
# this is used to identify incoming requests
request_content_type = 'application/json-rpc'
@@ -200,11 +200,6 @@
# Patching processInputs of ZPublisher.HTTPRequest
# --
-class JsonRpcRequest(HTTPRequest):
- 'JSON-RPC HTTP request'
- # this is just used to force the interface on the object
- implements(IJsonRequest)
-
re_content_type= re.compile(r'charset\s*=\s*([^;]+)')
def processInputs(self, **kw):
@@ -255,10 +250,18 @@
# XXX this would be good but for some reason gets "swallowed"
# by the time we get there, so we override the class instead.
# This error first manifested in Zope2.9, it was ok. till 2.8.
- ##interfaces = directlyProvidedBy(self)
- ##interfaces += IJsonRequest
- ##directlyProvides(self, interfaces)
- self.__class__ = JsonRpcRequest
+ # The problem is triggered from the traverse hook set up by Five
+ # on traversable objects. This calls setDefaultSkin in zope and this
+ # in effect sets the IBrowserLayer on the request but also purges
+ # all other interfaces. Which may not be a bug from a zope3 point
+ # of view, but it screws things in this combination
+ # XXX Workaround. We call setDefaultSkin ourselves, so later it
+ # does not touch the interface any more.
+ setDefaultSkin(self)
+ #
+ interfaces = directlyProvidedBy(self)
+ interfaces += IJsonRequest
+ directlyProvides(self, interfaces)
#
response = Response(response, jsonID)
other['RESPONSE'] = self.response = response
From regebro at codespeak.net Tue May 2 17:46:44 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Tue May 2 17:46:45 2006
Subject: [z3-checkins] r26677 - in z3/CMFonFive/trunk: .
tests/products/CMFonFiveTest tests/products/CMFonFiveTest/tests
Message-ID: <20060502154644.8E2BA100BB@code0.codespeak.net>
Author: regebro
Date: Tue May 2 17:46:44 2006
New Revision: 26677
Modified:
z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/trunk/configure.zcml
z3/CMFonFive/trunk/tests/products/CMFonFiveTest/configure.zcml
z3/CMFonFive/trunk/tests/products/CMFonFiveTest/tests/test_actionstool.py
Log:
- Got rid of some i18n warnings.
- Fixed an incorrect import so it works in Zope 2.10 as well.
Modified: z3/CMFonFive/trunk/CHANGES.txt
==============================================================================
--- z3/CMFonFive/trunk/CHANGES.txt (original)
+++ z3/CMFonFive/trunk/CHANGES.txt Tue May 2 17:46:44 2006
@@ -1,6 +1,9 @@
CMFonFive Product Changelog
CMFonFive 1.3.3 (unreleased)
+ - Got rid of some i18n warnings.
+
+ - Fixed an incorrect import so it works in Zope 2.10 as well.
- The id of the action is now generated from the last part of the interface
the menu item is defined for, and the last part of the action. This should
Modified: z3/CMFonFive/trunk/configure.zcml
==============================================================================
--- z3/CMFonFive/trunk/configure.zcml (original)
+++ z3/CMFonFive/trunk/configure.zcml Tue May 2 17:46:44 2006
@@ -1,5 +1,6 @@
Modified: z3/CMFonFive/trunk/tests/products/CMFonFiveTest/configure.zcml
==============================================================================
--- z3/CMFonFive/trunk/tests/products/CMFonFiveTest/configure.zcml (original)
+++ z3/CMFonFive/trunk/tests/products/CMFonFiveTest/configure.zcml Tue May 2 17:46:44 2006
@@ -1,6 +1,7 @@
+ xmlns:five="http://namespaces.zope.org/five"
+ i18n_domain="CMF">
Modified: z3/CMFonFive/trunk/tests/products/CMFonFiveTest/tests/test_actionstool.py
==============================================================================
--- z3/CMFonFive/trunk/tests/products/CMFonFiveTest/tests/test_actionstool.py (original)
+++ z3/CMFonFive/trunk/tests/products/CMFonFiveTest/tests/test_actionstool.py Tue May 2 17:46:44 2006
@@ -7,7 +7,8 @@
from Testing import ZopeTestCase
from Testing.ZopeTestCase.functional import Functional
from Products.CMFCore.utils import getToolByName
-from Products.Five.traversable import newInteraction
+
+from Products.Five.security import newInteraction
# we need to install test products *before* Five as Five
# looks up zcml files in the products it can find.
@@ -31,10 +32,10 @@
newInteraction()
actions = tool.listActions(object=self.folder.content)
action_names = [action.id for action in actions]
- self.failUnless('action_content_public.html' in action_names,
+ self.failUnless('icmfcontent_public.html' in action_names,
'Expected menu item was not found in action list')
# But not the protected action:
- self.failIf('action_content_protected.html' in action_names,
+ self.failIf('icmfcontent_protected.html' in action_names,
'Protected menu item was found in action list')
# And there should be no actions anywhere else:
self.failUnlessEqual(list(tool.listActions(object=self.folder)), [])
From regebro at codespeak.net Tue May 2 17:57:56 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Tue May 2 17:57:57 2006
Subject: [z3-checkins] r26679 - z3/CMFonFive/trunk
Message-ID: <20060502155756.871FE100BF@code0.codespeak.net>
Author: regebro
Date: Tue May 2 17:57:56 2006
New Revision: 26679
Modified:
z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/trunk/README.txt
Log:
Updated teh readmes to refelct the fact that GenericSetup has been required for quite
some time.
Modified: z3/CMFonFive/trunk/CHANGES.txt
==============================================================================
--- z3/CMFonFive/trunk/CHANGES.txt (original)
+++ z3/CMFonFive/trunk/CHANGES.txt Tue May 2 17:57:56 2006
@@ -13,12 +13,13 @@
The reason for this change is that it enables you to add icons with the CMF
ActionIconsTool.
- CMFonFive 1.3.2 (2005-02-22)
+ CMFonFive 1.3.2 (2006-02-22)
- GenericSetup calls all action providers with both object and info
as None, which resulted in an attribute error.
- - Added a GenericSetup profile.
+ - Added a GenericSetup profile. This means you need to use CMF 1.6.0 or
+ later, or download and install GenericSetup.
- Got rid of a deprecation warning for product_name.
Modified: z3/CMFonFive/trunk/README.txt
==============================================================================
--- z3/CMFonFive/trunk/README.txt (original)
+++ z3/CMFonFive/trunk/README.txt Tue May 2 17:57:56 2006
@@ -41,7 +41,8 @@
* CMFonFive 1.3.2 (2006-02-22)
- For CMF 1.5.2 and later, with Zope 2.9.
+ For CMF 1.5.2 and later, with Zope 2.9.
+ Requires GenericSetup or CMF 1.6 (Where GenericSetup is included).
http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.2.tgz
From jinty at codespeak.net Wed May 3 09:21:24 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 3 09:21:26 2006
Subject: [z3-checkins] r26704 - z3/sqlos/branch/0.2/Zope2/FiveSQLOS
Message-ID: <20060503072124.4BA96100BB@code0.codespeak.net>
Author: jinty
Date: Wed May 3 09:21:21 2006
New Revision: 26704
Modified:
z3/sqlos/branch/0.2/Zope2/FiveSQLOS/configure.zcml
Log:
oops, that was the wrong place to get ISQLObject.
Modified: z3/sqlos/branch/0.2/Zope2/FiveSQLOS/configure.zcml
==============================================================================
--- z3/sqlos/branch/0.2/Zope2/FiveSQLOS/configure.zcml (original)
+++ z3/sqlos/branch/0.2/Zope2/FiveSQLOS/configure.zcml Wed May 3 09:21:21 2006
@@ -7,7 +7,7 @@
From jinty at codespeak.net Wed May 3 09:23:04 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 3 09:23:06 2006
Subject: [z3-checkins] r26706 - z3/sqlos/trunk/Zope2/FiveSQLOS
Message-ID: <20060503072304.7EBF9100C2@code0.codespeak.net>
Author: jinty
Date: Wed May 3 09:23:02 2006
New Revision: 26706
Modified:
z3/sqlos/trunk/Zope2/FiveSQLOS/configure.zcml
Log:
oops, that was the wrong place to get ISQLObject.
Modified: z3/sqlos/trunk/Zope2/FiveSQLOS/configure.zcml
==============================================================================
--- z3/sqlos/trunk/Zope2/FiveSQLOS/configure.zcml (original)
+++ z3/sqlos/trunk/Zope2/FiveSQLOS/configure.zcml Wed May 3 09:23:02 2006
@@ -7,7 +7,7 @@
From faassen at codespeak.net Wed May 3 11:42:23 2006
From: faassen at codespeak.net (faassen@codespeak.net)
Date: Wed May 3 11:42:24 2006
Subject: [z3-checkins] r26715 - z3/hurry/trunk
Message-ID: <20060503094223.774B5100AB@code0.codespeak.net>
Author: faassen
Date: Wed May 3 11:42:22 2006
New Revision: 26715
Modified:
z3/hurry/trunk/INSTALL.txt
Log:
Update a bit.
Modified: z3/hurry/trunk/INSTALL.txt
==============================================================================
--- z3/hurry/trunk/INSTALL.txt (original)
+++ z3/hurry/trunk/INSTALL.txt Wed May 3 11:42:22 2006
@@ -1,13 +1,14 @@
Installation
------------
-Hurry needs Zope 3.1. It can work with Zope 3.2 too. Make sure hurry's
-src directory is on the Python path somehow, and then copy
-hurry-configure.zcml into your Zope's `etc/package-includes`
+Hurry needs Zope 3.1 or Zope 3.2.
+
+Make sure hurry's src directory is on the Python path somehow, and
+then copy hurry-configure.zcml into your Zope's `etc/package-includes`
directory.
hurry.query also has support for zc.catalog SetIndexes in
-hurry.query.set. zc.catalog can be found here in the Zope 3 SVN
-repository, in Sandbox/zc/catalog/. You also need to copy
-`zc.catalog-configure.zcml` into your Zope's `etc/package-includes`
-directory.
+hurry.query.set. If you want to use this extension, you need to
+install zc.catalog. It can be found in Zope's SVN repository. You
+then also need to copy `zc.catalog-configure.zcml` into your Zope's
+`etc/package-includes` directory.
From faassen at codespeak.net Wed May 3 11:51:49 2006
From: faassen at codespeak.net (faassen@codespeak.net)
Date: Wed May 3 11:51:50 2006
Subject: [z3-checkins] r26716 - z3/hurry/tag
Message-ID: <20060503095149.6F143100AB@code0.codespeak.net>
Author: faassen
Date: Wed May 3 11:51:48 2006
New Revision: 26716
Added:
z3/hurry/tag/
Log:
Directory to make releases in.
From faassen at codespeak.net Wed May 3 11:51:57 2006
From: faassen at codespeak.net (faassen@codespeak.net)
Date: Wed May 3 11:51:58 2006
Subject: [z3-checkins] r26717 - z3/hurry/tag/hurry-0.8
Message-ID: <20060503095157.4CA2C100AB@code0.codespeak.net>
Author: faassen
Date: Wed May 3 11:51:56 2006
New Revision: 26717
Added:
z3/hurry/tag/hurry-0.8/
- copied from r26716, z3/hurry/trunk/
Log:
Create hurry 0.8 release tag.
From srichter at codespeak.net Thu May 4 00:13:02 2006
From: srichter at codespeak.net (srichter@codespeak.net)
Date: Thu May 4 00:13:11 2006
Subject: [z3-checkins] r26742 - z3/hurry/trunk/src/hurry/query
Message-ID: <20060503221302.2507910092@code0.codespeak.net>
Author: srichter
Date: Thu May 4 00:12:11 2006
New Revision: 26742
Modified:
z3/hurry/trunk/src/hurry/query/set.py
Log:
ICatalogSetIndex is an overly strict requirement; ISetIndex is really
what you wanted in the first place.
Modified: z3/hurry/trunk/src/hurry/query/set.py
==============================================================================
--- z3/hurry/trunk/src/hurry/query/set.py (original)
+++ z3/hurry/trunk/src/hurry/query/set.py Thu May 4 00:12:11 2006
@@ -1,10 +1,10 @@
-from zc.catalog.interfaces import ICatalogSetIndex
+from zc.catalog.interfaces import ISetIndex
from hurry.query import query
class SetTerm(query.IndexTerm):
def getIndex(self):
index = super(SetTerm, self).getIndex()
- assert ICatalogSetIndex.providedBy(index)
+ assert ISetIndex.providedBy(index)
return index
class AnyOf(SetTerm):
From philikon at codespeak.net Thu May 4 01:29:46 2006
From: philikon at codespeak.net (philikon@codespeak.net)
Date: Thu May 4 01:29:58 2006
Subject: [z3-checkins] r26743 - z3/www/trunk
Message-ID: <20060503232946.C78FF10090@code0.codespeak.net>
Author: philikon
Date: Thu May 4 01:29:36 2006
New Revision: 26743
Modified:
z3/www/trunk/mkwebsite.py
Log:
new releases
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Thu May 4 01:29:36 2006
@@ -152,24 +152,24 @@
site.registerReleases([
Z3ReleaseResource(
- 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.1'),
+ 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.2.4'),
Z3ReleaseResource(
- 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.2.2'),
+ 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.3.5'),
Z3ReleaseResource(
- 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.3.3'),
+ 'Five', 'svn://svn.zope.org/repos/main/Products.Five/tags/1.4c'),
], project.getName())
from z3publish import Z3TestPage
site.registerPages([
- ZopeOrgPage('Products.Five/trunk', 'doc/main.txt', 'index'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/features.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/directives.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/manual.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/i18n.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/localsite.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'doc/event.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'CHANGES.txt'),
- ZopeOrgPage('Products.Five/tags/1.3.3', 'INSTALL.txt'),],
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/main.txt', 'index'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/features.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/directives.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/manual.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/i18n.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/localsite.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'doc/event.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'CHANGES.txt'),
+ ZopeOrgPage('Products.Five/tags/1.5b', 'INSTALL.txt'),],
site.getProjectLayouter(project),
project.getName(),
nav_links=nav_links,
From philikon at codespeak.net Thu May 4 01:30:28 2006
From: philikon at codespeak.net (philikon@codespeak.net)
Date: Thu May 4 01:30:30 2006
Subject: [z3-checkins] r26744 - z3/www/trunk/text
Message-ID: <20060503233028.DB1C010090@code0.codespeak.net>
Author: philikon
Date: Thu May 4 01:30:22 2006
New Revision: 26744
Modified:
z3/www/trunk/text/index.txt
Log:
news
Modified: z3/www/trunk/text/index.txt
==============================================================================
--- z3/www/trunk/text/index.txt (original)
+++ z3/www/trunk/text/index.txt Thu May 4 01:30:22 2006
@@ -21,6 +21,8 @@
News
----
+* 2005-05-04 `Five`_ 1.2.4, 1.3.5, 1.4c and 1.5b released!
+
* 2005-02-25 `Five`_ 1.2.1 and 1.3.2 released! Download `Five 1.2.1`_
and `Five 1.3.2`_
From philikon at codespeak.net Thu May 4 01:39:17 2006
From: philikon at codespeak.net (philikon@codespeak.net)
Date: Thu May 4 01:39:20 2006
Subject: [z3-checkins] r26745 - z3/www/trunk/text
Message-ID: <20060503233917.7841510090@code0.codespeak.net>
Author: philikon
Date: Thu May 4 01:39:11 2006
New Revision: 26745
Added:
z3/www/trunk/text/five_releasefest.txt
- copied, changed from r26742, z3/www/trunk/text/five_1_2_1_3_release.txt
Log:
release notes for release fest
Copied: z3/www/trunk/text/five_releasefest.txt (from r26742, z3/www/trunk/text/five_1_2_1_3_release.txt)
==============================================================================
--- z3/www/trunk/text/five_1_2_1_3_release.txt (original)
+++ z3/www/trunk/text/five_releasefest.txt Thu May 4 01:39:11 2006
@@ -1,8 +1,9 @@
-Five 1.2 and 1.3 released!
-==========================
+Five 1.2.4, 1.3.5, 1.4c and 1.5b released!
+==========================================
-The Five team is happy to announce the release of two Five versions
-today, Five 1.2 and 1.3!
+The Five team is happy to announce the release of two Five bugfix
+releases, 1.2.4 and 1.3.5, as well as two Five betas, 1.4c and 1.5b
+today.
What is Five
@@ -23,88 +24,47 @@
http://codespeak.net/z3/five/.
-Five 1.2
---------
+About Five 1.4 and 1.5
+----------------------
-Five 1.2 is the last release line of Five to work with Zope 2.8 and
-its included Zope X3 3.0. It does not work on Zope 2.7 anymore (use
-Five 1.1 if you're bound to Zope 2.7)
-
-Compared to 1.1, it introduces the following compelling list of new
-features:
-
-* Local site support
-
- Five now supports local sites in Zope 2. Sites are a concept known
- from Zope 3 and similar to CMF's sites (only that they can be
- nested). Thanks to Sidnei da Silva for the initial development back
- in March, Lennart Regebro and Philipp von Weitershausen for bringing
- it up to date for inclusion into Five 1.2.
-
-* Improved event support
-
- Five can now make standard Zope 2 containers (aka object managers)
- send Zope 3-style events for adding, moving, copying and deleting
- contained objects, instead of calling their manage_afterAdd,
- manage_beforeDelete, etc. methods. Thanks to Florent Guillaume for
- thinking through this non-trivial matter and implementing it.
-
-* Marker interfaces utility
-
- Five now includes a feature known from Zope X3 3.0's introspector,
- the ability to set marker interfaces on objects to influence their
- behaviour (such as view or adapter look-up). This also includes a
- browser page with a page template macro for doing so
- through-the-web. This feature is based on Sidnei da Silva's
- Plone-based product Flon. Thanks to him for the original
- implementation as well as Godefroid Chapelle, Whit Morriss and Yvo
- Schubbe for bringing it to Five 1.2.
-
-* Class registration through ZCML
-
- It is now possible to register Zope 2 classes through ZCML so that
- they show up in the ZMI as addable meta types. This basically
- obsolete's the boiler-plate ``initialize()`` function in products'
- ``__init__.py`` files, as well as equipping classes with a
- ``meta_type`` in the first place. Thanks to Yvo Schubbe for
- suggesting and implementing this great helper for cleaning out Zope
- 2 boiler plate code out of products.
-
-* New test runner
-
- Five 1.2 (and only 1.2) includes a forked copy of Zope 3.2's
- improved test runner which brings, among others, better doctest
- debugging and support for running tests on different levels and
- layers. Thanks to Tres Seaver for integrating this into Five 1.2.
-
-For more information please consult the `changes document`_.
-
-.. _changes document: http://codespeak.net/z3/five/CHANGES.html
-
-Five 1.2 can be downloaded at
-http://codespeak.net/z3/five/release/Five-1.2.tgz.
-
-
-Five 1.3
---------
-
-Five 1.3 is a straight port of Five 1.2 to Zope 3.2 which will be
-included in this December's Zope 2.9 release. Five 1.3 itself will
-also be part of Zope 2.9. It does not introduce any new features
-compared to Five 1.2, however, some restructuring has been made:
-
-* Most of the event work has been folded into Zope 2. That means that
- Zope 2.9 will ship with event-enabled object managers out of the
- box!
-
-* Several legacy packages were removed from Five as they are now
- included in Zope 2, such as Zope 3-style interfaces for OFS
- et.al. as well as the new test runner
-
-We are not providing a downloadable tarball of Five 1.3. Instead it
-has been integrated into Zope 2.9 with which it will ship. To try out
-Zope 2.9, you have to currently check out the Zope 2 trunk from the
-subversion repository.
+Five 1.4 and 1.5 are feature releases. They are basically equivalent
+except that Five 1.4 works with Zope 2.9/3.2 (only) and 1.5 works with
+Zope 2.10/3.3 (only). Five 1.5 will be included in Zope 2.10.
+
+Most important features are:
+
+* Added viewlet and content provider support. A big thanks to Alec
+ Mitchell and his helpers at the Archipelago sprint for making this
+ possible.
+
+* Add zope.formlib support. Please see ``doc/formlib.txt`` for more
+ information. A big thanks to Jan-Wijbrand Kolman for this.
+
+* Port zope.testbrowser to Zope 2. You can now use
+ Products.Five.testbrowser.Browser in functional tests. Much thanks
+ to Brian Sutherland.
+
+* Add python-packages-as-zope-products support which basically allows
+ for using any python package as a zope product without it having to
+ live in Products/. Much thanks to Rocky Burt for this.
+
+Zope 2.10 and Five 1.5 are also a big milestone in the convergence of
+Zope 2 and Zope 3, for it is no longer necessary to mark classes with
+five:traversable and five:defaultViewable to enable Zope 3 view lookup
+functionality. A big thanks goes to Lennart Regebro and Michael
+Kerrin for making this possible!
+
+
+Changes in Five 1.2.4/1.3.5 and 1.4c (compared to 1.4b)
+-------------------------------------------------------
+
+* Made sure that events are fired as expected in add and edit forms.
+
+* Made sure LocalizerLanguages class normalized language codes to
+ xx-yy, instead of xx_YY or xx-YY.
+
+* Fixed a problem with the new traversal look-up order and the root
+ object (OFS.Application.Application).
About the Zope 3 Base
From jinty at codespeak.net Fri May 5 05:31:41 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 05:31:42 2006
Subject: [z3-checkins] r26781 - z3/sqlos/trunk
Message-ID: <20060505033141.443B110088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 05:26:18 2006
New Revision: 26781
Modified:
z3/sqlos/trunk/setup.cfg
z3/sqlos/trunk/setup.py
Log:
Bump version number to the next release and fix setup.cfg
Modified: z3/sqlos/trunk/setup.cfg
==============================================================================
--- z3/sqlos/trunk/setup.cfg (original)
+++ z3/sqlos/trunk/setup.cfg Fri May 5 05:26:18 2006
@@ -1,2 +1,3 @@
-[egg-info]
+[egg_info]
+tag_build = .svn
tag_svn_revision = 1
Modified: z3/sqlos/trunk/setup.py
==============================================================================
--- z3/sqlos/trunk/setup.py (original)
+++ z3/sqlos/trunk/setup.py Fri May 5 05:26:18 2006
@@ -9,7 +9,7 @@
fiddly details that always seem to take a lot of time.
""",
url='http://codespeak.net/z3/sqlos/',
- version="0.1",
+ version="0.3",
license="ZPL",
maintainer="SQLOS development team",
maintainer_email="z3-sqlos@codespeak.net",
From jinty at codespeak.net Fri May 5 05:53:02 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 05:53:03 2006
Subject: [z3-checkins] r26782 - z3/sqlos/trunk/src/sqlos
Message-ID: <20060505035302.1B37A10088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 05:53:00 2006
New Revision: 26782
Modified:
z3/sqlos/trunk/src/sqlos/README.txt
Log:
Add an installation section to the README.
Modified: z3/sqlos/trunk/src/sqlos/README.txt
==============================================================================
--- z3/sqlos/trunk/src/sqlos/README.txt (original)
+++ z3/sqlos/trunk/src/sqlos/README.txt Fri May 5 05:53:00 2006
@@ -50,7 +50,7 @@
------------ --------
. Zope 3.2
============ ========
-sqlos 0.2 X
+sqlos 0.2.x X
============ ========
.. _FiveSQLOS: http://codespeak.net/svn/z3/sqlos/trunk/Zope2/FiveSQLOS/
@@ -121,6 +121,37 @@
connection and any registered class you wish.
+Installation
+------------
+
+Zope3
+_____
+
+You can easily install sqlos from the python cheeseshop using easy_install.
+To do this, you will have to first install setuptools_.
+
+For example, this command will install sqlos and it's dependencies in
+~/lib/python2.4/site-packages. Note that ~/lib/python2.4/site-packages should
+be on the python path.
+
+ $ easy_install --install-dir=~/lib/python2.4/site-packages 'sqlos == 0.2'
+
+After that, you should install the Zope Database Adapter you wish to use and
+copy the sqlos-*.zcml package includes (in the includes directory in the
+tarball) to the package-includes directory of your Zope instance.
+
+NOTE: the sqlos.ftesting-configure.zcml shouldn't be copied unless you want
+ to test the sample application.
+
+
+Zope2
+_____
+
+Same as for Zope3 above, except you do not have to setup the zcml package
+includes. However, you do need to install the FiveSQLOS Zope2 product. This can
+be found in the Zope2 directory in the tarball.
+
+
A Sample Application
--------------------
@@ -147,6 +178,7 @@
NOTE: changing debug=1 in src/sqlos/adapter.py will cause the SQL
executed to be printed on the terminal
+
Setting up a connection for SQLObject
-------------------------------------
From jinty at codespeak.net Fri May 5 05:56:02 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 05:56:04 2006
Subject: [z3-checkins] r26783 - z3/sqlos/trunk
Message-ID: <20060505035602.CADB010088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 05:55:55 2006
New Revision: 26783
Modified:
z3/sqlos/trunk/makefile
Log:
Cut un-necssary cruft not needed by the latest setuptools.
Modified: z3/sqlos/trunk/makefile
==============================================================================
--- z3/sqlos/trunk/makefile (original)
+++ z3/sqlos/trunk/makefile Fri May 5 05:55:55 2006
@@ -53,8 +53,7 @@
.PHONY: develop
develop: Zope3-build sqlos-meta
- touch Zope3/src/easy-install.pth
- PYTHONPATH=Zope3/src $(PYTHON) setup.py develop -S Zope3/src --install-dir Zope3/src
+ PYTHONPATH=Zope3/src $(PYTHON) setup.py develop --install-dir Zope3/src
.PHONY: testall
test: develop
From jinty at codespeak.net Fri May 5 06:00:01 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 06:00:03 2006
Subject: [z3-checkins] r26784 - z3/sqlos/tag/0.2.1
Message-ID: <20060505040001.D43A310088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 05:59:57 2006
New Revision: 26784
Added:
z3/sqlos/tag/0.2.1/
- copied from r26783, z3/sqlos/branch/0.2/
Log:
Tag 0.2.1 release
From jinty at codespeak.net Fri May 5 06:08:53 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 06:08:54 2006
Subject: [z3-checkins] r26785 - z3/sqlos/tag/0.2.1
Message-ID: <20060505040853.BA15210088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 06:08:43 2006
New Revision: 26785
Modified:
z3/sqlos/tag/0.2.1/setup.py
Log:
Bump version number.
Modified: z3/sqlos/tag/0.2.1/setup.py
==============================================================================
--- z3/sqlos/tag/0.2.1/setup.py (original)
+++ z3/sqlos/tag/0.2.1/setup.py Fri May 5 06:08:43 2006
@@ -9,7 +9,7 @@
fiddly details that always seem to take a lot of time.
""",
url='http://codespeak.net/z3/sqlos/',
- version="0.2.0",
+ version="0.2.1",
license="ZPL",
maintainer="SQLOS development team",
maintainer_email="z3-sqlos@codespeak.net",
From jinty at codespeak.net Fri May 5 06:41:35 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 06:41:37 2006
Subject: [z3-checkins] r26786 - z3/www/trunk
Message-ID: <20060505044135.4246310088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 06:41:15 2006
New Revision: 26786
Modified:
z3/www/trunk/mkwebsite.py
Log:
Fix up sqlos links.
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Fri May 5 06:41:15 2006
@@ -223,11 +223,10 @@
def sqlos_site(site, project):
nav_links = [
('sqlos main', 'index.html'),
- ('mailing list', '/mailman/listinfo/z3-sqlos'),
]
quick_links = [
- ('sqlos 0.2.0 release (compatible with SQLObject 0.7)',
- 'http://cheeseshop.python.org/pypi/sqlos/0.2.0'),
+ ('Mailing List', '/mailman/listinfo/z3-sqlos'),
+ ('Latest Releases', 'http://cheeseshop.python.org/pypi/sqlos/'),
('sqlos 0.1 release (compatible with SQLObject 0.6)',
'release/sqlos-0.1.tgz'),
('svn (the code)',
From jinty at codespeak.net Fri May 5 06:55:19 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Fri May 5 06:55:20 2006
Subject: [z3-checkins] r26787 - z3/sqlos/trunk/doc
Message-ID: <20060505045519.BC83B10088@code0.codespeak.net>
Author: jinty
Date: Fri May 5 06:55:11 2006
New Revision: 26787
Modified:
z3/sqlos/trunk/doc/HowToMakeARealease.rst
Log:
Add a release message template.
Modified: z3/sqlos/trunk/doc/HowToMakeARealease.rst
==============================================================================
--- z3/sqlos/trunk/doc/HowToMakeARealease.rst (original)
+++ z3/sqlos/trunk/doc/HowToMakeARealease.rst Fri May 5 06:55:11 2006
@@ -54,7 +54,37 @@
To:
z3-sqlos@codespeak.net
+ zope-announce@zope.org
TODO: More?
Template:
- TODO
+
+XXXMESSAGE
+
+What is sqlos:
+
+ sqlos is a toolkit for using SQLObject (http://sqlobject.org)
+ inside Zope 3 or Zope 2. It tries to take care of many of the fiddly
+ details that always seem to take a lot of time. The major ways it
+ helps are:
+
+ - Integrates the Zope transaction system and SQLObject, allowing
+ SQLObject to be used in lazyUpdate mode.
+
+ - Uses Zope Database adapters in SQLObject.
+
+ - Provide zcml configuration directives.
+
+ - Provide ZODB persistent objects that can act as a "window" into
+ the database.
+
+ - A testing infrastructure for testing SQLObject based applications.
+
+ - Caches SQLObjects and database connections to improve
+ performance.
+
+More info:
+ http://codespeak.net/z3/sqlos/index.html
+
+Releases:
+ http://cheeseshop.python.org/pypi/sqlos
From philikon at codespeak.net Fri May 5 20:53:57 2006
From: philikon at codespeak.net (philikon@codespeak.net)
Date: Fri May 5 20:54:01 2006
Subject: [z3-checkins] r26830 - z3/www/trunk
Message-ID: <20060505185357.E979910092@code0.codespeak.net>
Author: philikon
Date: Fri May 5 20:53:55 2006
New Revision: 26830
Modified:
z3/www/trunk/mkwebsite.py
Log:
update releases in quicklinks
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Fri May 5 20:53:55 2006
@@ -142,12 +142,12 @@
'http://codespeak.net/mailman/listinfo/z3-five'),
('z3-checkins mailing list',
'http://codespeak.net/mailman/listinfo/z3-checkins'),
- ('Five 1.0.3 release',
- 'release/Five-1.0.3.tgz'),
- ('Five 1.2.2 release',
- 'release/Five-1.2.2.tgz'),
- ('Five 1.3.3 release',
- 'release/Five-1.3.3.tgz'),
+ ('Five 1.2.4 release',
+ 'release/Five-1.2.4.tgz'),
+ ('Five 1.3.5 release',
+ 'release/Five-1.3.5.tgz'),
+ ('Five 1.4c release',
+ 'release/Five-1.4c.tgz'),
]
site.registerReleases([
From srichter at codespeak.net Sat May 6 14:53:03 2006
From: srichter at codespeak.net (srichter@codespeak.net)
Date: Sat May 6 14:53:04 2006
Subject: [z3-checkins] r26869 - z3/hurry/trunk/src/hurry/query
Message-ID: <20060506125303.B22641007E@code0.codespeak.net>
Author: srichter
Date: Sat May 6 14:53:01 2006
New Revision: 26869
Added:
z3/hurry/trunk/src/hurry/query/value.py (contents, props changed)
Modified:
z3/hurry/trunk/src/hurry/query/query.py
z3/hurry/trunk/src/hurry/query/query.txt
z3/hurry/trunk/src/hurry/query/set.py
Log:
- Implemented queries for the ``zc.catalog`` module's ``ValueIndex``. It
pretty much does the same as the ``FieldIndex`` queries, except that
it supports the additional features of the value index, such as
extents, exclude_min and exclude_max.
- Soem whitespace cleanup.
Martijn, I hope you are okay with those changes. I think that we
eventually want to merge the ``set`` and ``value`` module queries into
the main ones as to not duplicate so much of the API.
Modified: z3/hurry/trunk/src/hurry/query/query.py
==============================================================================
--- z3/hurry/trunk/src/hurry/query/query.py (original)
+++ z3/hurry/trunk/src/hurry/query/query.py Sat May 6 14:53:01 2006
@@ -15,7 +15,7 @@
class Query(object):
implements(interfaces.IQuery)
-
+
def searchResults(self, query):
results = query.apply()
if results is not None:
@@ -29,7 +29,7 @@
def __rand__(self, other):
return And(other, self)
-
+
def __or__(self, other):
return Or(self, other)
@@ -38,7 +38,7 @@
def __invert__(self):
return Not(self)
-
+
class And(Term):
def __init__(self, *terms):
self.terms = terms
@@ -63,13 +63,13 @@
for _, r in results:
_, result = weightedIntersection(result, r)
return result
-
+
class Or(Term):
def __init__(self, *terms):
self.terms = terms
def apply(self):
- results = []
+ results = []
for term in self.terms:
r = term.apply()
# empty results
@@ -91,7 +91,7 @@
def __init__(self, term):
self.term = term
- def apply(self):
+ def apply(self):
return difference(self._all(), self.term.apply())
def _all(self):
@@ -123,17 +123,17 @@
index = super(Text, self).getIndex()
assert ITextIndex.providedBy(index)
return index
-
+
def apply(self):
index = self.getIndex()
return index.apply(self.text)
-
+
class FieldTerm(IndexTerm):
def getIndex(self):
index = super(FieldTerm, self).getIndex()
assert IFieldIndex.providedBy(index)
return index
-
+
class Eq(FieldTerm):
def __init__(self, index_id, value):
assert value is not None
@@ -176,7 +176,7 @@
assert None not in values
super(In, self).__init__(index_id)
self.values = values
-
+
def apply(self):
results = []
index = self.getIndex()
Modified: z3/hurry/trunk/src/hurry/query/query.txt
==============================================================================
--- z3/hurry/trunk/src/hurry/query/query.txt (original)
+++ z3/hurry/trunk/src/hurry/query/query.txt Sat May 6 14:53:01 2006
@@ -40,7 +40,7 @@
easily. By including the __cmp__ method we make sure search results
can be stably sorted.
-We use a fake int id utility here so we can test independent of
+We use a fake int id utility here so we can test independent of
the full-blown zope environment::
>>> from zope.interface import verify
@@ -98,7 +98,7 @@
... Content(6, 'Y', 'Z')]
And catalog them now::
-
+
>>> for entry in content:
... catalog.index_doc(intid.register(entry), entry)
@@ -168,7 +168,7 @@
Using and (&)::
- >>> f2 = ('catalog1', 'f2')
+ >>> f2 = ('catalog1', 'f2')
>>> displayQuery(Eq(f1, 'a') & Eq(f2, 'b'))
[1, 4]
@@ -209,6 +209,7 @@
>>> displayQuery(In(f1, ['a', 'X', 'Y', 'Z']) & In(f1, ['Z']))
[]
+
SetIndex queries
----------------
@@ -267,3 +268,127 @@
>>> displayQuery(AnyOf(f1, ['a']) & Eq(f2, 1))
[1, 2]
+
+
+ValueIndex queries
+------------------
+
+The ``ValueIndex`` is defined in ``zc.catalog`` and provides a generalization
+of the standard field index.
+
+ >>> from hurry.query import value
+
+Let's set up a catalog that uses this index. The ``ValueIndex`` is defined in
+``zc.catalog``. Let's make a catalog which uses it:
+
+ >>> intid = DummyIntId()
+ >>> ztapi.provideUtility(zope.app.intid.interfaces.IIntIds, intid)
+
+ >>> from zope.app.catalog.interfaces import ICatalog
+ >>> from zope.app.catalog.catalog import Catalog
+ >>> catalog = Catalog()
+ >>> ztapi.provideUtility(ICatalog, catalog, 'catalog1')
+
+ >>> from zc.catalog.catalogindex import ValueIndex
+ >>> catalog['f1'] = ValueIndex('f1', IContent)
+
+Next we set up some content data to fill the indices:
+
+ >>> content = [
+ ... Content(1, 'a'),
+ ... Content(2, 'b'),
+ ... Content(3, 'c'),
+ ... Content(4, 'd'),
+ ... Content(5, 'c'),
+ ... Content(6, 'a')]
+
+And catalog them now:
+
+ >>> for entry in content:
+ ... catalog.index_doc(intid.register(entry), entry)
+
+
+Let's now query for all objects where ``f1`` equals 'a':
+
+ >>> f1 = ('catalog1', 'f1')
+ >>> displayQuery(value.Eq(f1, 'a'))
+ [1, 6]
+
+Next, let's find all objects where ``f1`` does not equal 'a'; this is more
+efficient than the generic ``~`` operator:
+
+ >>> displayQuery(value.NotEq(f1, 'a'))
+ [2, 3, 4, 5]
+
+You can also query for all objects where the value of ``f1`` is in a set of
+values:
+
+ >>> displayQuery(value.In(f1, ['a', 'd']))
+ [1, 4, 6]
+
+The next interesting set of queries allows you to make evaluations of the
+values. For example, you can ask for all objects between a certain set of
+values:
+
+ >>> displayQuery(value.Between(f1, 'a', 'c'))
+ [1, 2, 3, 5, 6]
+
+ >>> displayQuery(value.Between(f1, 'a', 'c', exclude_min=True))
+ [2, 3, 5]
+
+ >>> displayQuery(value.Between(f1, 'a', 'c', exclude_max=True))
+ [1, 2, 6]
+
+ >>> displayQuery(value.Between(f1, 'a', 'c',
+ ... exclude_min=True, exclude_max=True))
+ [2]
+
+You can also leave out one end of the range:
+
+ >>> displayQuery(value.Between(f1, 'c', None))
+ [3, 4, 5]
+ >>> displayQuery(value.Between(f1, None, 'c'))
+ [1, 2, 3, 5, 6]
+
+You can also use greater-equals and lesser-equals for the same purpose:
+
+ >>> displayQuery(value.Ge(f1, 'c'))
+ [3, 4, 5]
+ >>> displayQuery(value.Le(f1, 'c'))
+ [1, 2, 3, 5, 6]
+
+Of course, you can chain those queries with the others as demonstrated before.
+
+The ``value`` module also supports ``zc.catalog`` extents. The first query is
+``ExtentAny``, which returns all douments matching the extent. If the the
+extent is ``None``, all document ids are returned:
+
+ >>> displayQuery(value.ExtentAny(f1, None))
+ [1, 2, 3, 4, 5, 6]
+
+If we now create an extent that is only in the scope of the first four
+documents,
+
+ >>> from zc.catalog.extentcatalog import FilterExtent
+ >>> extent = FilterExtent(lambda extent, uid, obj: True)
+ >>> for i in range(4):
+ ... extent.add(i, i)
+
+then only the first four are returned:
+
+ >>> displayQuery(value.ExtentAny(f1, extent))
+ [1, 2, 3, 4]
+
+The opposite query is the ``ExtentNone`` query, which returns all ids in the
+extent that are *not* in the index:
+
+ >>> id = intid.register(Content(7, 'b'))
+ >>> id = intid.register(Content(8, 'c'))
+ >>> id = intid.register(Content(9, 'a'))
+
+ >>> extent = FilterExtent(lambda extent, uid, obj: True)
+ >>> for i in range(9):
+ ... extent.add(i, i)
+
+ >>> displayQuery(value.ExtentNone(f1, extent))
+ [7, 8, 9]
Modified: z3/hurry/trunk/src/hurry/query/set.py
==============================================================================
--- z3/hurry/trunk/src/hurry/query/set.py (original)
+++ z3/hurry/trunk/src/hurry/query/set.py Sat May 6 14:53:01 2006
@@ -6,12 +6,12 @@
index = super(SetTerm, self).getIndex()
assert ISetIndex.providedBy(index)
return index
-
+
class AnyOf(SetTerm):
def __init__(self, index_id, values):
super(AnyOf, self).__init__(index_id)
self.values = values
-
+
def apply(self):
return self.getIndex().apply({'any_of': self.values})
Added: z3/hurry/trunk/src/hurry/query/value.py
==============================================================================
--- (empty file)
+++ z3/hurry/trunk/src/hurry/query/value.py Sat May 6 14:53:01 2006
@@ -0,0 +1,79 @@
+from zc.catalog.interfaces import IValueIndex
+from hurry.query import query
+
+class ValueTerm(query.IndexTerm):
+ def getIndex(self):
+ index = super(ValueTerm, self).getIndex()
+ assert IValueIndex.providedBy(index)
+ return index
+
+class Eq(ValueTerm):
+ def __init__(self, index_id, value):
+ assert value is not None
+ super(Eq, self).__init__(index_id)
+ self.value = value
+
+ def apply(self):
+ return self.getIndex().apply({'any_of': (self.value,)})
+
+class NotEq(ValueTerm):
+ def __init__(self, index_id, not_value):
+ super(NotEq, self).__init__(index_id)
+ self.not_value = not_value
+
+ def apply(self):
+ index = self.getIndex()
+ values = list(index.values())
+ values.remove(self.not_value)
+ return index.apply({'any_of': values})
+
+class Between(ValueTerm):
+ def __init__(self, index_id, min_value=None, max_value=None,
+ exclude_min=False, exclude_max=False):
+ super(Between, self).__init__(index_id)
+ self.min_value = min_value
+ self.max_value = max_value
+ self.exclude_min = exclude_min
+ self.exclude_max = exclude_max
+
+ def apply(self):
+ return self.getIndex().apply(
+ {'between': (self.min_value, self.max_value,
+ self.exclude_min, self.exclude_max)})
+
+class Ge(Between):
+ def __init__(self, index_id, min_value):
+ super(Ge, self).__init__(index_id, min_value=min_value)
+
+class Le(Between):
+ def __init__(self, index_id, max_value):
+ super(Le, self).__init__(index_id, max_value=max_value)
+
+class In(ValueTerm):
+ def __init__(self, index_id, values):
+ assert None not in values
+ super(In, self).__init__(index_id)
+ self.values = values
+
+ def apply(self):
+ return self.getIndex().apply({'any_of': self.values})
+
+class ExtentAny(ValueTerm):
+ """Any ids in the extent that are indexed by this index.
+ """
+ def __init__(self, index_id, extent):
+ super(ExtentAny, self).__init__(index_id)
+ self.extent = extent
+
+ def apply(self):
+ return self.getIndex().apply({'any': self.extent})
+
+class ExtentNone(ValueTerm):
+ """Any ids in the extent that are not indexed by this index.
+ """
+ def __init__(self, index_id, extent):
+ super(ExtentNone, self).__init__(index_id)
+ self.extent = extent
+
+ def apply(self):
+ return self.getIndex().apply({'none': self.extent})
From jinty at codespeak.net Mon May 8 14:21:38 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Mon May 8 14:21:41 2006
Subject: [z3-checkins] r26962 - z3/sqlos/trunk
Message-ID: <20060508122138.C604310070@code0.codespeak.net>
Author: jinty
Date: Mon May 8 14:21:37 2006
New Revision: 26962
Modified:
z3/sqlos/trunk/makefile
Log:
add src to the pythonpath so that we dont have to patch test.py.
Modified: z3/sqlos/trunk/makefile
==============================================================================
--- z3/sqlos/trunk/makefile (original)
+++ z3/sqlos/trunk/makefile Mon May 8 14:21:37 2006
@@ -57,7 +57,7 @@
.PHONY: testall
test: develop
- cd Zope3 && $(PYTHON) test.py --test-path=../src -s sqlos
+ cd Zope3 && PYTHONPATH=src $(PYTHON) test.py --test-path=../src -s sqlos
Zope3/principals.zcml: Zope3 Zope3/sample_principals.zcml
cp Zope3/sample_principals.zcml $@
From jinty at codespeak.net Wed May 10 12:35:16 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 10 12:35:17 2006
Subject: [z3-checkins] r27039 - z3/sqlos/branch/jinty-sqlobject2
Message-ID: <20060510103516.E8DD2100A4@code0.codespeak.net>
Author: jinty
Date: Wed May 10 12:35:15 2006
New Revision: 27039
Added:
z3/sqlos/branch/jinty-sqlobject2/
- copied from r27038, z3/sqlos/trunk/
Log:
Make a branch for playing with SQLObject2
From jinty at codespeak.net Wed May 10 12:48:33 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 10 12:48:35 2006
Subject: [z3-checkins] r27040 - in
z3/sqlos/branch/jinty-sqlobject2/src/sqlos: . interfaces
Message-ID: <20060510104833.610B1100B3@code0.codespeak.net>
Author: jinty
Date: Wed May 10 12:48:30 2006
New Revision: 27040
Added:
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py (contents, props changed)
Removed:
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/adapter.py
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces/
Modified:
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/__init__.py
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/connection.py
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/zsqlobject.py
Log:
Armageddon - Rip out stuff thats not going to be useful with SQLObject2. Of course that leaves this branch completely broken.
Modified: z3/sqlos/branch/jinty-sqlobject2/src/sqlos/__init__.py
==============================================================================
--- z3/sqlos/branch/jinty-sqlobject2/src/sqlos/__init__.py (original)
+++ z3/sqlos/branch/jinty-sqlobject2/src/sqlos/__init__.py Wed May 10 12:48:30 2006
@@ -9,25 +9,3 @@
"""
$Id$
"""
-
-from datetime import datetime, date
-from sqlobject.sqlbuilder import registerConverter
-
-# sqlos.SQLOS is softly deprecated, will go away sometime
-# (after at least one major release with deprecation warnings)
-# import directly from sqlos.zsqlobject
-from sqlos.zsqlobject import SQLOS
-
-
-## XXX: What are these?? I am sure there are no tests for them. - jinty
-def DateTimeConverter(value, db=None):
- return repr(value.isoformat())
-
-registerConverter(datetime, DateTimeConverter)
-
-def DateConverter(value, db=None):
- if isinstance(value, datetime):
- return repr(value.date().isoformat())
- return repr(value.isoformat())
-
-registerConverter(date, DateConverter)
Deleted: /z3/sqlos/branch/jinty-sqlobject2/src/sqlos/adapter.py
==============================================================================
--- /z3/sqlos/branch/jinty-sqlobject2/src/sqlos/adapter.py Wed May 10 12:48:30 2006
+++ (empty file)
@@ -1,162 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Enfold Systems LLC. All rights reserved.
-# Copyright (c) 2005-2006 Brian Sutherland. All rights reserved.
-#
-# This software is distributed under the terms of the Zope Public
-# License (ZPL) v2.1. See COPYING.txt for more information.
-#
-##############################################################################
-"""Connection adapters for sqlos.
-
-These adapters adapt Zope RDB Connections to SQLObject connections by
-sub-classing the SQLObject connection classes.
-
-$Id$
-"""
-
-__metaclass__ = type
-
-from sqlobject.dbconnection import DBAPI
-from sqlobject import _mysql, _postgres, _sqlite
-from sqlobject.converters import registerConverter
-from sqlobject.mysql import mysqlconnection
-from zope.app.rdb.interfaces import DatabaseException
-from zope.app.container.interfaces import INameChooser
-from zope.interface import implements
-
-from sqlos.interfaces import ISQLObject
-from sqlos._transaction import cache_manager
-
-# TODO: it is probably possible to optimize this by not creating a
-# ConnectionAdapter every adapter lookup, but rather caching one per thread,
-# and stuffing the connection into it using a factory function. Probably there
-# would be one factory function per adapter type and we could get rid of the
-# cache property on the ConnectionAdapter.
-
-class ConnectionAdapter:
-
- def __init__(self, connection):
- DBAPI.__init__(self)
- self._connection = connection
- self.autoCommit = None
- self.debug = 0
- self.supportTransactions = False
-
- def _get_cache(self):
- return cache_manager.cache
- def _set_cache(self, val):
- pass # don't let ourselves be overridden
- cache = property(_get_cache, _set_cache)
-
- def makeConnection(self):
- return self._connection
-
- def getConnection(self):
- # we override this because we really don't care about sqlobjects idea
- # of threadsafe pool of db connections. zope.app.rdb takes care of
- # that for us
- return self.makeConnection()
-
- def releaseConnection(self, conn, explicit=False):
- # we simply lobotomize this method because zope.app.rdb
- # takes care of all commits/rollbacks as well as all threading issues
- # with connections
- pass
-
- def close(self):
- # there is no sane way of doing this I can see. It would be nice to
- # raise an error here, but sqlobject.dbconnection registers this method
- # to be called when python exits.
- pass
-
- def _executeRetry(self, conn, cursor, query):
- try:
- return cursor.execute(query)
- except Exception, exc:
- raise DatabaseException(str(exc.args))
-
- def _runWithConnection(self, meth, *args):
- conn = self.getConnection()
- try:
- try:
- val = meth(conn, *args)
- except DatabaseException:
- raise # We may have already raised Database exception in
- # _executeRetry, so we re-raise it
- except Exception, exc:
- raise DatabaseException, tuple(exc.args)
- finally:
- self.releaseConnection(conn)
- return val
-
- def printDebug(self, conn, s, name, type='query'):
- # XXX this is a quick hack to get it to work - jinty
- if name == 'Pool' and self.debug != 'Pool':
- return
- if type == 'query':
- sep = ': '
- else:
- sep = '->'
- s = repr(s)
- spaces = ' '*(8-len(name))
- if self.debugThreading:
- threadName = threading.currentThread().getName()
- threadName = (':' + threadName + ' '*(8-len(threadName)))
- else:
- threadName = ''
- print '%(threadName)s/%(name)s%(spaces)s%(sep)s %(s)s' % locals()
-
-
-class MySQLAdapter(ConnectionAdapter, _mysql.builder()):
-
- def __init__(self, connection):
- if getattr(self, 'module', None) == None:
- import MySQLdb
- self.module = MySQLdb
- mysqlconnection.MySQLdb = MySQLdb
- super(MySQLAdapter, self).__init__(connection)
-
- def _executeRetry(*args, **kw):
- try:
- return mysqlconnection.MySQLConnection._executeRetry(*args, **kw)
- except Exception, exc:
- raise DatabaseException(str(exc.args))
-
-
-class PostgresAdapter(ConnectionAdapter, _postgres.builder()):
-
- def __init__(self, connection):
- #The import is needed, as sqlobject uses self.module.Binary uppon
- #startup. But until now we dont define .module. There is definitely
- #need for a better solution. Propably the other adapters need this as
- #well, but i cant test them, as i dont have them.
- #Andres Freund - 2005-10-17
- if getattr(self, 'module', None) == None:
- import psycopg
- self.module = psycopg
- #This is needed, because psycopg provides a optimized
- #Binary() function which sqlobject dont get along with. This is
- #normally done in sqlobject.postgres.pgconnection __init__ but we
- #dont call that.
- from sqlobject.postgres import pgconnection
- registerConverter(type(psycopg.Binary('')),
- pgconnection.PsycoBinaryConverter)
-
-
- super(PostgresAdapter, self).__init__(connection)
- self.supportTransactions = True
-
-
-class SQLiteAdapter(ConnectionAdapter, _sqlite.builder()):
-
- def __init__(self, connection):
- #see above
- if getattr(self, 'module', None) == None:
- try:
- from pysqlite2 import dbapi2 as sqlite
- except ImportError:
- import sqlite
- self.module = sqlite
- super(SQLiteAdapter, self).__init__(connection)
- self.supportTransactions = True
Modified: z3/sqlos/branch/jinty-sqlobject2/src/sqlos/connection.py
==============================================================================
--- z3/sqlos/branch/jinty-sqlobject2/src/sqlos/connection.py (original)
+++ z3/sqlos/branch/jinty-sqlobject2/src/sqlos/connection.py Wed May 10 12:48:30 2006
@@ -10,26 +10,12 @@
"""
Connection management.
-This module defines the connection descriptor used as the connection in a
-a sqlos SQLObject. This is responsible for getting the Zope connection and
-adapting it to look like a SQLObject connection.
-
-Connections are cached as experience has shown that all the utility and
-adapter utilities have a significant effect on speed.
-
$Id: factory.py 5216 2004-06-21 18:33:07Z dreamcatcher $
"""
__metaclass__ = type
-import warnings
-
-from zope.component import ComponentLookupError
-import zope.component
-from zope.app.rdb.interfaces import IZopeDatabaseAdapter
from zope.thread import local
-from sqlos.interfaces import IZopeSQLConnection, IConnectionName
-
class ConnectionCache(local):
"""A per thread cache for adapted connections."""
@@ -72,43 +58,3 @@
True
"""
conn_cache.clear()
-
-
-class SQLObjectWarning(UserWarning):
- pass
-
-
-class ConnectionDescriptor:
-
- def __init__(self, name=None):
- self.name = name
-
- def __get__(self, inst, cls=None):
- # get and cache the connection name
- name = self.name
- if name is None:
- try:
- ut = zope.component.getUtility(IConnectionName)
- except ComponentLookupError:
- return self
- if ut is None:
- warnings.warn("Couldn't find ISQLConnectionName utility. "
- "Please verify your setup.",
- SQLObjectWarning, 2)
- return
- name = ut.name
- # try get the connection from the cache, or make a new one
- conn = conn_cache.queryConnection(name)
- if conn is None:
- zda = zope.component.getUtility(IZopeDatabaseAdapter, name)
- try:
- conn = IZopeSQLConnection(zda())
- except ComponentLookupError:
- return self
- conn_cache.setConnection(name, conn)
- return conn
-
- def __set__(self, inst, value):
- # Ignore, so we don't get overriden.
- # We always use the connections from the IZopeDatabaseAdapter utility.
- pass
Added: z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py
==============================================================================
--- (empty file)
+++ z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py Wed May 10 12:48:30 2006
@@ -0,0 +1,80 @@
+##############################################################################
+#
+# Copyright (c) 2004 Enfold Systems LLC. All rights reserved.
+#
+# This software is distributed under the terms of the Zope Public
+# License (ZPL) v2.1. See COPYING.txt for more information.
+#
+##############################################################################
+"""
+$Id: adapter.py 5212 2004-06-21 18:09:05Z philikon $
+"""
+
+from zope.schema import TextLine
+from zope.interface import Interface, Attribute
+from zope.interface import Attribute
+from zope.app.container.constraints import ItemTypePrecondition
+from zope.app.annotation.interfaces import IAttributeAnnotatable
+from zope.app.container.interfaces import IContainerNamesContainer
+from zope.app.container.interfaces import IReadContainer, IContainer
+
+class ISQLObjectReadContainer(IReadContainer, IAttributeAnnotatable):
+ """ An SQLObject Container """
+
+
+class ISQLObjectContainer(IContainer, IContainerNamesContainer,
+ IAttributeAnnotatable):
+ """ An SQLObject Container """
+
+ def __setitem__(name, obj):
+ """Add a new object"""
+
+ __setitem__.precondition = ItemTypePrecondition()
+
+
+class IIsolatedSQLContainer(ISQLObjectContainer):
+ # TODO Attribute -> zope.schema.* - jinty
+ container_id = Attribute("The id of the containers, this is a filter on the"
+ "database table.")
+
+
+class IConnectionName(Interface):
+ """A marker interface for providing a connection name"""
+
+ name = TextLine(
+ title=u"Connection Name",
+ required=True
+ )
+
+
+class IISQLObject(IReadSQLObjectClass, IWriteSQLObjectClass):
+ """Class methods for SQLObject classes."""
+
+
+class IISQLObjectIsolated(IISQLObject):
+ """Support for using this class in isolated containers.
+
+ This interface is necessary to move the SQL query logic to the SQLOS class
+ as it can be implemented in various ways in the class.
+ """
+
+ def countByDomain(domain):
+ """Return the number of objects which are in the domain."""
+
+ def selectByDomain(domain):
+ """Returns an iterator of objects in the domain.
+
+ similar to select()
+ """
+
+
+class ISQLObject(Interface):
+ """Marker interface for SQLObjects.
+
+ Hopefully one day this will be a real interface in SQLObject.
+ """
+
+
+class ISQLObjectIsolated(ISQLObject):
+
+ domains = Attribute("A _tuple_ of containers_ids which contain this object")
Modified: z3/sqlos/branch/jinty-sqlobject2/src/sqlos/zsqlobject.py
==============================================================================
--- z3/sqlos/branch/jinty-sqlobject2/src/sqlos/zsqlobject.py (original)
+++ z3/sqlos/branch/jinty-sqlobject2/src/sqlos/zsqlobject.py Wed May 10 12:48:30 2006
@@ -24,64 +24,3 @@
>>> syncUpdateAll()
"""
_transaction.dirty_object_registry.syncUpdateAll()
-
-
-class SQLOS(SQLObject):
- """Subclass SQLObject to enable ``lazy updates`` by default,
- as well as adding knowledge to register ``dirty`` objects
- with SQLObjectTransactionManager so they get sync'd on transaction
- boundaries.
-
- First, make a test data base:
-
- >>> from sqlos import testing
- >>> testdb = testing.TestDB([SQLOS])
-
- Test the interface:
-
- >>> s = SQLOS()
- >>> from zope.interface.verify import verifyObject
- >>> verifyObject(ISQLObject, s)
- True
-
- And finally call tearDown and cleanup:
-
- >>> testdb.tearDown()
- """
- implements(ISQLObject)
- _connection = ConnectionDescriptor()
-
- class sqlmeta:
- lazyUpdate = True
-
- def _set_dirty(self, value):
- if value:
- _transaction.dirty_object_registry.register(self)
- self._dirty = value
-
- def _get_dirty(self):
- return self._dirty
-
- dirty = property(_get_dirty, _set_dirty)
-
- def get(self, id, connection=None, selectResults=None):
- # While interacting with zope, we may end up having
- # objects in the cache that have a __parent__ set.
- # This may be confusing when expect to get a object
- # which has no __parent__ and thats not what you get.
- val = super(SQLOS, self).get(id, connection=connection,
- selectResults=selectResults)
- if getattr(val, '__parent__', None) is not None:
- val.__parent__ = None
- val.__name__ = None
- return val
- get = classmethod(get)
-
- def __repr__(self):
- return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
-
- def setConnection(self, connection):
- if connection is not None:
- self._connection = connection
-
- setConnection = classmethod(setConnection)
From jinty at codespeak.net Wed May 10 12:57:16 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 10 12:57:17 2006
Subject: [z3-checkins] r27041 - z3/sqlos/branch/jinty-sqlobject2
Message-ID: <20060510105716.CE171100BB@code0.codespeak.net>
Author: jinty
Date: Wed May 10 12:57:15 2006
New Revision: 27041
Modified:
z3/sqlos/branch/jinty-sqlobject2/setup.py
Log:
Update dependencies.
Modified: z3/sqlos/branch/jinty-sqlobject2/setup.py
==============================================================================
--- z3/sqlos/branch/jinty-sqlobject2/setup.py (original)
+++ z3/sqlos/branch/jinty-sqlobject2/setup.py Wed May 10 12:57:15 2006
@@ -19,6 +19,6 @@
zip_safe=False,
include_package_data=True,
install_requires = [
- 'SQLObject>=0.7',
+ 'SQLObject2',
] # XXX - what else? at least zope, let the users find out;)
)
From jinty at codespeak.net Wed May 10 12:58:14 2006
From: jinty at codespeak.net (jinty@codespeak.net)
Date: Wed May 10 12:58:16 2006
Subject: [z3-checkins] r27042 - z3/sqlos/branch/jinty-sqlobject2/src/sqlos
Message-ID: <20060510105814.81A64100BD@code0.codespeak.net>
Author: jinty
Date: Wed May 10 12:58:12 2006
New Revision: 27042
Modified:
z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py
Log:
Update dependencies.
Modified: z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py
==============================================================================
--- z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py (original)
+++ z3/sqlos/branch/jinty-sqlobject2/src/sqlos/interfaces.py Wed May 10 12:58:12 2006
@@ -47,7 +47,7 @@
)
-class IISQLObject(IReadSQLObjectClass, IWriteSQLObjectClass):
+class IISQLObject(Interface):
"""Class methods for SQLObject classes."""
From reebalazs at codespeak.net Wed May 10 20:55:58 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Wed May 10 20:56:00 2006
Subject: [z3-checkins] r27052 -
z3/jsonserver/branch/merge/concatresource/compression/thirdparty
Message-ID: <20060510185558.CCB3A10087@code0.codespeak.net>
Author: reebalazs
Date: Wed May 10 20:55:57 2006
New Revision: 27052
Modified:
z3/jsonserver/branch/merge/concatresource/compression/thirdparty/LICENSE
z3/jsonserver/branch/merge/concatresource/compression/thirdparty/packer.py
Log:
Change license of packer.py
Modified: z3/jsonserver/branch/merge/concatresource/compression/thirdparty/LICENSE
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/thirdparty/LICENSE (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/thirdparty/LICENSE Wed May 10 20:55:57 2006
@@ -1,8 +1,25 @@
-packer.py is originally licensed under GNU GPL
+packer.py is released under the MIT license.
+
+# packer.py
+#
+# Copyright (c) 2006 Florian Schulze
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
-# ------------------------------------------------------------------------------
-# used with permission by Florian Schulze,
-# originally from
-# https://svn.plone.org/svn/plone/ResourceRegistries/trunk/tools/packer.py
-# ------------------------------------------------------------------------------
Modified: z3/jsonserver/branch/merge/concatresource/compression/thirdparty/packer.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/compression/thirdparty/packer.py (original)
+++ z3/jsonserver/branch/merge/concatresource/compression/thirdparty/packer.py Wed May 10 20:55:57 2006
@@ -1,12 +1,29 @@
-
-# ------------------------------------------------------------------------------
-# used with permission by Florian Schulze,
-# originally from
-# https://svn.plone.org/svn/plone/ResourceRegistries/trunk/tools/packer.py
-# ------------------------------------------------------------------------------
+#
+# packer.py
+#
+# Copyright (c) 2006 Florian Schulze
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
import re
+
class KeywordMapper:
def __init__(self, regexp, encoder):
if isinstance(regexp, (str, unicode)):
From jwashin at codespeak.net Thu May 11 13:48:10 2006
From: jwashin at codespeak.net (jwashin@codespeak.net)
Date: Thu May 11 13:48:12 2006
Subject: [z3-checkins] r27069 - in z3/jsonserver/trunk: . tests
Message-ID: <20060511114810.649131007B@code0.codespeak.net>
Author: jwashin
Date: Thu May 11 13:48:07 2006
New Revision: 27069
Modified:
z3/jsonserver/trunk/CHANGES.txt
z3/jsonserver/trunk/VERSION.txt
z3/jsonserver/trunk/jsoncomponent.py
z3/jsonserver/trunk/jsonrpc.py
z3/jsonserver/trunk/metaconfigure.py
z3/jsonserver/trunk/tests/test_jsonrpcrequest.py
Log:
adjusted a few deprecated imports. preliminary support for json-rpc 1.1
Modified: z3/jsonserver/trunk/CHANGES.txt
==============================================================================
--- z3/jsonserver/trunk/CHANGES.txt (original)
+++ z3/jsonserver/trunk/CHANGES.txt Thu May 11 13:48:07 2006
@@ -1,17 +1,20 @@
#CHANGES.txt
-20051202 a bit of backward-compatibility with five:
- ++resource++ notation for the javascript. updated to the available
+20051202 a bit of backward-compatibility with five:
+ ++resource++ notation for the javascript. updated to the available
jsolait (2005-11-15.small)
-20051125 some work toward making json requests better zope citizens.
+20051125 some work toward making json requests better zope citizens.
Some work toward keyword parameter support.
-Some work toward making more information available in request: now
-provides IBrowserApplicationRequest. This is experimental. Let me
+Some work toward making more information available in request: now
+provides IBrowserApplicationRequest. This is experimental. Let me
know what you think.
20050921 Using the next beta of jsolait (20050914). The init file is now
- jsolait.js instead of init.js. jsolait installer adds init.js as a copy of jsolait.js
- for backwards compatibility. We are now using the 3.1 ResourceDirectory,
- so the jsolait file structure does not need to be flattened. Upgrade to this
- version using the installer is optional.
+ jsolait.js instead of init.js. jsolait installer adds init.js as a copy of
+ jsolait.js for backwards compatibility. We are now using the 3.1
+ ResourceDirectory, so the jsolait file structure does not need to be flattened.
+ Upgrade to this version of jsolait using the installer is optional.
+
+20060511 Removed gzip support, since that can be done more elegantly by other
+ means. Preliminary support for json-rpc 1.1.
\ No newline at end of file
Modified: z3/jsonserver/trunk/VERSION.txt
==============================================================================
--- z3/jsonserver/trunk/VERSION.txt (original)
+++ z3/jsonserver/trunk/VERSION.txt Thu May 11 13:48:07 2006
@@ -1 +1 @@
-jsonserver 3.2.2 svn
+jsonserver 3.3.0 svn
Modified: z3/jsonserver/trunk/jsoncomponent.py
==============================================================================
--- z3/jsonserver/trunk/jsoncomponent.py (original)
+++ z3/jsonserver/trunk/jsoncomponent.py Thu May 11 13:48:07 2006
@@ -17,6 +17,7 @@
# jwashin 2005-07-27
# 2005-10-09 updated to properly? handle unicode on the boundary
# 2005-09-08 updated for modularity and IResult
+# 2006-05-11 allowed encoding param for reader
import minjson as json
from interfaces import IJSONReader, IJSONWriter
@@ -26,14 +27,14 @@
class JSONReader(object):
"""component implementing JSON reading"""
implements(IJSONReader)
-
- def read(self,aString, encoding='utf-8'):
+
+ def read(self,aString,encoding=None):
return json.read(aString,encoding)
class JSONWriter(object):
"""component implementing JSON writing"""
implements(IJSONWriter)
-
+
def write(self,anObject):
return json.write(anObject)
Modified: z3/jsonserver/trunk/jsonrpc.py
==============================================================================
--- z3/jsonserver/trunk/jsonrpc.py (original)
+++ z3/jsonserver/trunk/jsonrpc.py Thu May 11 13:48:07 2006
@@ -20,7 +20,7 @@
#2005-09-08 updated to work with the new IResult idea (wsgi)
#2005-10-09 unicode handling update
#2006-03-09 enabled gzip compression for large responses
-#2006-04-27 updated to sync with z3 trunk changes jmw
+#2006-05-10 removed gzip compression and (prematurely) enabled json-rpc 1.1 jmw
__docformat__ = 'restructuredtext'
@@ -29,23 +29,18 @@
IJSONRPCRequest, IJSONReader, IJSONWriter
from zope.interface import implements
#from zope.publisher.http import IResult
-try:
- from zope.location.location import Location
-except ImportError:
- #deprecate this for 3.5
- from zope.app.location.location import Location
+from zope.location.location import Location
from zope.publisher.http import HTTPRequest, HTTPResponse, \
getCharsetUsingRequest, DirectResult
from zope.publisher.browser import BrowserRequest
from zope.security.proxy import isinstance
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.browser import IBrowserApplicationRequest
+from zope.component import getUtility
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IBrowserApplicationRequest
-from zope.component import getUtility
-import gzip
import traceback
import logging
@@ -74,6 +69,9 @@
def __call__(self):
return self.__pub
+def intsort(item):
+ return int(item[0])
+
class JSONRPCRequest(BrowserRequest):
"""a JSON-RPC Request
modeled after zope.publisher.xmlrpc.XMLRPCRequest
@@ -106,9 +104,6 @@
input = ''.join(input)
#make it unicode; we are at the boundary
input = self._decode(input)
- #encoding = getCharsetUsingRequest(self)
- #if not isinstance(input,unicode):
- # input = input.decode(encoding)
data = json.read(input)
if writeProfileData:
infile = 'profiledata.js'
@@ -121,69 +116,57 @@
# failure unless we split on '.' Why?
function = functionstr.split('.')
self.jsonID = data['id']
- args = list(data['params'])
- # now, look for keyword parameters
- kwargs = None
- notPositional = []
- for k in args:
- if isinstance(k,dict):
- if k.has_key(keyword_key):
- if isinstance(k[keyword_key],dict):
- j = k[keyword_key]
- kwargs= j
- notPositional.append(k)
- if notPositional:
- for k in notPositional:
- args.remove(k)
- if kwargs:
- for m in kwargs.keys():
- self.form[str(m)] = kwargs[m]
+ params = data['params']
+ if isinstance(params,list):
+ args = params
+ # now, look for keyword parameters, the old way
+ kwargs = None
+ notPositional = []
+ for k in args:
+ if isinstance(k,dict):
+ if k.has_key(keyword_key):
+ if isinstance(k[keyword_key],dict):
+ j = k[keyword_key]
+ kwargs= j
+ notPositional.append(k)
+ if notPositional:
+ for k in notPositional:
+ args.remove(k)
+ if kwargs:
+ for m in kwargs.keys():
+ self.form[str(m)] = kwargs[m]
+ elif isinstance(params,dict):
+ #json-rpc 1.1 (to be proposed)
+ #get the numeric params for positional params
+ temp_positional = []
+ for key in params:
+ if key.isdigit():
+ temp_positional.append((key,params[key]))
+ temp_positional.sort(key=intsort)
+ args = []
+ #make args from positional args and remove them from params
+ for item in temp_positional:
+ args.append(item[1])
+ del params[item[0]]
+ #drop remaining named params into request.form
+ for named_param in params:
+ #named_param is unicode; python needs string for param names
+ self.form[str(named_param)] = params[named_param]
+ else:
+ raise TypeError, 'Unsupported type for JSON-RPC "params" (%s)' \
+ % type(params)
self._args = tuple(args)
#make environment,cookies, etc., available to request.get()
super(JSONRPCRequest,self).processInputs()
self._environ['JSONRPC_MODE'] = True
if function:
self.setPathSuffix(function)
-
def traverse(self,object):
return super(BrowserRequest,self).traverse(object)
def __getitem__(self,key):
return self.get(key)
-# IResult has gone PRIVATE; for we now will send a bytestring and set
-# charset.
-
-##class JSONResult(object):
-## implements(IResult)
-## def __init__(self,aString, encoding='utf-8'):
-## #statements to help figure out Opera
-## #encoding='utf-8' #yields oriental charset, unparseable
-## #encoding='utf-16' #yields something that looks like the right code,
-## # no trouble in gecko, but opera refuses to parse it
-## #encoding = None is troublesome for gecko; only get '{'
-## #encoding = 'iso-8859-1'
-## try:
-## s= aString.encode(encoding)
-## except UnicodeEncodeError:
-## s = aString
-## self.body = [s]
-## if encoding == 'utf-8':
-## # don't need charset for utf-8; charset handling seems buggy on
-## # some browsers, so best not to use unnecessarily
-## self.headers = [('content-type',
-## 'application/x-javascript'),
-## ('content-length',str(len(s)))]
-## else:
-## self.headers = [('content-type',
-## 'application/x-javascript;charset=%s' % encoding),
-## ('content-length',str(len(s)))]
-#### else:
-#### self.body = [aString]
-#### self.headers = [('content-type','application/x-javascript'),
-#### ('content-length',str(len(aString)))]
-##
-
class JSONRPCResponse(HTTPResponse):
"""JSON-RPC Response
modeled after zope.publisher.xmlrpc.XMLRPCResponse
@@ -222,31 +205,16 @@
super(JSONRPCResponse,self).setResult('')
def _prepareResult(self,result):
- #we've asked json to return unicode. result should be unicode
-
+ #we've asked json to return unicode; result should be unicode
encoding = getCharsetUsingRequest(self._request) or 'utf-8'
+ #at outgoing boundary; encode it.
if isinstance(result,unicode):
body = result.encode(encoding)
charset = encoding
else:
#something's wrong. json did not return unicode.
- raise AttributeError
-
- #let's gzip compress it if it's big.
- #thanks to Alan Kennedy http://www.xhaus.com/alan/python/httpcomp.html
- compress_type = self._request.getHeader('Accept-Encoding', [])
- bodyLength = len(body)
- if 'gzip' in compress_type and bodyLength > compressionTrigger:
- #using cStringIO, but OK, because we have a byte string here
- zbuf = StringIO()
- zfile = gzip.GzipFile(mode='wb', fileobj=zbuf,
- compresslevel=compressionLevel)
- zfile.write(body)
- zfile.close()
- body = zbuf.getvalue()
- #a = len(body)
- #print "before %s after %s" % (bodyLength,a)
- self.setHeader('content-encoding','gzip')
+ raise TypeError, "JSON did not return unicode (%s)" % type(result)
+ #we used to gzip compress here, but that should be decided elsewhere
self.setHeader('content-type',"application/x-javascript;charset=%s" \
% charset)
return body
@@ -355,4 +323,3 @@
super(TestRequest, self).__init__(
body_instream, _testEnv, response)
-
Modified: z3/jsonserver/trunk/metaconfigure.py
==============================================================================
--- z3/jsonserver/trunk/metaconfigure.py (original)
+++ z3/jsonserver/trunk/metaconfigure.py Thu May 11 13:48:07 2006
@@ -17,7 +17,6 @@
like zope.app.publisher.xmlrpc.metaconfigure
-Updated 2006-04-27 to sync with zope3 trunk jmw
updated 2005-12-03 Roger Ineichen
jwashin 2005-06-06
"""
@@ -28,7 +27,7 @@
from interfaces import IJSONRPCRequest
from zope.component.interface import provideInterface
-from zope.component.zcml import handler
+from zope.app.component.metaconfigure import handler
from jsonrpc import MethodPublisher
def view(_context, for_=None, interface=None, methods=None,
@@ -58,7 +57,8 @@
# Make sure that the class inherits MethodPublisher, so that the views
# have a location
if class_ is None:
- class_ = original_class = MethodPublisher
+ class_ = MethodPublisher
+ original_class = class_
else:
original_class = class_
class_ = type(class_.__name__, (class_, MethodPublisher), {})
@@ -83,8 +83,8 @@
_context.action(
discriminator = ('view', for_, name, IJSONRPCRequest),
callable = handler,
- args = ('registerAdapter',
- class_, (for_, IJSONRPCRequest), Interface, name,
+ args = ('provideAdapter',
+ (for_, IJSONRPCRequest), Interface, name, class_,
_context.info)
)
else:
@@ -101,8 +101,8 @@
_context.action(
discriminator = ('view', for_, name, IJSONRPCRequest),
callable = handler,
- args = ('registerAdapter',
- new_class, (for_, IJSONRPCRequest), Interface, name,
+ args = ('provideAdapter',
+ (for_, IJSONRPCRequest), Interface, name, new_class,
_context.info)
)
Modified: z3/jsonserver/trunk/tests/test_jsonrpcrequest.py
==============================================================================
--- z3/jsonserver/trunk/tests/test_jsonrpcrequest.py (original)
+++ z3/jsonserver/trunk/tests/test_jsonrpcrequest.py Thu May 11 13:48:07 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -14,6 +14,8 @@
"""JSON-RPC Request Tests
modified from zope/publisher/tests/test_xmlrpcrequest.py jwashin 2005-06-06
"""
+#2006-05-10 updated to test json-rpc1.1 jmw
+
import unittest
from StringIO import StringIO
@@ -55,6 +57,17 @@
self.body = '{"id":"httpReq","method":"keyworded","params":[1,{"pythonKwMaRkEr":{"kw1":"aaa"}}]}'
self.headers = []
+class Param1_1SpecTestCall1:
+ def __init__(self):
+ self.body = '{"id":"httpReq","method":"keyworded","params":{"1":1,"kw1":"aaa"}}'
+ self.headers = []
+
+class Param1_1SpecTestCall2:
+ def __init__(self):
+ self.body = '{"id":"httpReq","method":"action1_1","params":{"1":1,"kw1":"aaa"}}'
+ self.headers = []
+
+
class JSONRPCTests(unittest.TestCase):
"""The only thing different to HTTP is the input processing; so there
is no need to redo all the HTTP tests again.
@@ -92,14 +105,18 @@
class View(object):
- def action(self, a):
+ def action(self, a, kw1=None):
return "Parameter[type: %s; value: %s" %(
type(a).__name__, `a`)
-
+
def keyworded(self, a, kw1="spam"):
return "kw1: [type: %s; value: %s]" %(
type(kw1).__name__, `kw1`)
-
+
+ def action1_1(self, a, kw1=None):
+ return "Parameter[type: %s; value: %s" %(
+ type(a).__name__, `a`)
+
class Item2(object):
view = View()
@@ -135,14 +152,28 @@
action = req.traverse(self.app)
self.failUnlessEqual(action(*req._args),
"Parameter[type: int; value: 1")
-
+
def testKeyword(self):
req = self._createRequest({}, ParamTestCall())
req.processInputs()
action = req.traverse(self.app)
self.failUnlessEqual(action(*req._args, **req.form),
"kw1: [type: unicode; value: u'aaa']")
-
+
+ def test1_1spec_kw(self):
+ req = self._createRequest({}, Param1_1SpecTestCall1())
+ req.processInputs()
+ action = req.traverse(self.app)
+ self.failUnlessEqual(action(*req._args, **req.form),
+ "kw1: [type: unicode; value: u'aaa']")
+
+ def test1_1spec2_p(self):
+ req = self._createRequest({}, Param1_1SpecTestCall2())
+ req.processInputs()
+ action = req.traverse(self.app)
+ self.failUnlessEqual(action(*req._args, **req.form),
+ "Parameter[type: int; value: 1")
+
def testJSONRPCMode(self):
req = self._createRequest({}, jsonrpc_call)
req.processInputs()
From jwashin at codespeak.net Thu May 11 14:12:12 2006
From: jwashin at codespeak.net (jwashin@codespeak.net)
Date: Thu May 11 14:12:14 2006
Subject: [z3-checkins] r27071 - in z3/jsonserver/trunk: . tests
Message-ID: <20060511121212.EA49710082@code0.codespeak.net>
Author: jwashin
Date: Thu May 11 14:12:10 2006
New Revision: 27071
Modified:
z3/jsonserver/trunk/configure.zcml
z3/jsonserver/trunk/tests/test_directives.py
Log:
resolved svn oops
Modified: z3/jsonserver/trunk/configure.zcml
==============================================================================
--- z3/jsonserver/trunk/configure.zcml (original)
+++ z3/jsonserver/trunk/configure.zcml Thu May 11 14:12:10 2006
@@ -12,17 +12,17 @@
mimetypes="application/json-rpc"
priority="25"
/>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+ />
+
-
+
Modified: z3/jsonserver/trunk/tests/test_directives.py
==============================================================================
--- z3/jsonserver/trunk/tests/test_directives.py (original)
+++ z3/jsonserver/trunk/tests/test_directives.py Thu May 11 14:12:10 2006
@@ -23,8 +23,6 @@
from zope.app.testing.placelesssetup import PlacelessSetup
from zope.security.proxy import ProxyFactory
-#from zope.component.tests.request import Request
-
from jsonserver.interfaces import IJSONRPCRequest
import jsonserver
From reebalazs at codespeak.net Thu May 11 17:12:58 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Thu May 11 17:12:59 2006
Subject: [z3-checkins] r27082 - z3/jsonserver/branch/zope2_test
Message-ID: <20060511151258.168F61007F@code0.codespeak.net>
Author: reebalazs
Date: Thu May 11 17:12:56 2006
New Revision: 27082
Modified:
z3/jsonserver/branch/zope2_test/jsonrpc.py
Log:
Fix the last fix to work with Z 2.8
Modified: z3/jsonserver/branch/zope2_test/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/zope2_test/jsonrpc.py (original)
+++ z3/jsonserver/branch/zope2_test/jsonrpc.py Thu May 11 17:12:56 2006
@@ -24,7 +24,12 @@
from zope.interface import directlyProvides, directlyProvidedBy
from interfaces import IJsonRequest
from ZPublisher.HTTPRequest import HTTPRequest
-from zope.app.publication.browser import setDefaultSkin
+
+try:
+ from zope.app.publication.browser import setDefaultSkin
+except ImportError:
+ # 2.8. We don't need this hack.
+ setDefaultSkin = lambda self: None
# this is used to identify incoming requests
request_content_type = 'application/json-rpc'
From jwashin at codespeak.net Thu May 11 17:30:43 2006
From: jwashin at codespeak.net (jwashin@codespeak.net)
Date: Thu May 11 17:30:45 2006
Subject: [z3-checkins] r27083 - in z3/jsonserver/branch/merge: . tests
Message-ID: <20060511153043.027E61007F@code0.codespeak.net>
Author: jwashin
Date: Thu May 11 17:30:39 2006
New Revision: 27083
Modified:
z3/jsonserver/branch/merge/CHANGES.txt
z3/jsonserver/branch/merge/VERSION.txt
z3/jsonserver/branch/merge/configure.zcml
z3/jsonserver/branch/merge/jsoncomponent.py
z3/jsonserver/branch/merge/jsonrpc.py
z3/jsonserver/branch/merge/metaconfigure.py
z3/jsonserver/branch/merge/tests/test_directives.py
z3/jsonserver/branch/merge/tests/test_httpfactory.py
z3/jsonserver/branch/merge/tests/test_jsonrpcrequest.py
Log:
removed gzip. updated some deprecated imports. preliminary support for json-rpc 1.1
Modified: z3/jsonserver/branch/merge/CHANGES.txt
==============================================================================
--- z3/jsonserver/branch/merge/CHANGES.txt (original)
+++ z3/jsonserver/branch/merge/CHANGES.txt Thu May 11 17:30:39 2006
@@ -1,17 +1,20 @@
#CHANGES.txt
-20051202 a bit of backward-compatibility with five:
- ++resource++ notation for the javascript. updated to the available
+20051202 a bit of backward-compatibility with five:
+ ++resource++ notation for the javascript. updated to the available
jsolait (2005-11-15.small)
-20051125 some work toward making json requests better zope citizens.
+20051125 some work toward making json requests better zope citizens.
Some work toward keyword parameter support.
-Some work toward making more information available in request: now
-provides IBrowserApplicationRequest. This is experimental. Let me
+Some work toward making more information available in request: now
+provides IBrowserApplicationRequest. This is experimental. Let me
know what you think.
20050921 Using the next beta of jsolait (20050914). The init file is now
- jsolait.js instead of init.js. jsolait installer adds init.js as a copy of jsolait.js
- for backwards compatibility. We are now using the 3.1 ResourceDirectory,
- so the jsolait file structure does not need to be flattened. Upgrade to this
- version using the installer is optional.
+ jsolait.js instead of init.js. jsolait installer adds init.js as a copy of
+ jsolait.js for backwards compatibility. We are now using the 3.1
+ ResourceDirectory, so the jsolait file structure does not need to be flattened.
+ Upgrade to this version of jsolait using the installer is optional.
+
+20060511 Removed gzip support, since that can be done more elegantly by other
+ means. Preliminary support for json-rpc 1.1.
\ No newline at end of file
Modified: z3/jsonserver/branch/merge/VERSION.txt
==============================================================================
--- z3/jsonserver/branch/merge/VERSION.txt (original)
+++ z3/jsonserver/branch/merge/VERSION.txt Thu May 11 17:30:39 2006
@@ -1 +1 @@
-jsonserver 3.2.2 svn
+jsonserver 3.3.0 svn
Modified: z3/jsonserver/branch/merge/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/configure.zcml (original)
+++ z3/jsonserver/branch/merge/configure.zcml Thu May 11 17:30:39 2006
@@ -66,15 +66,15 @@
-
+
-
+
+ />
-
-
-
-
-
-
-
-
Modified: z3/jsonserver/branch/merge/jsoncomponent.py
==============================================================================
--- z3/jsonserver/branch/merge/jsoncomponent.py (original)
+++ z3/jsonserver/branch/merge/jsoncomponent.py Thu May 11 17:30:39 2006
@@ -17,6 +17,7 @@
# jwashin 2005-07-27
# 2005-10-09 updated to properly? handle unicode on the boundary
# 2005-09-08 updated for modularity and IResult
+# 2006-05-11 allowed encoding param for reader
import minjson as json
from interfaces import IJSONReader, IJSONWriter
@@ -26,14 +27,14 @@
class JSONReader(object):
"""component implementing JSON reading"""
implements(IJSONReader)
-
- def read(self,aString, encoding='utf-8'):
+
+ def read(self,aString,encoding=None):
return json.read(aString,encoding)
class JSONWriter(object):
"""component implementing JSON writing"""
implements(IJSONWriter)
-
+
def write(self,anObject):
return json.write(anObject)
Modified: z3/jsonserver/branch/merge/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/merge/jsonrpc.py (original)
+++ z3/jsonserver/branch/merge/jsonrpc.py Thu May 11 17:30:39 2006
@@ -20,6 +20,7 @@
#2005-09-08 updated to work with the new IResult idea (wsgi)
#2005-10-09 unicode handling update
#2006-03-09 enabled gzip compression for large responses
+#2006-05-10 removed gzip compression and (prematurely) enabled json-rpc 1.1 jmw
__docformat__ = 'restructuredtext'
@@ -28,16 +29,18 @@
IJSONRPCRequest, IJSONReader, IJSONWriter
from zope.interface import implements
#from zope.publisher.http import IResult
-from zope.app.location.location import Location
+from zope.location.location import Location
from zope.publisher.http import HTTPRequest, HTTPResponse, \
getCharsetUsingRequest, DirectResult
from zope.publisher.browser import BrowserRequest
from zope.security.proxy import isinstance
-from cStringIO import StringIO
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.browser import IBrowserApplicationRequest
from zope.component import getUtility
-import gzip
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
import traceback
import logging
@@ -66,6 +69,9 @@
def __call__(self):
return self.__pub
+def intsort(item):
+ return int(item[0])
+
class JSONRPCRequest(BrowserRequest):
"""a JSON-RPC Request
modeled after zope.publisher.xmlrpc.XMLRPCRequest
@@ -98,9 +104,6 @@
input = ''.join(input)
#make it unicode; we are at the boundary
input = self._decode(input)
- #encoding = getCharsetUsingRequest(self)
- #if not isinstance(input,unicode):
- # input = input.decode(encoding)
data = json.read(input)
if writeProfileData:
infile = 'profiledata.js'
@@ -113,69 +116,57 @@
# failure unless we split on '.' Why?
function = functionstr.split('.')
self.jsonID = data['id']
- args = list(data['params'])
- # now, look for keyword parameters
- kwargs = None
- notPositional = []
- for k in args:
- if isinstance(k,dict):
- if k.has_key(keyword_key):
- if isinstance(k[keyword_key],dict):
- j = k[keyword_key]
- kwargs= j
- notPositional.append(k)
- if notPositional:
- for k in notPositional:
- args.remove(k)
- if kwargs:
- for m in kwargs.keys():
- self.form[str(m)] = kwargs[m]
+ params = data['params']
+ if isinstance(params,list):
+ args = params
+ # now, look for keyword parameters, the old way
+ kwargs = None
+ notPositional = []
+ for k in args:
+ if isinstance(k,dict):
+ if k.has_key(keyword_key):
+ if isinstance(k[keyword_key],dict):
+ j = k[keyword_key]
+ kwargs= j
+ notPositional.append(k)
+ if notPositional:
+ for k in notPositional:
+ args.remove(k)
+ if kwargs:
+ for m in kwargs.keys():
+ self.form[str(m)] = kwargs[m]
+ elif isinstance(params,dict):
+ #json-rpc 1.1 (to be proposed)
+ #get the numeric params for positional params
+ temp_positional = []
+ for key in params:
+ if key.isdigit():
+ temp_positional.append((key,params[key]))
+ temp_positional.sort(key=intsort)
+ args = []
+ #make args from positional args and remove them from params
+ for item in temp_positional:
+ args.append(item[1])
+ del params[item[0]]
+ #drop remaining named params into request.form
+ for named_param in params:
+ #named_param is unicode; python needs string for param names
+ self.form[str(named_param)] = params[named_param]
+ else:
+ raise TypeError, 'Unsupported type for JSON-RPC "params" (%s)' \
+ % type(params)
self._args = tuple(args)
#make environment,cookies, etc., available to request.get()
super(JSONRPCRequest,self).processInputs()
self._environ['JSONRPC_MODE'] = True
if function:
self.setPathSuffix(function)
-
def traverse(self,object):
return super(BrowserRequest,self).traverse(object)
def __getitem__(self,key):
return self.get(key)
-# IResult has gone PRIVATE; for we now will send a bytestring and set
-# charset.
-
-##class JSONResult(object):
-## implements(IResult)
-## def __init__(self,aString, encoding='utf-8'):
-## #statements to help figure out Opera
-## #encoding='utf-8' #yields oriental charset, unparseable
-## #encoding='utf-16' #yields something that looks like the right code,
-## # no trouble in gecko, but opera refuses to parse it
-## #encoding = None is troublesome for gecko; only get '{'
-## #encoding = 'iso-8859-1'
-## try:
-## s= aString.encode(encoding)
-## except UnicodeEncodeError:
-## s = aString
-## self.body = [s]
-## if encoding == 'utf-8':
-## # don't need charset for utf-8; charset handling seems buggy on
-## # some browsers, so best not to use unnecessarily
-## self.headers = [('content-type',
-## 'application/x-javascript'),
-## ('content-length',str(len(s)))]
-## else:
-## self.headers = [('content-type',
-## 'application/x-javascript;charset=%s' % encoding),
-## ('content-length',str(len(s)))]
-#### else:
-#### self.body = [aString]
-#### self.headers = [('content-type','application/x-javascript'),
-#### ('content-length',str(len(aString)))]
-##
-
class JSONRPCResponse(HTTPResponse):
"""JSON-RPC Response
modeled after zope.publisher.xmlrpc.XMLRPCResponse
@@ -214,31 +205,16 @@
super(JSONRPCResponse,self).setResult('')
def _prepareResult(self,result):
- #we've asked json to return unicode. result should be unicode
-
+ #we've asked json to return unicode; result should be unicode
encoding = getCharsetUsingRequest(self._request) or 'utf-8'
+ #at outgoing boundary; encode it.
if isinstance(result,unicode):
body = result.encode(encoding)
charset = encoding
else:
#something's wrong. json did not return unicode.
- raise AttributeError
-
- #let's gzip compress it if it's big.
- #thanks to Alan Kennedy http://www.xhaus.com/alan/python/httpcomp.html
- compress_type = self._request.getHeader('Accept-Encoding',[])
- bodyLength = len(body)
- if 'gzip' in compress_type and bodyLength > compressionTrigger:
- #using cStringIO, but OK, because we have a byte string here
- zbuf = StringIO()
- zfile = gzip.GzipFile(mode='wb', fileobj=zbuf,
- compresslevel=compressionLevel)
- zfile.write(body)
- zfile.close()
- body = zbuf.getvalue()
- #a = len(body)
- #print "before %s after %s" % (bodyLength,a)
- self.setHeader('content-encoding','gzip')
+ raise TypeError, "JSON did not return unicode (%s)" % type(result)
+ #we used to gzip compress here, but that should be decided elsewhere
self.setHeader('content-type',"application/x-javascript;charset=%s" \
% charset)
return body
@@ -347,4 +323,3 @@
super(TestRequest, self).__init__(
body_instream, _testEnv, response)
-
Modified: z3/jsonserver/branch/merge/metaconfigure.py
==============================================================================
--- z3/jsonserver/branch/merge/metaconfigure.py (original)
+++ z3/jsonserver/branch/merge/metaconfigure.py Thu May 11 17:30:39 2006
@@ -1,7 +1,7 @@
############################################################################
##
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -26,7 +26,7 @@
from zope.configuration.exceptions import ConfigurationError
from interfaces import IJSONRPCRequest
-from zope.app.component.interface import provideInterface
+from zope.component.interface import provideInterface
from zope.app.component.metaconfigure import handler
from jsonrpc import MethodPublisher
Modified: z3/jsonserver/branch/merge/tests/test_directives.py
==============================================================================
--- z3/jsonserver/branch/merge/tests/test_directives.py (original)
+++ z3/jsonserver/branch/merge/tests/test_directives.py Thu May 11 17:30:39 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -19,12 +19,10 @@
from zope.configuration import xmlconfig
from zope.configuration.exceptions import ConfigurationError
-from zope.app.component.tests.views import IC, V1
+from zope.app.component.tests.views import IC, V1, Request
from zope.app.testing.placelesssetup import PlacelessSetup
from zope.security.proxy import ProxyFactory
-from zope.component.tests.request import Request
-
from jsonserver.interfaces import IJSONRPCRequest
import jsonserver
Modified: z3/jsonserver/branch/merge/tests/test_httpfactory.py
==============================================================================
--- z3/jsonserver/branch/merge/tests/test_httpfactory.py (original)
+++ z3/jsonserver/branch/merge/tests/test_httpfactory.py Thu May 11 17:30:39 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2003 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2003 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -23,7 +23,7 @@
from zope.publisher.browser import BrowserRequest
from zope.publisher.http import HTTPRequest
from jsonserver.jsonrpc import JSONRPCRequest
-from zope.component.tests.placelesssetup import PlacelessSetup
+from zope.component.testing import PlacelessSetup
from jsonserver.interfaces import IJSONRPCRequestFactory
from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
from zope.app.publication.browser import BrowserPublication
Modified: z3/jsonserver/branch/merge/tests/test_jsonrpcrequest.py
==============================================================================
--- z3/jsonserver/branch/merge/tests/test_jsonrpcrequest.py (original)
+++ z3/jsonserver/branch/merge/tests/test_jsonrpcrequest.py Thu May 11 17:30:39 2006
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
+# Copyright (c) 2001 - 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -14,6 +14,8 @@
"""JSON-RPC Request Tests
modified from zope/publisher/tests/test_xmlrpcrequest.py jwashin 2005-06-06
"""
+#2006-05-10 updated to test json-rpc1.1 jmw
+
import unittest
from StringIO import StringIO
@@ -55,6 +57,17 @@
self.body = '{"id":"httpReq","method":"keyworded","params":[1,{"pythonKwMaRkEr":{"kw1":"aaa"}}]}'
self.headers = []
+class Param1_1SpecTestCall1:
+ def __init__(self):
+ self.body = '{"id":"httpReq","method":"keyworded","params":{"1":1,"kw1":"aaa"}}'
+ self.headers = []
+
+class Param1_1SpecTestCall2:
+ def __init__(self):
+ self.body = '{"id":"httpReq","method":"action1_1","params":{"1":1,"kw1":"aaa"}}'
+ self.headers = []
+
+
class JSONRPCTests(unittest.TestCase):
"""The only thing different to HTTP is the input processing; so there
is no need to redo all the HTTP tests again.
@@ -92,14 +105,18 @@
class View(object):
- def action(self, a):
+ def action(self, a, kw1=None):
return "Parameter[type: %s; value: %s" %(
type(a).__name__, `a`)
-
+
def keyworded(self, a, kw1="spam"):
return "kw1: [type: %s; value: %s]" %(
type(kw1).__name__, `kw1`)
-
+
+ def action1_1(self, a, kw1=None):
+ return "Parameter[type: %s; value: %s" %(
+ type(a).__name__, `a`)
+
class Item2(object):
view = View()
@@ -135,14 +152,28 @@
action = req.traverse(self.app)
self.failUnlessEqual(action(*req._args),
"Parameter[type: int; value: 1")
-
+
def testKeyword(self):
req = self._createRequest({}, ParamTestCall())
req.processInputs()
action = req.traverse(self.app)
self.failUnlessEqual(action(*req._args, **req.form),
"kw1: [type: unicode; value: u'aaa']")
-
+
+ def test1_1spec_kw(self):
+ req = self._createRequest({}, Param1_1SpecTestCall1())
+ req.processInputs()
+ action = req.traverse(self.app)
+ self.failUnlessEqual(action(*req._args, **req.form),
+ "kw1: [type: unicode; value: u'aaa']")
+
+ def test1_1spec2_p(self):
+ req = self._createRequest({}, Param1_1SpecTestCall2())
+ req.processInputs()
+ action = req.traverse(self.app)
+ self.failUnlessEqual(action(*req._args, **req.form),
+ "Parameter[type: int; value: 1")
+
def testJSONRPCMode(self):
req = self._createRequest({}, jsonrpc_call)
req.processInputs()
From reebalazs at codespeak.net Thu May 11 17:35:39 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Thu May 11 17:35:40 2006
Subject: [z3-checkins] r27084 - z3/jsonserver/branch/merge/browser
Message-ID: <20060511153539.B56BF10082@code0.codespeak.net>
Author: reebalazs
Date: Thu May 11 17:35:38 2006
New Revision: 27084
Modified:
z3/jsonserver/branch/merge/browser/json.js
Log:
Implement JSON-RPC 1.1
Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js (original)
+++ z3/jsonserver/branch/merge/browser/json.js Thu May 11 17:35:38 2006
@@ -123,6 +123,46 @@
var _dummyRequestManager = new _DummyRequestManager();
+function JSONSig(params, allowSupplement) {
+ // Params are those submitted to the rpc method
+ // Params can contain _JsonNamedWrapper and _JsonSupplement items
+ // they must be sorted out
+ // and finally the result is converted to the 1.1 marshall format
+ // that only needs to be jsonized after
+ this.supplementWrapper = null;
+ var args = new Array();
+ for(var i=0;i= 1 && typeof(args[args.length-1]) == 'object' && ! args[args.length-1].toJSON) {
+ // we have named parms!
+ this.args = {};
+ var kw = args[args.length-1];
+ for (var key in kw) {
+ this.args[key] = kw[key];
+ }
+ for (var i=0; i
Author: reebalazs
Date: Thu May 11 17:36:03 2006
New Revision: 27085
Modified:
z3/jsonserver/branch/zope2_test/jsonrpc.py
Log:
Implement JSON-RPC 1.1
Modified: z3/jsonserver/branch/zope2_test/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/zope2_test/jsonrpc.py (original)
+++ z3/jsonserver/branch/zope2_test/jsonrpc.py Thu May 11 17:36:03 2006
@@ -78,19 +78,37 @@
# Separare positional keywords from args
# this works if client emits {'jsonclass': ['zope.kw', kw]}
args, kw = [], {}
- for arg in params:
- success = False
- if isinstance(arg, dict) and 'jsonclass' in arg:
- # json class hints
- # TODO handle Date
- pass
- elif isinstance(arg, dict) and pythonkwmarker in arg:
- # a keyword parm
- kw.update(arg[pythonkwmarker])
- success = True
- if not success:
- # a normal positional parm
- args.append(arg)
+ if isinstance(params, dict):
+ argcounter = []
+ for key, value in params.iteritems():
+ try:
+ index = int(key)
+ except ValueError:
+ # a key
+ kw[key] = value
+ else:
+ # an arg
+ argcounter.append((index, value))
+ # now put together the args
+ argcounter.sort()
+ for i, (index, value) in enumerate(argcounter):
+ if i != index:
+ raise IndexError, "Bad order or arguments in JSON payload"
+ args.append(value)
+ else:
+ for arg in params:
+ success = False
+ if isinstance(arg, dict) and 'jsonclass' in arg:
+ # json class hints
+ # TODO handle Date
+ pass
+ elif isinstance(arg, dict) and pythonkwmarker in arg:
+ # a keyword parm
+ kw.update(arg[pythonkwmarker])
+ success = True
+ if not success:
+ # a normal positional parm
+ args.append(arg)
return jsonID, method, args, kw
From jwashin at codespeak.net Thu May 11 18:31:06 2006
From: jwashin at codespeak.net (jwashin@codespeak.net)
Date: Thu May 11 18:31:07 2006
Subject: [z3-checkins] r27088 - z3/jsonserver/branch/merge/concatresource
Message-ID: <20060511163106.CDF2810082@code0.codespeak.net>
Author: jwashin
Date: Thu May 11 18:31:04 2006
New Revision: 27088
Added:
z3/jsonserver/branch/merge/concatresource/concatresource-configure.zcml
z3/jsonserver/branch/merge/concatresource/concatresource-meta.zcml
Modified:
z3/jsonserver/branch/merge/concatresource/__init__.py
z3/jsonserver/branch/merge/concatresource/concatfileresource.py
Log:
conditional imports for z3 compatibility. files for etc/package-includes
Modified: z3/jsonserver/branch/merge/concatresource/__init__.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/__init__.py (original)
+++ z3/jsonserver/branch/merge/concatresource/__init__.py Thu May 11 18:31:04 2006
@@ -1,9 +1,11 @@
'''\
Product init
'''
-
# alias myself to Products, directly
-import sys, Products
-if not hasattr(Products, 'concatresource'):
+try:
+ import sys, Products
+ if not hasattr(Products, 'concatresource'):
# only 1st import is aliased.
- Products.concatresource = sys.modules['Products.concatresource'] = sys.modules[globals()['__name__']]
+ Products.concatresource = sys.modules['Products.concatresource'] = sys.modules[globals()['__name__']]
+except ImportError:
+ pass
Modified: z3/jsonserver/branch/merge/concatresource/concatfileresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatfileresource.py (original)
+++ z3/jsonserver/branch/merge/concatresource/concatfileresource.py Thu May 11 18:31:04 2006
@@ -9,7 +9,10 @@
from zope.interface import implements
from interfaces import IContextFile
# we are aliased to Products, hence the following absolute import
-from Products.concatresource.interfaces import IConcatResourceAddon
+try:
+ from Products.concatresource.interfaces import IConcatResourceAddon
+except ImportError:
+ from interfaces import IConcatResourceAddon
from fileresource import File
from compression import compress
import time
@@ -18,7 +21,7 @@
class ConcatFiles(object):
'''A resource that concatenates files and compresses the result
-
+
It is also possible to extend the statically given list via
a utility.
'''
@@ -50,7 +53,7 @@
extend = registry.getAddonFiles()
pathlist = self.pathlist_base + extend
return pathlist
-
+
def getFilesList(self):
'Gets the list of files'
## # XXX We have two choices:
@@ -70,13 +73,13 @@
else:
fileslist = self.fileslist
return fileslist
-
+
def getLastMod(self):
# We take in consideration that the pathlist
# itself could have changed too.
- return max([f.getLastMod() for f in self.getFilesList()] +
+ return max([f.getLastMod() for f in self.getFilesList()] +
[self.fileslist_changed])
-
+
def getContents(self):
fileslist = self.getFilesList()
assert fileslist, 'Must contain at least one resource.'
Added: z3/jsonserver/branch/merge/concatresource/concatresource-configure.zcml
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/concatresource/concatresource-configure.zcml Thu May 11 18:31:04 2006
@@ -0,0 +1 @@
+
Added: z3/jsonserver/branch/merge/concatresource/concatresource-meta.zcml
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/concatresource/concatresource-meta.zcml Thu May 11 18:31:04 2006
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
From reebalazs at codespeak.net Fri May 12 09:36:13 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 09:36:15 2006
Subject: [z3-checkins] r27106 - z3/jsonserver/branch/merge/concatresource
Message-ID: <20060512073613.B704F1009D@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 09:36:12 2006
New Revision: 27106
Modified:
z3/jsonserver/branch/merge/concatresource/README
Log:
Release notes about brokenness with Zope 2.9.2
Modified: z3/jsonserver/branch/merge/concatresource/README
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/README (original)
+++ z3/jsonserver/branch/merge/concatresource/README Fri May 12 09:36:12 2006
@@ -69,4 +69,14 @@
- Specifying "none" will leave your resource uncompressed. This
can be useful for debugging.
+Release notes
+-------------
+
+In Zope 2.9.2 there is Five 1.3.3 included. This contains a but that
+the resources will never be looked up from the
+application root.
+
+To fix this, you need to update Five to version 1.3.5, or update Zope
+to version 2.9.3 (not available of the time of writing this).
+
From reebalazs at codespeak.net Fri May 12 09:36:22 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 09:36:24 2006
Subject: [z3-checkins] r27107 - z3/jsonserver/branch/zope2_test
Message-ID: <20060512073622.DE937100A5@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 09:36:21 2006
New Revision: 27107
Modified:
z3/jsonserver/branch/zope2_test/README.txt
Log:
Release notes about brokenness with Zope 2.9.2
Modified: z3/jsonserver/branch/zope2_test/README.txt
==============================================================================
--- z3/jsonserver/branch/zope2_test/README.txt (original)
+++ z3/jsonserver/branch/zope2_test/README.txt Fri May 12 09:36:21 2006
@@ -163,7 +163,14 @@
**json:page** declarations will be callable from code and
their macros will be visible from other templates.
-TODO:
------
-gzip?
+Release notes
+-------------
+
+In Zope 2.9.2 there is Five 1.3.3 included. This contains a but that
+the resources will never be looked up from the
+application root.
+
+To fix this, you need to update Five to version 1.3.5, or update Zope
+to version 2.9.3 (not available of the time of writing this).
+
From reebalazs at codespeak.net Fri May 12 11:17:11 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 11:17:12 2006
Subject: [z3-checkins] r27114 - z3/jsonserver/branch/merge/browser
Message-ID: <20060512091711.71D7110093@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 11:17:10 2006
New Revision: 27114
Modified:
z3/jsonserver/branch/merge/browser/json.js
Log:
Clean up instantiation of JSONMethod
Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js (original)
+++ z3/jsonserver/branch/merge/browser/json.js Fri May 12 11:17:10 2006
@@ -52,21 +52,6 @@
return new json.SupplementWrapper(data, id);
}
-// Direct method creation, by creating an implicit proxy
-// if methodName == '' then the url is taken as full url
-function makeJSONRPCMethod(url, methodName, callback, error, timeout, supplementData,
- requestId, requestManager, user, pass) {
- if (typeof(methodName) == 'undefined' || methodName == null || methodName == '') {
- var pieces = url.split('/');
- methodName = pieces.pop();
- url = pieces.join('/');
- }
- var proxy = new JSONRPC(url);
- proxy.addMethod(methodName, callback, error, timeout, supplementData,
- requestId, requestManager, user, pass);
- return proxy[methodName];
-}
-
function JSONRPC(url) {
this._url = url;
this._methods = new Array();
@@ -79,21 +64,6 @@
}
JSONRPC.prototype.addMethod = function(name, callback, errHandler, timeout, supplementData, requestId, requestManager) {
- if (typeof(errHandler) == 'undefined') {
- errHandler = null;
- }
- if (typeof(timeout) == 'undefined') {
- timeout = null;
- }
- if (typeof(supplementData) == 'undefined') {
- supplementData = null;
- }
- if (typeof(requestId) == 'undefined' || requestId == null) {
- requestId = "jsonRequest";
- }
- if (typeof(requestManager) == 'undefined' || requestManager == null) {
- requestManager = _dummyRequestManager;
- }
var self = this;
if(!self[name]){
var method = new JSONRPCMethod(this._url, name, callback, errHandler, timeout, supplementData, requestId,
@@ -165,6 +135,28 @@
function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId,
requestManager, user, pass) {
+ // Make it possible to call it with no methodName, and just an url.
+ // if methodName == null, it will be figured out from the url.
+ if (typeof(methodName) == 'undefined' || methodName == null || methodName == '') {
+ var pieces = url.split('/');
+ methodName = pieces.pop();
+ url = pieces.join('/');
+ }
+ if (typeof(errHandler) == 'undefined') {
+ errHandler = null;
+ }
+ if (typeof(timeout) == 'undefined') {
+ timeout = null;
+ }
+ if (typeof(supplementData) == 'undefined') {
+ supplementData = null;
+ }
+ if (typeof(requestId) == 'undefined' || requestId == null) {
+ requestId = "jsonRequest";
+ }
+ if (typeof(requestManager) == 'undefined' || requestManager == null) {
+ requestManager = _dummyRequestManager;
+ }
this.methodName = methodName;
this.callback = callback;
this.errHandler = errHandler;
From reebalazs at codespeak.net Fri May 12 19:00:53 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 19:00:54 2006
Subject: [z3-checkins] r27146 - in z3/jsonserver/branch: merge/minjson
zope2_test/minjson
Message-ID: <20060512170053.A0567100BA@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 19:00:51 2006
New Revision: 27146
Added:
z3/jsonserver/branch/merge/minjson/
- copied from r27145, z3/jsonserver/branch/zope2_test/minjson/
Removed:
z3/jsonserver/branch/zope2_test/minjson/
Log:
Relocate minjson to the merge branch
From reebalazs at codespeak.net Fri May 12 19:02:03 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 19:02:04 2006
Subject: [z3-checkins] r27147 - z3/jsonserver/branch/zope2_test
Message-ID: <20060512170203.1FAFF100BA@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 19:02:01 2006
New Revision: 27147
Modified:
z3/jsonserver/branch/zope2_test/ (props changed)
z3/jsonserver/branch/zope2_test/EXTERNALS.TXT
Log:
link to minjson
Modified: z3/jsonserver/branch/zope2_test/EXTERNALS.TXT
==============================================================================
--- z3/jsonserver/branch/zope2_test/EXTERNALS.TXT (original)
+++ z3/jsonserver/branch/zope2_test/EXTERNALS.TXT Fri May 12 19:02:01 2006
@@ -8,4 +8,5 @@
browser http://codespeak.net/svn/z3/jsonserver/branch/merge/browser
concatresource http://codespeak.net/svn/z3/jsonserver/branch/merge/concatresource
utils http://codespeak.net/svn/z3/jsonserver/branch/merge/utils
+minjson http://codespeak.net/svn/z3/jsonserver/branch/merge/minjson
From reebalazs at codespeak.net Fri May 12 19:04:20 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 19:04:22 2006
Subject: [z3-checkins] r27148 - z3/jsonserver/branch/merge
Message-ID: <20060512170420.B25CD100BA@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 19:04:19 2006
New Revision: 27148
Removed:
z3/jsonserver/branch/merge/minjson.py
Modified:
z3/jsonserver/branch/merge/configure.zcml
Log:
Use new minjson
Modified: z3/jsonserver/branch/merge/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/configure.zcml (original)
+++ z3/jsonserver/branch/merge/configure.zcml Fri May 12 19:04:19 2006
@@ -5,6 +5,8 @@
i18n_domain="zope"
>
+
+
Author: reebalazs
Date: Fri May 12 19:13:40 2006
New Revision: 27149
Added:
z3/jsonserver/branch/merge/z2_compatibility/
Log:
add dir
From reebalazs at codespeak.net Fri May 12 19:14:56 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Fri May 12 19:14:57 2006
Subject: [z3-checkins] r27150 - z3/jsonserver/branch/merge/z2_compatibility
Message-ID: <20060512171456.8CCE3100BA@code0.codespeak.net>
Author: reebalazs
Date: Fri May 12 19:14:54 2006
New Revision: 27150
Added:
z3/jsonserver/branch/merge/z2_compatibility/jsonrpc.py
- copied unchanged from r27149, z3/jsonserver/branch/zope2_test/jsonrpc.py
Log:
Copy this to the merge branch
From reebalazs at codespeak.net Sat May 13 10:55:36 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat May 13 10:55:46 2006
Subject: [z3-checkins] r27159 - z3/jsonserver/branch/merge/z2_compatibility
Message-ID: <20060513085536.8F338100AA@code0.codespeak.net>
Author: reebalazs
Date: Sat May 13 10:55:31 2006
New Revision: 27159
Added:
z3/jsonserver/branch/merge/z2_compatibility/configure.zcml
- copied unchanged from r27158, z3/jsonserver/branch/zope2_test/configure.zcml
Log:
Relocation
From reebalazs at codespeak.net Sat May 13 10:55:50 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat May 13 10:55:52 2006
Subject: [z3-checkins] r27160 - z3/jsonserver/branch/merge/z2_compatibility
Message-ID: <20060513085550.4323D100B6@code0.codespeak.net>
Author: reebalazs
Date: Sat May 13 10:55:47 2006
New Revision: 27160
Added:
z3/jsonserver/branch/merge/z2_compatibility/meta.zcml
- copied unchanged from r27159, z3/jsonserver/branch/zope2_test/meta.zcml
Log:
Relocation
From reebalazs at codespeak.net Sat May 13 10:56:03 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat May 13 10:56:05 2006
Subject: [z3-checkins] r27161 - z3/jsonserver/branch/merge/z2_compatibility
Message-ID: <20060513085603.E5488100B2@code0.codespeak.net>
Author: reebalazs
Date: Sat May 13 10:56:01 2006
New Revision: 27161
Added:
z3/jsonserver/branch/merge/z2_compatibility/browserconfigure.py
- copied unchanged from r27160, z3/jsonserver/branch/zope2_test/browserconfigure.py
Log:
Relocation
From reebalazs at codespeak.net Sat May 13 10:57:55 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat May 13 10:57:56 2006
Subject: [z3-checkins] r27162 - z3/jsonserver/branch/merge/z2_compatibility
Message-ID: <20060513085755.19F63100AA@code0.codespeak.net>
Author: reebalazs
Date: Sat May 13 10:57:53 2006
New Revision: 27162
Added:
z3/jsonserver/branch/merge/z2_compatibility/interfaces.py
- copied unchanged from r27161, z3/jsonserver/branch/zope2_test/interfaces.py
Log:
Relocation
From reebalazs at codespeak.net Sat May 13 15:42:36 2006
From: reebalazs at codespeak.net (reebalazs@codespeak.net)
Date: Sat May 13 15:42:37 2006
Subject: [z3-checkins] r27172 - in z3/jsonserver/branch/merge: . minjson
z2_compatibility
Message-ID: <20060513134236.33A8F100AA@code0.codespeak.net>
Author: reebalazs
Date: Sat May 13 15:42:32 2006
New Revision: 27172
Added:
z3/jsonserver/branch/merge/__compat__.py
z3/jsonserver/branch/merge/z2_compatibility/__init__.py
Modified:
z3/jsonserver/branch/merge/__init__.py
z3/jsonserver/branch/merge/configure.zcml
z3/jsonserver/branch/merge/jsonrpc.py
z3/jsonserver/branch/merge/meta.zcml
z3/jsonserver/branch/merge/metaconfigure.py
z3/jsonserver/branch/merge/minjson/configure.zcml
z3/jsonserver/branch/merge/z2_compatibility/configure.zcml
z3/jsonserver/branch/merge/z2_compatibility/jsonrpc.py
z3/jsonserver/branch/merge/z2_compatibility/meta.zcml
Log:
Merge progress. Not yet done.
Added: z3/jsonserver/branch/merge/__compat__.py
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/__compat__.py Sat May 13 15:42:32 2006
@@ -0,0 +1,74 @@
+'''\
+Compatibility configuration switches
+
+This is a transitional solution to attack the problem
+of quickly changing Zope3 and Five apis.
+
+Import checks are done centrally from here.
+The point is that compatibility imports should fail here,
+if anything goes wrong. Components should only check
+the switches set from here.
+
+Supported versions:
+-------------------
+
+Zope 2.9, 2.10
+Zope 3.2, 3.3
+
+Compatibility matrix
+--------------------
+
+The following table shows which Five version can and should be used
+with which Zope 2 and Zope 3 versions.
+
+. Zope 2.8 Zope 2.9 Zope 2.10
+. Zope X3 3.0 Zope 3.2 Zope 3.3
+Five 1.0 included
+Five 1.2 X
+Five 1.3 included
+Five 1.4 X
+Five trunk included
+
+'''
+
+__all__ = ('__compat__', )
+
+class DictLike(object):
+ pass
+
+__compat__ = DictLike()
+
+try:
+ import zope.component.interface
+ import zope.component.location
+ __compat__.zope_pre_3_3 = False
+except ImportError:
+ # The only supported pre_3_3 version is 3.2
+ import zope.app.component.interface
+ import zope.app.location
+ __compat__.zope_pre_3_3 = True
+
+try:
+ import Products.Five
+except ImportError:
+ __compat__.five = False
+else:
+ __compat__.five = True
+ try:
+ # Zope 2.8 / Five 1.0.2
+ from Products.Five.resource import Resource
+ __compat__.five_pre_1_3 = True
+ except ImportError:
+ # Zope 2.9 / Five 1.3
+ from Products.Five.browser.resource import Resource
+ __compat__.five_pre_1_3 = False
+
+# Unsupported versions.
+if __compat__.five and __compat__.five_pre_1_3:
+ raise Exception, 'Zope 2.8 or prior versions (Five 1.2 or prior versions) are unsupported, please upgrade!'
+
+# If running on zope3, make a fake installed product. We need this because
+# there is no negation of zcml:condition="installed Zope2".
+import sys
+if not __compat__.five:
+ sys.modules['not_Zope2'] = sys.modules[globals()['__name__']]
Modified: z3/jsonserver/branch/merge/__init__.py
==============================================================================
--- z3/jsonserver/branch/merge/__init__.py (original)
+++ z3/jsonserver/branch/merge/__init__.py Sat May 13 15:42:32 2006
@@ -1 +1,14 @@
#python package
+
+import __compat__
+
+# Debugging
+#from AccessControl import allow_module
+#allow_module('pdb')
+
+# This is only executed on Zope 2 and ignored of Z3.
+def initialize(context):
+ from z2_compatibility import jsonrpc
+
+ # patches the zpublisher to provide json-rpc
+ jsonrpc.patch_HTTPRequest()
Modified: z3/jsonserver/branch/merge/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/configure.zcml (original)
+++ z3/jsonserver/branch/merge/configure.zcml Sat May 13 15:42:32 2006
@@ -2,11 +2,22 @@
xmlns:jsonrpc="http://namespaces.zope.org/jsonrpc"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:help="http://namespaces.zope.org/help"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="zope"
>
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
Modified: z3/jsonserver/branch/merge/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/merge/jsonrpc.py (original)
+++ z3/jsonserver/branch/merge/jsonrpc.py Sat May 13 15:42:32 2006
@@ -24,12 +24,17 @@
__docformat__ = 'restructuredtext'
+from __compat__ import __compat__
+
from zope.app.publication.http import BaseHTTPPublication
from interfaces import IMethodPublisher, IJSONRPCView, IJSONRPCPublisher,\
IJSONRPCRequest, IJSONReader, IJSONWriter
from zope.interface import implements
#from zope.publisher.http import IResult
-from zope.location.location import Location
+if __compat__.zope_pre_3_3:
+ from zope.app.location import Location
+else:
+ from zope.location.location import Location
from zope.publisher.http import HTTPRequest, HTTPResponse, \
getCharsetUsingRequest, DirectResult
from zope.publisher.browser import BrowserRequest
Modified: z3/jsonserver/branch/merge/meta.zcml
==============================================================================
--- z3/jsonserver/branch/merge/meta.zcml (original)
+++ z3/jsonserver/branch/merge/meta.zcml Sat May 13 15:42:32 2006
@@ -1,5 +1,6 @@
+
+
+
-
+
+
-
+
+
+
+
+
Modified: z3/jsonserver/branch/merge/metaconfigure.py
==============================================================================
--- z3/jsonserver/branch/merge/metaconfigure.py (original)
+++ z3/jsonserver/branch/merge/metaconfigure.py Sat May 13 15:42:32 2006
@@ -20,13 +20,19 @@
updated 2005-12-03 Roger Ineichen
jwashin 2005-06-06
"""
+
+from __compat__ import __compat__
+
import zope.interface
from zope.interface import Interface
from zope.security.checker import CheckerPublic, Checker
from zope.configuration.exceptions import ConfigurationError
from interfaces import IJSONRPCRequest
-from zope.component.interface import provideInterface
+if __compat__.zope_pre_3_3:
+ from zope.app.component.interface import provideInterface
+else:
+ from zope.component.interface import provideInterface
from zope.app.component.metaconfigure import handler
from jsonrpc import MethodPublisher
Modified: z3/jsonserver/branch/merge/minjson/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/minjson/configure.zcml (original)
+++ z3/jsonserver/branch/merge/minjson/configure.zcml Sat May 13 15:42:32 2006
@@ -1,7 +1,7 @@
-
+
-
-
-
-
@@ -38,20 +34,4 @@
-
-
-
-
-
-
-
Modified: z3/jsonserver/branch/merge/z2_compatibility/jsonrpc.py
==============================================================================
--- z3/jsonserver/branch/merge/z2_compatibility/jsonrpc.py (original)
+++ z3/jsonserver/branch/merge/z2_compatibility/jsonrpc.py Sat May 13 15:42:32 2006
@@ -14,7 +14,7 @@
__docformat__ = 'restructuredtext'
-from minjson import read, write, ReadException, WriteException
+from Products.jsonserver.minjson import read, write, ReadException, WriteException
from zExceptions.ExceptionFormatter import format_exception
from StringIO import StringIO
import sys, traceback, re
Modified: z3/jsonserver/branch/merge/z2_compatibility/meta.zcml
==============================================================================
--- z3/jsonserver/branch/merge/z2_compatibility/meta.zcml (original)
+++ z3/jsonserver/branch/merge/z2_compatibility/meta.zcml Sat May 13 15:42:32 2006
@@ -1,7 +1,7 @@
-
+
-
-
From regebro at codespeak.net Mon May 15 12:25:57 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 12:25:59 2006
Subject: [z3-checkins] r27227 - z3/CMFonFive/trunk
Message-ID: <20060515102557.3FC38100B6@code0.codespeak.net>
Author: regebro
Date: Mon May 15 12:25:56 2006
New Revision: 27227
Modified:
z3/CMFonFive/trunk/README.txt
Log:
Noting that 2.9.0 dosn't work.
Modified: z3/CMFonFive/trunk/README.txt
==============================================================================
--- z3/CMFonFive/trunk/README.txt (original)
+++ z3/CMFonFive/trunk/README.txt Mon May 15 12:25:56 2006
@@ -37,11 +37,12 @@
--------
Which version you should download depends on the version of Zope and CMF.
Make sure you match these versions with your CMFonFive version!
-Note that there is no CMFonFive for CMF versions before 1.5.2 on Zope 2.9.
+Note that there is no CMFonFive for CMF versions before 1.5.2 on Zope 2.9
+and no support for Zope 2.9.0.
* CMFonFive 1.3.2 (2006-02-22)
- For CMF 1.5.2 and later, with Zope 2.9.
+ For CMF 1.5.2 and later, with Zope 2.9.1 or 2.9.2.
Requires GenericSetup or CMF 1.6 (Where GenericSetup is included).
http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.2.tgz
From regebro at codespeak.net Mon May 15 18:26:06 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 18:26:07 2006
Subject: [z3-checkins] r27242 - z3/CMFonFive/trunk
Message-ID: <20060515162606.D386810093@code0.codespeak.net>
Author: regebro
Date: Mon May 15 18:26:06 2006
New Revision: 27242
Modified:
z3/CMFonFive/trunk/__init__.py
Log:
Made GenericSetup optional (for 1.5.x support).
Modified: z3/CMFonFive/trunk/__init__.py
==============================================================================
--- z3/CMFonFive/trunk/__init__.py (original)
+++ z3/CMFonFive/trunk/__init__.py Mon May 15 18:26:06 2006
@@ -10,9 +10,7 @@
$Id$
"""
-from Products.GenericSetup import profile_registry, EXTENSION
from Products.CMFCore.utils import ToolInit
-from Products.CMFCore.interfaces import ISiteRoot
import fiveactionstool
def initialize(context):
@@ -22,10 +20,15 @@
, icon='tool.gif'
).initialize( context )
- profile_registry.registerProfile('default',
- 'CMFonFive',
- "Profile for a CMFonFive installation",
- 'profiles/default',
- 'CMFonFive',
- EXTENSION,
- for_=ISiteRoot)
+ try:
+ from Products.GenericSetup import profile_registry, EXTENSION
+ from Products.CMFCore.interfaces import ISiteRoot
+ profile_registry.registerProfile('default',
+ 'CMFonFive',
+ "Profile for a CMFonFive installation",
+ 'profiles/default',
+ 'CMFonFive',
+ EXTENSION,
+ for_=ISiteRoot)
+ except ImportError:
+ pass
From regebro at codespeak.net Mon May 15 18:27:11 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 18:27:12 2006
Subject: [z3-checkins] r27243 - z3/CMFonFive/trunk
Message-ID: <20060515162711.CECAE10093@code0.codespeak.net>
Author: regebro
Date: Mon May 15 18:27:11 2006
New Revision: 27243
Modified:
z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/trunk/README.txt
z3/CMFonFive/trunk/version.txt
Log:
Preparing for release.
Modified: z3/CMFonFive/trunk/CHANGES.txt
==============================================================================
--- z3/CMFonFive/trunk/CHANGES.txt (original)
+++ z3/CMFonFive/trunk/CHANGES.txt Mon May 15 18:27:11 2006
@@ -13,6 +13,8 @@
The reason for this change is that it enables you to add icons with the CMF
ActionIconsTool.
+ - GenericSetup is now optional.
+
CMFonFive 1.3.2 (2006-02-22)
- GenericSetup calls all action providers with both object and info
Modified: z3/CMFonFive/trunk/README.txt
==============================================================================
--- z3/CMFonFive/trunk/README.txt (original)
+++ z3/CMFonFive/trunk/README.txt Mon May 15 18:27:11 2006
@@ -26,44 +26,34 @@
Requirements
------------
-* Zope 2.7 or later.
+* Zope 2.9.1 or later.
-* If you use Zope 2.7 you also need Five 1.0 or 1.1.
-
-* CMF 1.4 or 1.5.
+* CMF 1.5.2 or later.
+ CMF 2.0 does not need CMFonFive.
Download
--------
-Which version you should download depends on the version of Zope and CMF.
-Make sure you match these versions with your CMFonFive version!
-Note that there is no CMFonFive for CMF versions before 1.5.2 on Zope 2.9
-and no support for Zope 2.9.0.
-
-* CMFonFive 1.3.2 (2006-02-22)
- For CMF 1.5.2 and later, with Zope 2.9.1 or 2.9.2.
- Requires GenericSetup or CMF 1.6 (Where GenericSetup is included).
-
- http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.2.tgz
+* CMFonFive 1.3.3 (2006-05-15)
-* CMFonFive 1.2.1 (2006-01-02)
+ For CMF 1.5.2 and later, with Zope 2.9.1, 2.9.2, 2.9.3 and 2.10.0.
- For CMF 1.5.2 and later, with Zope 2.8.
+ http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.3.tgz
- http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.2.1.tgz
-* CMFonFive 1.1.1 (2006-01-02)
+Earlier versions
+----------------
- For CMF 1.4.0 to 1.5.1 with Zope 2.7 or 2.8.
+These earlier versions are deprecated, but if you need CMFonFive for older
+versions of CMF or Zope, you can still download them here:
- http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.1.1.tgz
+* CMFonFive 1.3.2 (2006-02-22)
+ For CMF 1.5.2 and later, with Zope 2.9. Requires GenericSetup or CMF 1.6
+ (Where GenericSetup is included).
-Earlier versions
-----------------
-
-These earlier versions are depracated, as later version have had bugs fixed.
+ http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.2.tgz
* CMFonFive 1.3.1 (2006-02-10)
@@ -77,12 +67,24 @@
http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.0.tgz
+* CMFonFive 1.2.1 (2006-01-02)
+
+ For CMF 1.5.2 and later, with Zope 2.8.
+
+ http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.2.1.tgz
+
* CMFonFive 1.2.0 (2005-07-22)
For CMF 1.5.2 and later, with Zope 2.9.
http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.2.0.tgz
+* CMFonFive 1.1.1 (2006-01-02)
+
+ For CMF 1.4.0 to 1.5.1 with Zope 2.7 or 2.8.
+
+ http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.1.1.tgz
+
* CMFonFive 1.1.0 (2005-06-19)
For CMF 1.4.0 to 1.5.1 with Zope 2.7 or 2.8.
Modified: z3/CMFonFive/trunk/version.txt
==============================================================================
--- z3/CMFonFive/trunk/version.txt (original)
+++ z3/CMFonFive/trunk/version.txt Mon May 15 18:27:11 2006
@@ -1 +1 @@
-CMFonFive-1.3.2+
+CMFonFive-1.3.3
From regebro at codespeak.net Mon May 15 18:28:44 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 18:28:45 2006
Subject: [z3-checkins] r27244 - z3/CMFonFive/trunk
Message-ID: <20060515162844.D605D10093@code0.codespeak.net>
Author: regebro
Date: Mon May 15 18:28:44 2006
New Revision: 27244
Modified:
z3/CMFonFive/trunk/README.txt
Log:
Simplified.
Modified: z3/CMFonFive/trunk/README.txt
==============================================================================
--- z3/CMFonFive/trunk/README.txt (original)
+++ z3/CMFonFive/trunk/README.txt Mon May 15 18:28:44 2006
@@ -37,7 +37,7 @@
* CMFonFive 1.3.3 (2006-05-15)
- For CMF 1.5.2 and later, with Zope 2.9.1, 2.9.2, 2.9.3 and 2.10.0.
+ For CMF 1.5.2 and later, with Zope 2.9.1 or later.
http://codespeak.net/z3/cmfonfive/release/CMFonFive-1.3.3.tgz
From regebro at codespeak.net Mon May 15 18:31:37 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 18:31:39 2006
Subject: [z3-checkins] r27246 - z3/CMFonFive/tag/CMFonFive-1.3.3
Message-ID: <20060515163137.5545A100BD@code0.codespeak.net>
Author: regebro
Date: Mon May 15 18:31:33 2006
New Revision: 27246
Added:
z3/CMFonFive/tag/CMFonFive-1.3.3/
- copied from r27226, z3/CMFonFive/trunk/
z3/CMFonFive/tag/CMFonFive-1.3.3/CHANGES.txt
- copied unchanged from r27243, z3/CMFonFive/trunk/CHANGES.txt
z3/CMFonFive/tag/CMFonFive-1.3.3/README.txt
- copied unchanged from r27244, z3/CMFonFive/trunk/README.txt
z3/CMFonFive/tag/CMFonFive-1.3.3/__init__.py
- copied unchanged from r27242, z3/CMFonFive/trunk/__init__.py
z3/CMFonFive/tag/CMFonFive-1.3.3/version.txt
- copied unchanged from r27243, z3/CMFonFive/trunk/version.txt
Log:
Releasing 1.3.3
From regebro at codespeak.net Mon May 15 18:53:14 2006
From: regebro at codespeak.net (regebro@codespeak.net)
Date: Mon May 15 18:53:15 2006
Subject: [z3-checkins] r27247 - z3/www/trunk
Message-ID: <20060515165314.5BB61100B6@code0.codespeak.net>
Author: regebro
Date: Mon May 15 18:53:13 2006
New Revision: 27247
Modified:
z3/www/trunk/mkwebsite.py
Log:
Added the later CMFonFive releases.
Modified: z3/www/trunk/mkwebsite.py
==============================================================================
--- z3/www/trunk/mkwebsite.py (original)
+++ z3/www/trunk/mkwebsite.py Mon May 15 18:53:13 2006
@@ -209,6 +209,8 @@
Z3ReleaseResource('CMFonFive', 'http://codespeak.net/svn/z3/CMFonFive/tag/CMFonFive-1.2.1'),
Z3ReleaseResource('CMFonFive', 'http://codespeak.net/svn/z3/CMFonFive/tag/CMFonFive-1.3.0'),
Z3ReleaseResource('CMFonFive', 'http://codespeak.net/svn/z3/CMFonFive/tag/CMFonFive-1.3.1'),
+ Z3ReleaseResource('CMFonFive', 'http://codespeak.net/svn/z3/CMFonFive/tag/CMFonFive-1.3.2'),
+ Z3ReleaseResource('CMFonFive', 'http://codespeak.net/svn/z3/CMFonFive/tag/CMFonFive-1.3.3'),
], project.getName())
From gintas at codespeak.net Mon May 15 22:49:39 2006
From: gintas at codespeak.net (gintas@codespeak.net)
Date: Mon May 15 22:49:41 2006
Subject: [z3-checkins] r27253 - z3/z3reload
Message-ID: <20060515204939.D6BC6100C5@code0.codespeak.net>
Author: gintas
Date: Mon May 15 22:49:38 2006
New Revision: 27253
Added:
z3/z3reload/
Log:
Importing z3reload (1/4).
From gintas at codespeak.net Mon May 15 22:49:52 2006
From: gintas at codespeak.net (gintas@codespeak.net)
Date: Mon May 15 22:49:53 2006
Subject: [z3-checkins] r27254 - z3/z3reload/trunk
Message-ID: <20060515204952.A7B41100C5@code0.codespeak.net>
Author: gintas
Date: Mon May 15 22:49:52 2006
New Revision: 27254
Added:
z3/z3reload/trunk/
Log:
Importing z3reload (2/4).
From gintas at codespeak.net Mon May 15 22:51:58 2006
From: gintas at codespeak.net (gintas@codespeak.net)
Date: Mon May 15 22:51:59 2006
Subject: [z3-checkins] r27255 - in z3/z3reload/trunk: . ftests
package-includes
Message-ID: <20060515205158.647F6100C5@code0.codespeak.net>
Author: gintas
Date: Mon May 15 22:51:57 2006
New Revision: 27255
Added:
z3/z3reload/trunk/README.txt (contents, props changed)
z3/z3reload/trunk/__init__.py (contents, props changed)
z3/z3reload/trunk/configure.zcml (contents, props changed)
z3/z3reload/trunk/ftests/
z3/z3reload/trunk/ftests/__init__.py (contents, props changed)
z3/z3reload/trunk/ftests/dynamic.pt (contents, props changed)
z3/z3reload/trunk/ftests/dynamic.py (contents, props changed)
z3/z3reload/trunk/ftests/dynamic_orig.py (contents, props changed)
z3/z3reload/trunk/ftests/ftesting.zcml (contents, props changed)
z3/z3reload/trunk/ftests/reload.txt (contents, props changed)
z3/z3reload/trunk/ftests/tests.py (contents, props changed)
z3/z3reload/trunk/meta.zcml (contents, props changed)
z3/z3reload/trunk/metaconfigure.py (contents, props changed)
z3/z3reload/trunk/metadirectives.py (contents, props changed)
z3/z3reload/trunk/package-includes/
z3/z3reload/trunk/package-includes/z3reload-configure.zcml (contents, props changed)
z3/z3reload/trunk/package-includes/z3reload-ftesting.zcml (contents, props changed)
z3/z3reload/trunk/package-includes/z3reload-meta.zcml (contents, props changed)
z3/z3reload/trunk/reload.py (contents, props changed)
z3/z3reload/trunk/subscriber.py (contents, props changed)
Log:
Importing z3reload (3/4).
Added: z3/z3reload/trunk/README.txt
==============================================================================
--- (empty file)
+++ z3/z3reload/trunk/README.txt Mon May 15 22:51:57 2006
@@ -0,0 +1,118 @@
+z3reload
+========
+
+Version 0.1
+
+http://gintas.pov.lt/z3reload
+
+
+z3reload is a Zope 3 product that enables automatic reloading of view code.
+
+Make sure to read the *pitfalls* section before you delve in.
+
+View instances are short-lived and references to them are stored very
+infrequently, which makes them a good candidate for dynamic reloading.
+In addition they are frequently the largest and most complex part of
+the code in a typical web application. Even within the restrictions of
+this implementation automatic code reloading is very handy to have as Zope 3
+requires a noticeable amount of time to restart.
+
+
+Installation
+------------
+
+Copy the z3reload directory where Zope 3 can find it, copy all files in
+the package-includes/ subdirectory to package-includes/ in Zope 3.
+
+
+Configuration
+-------------
+
+In package-includes/z3reload-configure.zcml (the global one which you created,
+not the one inside the package), the namespace `reload` should be registered,
+like this:
+
+
+
+In the same file you can specify individual classes, modules or packages which
+contain views that should be made reloadable using the ZCML directive
+`reload`. Here is an example:
+
+
+
+This configuration would make views SomeView and AnotherView reloadable.
+All views directly in anotherpackage.views, for example,
+anotherpackage.views.FooView (but not anotherpackage.views.admin.BarView),
+would be included too. Finally, all views in all modules that reside
+in thirdpackage.browser would be processed (thirdpackage.browser.XView,
+thirdpackage.browser.admin.YView, etc.).
+
+
+Usage
+-----
+
+Use the views as you normally would. The view code will be automatically
+reloaded before just before rendering the view each time.
+
+
+Pitfalls
+--------
+
+Only the module that the view code resides in will be reloaded. E.g., if
+you have a view mypackage.browser.admin.AdminView that inherits from
+mypackage.browser.ViewBase, the mypackage.browser module will not be
+reloaded, and therefore changes in ViewBase will not take effect.
+
+It is important to understand the implications of reloading a Python
+module. Basically, all objects -- classes, functions and others --
+defined in the top level of the module "change". Old references
+(frequently in the form of imports) from other modules, however, will
+still point to the old objects. This way you can end up with two
+different references to distinct versions of the same class, which may
+cause unexpected behaviour with issubclass(). A similar problem can arise
+if the module defines interfaces which other modules use.
+
+z3reload can deal with updated views, but it will not notice changes in
+other components: adapters, utilities, subscribers. It will work with
+code outside the components (top-level functions and classes other than
+the registered one) though. This is because Zope 3 stores references to
+the components at startup time. It should be possible to reload these
+components automatically too, but that would probably require a different
+approach, because we would not be able not use the mixin hack.
+
+In general it is a good idea to only use automatic reloading for
+non-structural changes such as defining or modifying methods of views
+and do an old-fashioned server restart when you make a more significant
+change.
+
+
+Implementation details
+----------------------
+
+z3reload waits for the DatabaseOpened event, when all view registration has
+been completed, and then walks through the global adapter registry. For
+each view to be processed according to the `reload` directive it installs
+the mixin Reloader.
+
+Actually, Zope 3 ZCML directives that register views do not register the
+plain view class as a multi-adapter. Instead, they dynamically construct
+a new type which inherits from the given class and from a `simple view` class
+(that would be zope.app.pagetemplate.simpleviewclass.simple for views that
+have page templates defined in ZCML, and
+zope.app.publisher.browser.viewmeta.simple for views that don't). We use
+this fact and add Reloader as the first base class.
+
+Reloader overrides the __init__() method of the real view. In this method
+the module of the class is reloaded and the attribute __bases__ of the class
+is updated with a new reference to the reloaded class. Then __init__ of the
+actual reloaded view is invoked.
+
+
+Gintautas Miliauskas
+2005-08-20
Added: z3/z3reload/trunk/__init__.py
==============================================================================
--- (empty file)
+++ z3/z3reload/trunk/__init__.py Mon May 15 22:51:57 2006
@@ -0,0 +1,2 @@
+# Set this to True to list processed view classes on stderr.
+BLATHER = False
Added: z3/z3reload/trunk/configure.zcml
==============================================================================
--- (empty file)
+++ z3/z3reload/trunk/configure.zcml Mon May 15 22:51:57 2006
@@ -0,0 +1,9 @@
+
+
+
+
+
+
Added: z3/z3reload/trunk/ftests/__init__.py
==============================================================================
Added: z3/z3reload/trunk/ftests/dynamic.pt
==============================================================================
--- (empty file)
+++ z3/z3reload/trunk/ftests/dynamic.pt Mon May 15 22:51:57 2006
@@ -0,0 +1 @@
+