From sidnei at x3ng.com.br Thu May 8 17:15:57 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout/rc - rsyncd.rc.in:NONE Message-ID: <200305082115.h48LFvO09463@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout/rc In directory cvs.zope.org:/tmp/cvs-serv9369/rc Removed Files: rsyncd.rc.in Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/rc/rsyncd.rc.in === From sidnei at x3ng.com.br Thu May 8 17:15:56 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout/bin - zctlinstance.in:NONE zeoctl.in:NONE zopectl.in:NONE Message-ID: <200305082115.h48LFuQ09440@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout/bin In directory cvs.zope.org:/tmp/cvs-serv9369/bin Removed Files: zctlinstance.in zeoctl.in zopectl.in Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/bin/zctlinstance.in === === Removed File NZO_SiteLayout/bin/zeoctl.in === === Removed File NZO_SiteLayout/bin/zopectl.in === From sidnei at x3ng.com.br Thu May 8 17:15:56 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - Makefile.ldap-client:NONE Makefile.ldap-server:NONE Makefile.rsyncd:NONE Makefile.skel:NONE Makefile.squid:NONE Makefile.zinstance:NONE Makefile.zope:NONE Makefile.zss:NONE README.txt:NONE ZopeCtl.py:NONE buildinstance:NONE buildout:NONE cleaninstance:NONE cmf_recipes.mk:NONE cmf_targets.mk:NONE cvs.mk:NONE cvsup:NONE ldap_recipes.mk:NONE ldap_targets.mk:NONE python_recipes.mk:NONE python_targets.mk:NONE rsyncd_recipes.mk:NONE rsyncd_targets.mk:NONE squid_recipes.mk:NONE squid_targets.mk:NONE standard_targets.mk:NONE szodb_recipes.mk:NONE szodb_targets.mk:NONE tools.mk:NONE zeo_recipes.mk:NONE zeo_targets.mk:NONE zinstance_recipes.mk:NONE zinstance_targets.mk:NONE zope_recipes.mk:NONE zope_targets.mk:NONE zproduct_recipes.mk:NONE zproduct_targets.mk:NONE zss_recipes.mk:NONE zss_targets.mk:NONE Message-ID: <200305082115.h48LFue09426@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv9369 Removed Files: Makefile.ldap-client Makefile.ldap-server Makefile.rsyncd Makefile.skel Makefile.squid Makefile.zinstance Makefile.zope Makefile.zss README.txt ZopeCtl.py buildinstance buildout cleaninstance cmf_recipes.mk cmf_targets.mk cvs.mk cvsup ldap_recipes.mk ldap_targets.mk python_recipes.mk python_targets.mk rsyncd_recipes.mk rsyncd_targets.mk squid_recipes.mk squid_targets.mk standard_targets.mk szodb_recipes.mk szodb_targets.mk tools.mk zeo_recipes.mk zeo_targets.mk zinstance_recipes.mk zinstance_targets.mk zope_recipes.mk zope_targets.mk zproduct_recipes.mk zproduct_targets.mk zss_recipes.mk zss_targets.mk Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/Makefile.ldap-client === === Removed File NZO_SiteLayout/Makefile.ldap-server === === Removed File NZO_SiteLayout/Makefile.rsyncd === === Removed File NZO_SiteLayout/Makefile.skel === === Removed File NZO_SiteLayout/Makefile.squid === === Removed File NZO_SiteLayout/Makefile.zinstance === === Removed File NZO_SiteLayout/Makefile.zope === === Removed File NZO_SiteLayout/Makefile.zss === === Removed File NZO_SiteLayout/README.txt === === Removed File NZO_SiteLayout/ZopeCtl.py === === Removed File NZO_SiteLayout/buildinstance === === Removed File NZO_SiteLayout/buildout === === Removed File NZO_SiteLayout/cleaninstance === === Removed File NZO_SiteLayout/cmf_recipes.mk === === Removed File NZO_SiteLayout/cmf_targets.mk === === Removed File NZO_SiteLayout/cvs.mk === === Removed File NZO_SiteLayout/cvsup === === Removed File NZO_SiteLayout/ldap_recipes.mk === === Removed File NZO_SiteLayout/ldap_targets.mk === === Removed File NZO_SiteLayout/python_recipes.mk === === Removed File NZO_SiteLayout/python_targets.mk === === Removed File NZO_SiteLayout/rsyncd_recipes.mk === === Removed File NZO_SiteLayout/rsyncd_targets.mk === === Removed File NZO_SiteLayout/squid_recipes.mk === === Removed File NZO_SiteLayout/squid_targets.mk === === Removed File NZO_SiteLayout/standard_targets.mk === === Removed File NZO_SiteLayout/szodb_recipes.mk === === Removed File NZO_SiteLayout/szodb_targets.mk === === Removed File NZO_SiteLayout/tools.mk === === Removed File NZO_SiteLayout/zeo_recipes.mk === === Removed File NZO_SiteLayout/zeo_targets.mk === === Removed File NZO_SiteLayout/zinstance_recipes.mk === === Removed File NZO_SiteLayout/zinstance_targets.mk === === Removed File NZO_SiteLayout/zope_recipes.mk === === Removed File NZO_SiteLayout/zope_targets.mk === === Removed File NZO_SiteLayout/zproduct_recipes.mk === === Removed File NZO_SiteLayout/zproduct_targets.mk === === Removed File NZO_SiteLayout/zss_recipes.mk === === Removed File NZO_SiteLayout/zss_targets.mk === From sidnei at x3ng.com.br Thu May 8 17:15:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout/var/zope - custom_zodb.py.in:NONE Message-ID: <200305082115.h48LFwP09482@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout/var/zope In directory cvs.zope.org:/tmp/cvs-serv9369/var/zope Removed Files: custom_zodb.py.in Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/var/zope/custom_zodb.py.in === From sidnei at x3ng.com.br Thu May 8 17:15:57 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout/doc - README.txt:NONE Message-ID: <200305082115.h48LFvK09452@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout/doc In directory cvs.zope.org:/tmp/cvs-serv9369/doc Removed Files: README.txt Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/doc/README.txt === From sidnei at x3ng.com.br Thu May 8 17:15:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout/var/ZEOStorage - Storage.py.in:NONE Message-ID: <200305082115.h48LFwH09476@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout/var/ZEOStorage In directory cvs.zope.org:/tmp/cvs-serv9369/var/ZEOStorage Removed Files: Storage.py.in Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Removed File NZO_SiteLayout/var/ZEOStorage/Storage.py.in === From sidnei at x3ng.com.br Thu May 8 17:16:15 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.1 Message-ID: <200305082116.h48LGFV09634@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv9620 Added Files: buildout_zope_sandbox Log Message: Removing old cruft and replacing by a cleaner approach, based on Tres OSCOM script === Added File NZO_SiteLayout/buildout_zope_sandbox === (436/536 lines abridged) #!/bin/sh #============================================================================== # OSCOM 2003: Zope CMS Interoperability Workshop # # Build out a working Zope sandbox from sources. # # - Python and PyXML build from tarballs, because SourceForge won't # do :pserver: CVS reliably. # # - Zope, CMF, and other products build from CVS checkouts. # # Usage: # # Run this script from within an empty "sandbox" directory. # # $ mkdir /tmp/OSCOM # $ cd /tmp/OSCOM # $ /tmp/build_sandbox # # Theory of Operation # # This script creates all the software needed to start a Zope application # server (with the corresponding ZEO storage server); in particular, # it *builds its own Python*, to avoid clashing with the system version, # and to ease installation of packages which Zope depends on. # # It creates the following top-level directories: # # 'src' -- "pristine" sources (from tarballs / CVS checkouts), in # "version-qualified" directories # # 'opt' -- "built" sources (compilation artifacts go here) are in # "version-qualified" directories. The versions in actual # use are symlinked to "standard" names (e.g., 'opt/Python2' # is symlinked to 'opt/Python-2.1.3'). # # 'bin' -- executables are linked here from the 'opt' tree. # # 'etc' -- configuration files for the appserver / storage server. # # 'var' -- log, data, and pid files for running servers. The Zope # INSTANCE_HOME is in 'var/zope'. # # 'tmp' -- fetch directory for tarballs. # # $Id: buildout_zope_sandbox,v 1.1 2003/05/08 21:16:15 sidnei Exp $ #============================================================================== PLATFORM=`uname` echo Building OSCOM Zope sandbox: PLATFORM is $PLATFORM [-=- -=- -=- 436 lines omitted -=- -=- -=-] start_zope () { echo Starting Zope application server echo \$python \$zope_start -X -w \$www_port "\$@" \$python \$zope_start -X -w \$www_port "\$@" } stop_zope () { echo Stopping Zope application server pid=\`cat \$pidfile\` echo kill "\$@" \$pid kill "\$@" \$pid } case "\$1" in start) start_zope ;; stop) stop_zope ;; restart) stop_zope start_zope ;; *) echo "zopectl [ start | stop | restart ]" esac ZOPECTL_EOF chmod +x $bindir/zopectl else # Zope 2.7+ ln -s $vardir/storage/bin/zeoctl . ln -s $vardir/zope/bin/zopectl . fi #------------------------------------------------------------------------------ # Start the storage and the appserver #------------------------------------------------------------------------------ cd $sandbox $bindir/zeoctl start $bindir/zopectl start From sidnei at x3ng.com.br Thu May 29 11:19:06 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.2 Message-ID: <200305291519.h4TFJ6W02002@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv1960 Modified Files: buildout_zope_sandbox Log Message: Added QueueCatalog. Changed Zope to 2.6-branch. Changed ZODB to 3_1-branch. Changed Python to release22-maint. === NZO_SiteLayout/buildout_zope_sandbox 1.1 => 1.2 === PYXML_URL=$PYXML_SF_DOWNLOAD/PyXML-$PYXML_VERSION.tar.gz ZOPE_CVSROOT=:pserver:anonymous@cvs.zope.org:/cvs-repository +PYTHON_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/python ZOPEORG_CVS_REPOSITORY=:pserver:anonymous@cvs.zope.org:/cvs-zopeorg COLLECTIVE_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/collective ZWIKI_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/zwiki @@ -67,21 +68,28 @@ PLONE_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/plone FORMULATOR_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/formulator -ZOPE_VERSION=${ZOPE_VERSION:-2.6.1} # XXX 2.6.2, 2.7? +PYTHON_TAG=release22-maint +PYTHON_MODULE=python/dist/src + +ZOPE_VERSION=${ZOPE_VERSION:-2.6-branch} # XXX 2.6.2, 2.7? ZOPE_MODULE=Zope if [ "$ZOPE_VERSION" == "2.6.1" ]; then ZOPE_TAG=Zope-2-6-1-src +elif [ "$ZOPE_VERSION" == "2.6-branch" ]; then + ZOPE_TAG=Zope-2_6-branch elif [ "$ZOPE_VERSION" == "head" ]; then ZOPE_TAG=HEAD fi -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then - ZODB3_VERSION=${ZODB3_VERSION:-3.1.1} # XXX 3.1.2? +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then + ZODB3_VERSION=${ZODB3_VERSION:-3.1-branch} # XXX 3.1.2? ZODB3_MODULE=ZODB3 if [ "$ZODB3_VERSION" == "3.1.1" ]; then ZODB3_TAG=ZODB3-3-1-1-final + elif [ "$ZODB3_VERSION" == "3.1-branch" ]; then + ZODB3_TAG=ZODB3-3_1-branch elif [ "$ZODB3_VERSION" == "3.1.2" ]; then ZODB3_TAG=ZODB3-3-1-2-final elif [ "$ZODB3_VERSION" == "head" ]; then @@ -119,7 +127,7 @@ DCWORKFLOW_TAG=HEAD fi -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then # DBTab makes managing ZEO ClientStorage simpler under 2.6.* DBTAB_VERSION=${DBTAB_VERSION:-1.2} @@ -137,9 +145,9 @@ # Product Repositories #------------------------------------------------------------------------------ ZopeOrg="$ZOPEORG_CVS_REPOSITORY co -dZopeOrg Products/ZopeOrg-NV" +QueueCatalog="$ZOPEORG_CVSROOT co -dQueueCatalog Products/QueueCatalog" BTreeFolder2="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder2 Products/BTreeFolder2" Rewriter="$ZOPEORG_CVS_REPOSITORY co -dRewriter Products/Rewriter-NV" -CMFDateIndexes="$ZOPEORG_CVS_REPOSITORY co -dCMFDateIndexes Products/CMFDateIndexes-NV" ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki" BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk" CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk" @@ -182,38 +190,11 @@ PYTHON_CONFIGS="$PYTHON_CONFIGS --with-dyld --with-suffix" fi -cd $tmpdir -wget --continue $PYTHON_SOURCE_URL cd $srcdir -tar xzf $tmpdir/Python-$PYTHON_VERSION.tgz - -# -# Work around glitch in remote configure for 2.2.2 -# -if [ "$PYTHON_VERSION" == "2.2.2" ]; then - cd $srcdir/Python-$PYTHON_VERSION - patch Lib/distutils/sysconfig.py << PYTHON_222_DISTUTILS_PATCH_EOF ---- python/python/dist/src/Lib/distutils/sysconfig.py 2002/10/08 14:59:43 1.44.6.2 -+++ python/python/dist/src/Lib/distutils/sysconfig.py 2002/11/26 09:42:57 1.44.6.3 -@@ -29,13 +29,9 @@ - - argv0_path = os.path.dirname(os.path.abspath(sys.executable)) - landmark = os.path.join(argv0_path, "Modules", "Setup") --if not os.path.isfile(landmark): -- python_build = 0 --elif os.path.isfile(os.path.join(argv0_path, "Lib", "os.py")): -- python_build = 1 --else: -- python_build = os.path.isfile(os.path.join(os.path.dirname(argv0_path), -- "Lib", "os.py")) -+ -+python_build = os.path.isfile(landmark) -+ - del argv0_path, landmark - - # set_python_build() was present in 2.2 and 2.2.1; it's not needed -PYTHON_222_DISTUTILS_PATCH_EOF -fi +while ! `cvs -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE`; do + echo "cvs -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE"; + echo "Checking out Python"; +done cd $optdir mkdir -p Python-$PYTHON_VERSION/build @@ -240,12 +221,12 @@ cd $srcdir/PyXML-$PYXML_VERSION patch xml/sax/xmlreader.py << PYXML_081_PATCH_EOF @@ -221,7 +221,7 @@ - + def getSystemId(self): "Returns the system identifier of this InputSource." - return self.__system_id + return str(self.__system_id) - + def setEncoding(self, encoding): """Sets the character encoding of this InputSource. PYXML_081_PATCH_EOF @@ -261,7 +242,7 @@ cd $srcdir cvs -d $ZOPE_CVSROOT co -d Zope-$ZOPE_VERSION -r $ZOPE_TAG $ZOPE_MODULE cd $optdir -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cp -rs $srcdir/Zope-$ZOPE_VERSION . cd Zope-$ZOPE_VERSION $bindir/python wo_pcgi.py @@ -291,7 +272,7 @@ # # Build ZEO INSTANCE_HOME # -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $vardir mkdir -p storage/var else @@ -307,7 +288,7 @@ # # Build Zope INSTANCE_HOME # -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $vardir mkdir -p zope/var zope/Products zope/import zope/Extensions echo Creating initial "manager" account. @@ -325,17 +306,60 @@ # Fetch products. #------------------------------------------------------------------------------ cd $srcdir -cvs -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE -cvs -d $ZopeOrg -cvs -d $BTreeFolder2 -cvs -d $Rewriter -cvs -d $CMFDateIndexes -cvs -d $ZWiki -cvs -d $BackTalk -cvs -d $CMFPlone -cvs -d $Formulator -cvs -d $ExternalEditor -cvs -d $CMFPackage +while ! `cvs -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE`; do + echo "Checking out CMF"; + echo "cvs -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE" +done + +while ! `cvs -d $QueueCatalog`; do + echo "Checking out QueueCatalog"; + echo "cvs -d $QueueCatalog"; +done + +while ! `cvs -d $ZopeOrg`; do + echo "Checking out ZopeOrg"; + echo "cvs -d $ZopeOrg"; +done + +while ! `cvs -d $BTreeFolder2`; do + echo "Checking out BTreeFolder2"; + echo "cvs -d $BTreeFolder2"; +done + +while ! `cvs -d $Rewriter`; do + echo "Checking out Rewriter"; + echo "cvs -d $Rewriter"; +done + +while ! `cvs -d $ZWiki`; do + echo "Checking out ZWiki"; + echo "cvs -d $ZWiki"; +done + +while ! `cvs -d $BackTalk`; do + echo "Checking out BackTalk"; + echo "cvs -d $BackTalk"; +done + +while ! `cvs -d $CMFPlone`; do + echo "Checking out CMFPlone"; + echo "cvs -d $CMFPlone"; +done + +while ! `cvs -d $Formulator`; do + echo "Checking out Formulator"; + echo "cvs -d $Formulator"; +done + +while ! `cvs -d $ExternalEditor`; do + echo "Checking out ExternalEditor"; + echo "cvs -d $ExternalEditor"; +done + +while ! `cvs -d $CMFPackage`; do + echo "Checking out CMFPackage"; + echo "cvs -d $CMFPackage"; +done cd $optdir cp -rs $srcdir/CMF-$CMF_VERSION . @@ -343,11 +367,10 @@ ln -s $srcdir/ZopeOrg . ln -s $srcdir/BTreeFolder2 . ln -s $srcdir/Rewriter . -ln -s $srcdir/CMFDateIndexes . ln -s $srcdir/ZWiki . ln -s $srcdir/BackTalk . ln -s $srcdir/CMFPlone . -ln -s $srcdir/Formulator . +ln -s $srcdir/Formulator . ln -s $srcdir/ExternalEditor . ln -s $srcdir/CMFPackage . @@ -360,7 +383,7 @@ ln -s DCWorkflow-$DCWORKFLOW_VERSION DCWorkflow fi -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $srcdir cvs -d $ZOPE_CVSROOT co -d DBTab-$DBTAB_VERSION -r $DBTAB_TAG $DBTAB_MODULE cd $optdir @@ -380,22 +403,21 @@ ln -s $optdir/ZopeOrg . ln -s $optdir/BTreeFolder2 . ln -s $optdir/Rewriter . -ln -s $optdir/CMFDateIndexes . ln -s $optdir/ZWiki . ln -s $optdir/BackTalk . ln -s $optdir/CMFPlone . -ln -s $optdir/Formulator . +ln -s $optdir/Formulator . ln -s $optdir/ExternalEditor . ln -s $optdir/CMFPackage . -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then ln -s $optdir/DBTab . fi #------------------------------------------------------------------------------ # Set up DBTab #------------------------------------------------------------------------------ -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $vardir/zope ln -s Products/DBTab/custom_zodb.py . cat > $etcdir/dbtab.conf << DBTAB_CONF_EOF @@ -418,7 +440,7 @@ # Set up start / stop scripts #------------------------------------------------------------------------------ -if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6.2" ]; then +if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cat > $bindir/zeoctl << ZEOCTL_EOF #!/bin/sh #------------------------------------------------------------------------------ From sidnei at x3ng.com.br Thu May 29 15:01:35 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.3 Message-ID: <200305291901.h4TJ1Z804518@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv4504 Modified Files: buildout_zope_sandbox Log Message: Reworked the script a bit, to be less verbose === NZO_SiteLayout/buildout_zope_sandbox 1.2 => 1.3 === #------------------------------------------------------------------------------ # Version / repository selectors #------------------------------------------------------------------------------ -PYTHON_VERSION=${PYTHON_VERSION:-2.2.2} # XXX 2.2.3? +PYTHON_VERSION=${PYTHON_VERSION:-2.2.3} PYTHON_ORG=http://www.python.org/ftp/python PYTHON_SOURCE_URL=$PYTHON_ORG/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz -PYXML_VERSION=${PYXML_VERSION:-0.8.1} # 0.8.2? +PYXML_VERSION=${PYXML_VERSION:-0.8.1} PYXML_SF_DOWNLOAD=http://aleron.dl.sourceforge.net/sourceforge/pyxml PYXML_URL=$PYXML_SF_DOWNLOAD/PyXML-$PYXML_VERSION.tar.gz @@ -66,7 +66,8 @@ ZWIKI_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/zwiki BACKTALK_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/backtalk PLONE_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/plone -FORMULATOR_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/formulator +FORMULATOR_CVS_REPOSITORY=:pserver:anonymous@cvs.infrae.com:/cvs/infrae +FORMULATOR_TAG=Formulator-1_4_1 PYTHON_TAG=release22-maint PYTHON_MODULE=python/dist/src @@ -144,17 +145,18 @@ #------------------------------------------------------------------------------ # Product Repositories #------------------------------------------------------------------------------ -ZopeOrg="$ZOPEORG_CVS_REPOSITORY co -dZopeOrg Products/ZopeOrg-NV" -QueueCatalog="$ZOPEORG_CVSROOT co -dQueueCatalog Products/QueueCatalog" -BTreeFolder2="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder2 Products/BTreeFolder2" -Rewriter="$ZOPEORG_CVS_REPOSITORY co -dRewriter Products/Rewriter-NV" -ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki" -BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk" -CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk" -CMFPlone="$PLONE_CVS_REPOSITORY co -dCMFPlone -r${PLONE_TAG} CMFPlone" -Formulator="$FORMULATOR_CVS_REPOSITORY co -dFormulator Formulator" -ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor ExternalEditor" -CMFPackage="$COLLECTIVE_CVS_REPOSITORY co -dCMFPackage CMFPackage" +ZopeOrg="$ZOPEORG_CVS_REPOSITORY co -dZopeOrg Products/ZopeOrg-NV 2&>/dev/null" +QueueCatalog="$ZOPE_CVSROOT co -dQueueCatalog Products/QueueCatalog 2&>/dev/null" +CMFCollector="$ZOPE_CVSROOT co -dCMFCollector CMF/CMFCollector 2&>/dev/null" +BTreeFolder2="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder2 Products/BTreeFolder2 2&>/dev/null" +Rewriter="$ZOPEORG_CVS_REPOSITORY co -dRewriter Products/Rewriter-NV 2&>/dev/null" +ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki 2&>/dev/null" +BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk 2&>/dev/null" +CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk 2&>/dev/null" +CMFPlone="$PLONE_CVS_REPOSITORY co -dCMFPlone -r$PLONE_TAG CMFPlone 2&>/dev/null" +Formulator="$FORMULATOR_CVS_REPOSITORY co -dFormulator -r$FORMULATOR_TAG Formulator 2&>/dev/null" +ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor Products/ExternalEditor 2&>/dev/null" +CMFPackage="$COLLECTIVE_CVS_REPOSITORY co -dCMFPackage CMFPackage 2&>/dev/null" #------------------------------------------------------------------------------ # Build top-level sandbox dirs @@ -191,9 +193,10 @@ fi cd $srcdir -while ! `cvs -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE`; do - echo "cvs -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE"; - echo "Checking out Python"; +echo "Checking out Python"; +echo "cvs -Q -z7 -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE"; +while ! `cvs -Q -z7 -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE 2&>/dev/null`; do + echo -n . done cd $optdir @@ -240,7 +243,7 @@ # Build Zope SOFTWARE_HOME #------------------------------------------------------------------------------ cd $srcdir -cvs -d $ZOPE_CVSROOT co -d Zope-$ZOPE_VERSION -r $ZOPE_TAG $ZOPE_MODULE +cvs -Q -z7 -d $ZOPE_CVSROOT co -d Zope-$ZOPE_VERSION -r $ZOPE_TAG $ZOPE_MODULE cd $optdir if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cp -rs $srcdir/Zope-$ZOPE_VERSION . @@ -251,7 +254,7 @@ # Install ZODB (only needed for Zope 2.6.*). # cd $srcdir - cvs -d $ZOPE_CVSROOT co -d ZODB3-$ZODB3_VERSION -r $ZODB3_TAG $ZODB3_MODULE + cvs -Q -z7 -d $ZOPE_CVSROOT co -d ZODB3-$ZODB3_VERSION -r $ZODB3_TAG $ZODB3_MODULE cd $optdir cp -rs $srcdir/ZODB3-$ZODB3_VERSION . ln -s ZODB3-$ZODB3_VERSION ZODB3 @@ -291,8 +294,8 @@ if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $vardir mkdir -p zope/var zope/Products zope/import zope/Extensions - echo Creating initial "manager" account. - $bindir/python $optdir/Zope/zpasswd.py $vardir/zope/inituser + #echo Creating initial "manager" account. + #$bindir/python $optdir/Zope/zpasswd.py $vardir/zope/inituser else cd $optdir/Zope-$ZOPE_VERSION bin/mkzopeinstance --zeo localhost:8001 $vardir/zope @@ -306,59 +309,76 @@ # Fetch products. #------------------------------------------------------------------------------ cd $srcdir -while ! `cvs -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE`; do - echo "Checking out CMF"; - echo "cvs -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE" +echo "Checking out CMF"; +echo "cvs -Q -z7 -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE" +while ! `cvs -Q -z7 -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE`; do + echo -n . done -while ! `cvs -d $QueueCatalog`; do - echo "Checking out QueueCatalog"; - echo "cvs -d $QueueCatalog"; +echo "Checking out QueueCatalog"; +echo "cvs -Q -z7 -d $QueueCatalog"; +while ! `cvs -Q -z7 -d $QueueCatalog`; do + echo -n . done -while ! `cvs -d $ZopeOrg`; do - echo "Checking out ZopeOrg"; - echo "cvs -d $ZopeOrg"; +echo "Checking out CMFCollector"; +echo "cvs -Q -z7 -d $CMFCollector"; +while ! `cvs -Q -z7 -d $CMFCollector`; do + echo -n . done -while ! `cvs -d $BTreeFolder2`; do - echo "Checking out BTreeFolder2"; - echo "cvs -d $BTreeFolder2"; +echo "Checking out ZopeOrg"; +echo "cvs -Q -z7 -d $ZopeOrg"; +while ! `cvs -Q -z7 -d $ZopeOrg`; do + echo -n . done -while ! `cvs -d $Rewriter`; do - echo "Checking out Rewriter"; - echo "cvs -d $Rewriter"; +echo "Checking out BTreeFolder2"; +echo "cvs -Q -z7 -d $BTreeFolder2"; +while ! `cvs -Q -z7 -d $BTreeFolder2`; do + echo -n . done -while ! `cvs -d $ZWiki`; do - echo "Checking out ZWiki"; - echo "cvs -d $ZWiki"; +echo "Checking out Rewriter"; +echo "cvs -Q -z7 -d $Rewriter"; +while ! `cvs -Q -z7 -d $Rewriter`; do + echo -n . done -while ! `cvs -d $BackTalk`; do - echo "Checking out BackTalk"; - echo "cvs -d $BackTalk"; +echo "Checking out ZWiki"; +echo "cvs -Q -z7 -d $ZWiki"; +while ! `cvs -Q -z7 -d $ZWiki`; do + echo -n . done -while ! `cvs -d $CMFPlone`; do - echo "Checking out CMFPlone"; - echo "cvs -d $CMFPlone"; +echo "Checking out BackTalk"; +echo "cvs -Q -z7 -d $BackTalk"; +while ! `cvs -Q -z7 -d $BackTalk`; do + echo -n . done -while ! `cvs -d $Formulator`; do - echo "Checking out Formulator"; - echo "cvs -d $Formulator"; +echo "Checking out CMFPlone"; +echo "cvs -Q -z7 -d $CMFPlone"; +while ! `cvs -Q -z7 -d $CMFPlone`; do + echo -n . done -while ! `cvs -d $ExternalEditor`; do - echo "Checking out ExternalEditor"; - echo "cvs -d $ExternalEditor"; +echo "Checking out Formulator"; +echo "cvs -Q -z7 -d $Formulator"; +while ! `cvs -Q -z7 -d $Formulator`; do + echo -n . done -while ! `cvs -d $CMFPackage`; do - echo "Checking out CMFPackage"; - echo "cvs -d $CMFPackage"; +echo "Checking out ExternalEditor"; +echo "cvs -Q -z7 -d $ExternalEditor"; +while ! `cvs -Q -z7 -d $ExternalEditor`; do + echo -n . +done + +echo "Checking out CMFPackage"; +echo "cvs -Q -z7 -d $CMFPackage"; +while ! `cvs -Q -z7 -d $CMFPackage`; do + echo -n . done cd $optdir @@ -376,7 +396,7 @@ if [ "$CMF_VERSION" == "1.3.1" -o "$CMF_VERSION" == "1.3-branch" ]; then cd $srcdir - cvs -d $ZOPE_CVSROOT co -d DCWorkflow-$DCWORKFLOW_VERSION \ + cvs -Q -z7 -d $ZOPE_CVSROOT co -d DCWorkflow-$DCWORKFLOW_VERSION \ -r $DCWORKFLOW_TAG $DCWORKFLOW_MODULE cd $optdir cp -rs $srcdir/DCWorkflow-$DCWORKFLOW_VERSION . @@ -385,7 +405,7 @@ if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then cd $srcdir - cvs -d $ZOPE_CVSROOT co -d DBTab-$DBTAB_VERSION -r $DBTAB_TAG $DBTAB_MODULE + cvs -Q -z7 -d $ZOPE_CVSROOT co -d DBTab-$DBTAB_VERSION -r $DBTAB_TAG $DBTAB_MODULE cd $optdir cp -rs $srcdir/DBTab-$DBTAB_VERSION . ln -s DBTab-$DBTAB_VERSION DBTab From sidnei at x3ng.com.br Fri May 30 09:22:17 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.4 Message-ID: <200305301322.h4UDMHV01459@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv1445 Modified Files: buildout_zope_sandbox Log Message: Forgot to link some dirs === NZO_SiteLayout/buildout_zope_sandbox 1.3 => 1.4 === #------------------------------------------------------------------------------ # Product Repositories #------------------------------------------------------------------------------ -ZopeOrg="$ZOPEORG_CVS_REPOSITORY co -dZopeOrg Products/ZopeOrg-NV 2&>/dev/null" -QueueCatalog="$ZOPE_CVSROOT co -dQueueCatalog Products/QueueCatalog 2&>/dev/null" -CMFCollector="$ZOPE_CVSROOT co -dCMFCollector CMF/CMFCollector 2&>/dev/null" -BTreeFolder2="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder2 Products/BTreeFolder2 2&>/dev/null" -Rewriter="$ZOPEORG_CVS_REPOSITORY co -dRewriter Products/Rewriter-NV 2&>/dev/null" -ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki 2&>/dev/null" -BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk 2&>/dev/null" -CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk 2&>/dev/null" -CMFPlone="$PLONE_CVS_REPOSITORY co -dCMFPlone -r$PLONE_TAG CMFPlone 2&>/dev/null" -Formulator="$FORMULATOR_CVS_REPOSITORY co -dFormulator -r$FORMULATOR_TAG Formulator 2&>/dev/null" -ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor Products/ExternalEditor 2&>/dev/null" -CMFPackage="$COLLECTIVE_CVS_REPOSITORY co -dCMFPackage CMFPackage 2&>/dev/null" +ZopeOrg="$ZOPEORG_CVS_REPOSITORY co -dZopeOrg Products/ZopeOrg-NV " +QueueCatalog="$ZOPE_CVSROOT co -dQueueCatalog Products/QueueCatalog " +CMFCollector="$ZOPE_CVSROOT co -dCMFCollector CMF/CMFCollector " +BTreeFolder2="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder2 Products/BTreeFolder2 " +Rewriter="$ZOPEORG_CVS_REPOSITORY co -dRewriter Products/Rewriter-NV " +ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki " +BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk " +CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk " +CMFPlone="$PLONE_CVS_REPOSITORY co -dCMFPlone -r$PLONE_TAG CMFPlone " +Formulator="$FORMULATOR_CVS_REPOSITORY co -dFormulator -r$FORMULATOR_TAG Formulator " +ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor Products/ExternalEditor " +CMFPackage="$COLLECTIVE_CVS_REPOSITORY co -dCMFPackage CMFPackage " #------------------------------------------------------------------------------ # Build top-level sandbox dirs @@ -195,8 +195,8 @@ cd $srcdir echo "Checking out Python"; echo "cvs -Q -z7 -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE"; -while ! `cvs -Q -z7 -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE 2&>/dev/null`; do - echo -n . +while ! `cvs -Q -z7 -d $PYTHON_CVS_REPOSITORY co -d Python-$PYTHON_VERSION -r $PYTHON_TAG $PYTHON_MODULE `; do + echo "Retrying in 30s"; sleep 30; done cd $optdir @@ -312,73 +312,79 @@ echo "Checking out CMF"; echo "cvs -Q -z7 -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE" while ! `cvs -Q -z7 -d $ZOPE_CVSROOT co -d CMF-$CMF_VERSION -r $CMF_TAG $CMF_MODULE`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out QueueCatalog"; echo "cvs -Q -z7 -d $QueueCatalog"; while ! `cvs -Q -z7 -d $QueueCatalog`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out CMFCollector"; echo "cvs -Q -z7 -d $CMFCollector"; while ! `cvs -Q -z7 -d $CMFCollector`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out ZopeOrg"; echo "cvs -Q -z7 -d $ZopeOrg"; while ! `cvs -Q -z7 -d $ZopeOrg`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out BTreeFolder2"; echo "cvs -Q -z7 -d $BTreeFolder2"; while ! `cvs -Q -z7 -d $BTreeFolder2`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out Rewriter"; echo "cvs -Q -z7 -d $Rewriter"; while ! `cvs -Q -z7 -d $Rewriter`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out ZWiki"; echo "cvs -Q -z7 -d $ZWiki"; while ! `cvs -Q -z7 -d $ZWiki`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out BackTalk"; echo "cvs -Q -z7 -d $BackTalk"; while ! `cvs -Q -z7 -d $BackTalk`; do - echo -n . + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out CMFBackTalk"; +echo "cvs -Q -z7 -d $CMFBackTalk"; +while ! `cvs -Q -z7 -d $CMFBackTalk`; do + echo "Retrying in 30s"; sleep 30; done echo "Checking out CMFPlone"; echo "cvs -Q -z7 -d $CMFPlone"; while ! `cvs -Q -z7 -d $CMFPlone`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out Formulator"; echo "cvs -Q -z7 -d $Formulator"; while ! `cvs -Q -z7 -d $Formulator`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out ExternalEditor"; echo "cvs -Q -z7 -d $ExternalEditor"; while ! `cvs -Q -z7 -d $ExternalEditor`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done echo "Checking out CMFPackage"; echo "cvs -Q -z7 -d $CMFPackage"; while ! `cvs -Q -z7 -d $CMFPackage`; do - echo -n . + echo "Retrying in 30s"; sleep 30; done cd $optdir @@ -389,6 +395,9 @@ ln -s $srcdir/Rewriter . ln -s $srcdir/ZWiki . ln -s $srcdir/BackTalk . +ln -s $srcdir/CMFBackTalk . +ln -s $srcdir/CMFCollector . +ln -s $srcdir/QueueCatalog . ln -s $srcdir/CMFPlone . ln -s $srcdir/Formulator . ln -s $srcdir/ExternalEditor . From sidnei at x3ng.com.br Fri May 30 10:56:22 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.5 Message-ID: <200305301456.h4UEuMN15135@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv15121 Modified Files: buildout_zope_sandbox Log Message: Forgot a few more links, and add EVENT_LOG_FILE === NZO_SiteLayout/buildout_zope_sandbox 1.4 => 1.5 === ln -s $optdir/CMF/CMFDefault . ln -s $optdir/CMF/CMFTopic . ln -s $optdir/CMF/CMFCalendar . +ln -s $optdir/CMFBackTalk . +ln -s $optdir/CMFCollector . +ln -s $optdir/QueueCatalog . ln -s $optdir/DCWorkflow . ln -s $optdir/ZopeOrg . ln -s $optdir/BTreeFolder2 . @@ -480,7 +483,8 @@ zeo_start=$optdir/Zope/lib/python/ZEO/start.py INSTANCE_HOME=$vardir/storage -export INSTANCE_HOME +EVENT_LOG_FILE=$INSTANCE_HOME/var/debug.log +export INSTANCE_HOME EVENT_LOG_FILE pidfile=\$INSTANCE_HOME/var/ZEO_SERVER.pid start_zeo () { @@ -533,7 +537,8 @@ INSTANCE_HOME=$vardir/zope SOFTWARE_HOME=\$zope_home/lib/python PYTHONPATH=\$SOFTWARE_HOME:\$PYTHONPATH -export INSTANCE_HOME SOFTWARE_HOME PYTHONPATH +EVENT_LOG_FILE=\$INSTANCE_HOME/var/debug.log +export INSTANCE_HOME SOFTWARE_HOME PYTHONPATH EVENT_LOG_FILE pidfile=\$INSTANCE_HOME/var/Z2.pid start_zope () { From sidnei at x3ng.com.br Fri May 30 11:06:47 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ExternalMount Products/ExternalMount - New directory Message-ID: <200305301506.h4UF6lK16874@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ExternalMount In directory cvs.zope.org:/tmp/cvs-serv16862/ExternalMount Log Message: Directory /cvs-zopeorg/Products/ExternalMount added to the repository === Added directory Products/ExternalMount === From sidnei at x3ng.com.br Fri May 30 11:06:51 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML Products/ParsedXML - New directory Message-ID: <200305301506.h4UF6pE16888@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML In directory cvs.zope.org:/tmp/cvs-serv16876/ParsedXML Log Message: Directory /cvs-zopeorg/Products/ParsedXML added to the repository === Added directory Products/ParsedXML === From sidnei at x3ng.com.br Fri May 30 11:06:56 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PortalBase Products/PortalBase - New directory Message-ID: <200305301506.h4UF6un16909@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PortalBase In directory cvs.zope.org:/tmp/cvs-serv16898/PortalBase Log Message: Directory /cvs-zopeorg/Products/PortalBase added to the repository === Added directory Products/PortalBase === From sidnei at x3ng.com.br Fri May 30 11:07:07 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/Redirector Products/Redirector - New directory Message-ID: <200305301507.h4UF77x17065@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Redirector In directory cvs.zope.org:/tmp/cvs-serv17053/Redirector Log Message: Directory /cvs-zopeorg/Products/Redirector added to the repository === Added directory Products/Redirector === From sidnei at x3ng.com.br Fri May 30 11:07:00 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod Products/PythonMethod - New directory Message-ID: <200305301507.h4UF70K16924@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod In directory cvs.zope.org:/tmp/cvs-serv16912/PythonMethod Log Message: Directory /cvs-zopeorg/Products/PythonMethod added to the repository === Added directory Products/PythonMethod === From sidnei at x3ng.com.br Fri May 30 11:07:10 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/TrackerBase Products/TrackerBase - New directory Message-ID: <200305301507.h4UF7AR17079@cvs.baymountain.com> Update of /cvs-zopeorg/Products/TrackerBase In directory cvs.zope.org:/tmp/cvs-serv17067/TrackerBase Log Message: Directory /cvs-zopeorg/Products/TrackerBase added to the repository === Added directory Products/TrackerBase === From sidnei at x3ng.com.br Fri May 30 11:07:14 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/XMLDocument Products/XMLDocument - New directory Message-ID: <200305301507.h4UF7Eq17092@cvs.baymountain.com> Update of /cvs-zopeorg/Products/XMLDocument In directory cvs.zope.org:/tmp/cvs-serv17081/XMLDocument Log Message: Directory /cvs-zopeorg/Products/XMLDocument added to the repository === Added directory Products/XMLDocument === From sidnei at x3ng.com.br Fri May 30 11:07:18 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ZDBase Products/ZDBase - New directory Message-ID: <200305301507.h4UF7Ir17106@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZDBase In directory cvs.zope.org:/tmp/cvs-serv17095/ZDBase Log Message: Directory /cvs-zopeorg/Products/ZDBase added to the repository === Added directory Products/ZDBase === From sidnei at x3ng.com.br Fri May 30 11:07:57 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/DOM Products/ParsedXML/DOM - New directory Message-ID: <200305301507.h4UF7vh17135@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/DOM In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/DOM Log Message: Directory /cvs-zopeorg/Products/ParsedXML/DOM added to the repository === Added directory Products/ParsedXML/DOM === From sidnei at x3ng.com.br Fri May 30 11:07:57 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/dtml Products/ParsedXML/dtml - New directory Message-ID: <200305301507.h4UF7vm17144@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/dtml In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/dtml Log Message: Directory /cvs-zopeorg/Products/ParsedXML/dtml added to the repository === Added directory Products/ParsedXML/dtml === From sidnei at x3ng.com.br Fri May 30 11:07:57 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/Expat Products/ParsedXML/Expat - New directory Message-ID: <200305301507.h4UF7vw17155@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/Expat In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/Expat Log Message: Directory /cvs-zopeorg/Products/ParsedXML/Expat added to the repository === Added directory Products/ParsedXML/Expat === From sidnei at x3ng.com.br Fri May 30 11:07:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/help Products/ParsedXML/help - New directory Message-ID: <200305301507.h4UF7wX17166@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/help In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/help Log Message: Directory /cvs-zopeorg/Products/ParsedXML/help added to the repository === Added directory Products/ParsedXML/help === From sidnei at x3ng.com.br Fri May 30 11:07:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/NodePath Products/ParsedXML/NodePath - New directory Message-ID: <200305301507.h4UF7w117175@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/NodePath In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/NodePath Log Message: Directory /cvs-zopeorg/Products/ParsedXML/NodePath added to the repository === Added directory Products/ParsedXML/NodePath === From sidnei at x3ng.com.br Fri May 30 11:07:59 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test Products/ParsedXML/test - New directory Message-ID: <200305301507.h4UF7xM17184@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/test Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test added to the repository === Added directory Products/ParsedXML/test === From sidnei at x3ng.com.br Fri May 30 11:08:04 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/www Products/PythonMethod/www - New directory Message-ID: <200305301508.h4UF84Z17333@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/www In directory cvs.zope.org:/tmp/cvs-serv17236/PythonMethod/www Log Message: Directory /cvs-zopeorg/Products/PythonMethod/www added to the repository === Added directory Products/PythonMethod/www === From sidnei at x3ng.com.br Fri May 30 11:08:04 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks Products/PythonMethod/zbytecodehacks - New directory Message-ID: <200305301508.h4UF84117341@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks In directory cvs.zope.org:/tmp/cvs-serv17236/PythonMethod/zbytecodehacks Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks added to the repository === Added directory Products/PythonMethod/zbytecodehacks === From sidnei at x3ng.com.br Fri May 30 11:08:05 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/Redirector/www Products/Redirector/www - New directory Message-ID: <200305301508.h4UF85317383@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Redirector/www In directory cvs.zope.org:/tmp/cvs-serv17357/Redirector/www Log Message: Directory /cvs-zopeorg/Products/Redirector/www added to the repository === Added directory Products/Redirector/www === From sidnei at x3ng.com.br Fri May 30 11:08:06 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/TrackerBase/forms Products/TrackerBase/forms - New directory Message-ID: <200305301508.h4UF86g17405@cvs.baymountain.com> Update of /cvs-zopeorg/Products/TrackerBase/forms In directory cvs.zope.org:/tmp/cvs-serv17386/TrackerBase/forms Log Message: Directory /cvs-zopeorg/Products/TrackerBase/forms added to the repository === Added directory Products/TrackerBase/forms === From sidnei at x3ng.com.br Fri May 30 11:08:37 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/Expat/lib Products/ParsedXML/Expat/lib - New directory Message-ID: <200305301508.h4UF8b817448@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/Expat/lib In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/Expat/lib Log Message: Directory /cvs-zopeorg/Products/ParsedXML/Expat/lib added to the repository === Added directory Products/ParsedXML/Expat/lib === From sidnei at x3ng.com.br Fri May 30 11:08:37 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/NodePath/tests Products/ParsedXML/NodePath/tests - New directory Message-ID: <200305301508.h4UF8bP17458@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/NodePath/tests In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/NodePath/tests Log Message: Directory /cvs-zopeorg/Products/ParsedXML/NodePath/tests added to the repository === Added directory Products/ParsedXML/NodePath/tests === From sidnei at x3ng.com.br Fri May 30 11:08:38 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/domapi Products/ParsedXML/test/domapi - New directory Message-ID: <200305301508.h4UF8ce17467@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/domapi In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/test/domapi Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/domapi added to the repository === Added directory Products/ParsedXML/test/domapi === From sidnei at x3ng.com.br Fri May 30 11:08:38 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/domapi Products/ParsedXML/tests/domapi - New directory Message-ID: <200305301508.h4UF8cg17477@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/domapi In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/tests/domapi Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/domapi added to the repository === Added directory Products/ParsedXML/tests/domapi === From sidnei at x3ng.com.br Fri May 30 11:08:38 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml Products/ParsedXML/tests/xml - New directory Message-ID: <200305301508.h4UF8cm17487@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/tests/xml Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml added to the repository === Added directory Products/ParsedXML/tests/xml === From sidnei at x3ng.com.br Fri May 30 11:08:39 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml Products/ParsedXML/test/xml - New directory Message-ID: <200305301508.h4UF8dh17492@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml In directory cvs.zope.org:/tmp/cvs-serv17431/ParsedXML/test/xml Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml added to the repository === Added directory Products/ParsedXML/test/xml === From sidnei at x3ng.com.br Fri May 30 11:08:41 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/code_gen Products/PythonMethod/zbytecodehacks/code_gen - New directory Message-ID: <200305301508.h4UF8f217534@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/code_gen In directory cvs.zope.org:/tmp/cvs-serv17508/PythonMethod/zbytecodehacks/code_gen Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/code_gen added to the repository === Added directory Products/PythonMethod/zbytecodehacks/code_gen === From sidnei at x3ng.com.br Fri May 30 11:08:42 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc Products/PythonMethod/zbytecodehacks/doc - New directory Message-ID: <200305301508.h4UF8gX17547@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc In directory cvs.zope.org:/tmp/cvs-serv17508/PythonMethod/zbytecodehacks/doc Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc added to the repository === Added directory Products/PythonMethod/zbytecodehacks/doc === From sidnei at x3ng.com.br Fri May 30 11:08:42 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/tests Products/PythonMethod/zbytecodehacks/tests - New directory Message-ID: <200305301508.h4UF8gh17552@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/tests In directory cvs.zope.org:/tmp/cvs-serv17508/PythonMethod/zbytecodehacks/tests Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/tests added to the repository === Added directory Products/PythonMethod/zbytecodehacks/tests === From sidnei at x3ng.com.br Fri May 30 11:07:59 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests Products/ParsedXML/tests - New directory Message-ID: <200305301507.h4UF7x917195@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/tests Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests added to the repository === Added directory Products/ParsedXML/tests === From sidnei at x3ng.com.br Fri May 30 11:07:59 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/www Products/ParsedXML/www - New directory Message-ID: <200305301507.h4UF7x317200@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/www In directory cvs.zope.org:/tmp/cvs-serv17118/ParsedXML/www Log Message: Directory /cvs-zopeorg/Products/ParsedXML/www added to the repository === Added directory Products/ParsedXML/www === From sidnei at x3ng.com.br Fri May 30 11:08:01 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PortalBase/oCVS Products/PortalBase/oCVS - New directory Message-ID: <200305301508.h4UF81317222@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PortalBase/oCVS In directory cvs.zope.org:/tmp/cvs-serv17203/PortalBase/oCVS Log Message: Directory /cvs-zopeorg/Products/PortalBase/oCVS added to the repository === Added directory Products/PortalBase/oCVS === From sidnei at x3ng.com.br Fri May 30 11:09:08 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf Products/ParsedXML/tests/xml/conf - New directory Message-ID: <200305301509.h4UF98w17726@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf In directory cvs.zope.org:/tmp/cvs-serv17707/ParsedXML/tests/xml/conf Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml/conf added to the repository === Added directory Products/ParsedXML/tests/xml/conf === From sidnei at x3ng.com.br Fri May 30 11:09:08 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml/conf Products/ParsedXML/test/xml/conf - New directory Message-ID: <200305301509.h4UF98817729@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml/conf In directory cvs.zope.org:/tmp/cvs-serv17707/ParsedXML/test/xml/conf Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml/conf added to the repository === Added directory Products/ParsedXML/test/xml/conf === From sidnei at x3ng.com.br Fri May 30 11:09:11 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc/diagrams Products/PythonMethod/zbytecodehacks/doc/diagrams - New directory Message-ID: <200305301509.h4UF9BI17753@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/diagrams In directory cvs.zope.org:/tmp/cvs-serv17736/PythonMethod/zbytecodehacks/doc/diagrams Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/diagrams added to the repository === Added directory Products/PythonMethod/zbytecodehacks/doc/diagrams === From sidnei at x3ng.com.br Fri May 30 11:09:11 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc/icons Products/PythonMethod/zbytecodehacks/doc/icons - New directory Message-ID: <200305301509.h4UF9BJ17757@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/icons In directory cvs.zope.org:/tmp/cvs-serv17736/PythonMethod/zbytecodehacks/doc/icons Log Message: Directory /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/icons added to the repository === Added directory Products/PythonMethod/zbytecodehacks/doc/icons === From sidnei at x3ng.com.br Fri May 30 11:11:33 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/BTreeFolder Products/BTreeFolder - New directory Message-ID: <200305301511.h4UFBXx18217@cvs.baymountain.com> Update of /cvs-zopeorg/Products/BTreeFolder In directory cvs.zope.org:/tmp/cvs-serv18206/BTreeFolder Log Message: Directory /cvs-zopeorg/Products/BTreeFolder added to the repository === Added directory Products/BTreeFolder === From sidnei at x3ng.com.br Fri May 30 11:12:43 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml/conf/xmltest Products/ParsedXML/test/xml/conf/xmltest - New directory Message-ID: <200305301512.h4UFChI18394@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest In directory cvs.zope.org:/tmp/cvs-serv18382/ParsedXML/test/xml/conf/xmltest Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest added to the repository === Added directory Products/ParsedXML/test/xml/conf/xmltest === From sidnei at x3ng.com.br Fri May 30 11:12:47 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml/conf/xmltest/sa Products/ParsedXML/test/xml/conf/xmltest/sa - New directory Message-ID: <200305301512.h4UFClk18408@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa In directory cvs.zope.org:/tmp/cvs-serv18397/ParsedXML/test/xml/conf/xmltest/sa Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa added to the repository === Added directory Products/ParsedXML/test/xml/conf/xmltest/sa === From sidnei at x3ng.com.br Fri May 30 11:12:51 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml/conf/xmltest/sa/out Products/ParsedXML/test/xml/conf/xmltest/sa/out - New directory Message-ID: <200305301512.h4UFCp918427@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa/out In directory cvs.zope.org:/tmp/cvs-serv18411/ParsedXML/test/xml/conf/xmltest/sa/out Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa/out added to the repository === Added directory Products/ParsedXML/test/xml/conf/xmltest/sa/out === From sidnei at x3ng.com.br Fri May 30 11:12:51 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut Products/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut - New directory Message-ID: <200305301512.h4UFCpB18432@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut In directory cvs.zope.org:/tmp/cvs-serv18411/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut Log Message: Directory /cvs-zopeorg/Products/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut added to the repository === Added directory Products/ParsedXML/test/xml/conf/xmltest/sa/ParsedXMLTestOut === From sidnei at x3ng.com.br Fri May 30 11:13:21 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest Products/ParsedXML/tests/xml/conf/xmltest - New directory Message-ID: <200305301513.h4UFDLf18578@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest In directory cvs.zope.org:/tmp/cvs-serv18567/ParsedXML/tests/xml/conf/xmltest Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest added to the repository === Added directory Products/ParsedXML/tests/xml/conf/xmltest === From sidnei at x3ng.com.br Fri May 30 11:13:30 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa Products/ParsedXML/tests/xml/conf/xmltest/sa - New directory Message-ID: <200305301513.h4UFDUc18592@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa In directory cvs.zope.org:/tmp/cvs-serv18581/ParsedXML/tests/xml/conf/xmltest/sa Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa added to the repository === Added directory Products/ParsedXML/tests/xml/conf/xmltest/sa === From sidnei at x3ng.com.br Fri May 30 11:13:38 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut - New directory Message-ID: <200305301513.h4UFDc718616@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut In directory cvs.zope.org:/tmp/cvs-serv18595/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut added to the repository === Added directory Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut === From sidnei at x3ng.com.br Fri May 30 11:13:38 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa/out Products/ParsedXML/tests/xml/conf/xmltest/sa/out - New directory Message-ID: <200305301513.h4UFDcb18612@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/out In directory cvs.zope.org:/tmp/cvs-serv18595/ParsedXML/tests/xml/conf/xmltest/sa/out Log Message: Directory /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/out added to the repository === Added directory Products/ParsedXML/tests/xml/conf/xmltest/sa/out === From sidnei at x3ng.com.br Fri May 30 11:17:26 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/BTreeFolder - BTreeFolder.py:1.1 BTreeFolder.pyc:1.1 __init__.py:1.1 __init__.pyc:1.1 contents.dtml:1.1 folderAdd.dtml:1.1 version.txt:1.1 Message-ID: <200305301517.h4UFHQV19232@cvs.baymountain.com> Update of /cvs-zopeorg/Products/BTreeFolder In directory cvs.zope.org:/tmp/cvs-serv19195/BTreeFolder Added Files: BTreeFolder.py BTreeFolder.pyc __init__.py __init__.pyc contents.dtml folderAdd.dtml version.txt Log Message: Adding products needed for migration of NZO === Added File Products/BTreeFolder/BTreeFolder.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## __doc__='''BTreeFolder Product $Id: BTreeFolder.py,v 1.1 2003/05/30 15:17:25 sidnei Exp $''' __version__='$Revision: 1.1 $'[11:-2] from AccessControl import getSecurityManager from OFS.Folder import Folder from BTree import BTree from Globals import HTMLFile from DocumentTemplate.DT_Util import html_quote from urllib import quote from cStringIO import StringIO import Globals manage_addBTreeFolderForm=HTMLFile('folderAdd', globals()) def manage_addBTreeFolder(self, id, title='', type='full', REQUEST=None): """Adds a new BTreeFolder object with id *id*. """ if type == 'full': ob = BTreeFolder() else: ob = BasicBTreeFolder() ob.id=str(id) ob.title=title self._setObject(id, ob) ob=self._getOb(id) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1) def _replaceFolder(parent, id, type='basic'): # Replaces an OFS.Folder with a BTreeFolder. if type == 'full': ob = BTreeFolder() else: ob = BasicBTreeFolder() f = parent._getOb(id) # Copy the contents of the folder to the new BTree folder. ids = f.objectIds() for key, value in f.__dict__.items(): if key not in ids: # Not an ObjectManager item. ob.__dict__[key] = value for key in ids: subob = f._getOb(key) subob = getattr(subob, 'aq_base', subob) ob._setOb(key, subob) parent._setOb(id, ob) listtext0 = ''' ''' _marker = [] # Create a new marker object. class BasicBTreeFolder (Folder): ' ' meta_type = 'Basic BTree Folder' __ac_permissions__=( ('View management screens', ('manage_main', 'manage_main_listing', 'manage_object_workspace',)), ) manage_options=( ({'label':'Contents', 'action':'manage_main',}, ) + Folder.manage_options[1:] ) manage_main = HTMLFile('contents', globals()) def __init__(self): self._tree = BTree() def _getOb(self, id, default=_marker): tree = self._tree if not tree.has_key(id): if default is _marker: raise AttributeError, id return default else: return tree[id].__of__(self) def _setOb(self, id, object): # Saves the object in the BTree instead of the dictionary. tree = self._tree tree[id] = object # May add logic here to make BTreeFolder work as expected with # transparent folders. def _delOb(self, id): # May add logic here to make BTreeFolder work as expected with # transparent folders. tree = self._tree del tree[id] def manage_main_listing(self, REQUEST): '''Generates a select box.''' if REQUEST.has_key('dtpref_rows'): pref_rows = REQUEST['dtpref_rows'] else: pref_rows = 20 rval = StringIO() rval.write(listtext0 % pref_rows) counter = 0 idlist = self.objectIds() idlist.sort() for id in idlist: html_fmt = html_quote(id) rval.write(listtext1 % html_fmt) counter = counter + 1 rval.write(listtext2) return rval.getvalue() def manage_object_workspace(self, REQUEST): '''Redirects to the workspace of the first object in the list.''' ids = REQUEST.get('ids', []) if len(ids) > 0: REQUEST.RESPONSE.redirect( '%s/%s/manage_workspace' % ( self.absolute_url(), quote(ids[0]))) else: return self.manage_main(self, REQUEST) Globals.default__class_init__(BasicBTreeFolder) class BTreeFolder (BasicBTreeFolder): ' ' meta_type = 'BTree Folder' def __getattr__(self, name): # Finds the attribute in the BTree instead of the dictionary. tree = self._tree if tree.has_key(name): ob = tree[name] return ob else: return higher_getattr(self, name) try: higher_getattr = BTreeFolder.inheritedAttribute('__getattr__') except: def higher_getattr(self, name): raise AttributeError, name Globals.default__class_init__(BTreeFolder) === Added File Products/BTreeFolder/BTreeFolder.pyc === === Added File Products/BTreeFolder/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## __doc__='''BTreeFolder Product Initialization $Id: __init__.py,v 1.1 2003/05/30 15:17:25 sidnei Exp $''' __version__='$Revision: 1.1 $'[11:-2] import BTreeFolder def initialize(context): context.registerClass( BTreeFolder.BTreeFolder, constructors=(BTreeFolder.manage_addBTreeFolderForm, BTreeFolder.manage_addBTreeFolder), ) #context.registerHelp() #context.registerHelpTitle('Zope Help') #context.registerBaseClass(BTreeFolder.BTreeFolder) === Added File Products/BTreeFolder/__init__.pyc === *ë ³s>cs9UdZWddd !ZYdkZ[d„ZdS(s]BTreeFolder Product Initialization $Id: __init__.pyc,v 1.1 2003/05/30 15:17:25 sidnei Exp $s$Revision: 1.1 $i iNcs/[]|iti_dtitifƒdS(Ns constructors(scontexts registerClasss BTreeFoldersmanage_addBTreeFolderFormsmanage_addBTreeFolder(scontext((s9/slab/alpha/var/Instance/Products/BTreeFolder/__init__.pys initialize[s(s__doc__s __version__s BTreeFolders initialize(s BTreeFolders __version__s__doc__s initialize((s9/slab/alpha/var/Instance/Products/BTreeFolder/__init__.pys?Us   === Added File Products/BTreeFolder/contents.dtml === Contents

Item count:

There are currently no items in

1">
To add a new item, select an item type .
To add a new item click "Add". ">
=== Added File Products/BTreeFolder/folderAdd.dtml === Add BTreeFolder

Add BTreeFolder

A Folder contains other objects. Use Folders to organize your web objects in to logical groups.

A BTree folder may be able to handle a larger number of objects than a standard folder because it does not need to activate other subobjects in order to access a single subobject.

The form below allows you to create a BTreeFolder. The Create public interface option creates an index_html DTML Method inside the Folder to give the Folder a default HTML representation. The Create user folder option creates a User Folder inside the Folder to hold authorization information for the Folder.

Id
Title
Type Basic (does not implement __getattr__)
Full (implements __getattr__ -- safer but slower)

=== Added File Products/BTreeFolder/version.txt === BTreeFolder-0.1.2 From sidnei at x3ng.com.br Fri May 30 11:17:27 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ExternalMount - ExMountForm.dtml:1.1 ExternalMount.py:1.1 MountedItem.py:1.1 __init__.py:1.1 mountfail.dtml:1.1 Message-ID: <200305301517.h4UFHRJ19252@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ExternalMount In directory cvs.zope.org:/tmp/cvs-serv19195/ExternalMount Added Files: ExMountForm.dtml ExternalMount.py MountedItem.py __init__.py mountfail.dtml Log Message: Adding products needed for migration of NZO === Added File Products/ExternalMount/ExMountForm.dtml === Add External Method Mount Point

Add External Method Mount Point

Create an external method that opens a storage and returns a ZODB.DB object. Enter the module and function name below, along with the path to traverse within the database to reach the object to be mounted.

An example external method:

  import ZODB
  from ZODB.FileStorage import FileStorage

  def createDB():
    return ZODB.DB(FileStorage('/usr/local/zodbs/db1.fs'))
Module
Function
Path
Note that the last name in the path will be used as the id.

=== Added File Products/ExternalMount/ExternalMount.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import Globals, string from MountedItem import MountedItem from Products.ExternalMethod.ExternalMethod import ExternalMethod from OFS.Folder import Folder class ExternalMount(MountedItem): '''A class for mounting a database using an External Method.''' def __init__(self, path, module, function): self.__exm = ExternalMethod('exm', '', module, function) params = (self.__class__.__name__, module, function) MountedItem.__init__(self, path, params) def _createDB(self): '''Calls the external method to create the DB object. ''' return apply(self.__exm, (), {}) manage_addExternalMountForm=Globals.HTMLFile('ExMountForm', globals()) def manage_addExternalMount(self, path, module, function, REQUEST=None): "Mount a Zope database via an ExternalMethod" if not path: raise ValueError, 'No Path given' f = ExternalMount(path, module, function) self = self.this() f._test(self) # Test the connection. self._setObject(f.id, f) if REQUEST is not None: REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main') === Added File Products/ExternalMount/MountedItem.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Mounted database support $Id: MountedItem.py,v 1.1 2003/05/30 15:17:26 sidnei Exp $""" __version__='$Revision: 1.1 $'[11:-2] from Globals import HTMLFile from ZODB.Mount import MountPoint import string import OFS class MountedItem(MountPoint, OFS.SimpleItem.Item): '''A MountPoint with a basic interface for displaying the reason the database did not connect. ''' icon = 'p_/broken' manage_options = ({'label':'Traceback', 'action':'manage_traceback'},) meta_type = 'Broken Mounted Database' def __init__(self, path, params=None): pathItems = string.split(path, '/') self.id = pathItems[-1] path = string.join(pathItems, '/') MountPoint.__init__(self, path, params) manage_traceback = HTMLFile('mountfail', globals()) def mount_error_(self): return self._v_connect_error === Added File Products/ExternalMount/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import ExternalMount def _initialize(context): context.registerClass( ExternalMount.ExternalMount, permission="Mount via External Methods", constructors=(ExternalMount.manage_addExternalMountForm, ExternalMount.manage_addExternalMount), meta_type="Mount via External Method" ) === Added File Products/ExternalMount/mountfail.dtml === Mount Failure Traceback

Mount Failure Traceback

Error type:
Error value:

Database not mounted.
From sidnei at x3ng.com.br Fri May 30 11:17:30 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/NodePath/tests - test_nodepath.py:1.1 Message-ID: <200305301517.h4UFHUw19362@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/NodePath/tests In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/NodePath/tests Added Files: test_nodepath.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/NodePath/tests/test_nodepath.py === import unittest # needed to import NodePath module import sys sys.path.insert(0, '../..') from NodePath import registry def DOMParseString(xml): # FIXME: change this if using another DOM from Products.ParsedXML.StrIO import StringIO from Products.ParsedXML.DOM import ExpatBuilder file = StringIO(xml) return ExpatBuilder.parse(file) class NodePathTestCase(unittest.TestCase): def setUp(self): doc = DOMParseString('''

This is a very trival XML document.

We will test whether our node path facility works with it.

Here is a second chapter, which contains a list.

Foo Bar Baz
''') self._doc = doc def _shotgun_check(self, top_node, node, scheme_name): path = registry.create_path(top_node, node, scheme_name) found = registry.resolve_path(top_node, path) assert found == node, ("Found %s with '%s', wanted %s" % (found, path, node)) cycled_path = registry.create_path(top_node, node, scheme_name) assert path == cycled_path, ("Cycled path %s found, wanted %s" % (cycled_path, path)) for child in node.childNodes: self._shotgun_check(top_node, child, scheme_name) def _shotgun_check_robust(self, top_node, node): path = registry.create_path(top_node, node, 'robust') found = registry.resolve_path(top_node, path) assert found == node, ("Found %s with '%s', wanted %s" % (found, path, node)) # can't cycle path as words are selected randomly for child in node.childNodes: self._shotgun_check_robust(top_node, child) def checkChildPath(self): self._shotgun_check(self._doc, self._doc.documentElement, 'child') def checkElementIdPath(self): self._shotgun_check(self._doc, self._doc.documentElement, 'element_id') def checkRobustPath(self): self._shotgun_check_robust(self._doc, self._doc.documentElement) def checkEmptyPath(self): self.assertEquals('', registry.create_path(self._doc, self._doc, 'child')) self.assertEquals('', registry.create_path(self._doc, self._doc, 'element_id')) #self.assertEquals('', # registry.create_path(self._doc, self._doc, 'robust')) found = registry.resolve_path(self._doc, '') self.assertEquals(self._doc, found) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(NodePathTestCase, "check")) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() From sidnei at x3ng.com.br Fri May 30 11:17:30 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/dtml - DOMTree.dtml:1.1 documentAdd.dtml:1.1 persEdit.dtml:1.1 transEdit.dtml:1.1 Message-ID: <200305301517.h4UFHUq19385@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/dtml In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/dtml Added Files: DOMTree.dtml documentAdd.dtml persEdit.dtml transEdit.dtml Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/dtml/DOMTree.dtml ===

You can view the DOM tree which represents your XML document by using the controls below. Clicking on a node will allow you to edit the contents of the node.

Expand entire tree | Collapse tree | no for... in attributes until issue (15) resolved Show/Hide Attributes | Show/Hide Attributes | Show/Hide text node values Show/Hide text node values


=""
O
 = ""
=== Added File Products/ParsedXML/dtml/documentAdd.dtml ===

A Parsed XML document can contain any well-formed XML text. You can use a Parsed XML document to hold and manipulate structured data in XML format.

You may create a new Parsed XML document using the form below. You may also choose to upload an existing html file from your local computer by clicking the Browse button.

Id
Title
File
Content-type
Parsing with namespaces
yes no
=== Added File Products/ParsedXML/dtml/persEdit.dtml === This form is for a persistent proxy node. It would be cleaner to just include a section specific to the persistent/transient node, but DTML can be tricky.

You may edit the source for this document using the form below. You may also upload the source for this document from a local file. Click the browse button to select a local file to upload.

this is the document not at the document, some things not editable
Title
Content-type
Parsing with namespaces
yes checked> no checked>
Title
Content-type
Parsing with namespaces:
no yes
     
File  
=== Added File Products/ParsedXML/dtml/transEdit.dtml === This form is for a transient proxy node, so some actions aren't present. It would be cleaner to just include a section specific to the persistent/transient node, but DTML can be tricky.

You may edit the source for this document using the form below. You may also upload the source for this document from a local file. Click the browse button to select a local file to upload.

this is the document

This is a transient proxy of the DOM Document node; unlike subnodes, the transient Document can't be edited. The persistent Document proxy can be edited. The persistent Document can be traversed to at /manage_editForm .

Title
Content-type
Parsing with namespaces:
no yes
     
File  
From sidnei at x3ng.com.br Fri May 30 11:17:30 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/NodePath - ElementIdPath.py:1.1 NodePath.py:1.1 README.txt:1.1 RobustPath.py:1.1 __init__.py:1.1 Message-ID: <200305301517.h4UFHUk19357@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/NodePath In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/NodePath Added Files: ElementIdPath.py NodePath.py README.txt RobustPath.py __init__.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/NodePath/ElementIdPath.py === from NodePath import BaseNodePathScheme, registry class ElementIdPathScheme(BaseNodePathScheme): def __init__(self, scheme_name=None): scheme_name = scheme_name or 'element_id' BaseNodePathScheme.__init__(self, scheme_name) def resolve_steps(self, top_node, steps): node = top_node for step in steps: if step[0] == 'e': element_id = int(step[1:]) for child in node.childNodes: if self.get_element_id(child) == element_id: node = child break else: # couldn't find node with such element_id return None else: node = node.childNodes.item(int(step)) if node is None: return None return node # return node def create_steps(self, top_node, node): steps = [] while node is not top_node: parent = node.parentNode if parent is None: break element_id = self.get_element_id(node) if element_id != -1: steps.append("e%s" % element_id) else: steps.append(str(parent.childNodes.index(node))) node = parent steps.reverse() return steps def get_element_id(self, node): return getattr(node, 'elementId', -1) === Added File Products/ParsedXML/NodePath/NodePath.py === import string class NodePathError(Exception): pass class NodePathSchemeRegistry: def __init__(self): self._schemes = {} def register_scheme(self, scheme): self._schemes[scheme._scheme_name] = scheme def resolve_steps(self, top_node, steps, scheme_name): """Resolve steps from top_node. """ # if we don't know scheme, return None as node could not be found if not self._schemes.has_key(scheme_name): raise NodePathError, "Unknown scheme: %s" % scheme_name # we do know the scheme, so look it up scheme = self._schemes[scheme_name] # now resolve steps using this scheme return scheme.resolve_steps(top_node, steps) def resolve_path(self, top_node, path): """Resolve path. """ if not path: return top_node steps = string.split(path, ',') # get scheme as first element of path scheme_name, steps = steps[0], steps[1:] # resolve steps using scheme return self.resolve_steps(top_node, steps, scheme_name) def create_steps(self, top_node, node, scheme_name): """Construct steps tuple to node. """ return self._schemes[scheme_name].create_steps(top_node, node) def create_path(self, top_node, node, scheme_name): """Construct path to node according to scheme_name. """ steps = self.create_steps(top_node, node, scheme_name) if not steps: return '' return '%s,%s' % (scheme_name, string.join(steps, ',')) class BaseNodePathScheme: def __init__(self, scheme_name): self._scheme_name = scheme_name def resolve_steps(self, top_node, steps): """Resolve path from top_node, return node found or None. Steps are in order top_node to node. """ pass def create_steps(self, top_node, node): """Return list of steps from top_node to node. Steps returned are in reverse order. """ pass class ChildNodePathScheme(BaseNodePathScheme): def __init__(self): BaseNodePathScheme.__init__(self, 'child') def resolve_steps(self, top_node, steps): node = top_node for step in steps: node = node.childNodes.item(int(step)) if node is None: return None return node # return node def create_steps(self, top_node, node): steps = [] # FIXME: is it safe to compare nodes like this? while node is not top_node: parent = node.parentNode if parent is None: break # FIXME: can index() be used in all python DOMs? steps.append(str(parent.childNodes.index(node))) node = parent steps.reverse() return steps # create the registry registry = NodePathSchemeRegistry() === Added File Products/ParsedXML/NodePath/README.txt === Everything in this directory, including the tests subdirectory, should work independently of ParsedXML and with another Python DOM as well. The only change necessary should be to the DOM loading in the unit tests subdir. === Added File Products/ParsedXML/NodePath/RobustPath.py === from NodePath import BaseNodePathScheme, NodePathError import random, string, urllib import xml.dom words_amount = 5 class RobustPathScheme(BaseNodePathScheme): def __init__(self): BaseNodePathScheme.__init__(self, 'robust') def resolve_steps(self, top_node, steps): steps, type_step, context_step = steps[:-2], steps[-2], steps[-1] rsteps = [] # create element steps for step in steps: nodeName, nodeIndex = string.split(step, "*") rsteps.append(GenericStep(xml.dom.Node.ELEMENT_NODE, nodeName, int(nodeIndex))) # now create type and context end steps context_parts = string.split(context_step, "*") node_type, nodeIndex = string.split(type_step, "*") nodeIndex = int(nodeIndex) if node_type == 'element': type_rstep = GenericStep(xml.dom.Node.ELEMENT_NODE, context_parts[0], nodeIndex) context_rstep = ElementEndStep(int(context_parts[1]), int(context_parts[2])) elif node_type == 'text': type_rstep = GenericStep(xml.dom.Node.TEXT_NODE, "#text", nodeIndex) words = [] for i in range(0, len(context_parts), 2): words.append((urllib.unquote(context_parts[i]), int(context_parts[i + 1]))) context_rstep = TextEndStep(words) elif node_type == 'empty': type_rstep = GenericStep(xml.dom.Node.TEXT_NODE, "#text", nodeIndex) context_rstep = EmptyTextEndStep() elif node_type == 'other': raise NodePathError, "Cannot handle other path elements yet." else: raise NodePathError, "Unknown step type in path: %s" % node_type rsteps.append(type_rstep) rsteps.append(context_rstep) # resolve the steps, starting with step 0 context = Context(0, rsteps) node, level = rsteps[0].resolve(context, top_node, 0) return node def create_steps(self, top_node, node): # first create last two steps parent = node.parentNode steps = self.create_end_steps(parent, node) node = parent # now create element steps while node is not top_node: parent = node.parentNode if parent is None: break steps.append(self.create_element_step(parent, node)) node = parent steps.reverse() return steps def create_end_steps(self, parent, node): nodeType = node.nodeType if nodeType == node.ELEMENT_NODE: return ['%s*%s*%s' % (node.nodeName, len(node.attributes), len(node.childNodes)), 'element*%s' % parent.childNodes.index(node) ] elif nodeType == node.TEXT_NODE: if string.strip(node.data) == '': return ['empty', 'empty*%s' % parent.childNodes.index(node)] else: return [string.join(get_words_sample(node.data), "*"), 'text*%s' % parent.childNodes.index(node)] else: # FIXME: simplistic way to deal with other nodes return ['%s' % node.nodeType, 'other*%s' % parent.childNodes.index(node)] def create_element_step(self, parent, node): return "%s*%s" % (node.nodeName, parent.childNodes.index(node)) class Context: threshold = 30 success_threshold = 10 offset_unreliability = 3 tree_skip_unreliability = 3 step_skip_unreliability = 3 word_max_distance = 7 word_offset_unreliability = 2 def __init__(self, i, steps): self._i = i self._steps = steps def resolve_next(self, node, level): steps = self._steps i = self._i + 1 if i < len(steps): # prepare new context for next step context = Context(i, steps) # resolve the next step return steps[i].resolve(context, node, level) else: return node, level class GenericStep: def __init__(self, nodeType, nodeName, index): self._nodeType = nodeType self._nodeName = nodeName self._index = index def resolve(self, context, node, level): nodeType = self._nodeType nodeName = self._nodeName i = self._index childNodes = node.childNodes l = len(childNodes) results = [] # try if the indicate node is the one, if so, return it if i < l: current = childNodes[i] if (current.nodeType == nodeType and current.nodeName == nodeName): current_node, current_unreliability = context.resolve_next( current, level) if current_unreliability < context.success_threshold: return current_node, current_unreliability results.append((current_node, current_unreliability)) # we need to go forward and backward from position i forward_i = i + 1 backward_i = i - 1 can_go_forward = can_go_backward = 1 else: # i is beyond length, so we need to go backward from end backward_i = l - 1 forward_i = l can_go_forward = 0 can_go_backward = 1 # try nodes forward and backward of this one unreliability = level + context.offset_unreliability while ((can_go_forward or can_go_backward) and unreliability < context.threshold): if forward_i < l: current = childNodes[forward_i] if (current.nodeType == nodeType and current.nodeName == nodeName): current_node, current_unreliability = context.resolve_next( current, unreliability) if current_unreliability < context.success_threshold: return current_node, current_unreliability results.append((current_node, current_unreliability)) forward_i = forward_i + 1 else: can_go_forward = 0 if backward_i >= 0: current = childNodes[backward_i] if (current.nodeType == nodeType and current.nodeName == nodeName): current_node, current_unreliability = context.resolve_next( current, unreliability) if current_unreliability < context.success_threshold: return current_node, current_unreliability results.append((current_node, current_unreliability)) backward_i = backward_i - 1 else: can_go_backward = 0 unreliability = unreliability + context.offset_unreliability # try skipping level in the tree unreliability = level + context.tree_skip_unreliability if unreliability < context.threshold: for current in childNodes: # use same step but with next nodes current_node, current_unreliability = self.resolve( context, current, unreliability) if current_unreliability < context.success_threshold: return current_node, current_unreliability results.append((current_node, current_unreliability)) # try skipping this step # use same node but with next step unreliability = level + context.step_skip_unreliability if unreliability < context.threshold: current_node, current_unreliability = context.resolve_next( node, unreliability) if current_unreliability < context.success_threshold: return current_node, current_unreliability results.append((current_node, current_unreliability)) # no immediate success, so try the best branch best_unreliability = context.threshold best_node = None for found_node, found_unreliability in results: if found_unreliability < best_unreliability: best_unreliability = found_unreliability best_node = found_node return best_node, best_unreliability class ElementEndStep: """Not very robust, but representable in a url pretty easily. """ def __init__(self, attributeAmount, childAmount): self._attributeAmount = attributeAmount self._childAmount = childAmount def resolve(self, context, node, level): if node.nodeType != node.ELEMENT_NODE: return None, context.threshold if (len(node.attributes) != self._attributeAmount or len(node.childNodes) != self._childAmount): return None, context.threshold return node, level class EmptyTextEndStep: def resolve(self, context, node, level): if node.nodeType != node.TEXT_NODE: return None, context.threshold if string.strip(node.data) == "": return node, level return None, context.threshold class TextEndStep: def __init__(self, words): self._words = words def resolve(self, context, node, level): if node.nodeType != node.TEXT_NODE: return None, context.threshold words = string.split(node.data) if len(words) == 0: return None, context.threshold unreliability = level for word, nr in self._words: unreliability = unreliability + ( find_word_distance(words, word, nr, context.word_max_distance) * context.word_offset_unreliability ) if unreliability >= context.threshold: return None, context.threshold return node, unreliability def find_word_distance(words, word, i, max_distance): """Find distance of word in words from expected location i. If word could not be found or is further than max_distance, return -1. """ try: if words[i] == word: return 0 except IndexError: l = len(words) distance = i - l + 1 forward_i = l backward_i = l - 1 can_go_forward = 0 can_go_backward = 1 else: l = len(words) distance = 1 forward_i = i + 1 backward_i = i - 1 can_go_forward = can_go_backward = 1 while (can_go_forward or can_go_backward) and (distance < max_distance): if forward_i < l: if words[forward_i] == word: return distance forward_i = forward_i + 1 else: can_go_forward = 0 if backward_i >= 0: if words[backward_i] == word: return distance backward_i = backward_i - 1 else: can_go_backward = 0 distance = distance + 1 return max_distance def get_words_sample(text, words_amount=words_amount, quote=urllib.quote): words = string.split(text) result = [] if len(words) <= words_amount: # get all words if there are only a few for i in range(len(words)): # don't add any words with separator in it, so as not to confuse if "*" not in words[i] and "," not in words[i]: qword = quote(words[i]) result.append(qword + "*" + str(i)) else: # otherwise, take a random sample of words from the text nrs = [] l = len(words) - 1 for i in range(words_amount): while 1: r = random.randint(0, l) # if we selected new word from sample, done # NOTE: would introduce subtle bug if we checked for # * or , here if r not in nrs: break nrs.append(r) nrs.sort() for nr in nrs: # don't want any word with separator in it if "*" not in words[nr] and "," not in words[nr]: qword = quote(words[nr]) result.append(qword + "*" + str(nr)) return result === Added File Products/ParsedXML/NodePath/__init__.py === import NodePath, RobustPath, ElementIdPath from NodePath import registry, BaseNodePathScheme registry.register_scheme(NodePath.ChildNodePathScheme()) registry.register_scheme(RobustPath.RobustPathScheme()) registry.register_scheme(ElementIdPath.ElementIdPathScheme()) From sidnei at x3ng.com.br Fri May 30 11:17:34 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf - README.ParsedXML:1.1 Message-ID: <200305301517.h4UFHYw19535@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/xml/conf Added Files: README.ParsedXML Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/xml/conf/README.ParsedXML === These tests are from the Oasis Open conformance suite, found at . From sidnei at x3ng.com.br Fri May 30 11:17:34 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml - 4ohn4ktj.xml:1.1 Message-ID: <200305301517.h4UFHYs19528@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/xml Added Files: 4ohn4ktj.xml Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/xml/4ohn4ktj.xml ===
sample1 a simple invoice
01786 2000-03-17 55377 2000-03-15 GJ03405 DAVE 1 2000-03-17 K5211(34) 23 23
SHIPWRIGHT RESTAURANTS LIMITED 125 NORTH SERVICE ROAD W WESTLAKE ACCESS NORTH BAY L8B1O5 ONTARIO CANADA ATTN: PAULINE DEGRASSI 1 CS DM 5309 #1013 12 OZ.MUNICH STEIN 37.72 37.72 6 DZ ON 6420 PROVINCIAL DINNER FORK 17.98 107.88 72 EA JR20643 PLASTIC HANDLED STEAK KNIFE .81 58.32 6 DZ ON 6410 PROVINCIAL TEASPOONS 12.16 72.96 0 DZ ON 6411 PROVINCIAL RD BOWL SPOON 6 17.98 0.00 1 EA DO 3218 34 OZ DUAL DIAL SCALE AM3218 70.00 5.0 66.50 1 CS DM 195 20 OZ.BEER PUB GLASS 55.90 55.90 399.28 3.50 23.75 29.61 33.84 33.84 486.48
From sidnei at x3ng.com.br Fri May 30 11:17:31 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/help - Core.py:1.1 ExpatBuilder.py:1.1 ExtraDOM.py:1.1 ManageableDOM.py:1.1 ParsedXML:1.1 ParsedXML.stx:1.1 ParsedXML_DOM.stx:1.1 ParsedXML_Edit.stx:1.1 ParsedXML_Raw.stx:1.1 ParsedXML_Security.stx:1.1 ParsedXML_URLTraversal.stx:1.1 ParsedXML_Upload.stx:1.1 Printer.py:1.1 Traversal.py:1.1 XMLExtended.py:1.1 Message-ID: <200305301517.h4UFHVH19439@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/help In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/help Added Files: Core.py ExpatBuilder.py ExtraDOM.py ManageableDOM.py ParsedXML ParsedXML.stx ParsedXML_DOM.stx ParsedXML_Edit.stx ParsedXML_Raw.stx ParsedXML_Security.stx ParsedXML_URLTraversal.stx ParsedXML_Upload.stx Printer.py Traversal.py XMLExtended.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/help/Core.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ DOM Level 2 Core classes. Classes and interfaces are made available according to the Python language mapping for the IDL interfaces described by the DOM recommendation; see for the mapping specification and for the IDL interfaces. """ === Added File Products/ParsedXML/help/ExpatBuilder.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ XML to DOM building methods using Expat. """ def parse(file, namespaces=1): """Parse a document, returning the resulting Document node. 'file' may be either a file name or an open file object. """ def parseFragment(file, context, namespaces=1): """Parse a fragment of a document, given the context from which it was originally extracted. context should be the parent of the node(s) which are in the fragment. 'file' may be either a file name or an open file object. """ === Added File Products/ParsedXML/help/ExtraDOM.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ Non-DOM helper functions. Useful when working with either of our DOM implementations, but not specific to any instantiation. """ def parseFile(node, file, namespaces = 1): """ Parse XML file, replace node with the resulting tree, return replacement. Node must be in an existing DOM tree if not a Document. """ def writeStream(node, stream = None, encoding = None): "Write the XML representation of node to stream." === Added File Products/ParsedXML/help/ManageableDOM.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ DOM proxying classes which provide Zope support. """ class DOMPublishable: "Mixin class for DOM classes to provide Zope publishability." def tpURL(self): """ Return a string used for an URL relative to parent. Used by the dtml-tree tag. """ def tpValues(self): "Return a list of immediate subobjects. Used by the dtml-tree tag." def tpId(self): "Return a value to be used as an id in tree state." def __getitem__(self, key): "" def manage_FTPget(self): """Returns the source content of an object. For example, the source text of a Document, or the data of a file.""" class DOMIO: "Mixin class for DOM classes to provide parsing, writing." def writeStream(self, stream = None, encoding = None): "Write the XML representation of this object to stream." def __str__(self): "Return the XML representation of this object." def get_size(self): "Size of this tree or subtree in bytes." def index_html(self, REQUEST, RESPONSE): "Returns publishable raw XML source" def parseXML(self, file): "Parse file as XML, replace myself with the resulting tree." class DOMManageable: "Mixin class for DOM classes to provide Zope management interfaces." def manage_edit(self, data, title = '', SUBMIT = 'Change', dtpref_cols = '50', dtpref_rows = '20', REQUEST = None): """ If SUBMIT is a size pref variable, handle a textarea size change. Otherwise parse the given text and handle the result. """ def manage_upload(self, file, REQUEST=None): "Parse the given file and handle the result." class ManageableWrapper: """ Mixin class to go alongside ManageableNode classes. Provides the wrapDOMObj function to create ManageableNode classes. """ def wrapDOMObj(self, node): "Return the appropriate manageable class wrapped around the Node." class ManageableDOMImplementation: """ A proxy of a DOMImplementation node that defines createDocument to return a ManageableDocument. """ class ManageableNode: "A wrapper around a DOM Node." class ManageableNodeList: "A wrapper around a DOM NodeList." class ManageableNamedNodeMap: "A wrapper around a DOM NamedNodeMap." class ManageableDocumentFragment: "A wrapper around a DOM DocumentFragment." class ManageableElement: "A wrapper around a DOM Element." class ManageableCharacterData: "A wrapper around a DOM CharacterData." class ManageableCDATASection: "A wrapper around a DOM CDATASection." class ManageableText: "A wrapper around a DOM Text." class ManageableComment: "A wrapper around a DOM Comment." class ManageableProcessingInstruction: "A wrapper around a DOM ProcessingInstruction." class ManageableAttr: "A wrapper around a DOM Attr." class ManageableDocument: "A wrapper around a DOM Document." class ManageableEntityReference: "A wrapper around a DOM EntityReference." class ManageableEntity: "A wrapper around a DOM Entity." class ManageableNotation: "A wrapper around a DOM Notation." class ManageableDocumentType: "A wrapper around a DOM DocumentType." === Added File Products/ParsedXML/help/ParsedXML === ParsedXML: Store XML as DOM objects Description ParsedXML products are DOM storage objects that support input and output in XML format, as well as DOM editing and discovery methods. === Added File Products/ParsedXML/help/ParsedXML.stx === ParsedXML: Store XML as DOM objects Description Parsed XML products are DOM storage objects that support input and output in XML format, as well as DOM editing and discovery methods. Parsed XML nodes are URL addressable, as are the argumentless DOM methods, and editable as XML. For more information, see the README file included with the distribution, or visit the Parsed XML "wiki":http://www.zope.org/Wikis/DevSite/Projects/ParsedXML. === Added File Products/ParsedXML/help/ParsedXML_DOM.stx === ParsdXML - DOM: View DOM tree Description This view shows the tree of DOM nodes that is rooted at this node. Clicking on a node will bring you to its management screen. At the top of the screen is a clickable "breadcrumbs" style path with links to ancestors of this node. === Added File Products/ParsedXML/help/ParsedXML_Edit.stx === ParsedXML - Edit: Edit and Upload XML Description This view allows you to alter the tree at a particular node by either editing the XML source or replacing the XML source with an uploaded file. An XML representation of the DOM tree is presented in a textarea. When the "Change" button is pressed, the XML in the textarea is parsed. Alternately, you can select a file from your local computer. When it is uploaded, it will be parsed. If the parse succeeds, the node that is being edited will be replaced with the parsed tree. If the parse fails, you will be presented with an error message. Note that because the storage uses DOM objects, rather than XML strings, the XML output after parsing may not be exactly the XML input, although it will be functionally the same and will follow the XML Infoset specification. The title, content type, and namespace usage are displayed. These values can be changed if the view is being displayed by the persistent version of the document, and not a transient version - currently, navigating to the top node using ownerDocument DOM calls reaches the persistent document. The title is the Zope title and does not affect the source. The content type will be returned by the HTTP server with the default publishing view index_html; receiving agents can act on this. A content type ending in "/html" will also cause index_html to use the HTML format. This doesn't affect the document content, just the rendering. Differences in HTML and XML formats are described at the "HTML Compatibility Guidelines":"http://www.w3.org/TR/xhtml1/#guidelines" Namespace usage affects which DOM calls are useful and which names are legal. === Added File Products/ParsedXML/help/ParsedXML_Raw.stx === ParsedXML - Raw: Download unformatted XML Description Clicking on the Raw tab will send the XML source for that node to your browser, unformatted, with a content-type of 'text/xml'. This is also the index_html method, so navigating to a node without a different view will also download the source. === Added File Products/ParsedXML/help/ParsedXML_Security.stx === ParsedXML - Security: About security settings for Parsed XML Description All Parsed XML security is handled by the document. Security settings for subnodes will be acquired from the document. The "Access contents information" setting will determine who can access DOM methods, including the ability to traverse to subnodes. === Added File Products/ParsedXML/help/ParsedXML_URLTraversal.stx === ParsedXML - URLTraversal: About URL accessibility of Parsed XML objects Description Currently, traversal uses an element's index within its parent as an URL key. For example, 'http://server/myDoc/0/2/mymethod' This URL traverses from an XML Document object with id 'myDoc' to it's first sub-element, to that element's second sub-element, and then to an acquired method with id 'myMethod' DOM methods can also be used in URLs, for example, 'http://server/myDoc/firstChild/nextSibling/mymethod' === Added File Products/ParsedXML/help/ParsedXML_Upload.stx === ParsedXML - Upload: Upload XML Description This view allows you to upload XML source at a particular node. A file can be chosen from your local computer. When it is uploaded, it will be parsed. If the parse succeeds, the node that the upload is calle on will be replaced with the parsed tree. If the parse fails, you will be presented with an error message. === Added File Products/ParsedXML/help/Printer.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## # # Specifically, most of this code is from PyXML's xml.dom.ext.Printer. # See LICENSE.Fourthought. # """ Printing and XML generating support for DOM classes. """ class Visitor: """A class to visit an entire tree according to a TreeWalker.""" def __init__(self, root, stream, encoding, whatToShow, filter, entityReferenceExpansion): "Init the walker." def visitWhole(self): "Visit the entire tree rooted at our current node." class PrintVisitor(Visitor): """A class to generate XML for a tree according to a TreeWalker""" === Added File Products/ParsedXML/help/Traversal.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ DOM Level 2 Traversal classes. Classes and interfaces are made available according to the Python language mapping for the IDL interfaces described by the DOM recommendation; see for the mapping specification and for the IDL interfaces. """ === Added File Products/ParsedXML/help/XMLExtended.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ DOM Level 2 Core extended classes. Classes and interfaces are made available according to the Python language mapping for the IDL interfaces described by the DOM recommendation; see for the mapping specification and for the IDL interfaces. """ From sidnei at x3ng.com.br Fri May 30 11:17:44 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/www - pxml.gif:1.1 Message-ID: <200305301517.h4UFHih20189@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/www In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/www Added Files: pxml.gif Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/www/pxml.gif === From sidnei at x3ng.com.br Fri May 30 11:17:39 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa - 001.xml:1.1 002.xml:1.1 003.xml:1.1 004.xml:1.1 005.xml:1.1 006.xml:1.1 007.xml:1.1 008.xml:1.1 009.xml:1.1 010.xml:1.1 011.xml:1.1 012.xml:1.1 013.xml:1.1 014.xml:1.1 015.xml:1.1 016.xml:1.1 017.xml:1.1 018.xml:1.1 019.xml:1.1 020.xml:1.1 021.xml:1.1 022.xml:1.1 023.xml:1.1 024.xml:1.1 025.xml:1.1 026.xml:1.1 027.xml:1.1 028.xml:1.1 029.xml:1.1 030.xml:1.1 031.xml:1.1 032.xml:1.1 033.xml:1.1 034.xml:1.1 035.xml:1.1 036.xml:1.1 037.xml:1.1 038.xml:1.1 039.xml:1.1 040.xml:1.1 041.xml:1.1 042.xml:1.1 043.xml:1.1 044.xml:1.1 045.xml:1.1 046.xml:1.1 047.xml:1.1 048.xml:1.1 049.xml:1.1 050.xml:1.1 051.xml:1.1 052.xml:1.1 053.xml:1.1 054.xml:1.1 055.xml:1.1 056.xml:1.1 057.xml:1.1 058.xml:1.1 059.xml:1.1 060.xml:1.1 061.xml:1.1 062.xml:1.1 063.xml:1.1 064.xml:1.1 065.xml:1.1 066.xml:1.1 067.xml:1.1 068.xml:1.1 069.xml:1.1 070.xml:1.1 071.xml:1.1 072.xml:1.1 073.xml:1.1 074.xml:1.1 075.xml:1.1 076.xml:1.1 077.xml:1.1 078.! xml:1.1 079.xml:1.1 080.xml:1.1 081.xml:1.1 082.xml:1.1 083.xml:1.1 084.xml:1.1 085.xml:1.1 086.xml:1.1 087.xml:1.1 088.xml:1.1 089.xml:1.1 090.xml:1.1 091.xml:1.1 092.xml:1.1 093.xml:1.1 094.xml:1.1 095.xml:1.1 096.xml:1.1 097.xml:1.1 098.xml:1.1 099.xml:1.1 100.xml:1.1 101.xml:1.1 102.xml:1.1 103.xml:1.1 104.xml:1.1 105.xml:1.1 106.xml:1.1 107.xml:1.1 108.xml:1.1 109.xml:1.1 110.xml:1.1 111.xml:1.1 112.xml:1.1 113.xml:1.1 114.xml:1.1 115.xml:1.1 116.xml:1.1 117.xml:1.1 118.xml:1.1 119.xml:1.1 Message-ID: <200305301517.h4UFHdv19890@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/xml/conf/xmltest/sa Added Files: 001.xml 002.xml 003.xml 004.xml 005.xml 006.xml 007.xml 008.xml 009.xml 010.xml 011.xml 012.xml 013.xml 014.xml 015.xml 016.xml 017.xml 018.xml 019.xml 020.xml 021.xml 022.xml 023.xml 024.xml 025.xml 026.xml 027.xml 028.xml 029.xml 030.xml 031.xml 032.xml 033.xml 034.xml 035.xml 036.xml 037.xml 038.xml 039.xml 040.xml 041.xml 042.xml 043.xml 044.xml 045.xml 046.xml 047.xml 048.xml 049.xml 050.xml 051.xml 052.xml 053.xml 054.xml 055.xml 056.xml 057.xml 058.xml 059.xml 060.xml 061.xml 062.xml 063.xml 064.xml 065.xml 066.xml 067.xml 068.xml 069.xml 070.xml 071.xml 072.xml 073.xml 074.xml 075.xml 076.xml 077.xml 078.xml 079.xml 080.xml 081.xml 082.xml 083.xml 084.xml 085.xml 086.xml 087.xml 088.xml 089.xml 090.xml 091.xml 092.xml 093.xml 094.xml 095.xml 096.xml 097.xml 098.xml 099.xml 100.xml 101.xml 102.xml 103.xml 104.xml 105.xml 106.xml 107.xml 108.xml 109.xml 110.xml 111.xml 112.xml 113.xml 114.xml 115.xml 116.xml 117.xml 118.xml 119.xml Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/001.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/002.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/003.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/004.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/005.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/006.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/007.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/008.xml === ]> &<>"' === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/009.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/010.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/011.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/012.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/013.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/014.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/015.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/016.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/017.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/018.xml === ]> ]]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/019.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/020.xml === ]> ]]]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/021.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/022.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/023.xml === ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/024.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/025.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/026.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/027.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/028.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/029.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/030.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/031.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/032.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/033.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/034.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/035.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/036.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/037.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/038.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/039.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/040.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/041.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/042.xml === ]> A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/043.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/044.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/045.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/046.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/047.xml === ]> X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/048.xml === ]> ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/049.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/050.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/051.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/052.xml === ]> ð€€ô¿½ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/053.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/054.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/055.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/056.xml === ]> A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/057.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/058.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/059.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/060.xml === ]> X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/061.xml === ]> £ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/062.xml === ]> เจมส์ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/063.xml === ]> <เจมส์> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/064.xml === ]> 𐀀􏿽 === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/065.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/066.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/067.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/068.xml === ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/069.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/070.xml === "> %e; ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/071.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/072.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/073.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/074.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/075.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/076.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/077.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/078.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/079.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/080.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/081.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/082.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/083.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/084.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/085.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/086.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/087.xml === ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/088.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/089.xml === ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/090.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/091.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/092.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/093.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/094.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/095.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/096.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/097.xml === %e; ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/098.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/099.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/100.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/101.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/102.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/103.xml === ]> <doc> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/104.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/105.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/106.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/107.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/108.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/109.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/110.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/111.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/112.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/113.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/114.xml === "> ]> &e; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/115.xml === ]> &e1; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/116.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/117.xml === ]> ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/118.xml === ]> ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/119.xml === ]> From sidnei at x3ng.com.br Fri May 30 11:17:42 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut - 001.xml:1.1 002.xml:1.1 003.xml:1.1 004.xml:1.1 005.xml:1.1 006.xml:1.1 007.xml:1.1 008.xml:1.1 009.xml:1.1 010.xml:1.1 011.xml:1.1 012.xml:1.1 013.xml:1.1 014.xml:1.1 015.xml:1.1 016.xml:1.1 017.xml:1.1 018.xml:1.1 019.xml:1.1 020.xml:1.1 021.xml:1.1 022.xml:1.1 023.xml:1.1 024.xml:1.1 025.xml:1.1 026.xml:1.1 027.xml:1.1 028.xml:1.1 029.xml:1.1 030.xml:1.1 031.xml:1.1 032.xml:1.1 033.xml:1.1 034.xml:1.1 035.xml:1.1 036.xml:1.1 037.xml:1.1 038.xml:1.1 039.xml:1.1 040.xml:1.1 041.xml:1.1 042.xml:1.1 043.xml:1.1 044.xml:1.1 045.xml:1.1 046.xml:1.1 047.xml:1.1 048.xml:1.1 049.xml:1.1 050.xml:1.1 051.xml:1.1 052.xml:1.1 053.xml:1.1 054.xml:1.1 055.xml:1.1 056.xml:1.1 057.xml:1.1 058.xml:1.1 059.xml:1.1 060.xml:1.1 061.xml:1.1 062.xml:1.1 063.xml:1.1 064.xml:1.1 065.xml:1.1 066.xml:1.1 067.xml:1.1 068.xml:1.1 069.xml:1.1 070.xml:1.1 071.xml:1.1 072.xml:1.1 073.xml:1.1 074.xml:1.1 075.xml:1.1 076.xml:1.1! 077.xml:1.1 078.xml:1.1 079.xml:1.1 080.xml:1.1 081.xml:1.1 082.xml:1.1 083.xml:1.1 084.xml:1.1 085.xml:1.1 086.xml:1.1 087.xml:1.1 088.xml:1.1 089.xml:1.1 090.xml:1.1 091.xml:1.1 092.xml:1.1 093.xml:1.1 094.xml:1.1 095.xml:1.1 096.xml:1.1 097.xml:1.1 098.xml:1.1 099.xml:1.1 100.xml:1.1 101.xml:1.1 102.xml:1.1 103.xml:1.1 104.xml:1.1 105.xml:1.1 106.xml:1.1 107.xml:1.1 108.xml:1.1 109.xml:1.1 110.xml:1.1 111.xml:1.1 112.xml:1.1 113.xml:1.1 114.xml:1.1 115.xml:1.1 116.xml:1.1 117.xml:1.1 118.xml:1.1 119.xml:1.1 Message-ID: <200305301517.h4UFHgd20144@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut Added Files: 001.xml 002.xml 003.xml 004.xml 005.xml 006.xml 007.xml 008.xml 009.xml 010.xml 011.xml 012.xml 013.xml 014.xml 015.xml 016.xml 017.xml 018.xml 019.xml 020.xml 021.xml 022.xml 023.xml 024.xml 025.xml 026.xml 027.xml 028.xml 029.xml 030.xml 031.xml 032.xml 033.xml 034.xml 035.xml 036.xml 037.xml 038.xml 039.xml 040.xml 041.xml 042.xml 043.xml 044.xml 045.xml 046.xml 047.xml 048.xml 049.xml 050.xml 051.xml 052.xml 053.xml 054.xml 055.xml 056.xml 057.xml 058.xml 059.xml 060.xml 061.xml 062.xml 063.xml 064.xml 065.xml 066.xml 067.xml 068.xml 069.xml 070.xml 071.xml 072.xml 073.xml 074.xml 075.xml 076.xml 077.xml 078.xml 079.xml 080.xml 081.xml 082.xml 083.xml 084.xml 085.xml 086.xml 087.xml 088.xml 089.xml 090.xml 091.xml 092.xml 093.xml 094.xml 095.xml 096.xml 097.xml 098.xml 099.xml 100.xml 101.xml 102.xml 103.xml 104.xml 105.xml 106.xml 107.xml 108.xml 109.xml 110.xml 111.xml 112.xml 113.xml 114.xml 115.xml 116.xml 117.xml 118.xml 119.xml Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/001.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/002.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/003.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/004.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/005.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/006.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/007.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/008.xml === &<>"' === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/009.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/010.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/011.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/012.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/013.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/014.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/015.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/016.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/017.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/018.xml === ]]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/019.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/020.xml === ]]]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/021.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/022.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/023.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/024.xml === "> ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/025.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/026.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/027.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/028.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/029.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/030.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/031.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/032.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/033.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/034.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/035.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/036.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/037.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/038.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/039.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/040.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/041.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/042.xml === A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/043.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/044.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/045.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/046.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/047.xml === X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/048.xml === ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/049.xml === £ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/050.xml === เจมส์ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/051.xml === <เจมส์/> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/052.xml === ð€€ô¿½ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/053.xml === "> ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/054.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/055.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/056.xml === A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/057.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/058.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/059.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/060.xml === X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/061.xml === £ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/062.xml === เจมส์ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/063.xml === <เจมส์/> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/064.xml === ð€€ô¿½ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/065.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/066.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/067.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/068.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/069.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/070.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/071.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/072.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/073.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/074.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/075.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/076.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/077.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/078.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/079.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/080.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/081.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/082.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/083.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/084.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/085.xml === "> ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/086.xml === "> ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/087.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/088.xml === "> ]> <foo> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/089.xml === ]> ð€€ô¿½ô¿¿ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/090.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/091.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/092.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/093.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/094.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/095.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/096.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/097.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/098.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/099.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/100.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/101.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/102.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/103.xml === <doc> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/104.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/105.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/106.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/107.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/108.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/109.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/110.xml === ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/111.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/112.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/113.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/114.xml === "> ]> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/115.xml === ]> v === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/116.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/117.xml === ]> ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/118.xml === ]> ]] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/ParsedXMLTestOut/119.xml === From sidnei at x3ng.com.br Fri May 30 11:17:46 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PortalBase/oCVS - Entries:1.1 Repository:1.1 Root:1.1 Message-ID: <200305301517.h4UFHkA20265@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PortalBase/oCVS In directory cvs.zope.org:/tmp/cvs-serv19195/PortalBase/oCVS Added Files: Entries Repository Root Log Message: Adding products needed for migration of NZO === Added File Products/PortalBase/oCVS/Entries === /CHANGES.txt/1.1/Wed Apr 28 16:00:14 1999// /Documents.py/1.1/Tue May 11 16:22:11 1999// /MemberFolder.gif/1.1/Wed Apr 28 16:00:15 1999// /User.gif/1.1/Wed Apr 28 16:00:15 1999// /ZopeSite.py/1.2/Thu Apr 29 18:05:12 1999// /__init__.py/1.2/Tue May 11 16:22:11 1999// /MemberFolder.py/1.5/Mon Jun 28 21:07:56 1999// D === Added File Products/PortalBase/oCVS/Repository === /cvs-repository/Packages/Products/PortalBase === Added File Products/PortalBase/oCVS/Root === :ext:amos@216.164.72.7:/cvs-repository From sidnei at x3ng.com.br Fri May 30 11:17:47 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/www - XXXmethodAdd.dtml:1.1 methodAdd.dtml:1.1 methodEdit.dtml:1.1 methodProxy.dtml:1.1 pymethod.gif:1.1 xpymethod.gif:1.1 Message-ID: <200305301517.h4UFHlH20361@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/www In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/www Added Files: XXXmethodAdd.dtml methodAdd.dtml methodEdit.dtml methodProxy.dtml pymethod.gif xpymethod.gif Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/www/XXXmethodAdd.dtml === Add XXX Python Method

Add XXX Python Method

XXX Python Methods allow you to add functionality to Zope by writing Python functions which are exposed as callable Zope objects.

Use the form below to add a Python Method. The Parameter list should be a standard Python parameter list (without the parens), and can include default values, as well as *tuple and **keyword arguments.

ID
Title
Parameter list
Python function body

=== Added File Products/PythonMethod/www/methodAdd.dtml === Add Python Method

Add Python Method

Python Methods allow you to add functionality to Zope by writing Python functions which are exposed as callable Zope objects.

Use the form below to add a Python Method. The Parameter list should be a standard Python parameter list, and can include default values, as well as *tuple and **keyword arguments.

ID
Title
Parameter list
Python function body

=== Added File Products/PythonMethod/www/methodEdit.dtml === Edit <dtml-var title_or_id>

Edit

Id
Title
Parameter list
Size bytes
Last modified

Height

Width
=== Added File Products/PythonMethod/www/methodProxy.dtml === Edit

Proxy Roles allow a Method to access restricted Zope resources. Normally a Method can only access resources for which the user is authorized. By adding Proxy Roles, you allow the Method to act with additional roles, beyond what the user may have.

Use the form below to select which roles this Method will have.

Id
Title
Proxy Roles
=== Added File Products/PythonMethod/www/pymethod.gif === === Added File Products/PythonMethod/www/xpymethod.gif === From sidnei at x3ng.com.br Fri May 30 11:17:49 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/code_gen - Makefile:1.1 __init__.py:1.1 op_execute_methods:1.1 opexfuncread.py:1.1 regen:1.1 write_ops.py:1.1 Message-ID: <200305301517.h4UFHns20473@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/code_gen In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks/code_gen Added Files: Makefile __init__.py op_execute_methods opexfuncread.py regen write_ops.py Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/code_gen/Makefile === clean: $(RM) *~ *.pyc *.pyo === Added File Products/PythonMethod/zbytecodehacks/code_gen/__init__.py === __all__=[ 'write_ops', 'opexecfuncread'] === Added File Products/PythonMethod/zbytecodehacks/code_gen/op_execute_methods === # -*- python -*- STOP_CODE: pass POP_TOP: stack.pop() ROT_TWO: stack[-2:]=[stack[-1],stack[-2]] ROT_THREE: stack[-3:]=[ stack[-1], stack[-3], stack[-2]] DUP_TOP: stack.append(stack[-1]) UNARY_POSITIVE: UNARY_NEGATIVE: UNARY_NOT: UNARY_CONVERT: UNARY_INVERT: stack[-1:]=[self] BINARY_POWER: BINARY_MULTIPLY: BINARY_DIVIDE: BINARY_MODULO: BINARY_ADD: BINARY_SUBTRACT: BINARY_SUBSCR: BINARY_LSHIFT: BINARY_RSHIFT: BINARY_AND: BINARY_XOR: BINARY_OR: stack[-2:]=[self] SLICE_0: stack[-1:]=[self] SLICE_1: SLICE_2: stack[-2:]=[self] SLICE_3: stack[-3:]=[self] STORE_SLICE_0: del stack[-2:] STORE_SLICE_1: STORE_SLICE_2: del stack[-3:] STORE_SLICE_3: del stack[-4:] DELETE_SLICE_0: del stack[-1:] DELETE_SLICE_1: DELETE_SLICE_2: del stack[-2:] DELETE_SLICE_3: del stack[-3:] STORE_SUBSCR: del stack[-3:] DELETE_SUBSCR: del stack[-2:] PRINT_EXPR: PRINT_ITEM: stack.pop() PRINT_NEWLINE: pass BREAK_LOOP: raise "No jumps here!" LOAD_LOCALS: stack.append(self) RETURN_VALUE: stack[:] = [] EXEC_STMT: pass POP_BLOCK: pass END_FINALLY: pass BUILD_CLASS: stack[-3:] = [self] STORE_NAME: DELETE_NAME: stack.pop() UNPACK_TUPLE: UNPACK_LIST: stack.append([self] * self.arg) STORE_ATTR: DELETE_ATTR: STORE_GLOBAL: DELETE_GLOBAL: stack.pop() LOAD_CONST: LOAD_NAME: stack.append(self) BUILD_TUPLE: BUILD_LIST: if self.arg>0: stack[-self.arg:]=[self] else: stack.append(self) BUILD_MAP: stack.append(self) LOAD_ATTR: stack[-1] = self COMPARE_OP: stack[-2:]=[self] # ???? IMPORT_NAME: stack.append(self) IMPORT_FROM: pass JUMP_FORWARD: JUMP_IF_TRUE: JUMP_IF_FALSE: JUMP_ABSOLUTE: raise "jumps not handled here!" FOR_LOOP: raise "loop alert" LOAD_GLOBAL: stack.append(self) SETUP_LOOP: raise "loop alert!" SETUP_EXCEPT: SETUP_FINALLY: pass # ?? LOAD_FAST: stack.append(self) STORE_FAST: DELETE_FAST: stack.pop() SET_LINENO: pass RAISE_VARARGS: raise "Exception!" CALL_FUNCTION: num_keyword_args=self.arg>>8 num_regular_args=self.arg&0xFF stack[-2*num_keyword_args-num_regular_args-1:]=[self] MAKE_FUNCTION: stack[-self.arg-1:]=[self] BUILD_SLICE: stack[-self.arg:]=[self] === Added File Products/PythonMethod/zbytecodehacks/code_gen/opexfuncread.py === import os,string file=open(os.path.join(os.path.dirname(__file__ ),'op_execute_methods'),'r') lines=string.split(file.read(),'\n')[1:] exec_funcs={} n=len(lines) for i in range(n): if (not lines[i]) or lines[i][0]==' ': continue j=i body=[] while j$') def main(file=sys.stdout): file.write(temphead) trans=string.maketrans('+','_') for index in range(len(dis.opname)): name=string.translate(dis.opname[index],trans) if notopprog.match(name): continue if not idprog.match(name): name="Opcode_%d"%index s = "generating %s ..."%name pad = " " * (30-len(s)) print s,pad, base="GenericOneByteCode" if index < dis.HAVE_ARGUMENT: template = noargtemplate base="GenericOneByteCode" elif index in dis.hasjrel: template = jumptemplate base="JRel" elif index in dis.hasjabs: template = jumptemplate base="JAbs" elif index in dis.hasname: template = argtemplate base="NameOpcode" elif index in dis.haslocal: template = argtemplate base="LocalOpcode" else: template = argtemplate base="GenericThreeByteCode" exec_body=opexfuncread.exec_funcs[name] file.write(template%locals()) print "done" def Main(): from bytecodehacks import __init__ main(open(os.path.join(os.path.dirname(__init__.__file__),'ops.py'),'w')) From sidnei at x3ng.com.br Fri May 30 11:17:47 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:11 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod - CHANGES.txt:1.1 COPYRIGHT.txt:1.1 Guarded.py:1.1 PythonMethod.py:1.1 README.txt:1.1 __init__.py:1.1 version.txt:1.1 Message-ID: <200305301517.h4UFHl220318@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod Added Files: CHANGES.txt COPYRIGHT.txt Guarded.py PythonMethod.py README.txt __init__.py version.txt Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/CHANGES.txt === 1999-12-13 Evan Simpson * Version 0.1.7 * Nested functions and lambdas are now supported, with full safety. * You can access all of the dtml-var format functions through a builtin dictionary called special_formats (eg: special_formats['html-quote']). * Handing off to Digital Creations for inclusion in CVS. * Packaged with packProduct script, which excludes parent directories and .pyc files. Makes for a smaller package, and doesn't step on ownership/permissions of lib/python/Products path elements. 1999-12-01 Evan Simpson * Added COPYRIGHT.txt, making Wide Open Source licence (BSD-style) explicit. (Mike Goldman provided the text, I provided the silly name). * Jeff Rush donated a PrincipiaSearchSource method, so that PythonMethod objects can be zcataloged to the same degree as DTML Methods. * Also from Jeff Rush, a document_src method, so that the source of PythonMethods can be viewed via a "View Source" link if desired. * If a PM has a 'traverse_subpath' parameter, you can now directly traverse it. The elements of the subpath will then be put into a list in 'traverse_subpath'. (thanks to Anthony Baxter) 1999-11-11 Evan Simpson * Version 0.1.6 * Fix to builtins messed up DTML Methods, so I re-fixed it. 1999-11-05 Evan Simpson * Version 0.1.5 * Killed *%#&$@ weird bug in which having 'add' documents in 'www' subdirectory prevented rename, paste, or import of existing PythonMethods! See use of '_www'. * Range, test, and several other Zope 'builtins' had an unbound 'self' argument unless called on _, but that's fixed. * Safe multiplication was utterly broken (thanks to the guard); now it works. Is anyone using the safe version?? 1999-10-18 Evan Simpson * Eliminated bug which delayed stringification of printed values. 1999-10-08 Evan Simpson * Version 0.1.4 * Fixed mis-design noticed by Michel Pelletier, and refactored MakeFunction. Now both kinds of Python Method have the bugfix from 0.1.3, and shouldn't provoke a transaction when called. 1999-10-07 Evan Simpson * Version 0.1.3 * Fixed parameter bug with 'self' and no defaults 1999-09-24 Evan Simpson * Version 0.1.2 * Added WebDAV/FTP access code donated by Michel Pelletier * Made parameters part of WebDAV/FTP text * Eliminated initialization of globals to None * Added 'global_exists' global function instead * Killed bug with unused parameters * Put switch in Guarded.py to allow both regular and dangerous (XXX) PythonMethods to live side-by-side. This means that people who patched version 0.1.1 will have to re-create any unsafe PMs they use (Sorry). 1999-09-10 Evan Simpson * Version 0.1.1 * Incorporated DT_Util builtins and guards * Fixed direct access via URL * Fixed methodAdd.dtml * rstrip function body * Major changes to zbytecodehacks === Added File Products/PythonMethod/COPYRIGHT.txt === This software is released under the following Wide-Open Source licence: Copyright (c) 1999 Evan Simpson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of 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. Neither the name of the Author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. === Added File Products/PythonMethod/Guarded.py === from zbytecodehacks.VSExec import SafeBlock, GuardedOps, UntupleFunction from DocumentTemplate.VSEval import careful_mul from DocumentTemplate.DT_Util import TemplateDict, test from DocumentTemplate.DT_Var import special_formats safefuncs = TemplateDict() safebin = safefuncs.__class__.__dict__.copy() for k, v in safebin.items(): if type(v)==type(test): safebin[k] = getattr(safefuncs, k) safebin['special_formats'] = special_formats class Guard: mul = careful_mul theGuard = Guard() class GuardedBlock(SafeBlock): Mungers = SafeBlock.Mungers + [GuardedOps(theGuard)] # BEWARE OF THE LEOPARD! # Set 'do_XXX' true to allow creation of XXXPythonMethods # and ADD A MASSIVE GAPING SECURITY HOLE to Zope. # DON'T DO THIS unless you use secure connections for ALL OF # YOUR ADMINISTRATION or are RECKLESS and/or FEARLESS. # Even if you DON'T create ANY XXXPythonMethods, just turning this # on will PUT YOU AT RISK BIGTIME! do_XXX = 0 if do_XXX: from zbytecodehacks.VSExec import CodeBlock, Printing class UnGuardedBlock(CodeBlock): Mungers = [Printing] === Added File Products/PythonMethod/PythonMethod.py === """Python Method Product This product provides support for internal methods, which allow safe implementation in a large Python subset. """ __version__='$Revision: 1.1 $'[11:-2] from Globals import MessageDialog, HTMLFile, package_home import sys, os, traceback, re from OFS.SimpleItem import pretty_tb, SimpleItem from DateTime.DateTime import DateTime from string import join, rstrip, split import Guarded class AnObject: def __init__(self, **kw): self.__dict__.update(kw) _www = os.path.join(package_home(globals()), 'www') manage_addPythonMethodForm=HTMLFile('methodAdd', _www) def manage_addPythonMethod(self, id, title, params, body, REQUEST=None): """Add an internal method to a folder In addition to the standard Zope object-creation arguments, 'id' and title, the following arguments are defined: params -- A standard Python parameter list. body -- The text of the Python function definition. """ it = PythonMethod(id, title, params, body) self._setObject(id, it) return self.manage_main(self, REQUEST) class PythonMethod(SimpleItem): """Web-callable functions written in a safe subset of Python. The function may include standard python code, so long as it does not assign to qualified names ([], .foo, ()), reference names beginning with an underscore, or attempt to use the "del", "exec", or "import" statements. """ meta_type='Python Method' _proxy_roles = () index_html = None _params = _body = None manage_options = ( {'label':'Edit', 'action':'manage_main'}, {'label':'Try It', 'action':''}, {'label':'Proxy', 'action':'manage_proxyForm'}, {'label':'Security', 'action':'manage_access'}, ) __ac_permissions__ = ( ('View management screens', ('manage_main',)), ('Change Python Methods', ('manage_edit',)), ('Change proxy roles', ('manage_proxyForm', 'manage_proxy')), ('View', ('__call__','')), ) def __init__(self, id, title, params, body): self.id = id self.manage_edit(title, params, body) manage = manage_main = HTMLFile('methodEdit', _www) manage_proxyForm = HTMLFile('methodProxy', _www) def manage_edit(self, title, params, body, height=None, width=None, dtpref_cols='50', dtpref_rows='20', REQUEST=None): """Change the method See the description of manage_addPythonMethod for a description of the arguments 'params' and 'body'. """ self._validateProxy(REQUEST) if height is not None or width is not None: return self._er(title, params, body, height, width, dtpref_cols, dtpref_rows, REQUEST) self.title = title if type(body) is not type(''): body = body.read() if self._params <> params or self._body <> body: self._params = params self._body = rstrip(body) self.makeFunction(1) if REQUEST: message = "Content changed." if self.warnings: message = ("Warning: %s" % join(self.warnings, '
')) return self.manage_main(self, REQUEST, manage_tabs_message=message) def _er(self, title, params, body, height, width, dtpref_cols, dtpref_rows, REQUEST): szch = {'+': 5, '-': -5, None: 0} try: rows = int(height) except: rows = max(1, int(dtpref_rows) + szch.get(height, 0)) try: cols = int(width) except: cols = max(40, int(dtpref_cols) + szch.get(width, 0)) e = (DateTime('GMT') + 365).rfc822() resp = REQUEST['RESPONSE'] resp.setCookie('dtpref_rows',str(rows),path='/',expires=e) resp.setCookie('dtpref_cols',str(cols),path='/',expires=e) return self.manage_main(self, REQUEST, title=title, params=params, body=body, dtpref_cols=cols, dtpref_rows=rows) def _checkCBlock(self, MakeBlock): blk = MakeBlock(self.id, self._params, self._body) self.errors, self.warnings = blk.errors, blk.warnings if blk.errors: if hasattr(self, '_v_f'): del self._v_f self.func_defaults = () self.func_code = AnObject(co_varnames = (), co_argcount=0) else: self._t = blk.t def _newfun(self, compiled, g, **kws): from Guarded import UntupleFunction self._v_f = f = apply(UntupleFunction, (self._t, g), kws) fc = f.func_code if compiled: self.func_defaults=f.func_defaults self.func_code=AnObject(co_varnames=fc.co_varnames, co_argcount=fc.co_argcount) fdefs = (f.func_defaults and len(f.func_defaults)) or 0 self._v_selfish = (fc.co_varnames and fc.co_varnames[0]=='self' and (fc.co_argcount - fdefs - 1)) return f def makeFunction(self, compile=0): from Guarded import GuardedBlock, safefuncs, theGuard, safebin if compile: self._checkCBlock(GuardedBlock) if self.errors: raise "Python Method Error", join(self.errors, '\n') return self._newfun(compile, {'$guard': theGuard}, __builtins__=safebin, _=safefuncs) def __call__(self, *args, **kw): """Call a Python Method Calling a Python Method is an actual function invocation. If: - The supplied number of arguments is one less than the required number of arguments, and - The name of the function's first argument is 'self'. then the URL parent of the object is supplied as the first argument. """ if hasattr(self, '_v_f'): f = self._v_f else: f = self.makeFunction() __traceback_info__=args, kw, self.func_defaults try: return apply(f, args, kw) except TypeError, v: tb=sys.exc_traceback try: if self._v_selfish == len(args): return apply(f,(self.aq_parent.this(),)+args,kw) raise TypeError, v, tb finally: tb=None def manage_haveProxy(self,r): return r in self._proxy_roles def _validateProxy(self, request, roles=None): if roles is None: roles=self._proxy_roles if not roles: return user=u=request.get('AUTHENTICATED_USER',None) if user is not None: user=user.hasRole for r in roles: if r and not user(None, (r,)): user=None break if user is not None: return raise 'Forbidden', ('You are not authorized to change %s ' 'because you do not have proxy roles.\n' % (self.id, u, roles)) def manage_proxy(self, roles=(), REQUEST=None): "Change Proxy Roles" self._validateProxy(REQUEST, roles) self._validateProxy(REQUEST) self._proxy_roles=tuple(roles) if REQUEST: return MessageDialog( title ='Success!', message='Your changes have been saved', action ='manage_main') def PUT(self, REQUEST, RESPONSE): """ Handle HTTP PUT requests """ self.dav__init(REQUEST, RESPONSE) body=REQUEST.get('BODY', '') self._validateProxy(REQUEST) m = re.match('\s*(.*)\s*\n', body, re.I) if m: self._params = m.group(1) body = body[m.end():] self._body = rstrip(body) self.makeFunction(1) RESPONSE.setStatus(204) return RESPONSE def manage_FTPget(self): "Get source for FTP download" return '%s\n%s' % (self._params, self._body) def params(self): return self._params def body(self): return self._body def get_size(self): return len(self._body) getSize = get_size def PrincipiaSearchSource(self): "Support for searching - the document's contents are searched." return "%s\n%s" % (self._params, self._body) def document_src(self, REQUEST, RESPONSE): """Return unprocessed document source.""" m = re.search('^[ ]+', self._body, re.M) if m: prefix = ' ' * len(m.group(0)) else: prefix = ' ' * 4 body = join(split(self._body, '\n'), '\n%s' % prefix) RESPONSE.setHeader('Content-Type', 'text/plain') return "def %s(%s):\n%s%s" % (self.id, self._params, prefix, body) def __bobo_traverse__(self, REQUEST, sub): """Collect direct traversal subpath if we have a parameter for it.""" vname = 'traverse_subpath' noaq = self.aq_explicit if hasattr(noaq, sub): return getattr(self, sub) varnames = noaq.func_code.co_varnames if not (varnames and vname in varnames): REQUEST.RESPONSE.notFoundError("%s\n%s" % (REQUEST.URL, sub)) subpath = REQUEST.other.get(vname, []) subpath.append(sub) REQUEST.set(vname, subpath) return self if Guarded.do_XXX: class XXXPythonMethod(PythonMethod): """Unsafe version of PythonMethod No restrictions, all normal builtins, unlimited import. The only thing funky is the same print-command interception as normal PMs. """ meta_type='XXX Python Method' def makeFunction(self, compile=0): from Guarded import UnGuardedBlock, safefuncs if compile: self._checkCBlock(UnGuardedBlock) if self.errors: raise "XXX Python Method Error", join(self.errors, '\n') return self._newfun(compile, {}, __builtins__=__builtins__, _=safefuncs) manage_addXXXPythonMethodForm=HTMLFile('XXXmethodAdd', _www) def manage_addXXXPythonMethod(self, id, title, params, body, REQUEST=None): """Add an internal method to a folder In addition to the standard Zope object-creation arguments, 'id' and title, the following arguments are defined: params -- A standard Python parameter list. body -- The text of the Python function definition. """ it = XXXPythonMethod(id, title, params, body) self._setObject(id, it) return self.manage_main(self, REQUEST) === Added File Products/PythonMethod/README.txt === Python Methods The Python Method product provides support for internal Python methods, exposing them as callable objects within the Zope environment. === Added File Products/PythonMethod/__init__.py === __doc__='''PythonMethod Product''' __version__='$Revision: 1.1 $'[11:-2] import PythonMethod def initialize(context): context.registerClass(instance_class=PythonMethod.PythonMethod, constructors=(PythonMethod.manage_addPythonMethodForm, PythonMethod.manage_addPythonMethod), icon='www/pymethod.gif') import Guarded if Guarded.do_XXX: context.registerClass(instance_class=PythonMethod.XXXPythonMethod, constructors=(PythonMethod.manage_addXXXPythonMethodForm, PythonMethod.manage_addXXXPythonMethod), icon='www/xpymethod.gif') === Added File Products/PythonMethod/version.txt === PythonMethod-0-1-7 From sidnei at x3ng.com.br Fri May 30 11:17:50 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc - Makefile:1.1 bch.tex:1.1 Message-ID: <200305301517.h4UFHoX20491@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks/doc Added Files: Makefile bch.tex Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/doc/Makefile === PAPER=--a4 all: bch.ps bch.pdf bch bch.txt MKHOWTO=TEXINPUTS=/usr/lib/texmf/texmf/tex/latex/latex2html: mkhowto ADDRESS='Send comments to
mwh21@cam.ac.uk' bch html: bch.tex $(MKHOWTO) --html $(PAPER) -a $(ADDRESS) bch.tex mkdir bch/diagrams cp diagrams/*.jpg bch/diagrams bch.pdf pdf: bch.tex $(MKHOWTO) --pdf $(PAPER) bch.tex bch.ps ps: bch.tex $(MKHOWTO) --ps $(PAPER) bch.tex bch.txt text: bch.tex $(MKHOWTO) --text $(PAPER) bch.tex tarball: html tar chozf bytecodehacks-doc.tar.gz bch clean: $(RM) -r bch bch.ps bch.pdf bch.txt *~ *.tar.gz core *.how *.l2h *.idx *.aux *.log *.syn *.toc *.ind release: tarball scp bytecodehacks-doc.tar.gz mwh@starship.python.net:~mwh/ftp/bytecodehacks-doc-$$(cat ../version).tar.gz === Added File Products/PythonMethod/zbytecodehacks/doc/bch.tex === (1411/1511 lines abridged) \documentclass{howto} \usepackage{graphicx} \usepackage{html} \makeindex \title{Bytecodehacks} \release{\input{../version}} \author{Michael Hudson} \authoraddress{mwh21@cam.ac.uk} \begin{document} \maketitle \ifhtml \chapter*{Front Matter\label{front}} \fi %\begin{copyright} These routines are placed in the public domain; downloaded them? They're yours. I'd be offended if you passed them off as your own work, but I'm not going to sue. %\end{copyright} \begin{abstract} \noindent This package contains a library of routines for editing the bytecodes executed by the Python virtual machine, and a set of routines that use the library to do unlikely things to Python functions and methods, such as locally binding references and inlining functions. \end{abstract} \tableofcontents This document describes how to use the bytecodehacks package to do unlikely things in Python. \section{Back end} The bits you need to know how to use to write your own bytecodehacks, or understand how the ones supplied actually do their stuff. I presuppose quite a detailed knowledge of the Python interpreter. If you don't know what the \module{new} or \module{dis} modules do, you're not likely to understand what goes on here. When I talk of ``user'' code in this section I mean code that uses the [-=- -=- -=- 1411 lines omitted -=- -=- -=-] come from the overhead of the former allocating lots and lots of stack frames, rather than the legendarily large Python function-call overhead. This could be because \function{make_tail_recursive} generates rather terrible code to save off some parameters while the others are being calculated. It wouldn't take much to improve this, but I don't have the stamina right now. On my machine, for smallish values of \var{n} (which means less than a thousand) \function{factr} runs in about 90\% of the time of \function{facr}. This gets (much) better as \var{n} increases, although this is very memory bound - and so not very predictable or consistent. Depends how much swapping has to be done. For what it's worth an explicitly iterative version \begin{verbatim} def faci(n): p = 1l; c = 1; while c <= n: p = c*p c = c+1 return p \end{verbatim} runs a few percent faster than \function{factr}. \section{The code generating stuff} The \refmodule{ops} module is an autogenerated file. The code in \module{bytecodehacks.code_gen} is responsible for generating this file. There is a tiny script in \file{bytecodehacks/code_gen/regen} that regenerates \file{ops.py}. I have a symlink to it on my \code{\$PATH}; you may want to do the same if you're hacking on bytecodehacks. \module{write_ops} does most of the legwork. The \method{execute} methods of all the bytecodes are listed in the file \file{op_execute_methods} and extracted from said file by \module{opexfuncread}. The code isn't pretty or very general, but it works well enough. I hope it's also fairly easy to understand, because I don't feel like writing detailed documentation right now... \input{bch.ind} \end{document} From sidnei at x3ng.com.br Fri May 30 11:17:49 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/xml/conf/xmltest/sa/out - 001.xml:1.1 002.xml:1.1 003.xml:1.1 004.xml:1.1 005.xml:1.1 006.xml:1.1 007.xml:1.1 008.xml:1.1 009.xml:1.1 010.xml:1.1 011.xml:1.1 012.xml:1.1 013.xml:1.1 014.xml:1.1 015.xml:1.1 016.xml:1.1 017.xml:1.1 018.xml:1.1 019.xml:1.1 020.xml:1.1 021.xml:1.1 022.xml:1.1 023.xml:1.1 024.xml:1.1 025.xml:1.1 026.xml:1.1 027.xml:1.1 028.xml:1.1 029.xml:1.1 030.xml:1.1 031.xml:1.1 032.xml:1.1 033.xml:1.1 034.xml:1.1 035.xml:1.1 036.xml:1.1 037.xml:1.1 038.xml:1.1 039.xml:1.1 040.xml:1.1 041.xml:1.1 042.xml:1.1 043.xml:1.1 044.xml:1.1 045.xml:1.1 046.xml:1.1 047.xml:1.1 048.xml:1.1 049.xml:1.1 050.xml:1.1 051.xml:1.1 052.xml:1.1 053.xml:1.1 054.xml:1.1 055.xml:1.1 056.xml:1.1 057.xml:1.1 058.xml:1.1 059.xml:1.1 060.xml:1.1 061.xml:1.1 062.xml:1.1 063.xml:1.1 064.xml:1.1 065.xml:1.1 066.xml:1.1 067.xml:1.1 068.xml:1.1 069.xml:1.1 070.xml:1.1 071.xml:1.1 072.xml:1.1 073.xml:1.1 074.xml:1.1 075.xml:1.1 076.xml:1.1 077.xml:1.1 ! 078.xml:1.1 079.xml:1.1 080.xml:1.1 081.xml:1.1 082.xml:1.1 083.xml:1.1 084.xml:1.1 085.xml:1.1 086.xml:1.1 087.xml:1.1 088.xml:1.1 089.xml:1.1 090.xml:1.1 091.xml:1.1 092.xml:1.1 093.xml:1.1 094.xml:1.1 095.xml:1.1 096.xml:1.1 097.xml:1.1 098.xml:1.1 099.xml:1.1 100.xml:1.1 101.xml:1.1 102.xml:1.1 103.xml:1.1 104.xml:1.1 105.xml:1.1 106.xml:1.1 107.xml:1.1 108.xml:1.1 109.xml:1.1 110.xml:1.1 111.xml:1.1 112.xml:1.1 113.xml:1.1 114.xml:1.1 115.xml:1.1 116.xml:1.1 117.xml:1.1 118.xml:1.1 119.xml:1.1 Message-ID: <200305301517.h4UFHnd20458@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/xml/conf/xmltest/sa/out In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/xml/conf/xmltest/sa/out Added Files: 001.xml 002.xml 003.xml 004.xml 005.xml 006.xml 007.xml 008.xml 009.xml 010.xml 011.xml 012.xml 013.xml 014.xml 015.xml 016.xml 017.xml 018.xml 019.xml 020.xml 021.xml 022.xml 023.xml 024.xml 025.xml 026.xml 027.xml 028.xml 029.xml 030.xml 031.xml 032.xml 033.xml 034.xml 035.xml 036.xml 037.xml 038.xml 039.xml 040.xml 041.xml 042.xml 043.xml 044.xml 045.xml 046.xml 047.xml 048.xml 049.xml 050.xml 051.xml 052.xml 053.xml 054.xml 055.xml 056.xml 057.xml 058.xml 059.xml 060.xml 061.xml 062.xml 063.xml 064.xml 065.xml 066.xml 067.xml 068.xml 069.xml 070.xml 071.xml 072.xml 073.xml 074.xml 075.xml 076.xml 077.xml 078.xml 079.xml 080.xml 081.xml 082.xml 083.xml 084.xml 085.xml 086.xml 087.xml 088.xml 089.xml 090.xml 091.xml 092.xml 093.xml 094.xml 095.xml 096.xml 097.xml 098.xml 099.xml 100.xml 101.xml 102.xml 103.xml 104.xml 105.xml 106.xml 107.xml 108.xml 109.xml 110.xml 111.xml 112.xml 113.xml 114.xml 115.xml 116.xml 117.xml 118.xml 119.xml Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/001.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/002.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/003.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/004.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/005.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/006.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/007.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/008.xml === &<>"' === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/009.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/010.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/011.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/012.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/013.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/014.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/015.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/016.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/017.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/018.xml === <foo> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/019.xml === <& === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/020.xml === <&]>] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/021.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/022.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/023.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/024.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/025.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/026.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/027.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/028.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/029.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/030.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/031.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/032.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/033.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/034.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/035.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/036.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/037.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/038.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/039.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/040.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/041.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/042.xml === A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/043.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/044.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/045.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/046.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/047.xml === X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/048.xml === ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/049.xml === £ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/050.xml === เจมส์ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/051.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/052.xml === ð€€ô¿½ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/053.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/054.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/055.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/056.xml === A === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/057.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/058.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/059.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/060.xml === X Y === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/061.xml === £ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/062.xml === เจมส์ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/063.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/064.xml === ð€€ô¿½ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/065.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/066.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/067.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/068.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/069.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/070.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/071.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/072.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/073.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/074.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/075.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/076.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/077.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/078.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/079.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/080.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/081.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/082.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/083.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/084.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/085.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/086.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/087.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/088.xml === <foo> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/089.xml === ð€€ô¿½ô¿¿ === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/090.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/091.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/092.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/093.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/094.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/095.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/096.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/097.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/098.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/099.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/100.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/101.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/102.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/103.xml === <doc> === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/104.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/105.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/106.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/107.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/108.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/109.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/110.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/111.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/112.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/113.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/114.xml === &foo; === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/115.xml === v === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/116.xml === === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/117.xml === ] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/118.xml === ]] === Added File Products/ParsedXML/tests/xml/conf/xmltest/sa/out/119.xml === From sidnei at x3ng.com.br Fri May 30 11:17:51 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc/icons - blank.png:1.1 contents.png:1.1 index.png:1.1 modules.png:1.1 next.png:1.1 previous.png:1.1 up.png:1.1 Message-ID: <200305301517.h4UFHpZ20556@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/icons In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks/doc/icons Added Files: blank.png contents.png index.png modules.png next.png previous.png up.png Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/doc/icons/blank.png === ‰PNG  IHDR D¤ŠÆPLTE 3f™Ìÿ333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌÿ3ÿfÿ™ÿÌÿÿÿ333f3™3Ì3ÿ333333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌffÿff™f3™ff™f™™fÌ™fÿ™fÌf3ÌffÌf™ÌfÌÌfÿÌfÿf3ÿffÿf™ÿfÌÿfÿÿf™3™f™™™Ì™ÿ™3™33™f3™™3™Ì3™ÿ3™f™3f™ff™™f™Ìf™ÿf™™™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌ™™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿ™Ì3ÌfÌ™ÌÌÌÿÌ3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌffÌ™fÌÌfÌÿfÌ™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÌÿ3ÿfÿ™ÿÌÿÿÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÿ™fÿÌfÿÿfÿ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿÿÿ3ÿÿfÿÿ™ÿÿÌÿÿÿÿÿâââãããäääåååæææçççèèèéééêêêëëëìììíííîîîïïïðððñññòòòóóóôôôõõõööö÷÷÷øøøùùùúúúûûûüüüýýýþþþÿÿÿCA×bKGDˆHIDATxÚc¸I0Œ*U0ª`¤*­d.¡ç®LzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚ3HL633H51³LK2N²°L455533MI322! I4IJÆ€†üÞzTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ === Added File Products/PythonMethod/zbytecodehacks/doc/icons/contents.png === ‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼lIDATxÚÍ’Ý’Ã …‹‚ ÆÞÿe1I»7íMgg3™xF>`|À‡çñüdydÍïlª•O'>hGBa®a¤ƒV8 +šVœ†½ï¨Õ—é‹v/ºŒæÜ{R˜38 wJŒhº"U‹o. i|ÂM-àI3è¯S$e¯Ú|§ÚÈEåoˆ3£vë èR°,߬3.7wè€å`ZËj === Added File Products/PythonMethod/zbytecodehacks/doc/icons/next.png === ‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒ =p3f]ž=ÆbKGDâµ=º“IDATxÚÍ“ÁÂ0Dc@©‰ ùÿ¯•‚vͶã­{åMf¥értF@š‡ñ u¬Q‚@îNô ;:ñÀ%ÙQ°…!X³ÁxmS1 ZOc*ŒTx×ô®<Ø wæçüqþžh“A,Z~LzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚ3231³´L47374K11426NL31·05L210HL3|nÐɾÈÄzTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ === Added File Products/PythonMethod/zbytecodehacks/doc/icons/previous.png === ‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼l“IDATxÚÕ’Aà DiIZ¼ÿe›€/Ù8vÛÎvþÃ$Ä/ ¿H5=°÷SÊ`óƒ'R3¿ÈÀjþŽBŠûj±yóìZLŒL ª´N€×„l-è1°wA4ð=r`Ð?7cÀj&$p¼ÇhÐá,²@ׄxx¢® 3LzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚ304L³0JL4M4KI4H56µ4L¶L444H40µ421vC·[̓zTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ From sidnei at x3ng.com.br Fri May 30 11:17:53 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/tests - Makefile:1.1 __init__.py:1.1 __init__.pyo:1.1 bench.py:1.1 inline_test.py:1.1 inline_test.pyo:1.1 macro_test.py:1.1 test.py:1.1 utils.py:1.1 utils.pyo:1.1 Message-ID: <200305301517.h4UFHrT20597@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/tests In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks/tests Added Files: Makefile __init__.py __init__.pyo bench.py inline_test.py inline_test.pyo macro_test.py test.py utils.py utils.pyo Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/tests/Makefile === clean: $(RM) *~ *.pyc === Added File Products/PythonMethod/zbytecodehacks/tests/__init__.py === === Added File Products/PythonMethod/zbytecodehacks/tests/__init__.pyo === ™N ;67csdS(N((s6/home/mwh21/src/python/bytecodehacks/tests/__init__.pys?s === Added File Products/PythonMethod/zbytecodehacks/tests/bench.py === import closure g1 = g2 = g3 = g4 = g5 = 0 def func0(x): return x + 0 + 0 + 0 + 0 + 0 def func01(x): return x def func1(x, g1=g1, g2=g2, g3=g3, g4=g4, g5=g5): return x + g1 + g2 + g3 + g4 + g5 def func2(x): return x + g1 + g2 + g3 + g4 + g5 func3 = closure.bind_now(func2) def timing(func, args, n=1, **keywords) : import time time=time.time appl=apply if type(args) != type(()) : args=(args,) rep=range(n) before=time() for i in rep: res=appl(func, args, keywords) return round(time()-before,4), res def test(): res = [0,0,0,0,0] for i in range(10): res[0]=res[0]+timing(func0, 42, 100000)[0] res[1]=res[1]+timing(func01, 42, 100000)[0] res[2]=res[2]+timing(func1, 42, 100000)[0] res[3]=res[3]+timing(func2, 42, 100000)[0] res[4]=res[4]+timing(func3, 42, 100000)[0] print res result = """ >>> test() func1 (1.54, 42) func2 (1.98, 42) func2 (1.59, 42) """ === Added File Products/PythonMethod/zbytecodehacks/tests/inline_test.py === from bytecodehacks import inline,macro def f(x,y): return x+y def f2((x),(y)): return x+y def integ_global(dx,x0,x1,y): x=x0 while x === Added File Products/PythonMethod/zbytecodehacks/tests/macro_test.py === from bytecodehacks import macro def incr((x)): x = x + 1 return x def postincr((x)): t = x x = x + 1 return t macro.add_macro(incr) def f(x): while incr(x) < 10: print x ff = macro.expand(f) gg = macro.expand_these(f,incr=postincr) === Added File Products/PythonMethod/zbytecodehacks/tests/test.py === from bytecodehacks import code_editor,ops def f(): return "This function does something really interesting" g=code_editor.Function(f) g.func_code.co_code[:]=[ops.SET_LINENO(3), ops.LOAD_CONST(len(g.func_code.co_consts)), ops.RETURN_VALUE()] g.func_code.co_consts.append("Not any more!") g=g.make_function() print f() print g() from bytecodehacks import attr_freeze import sys def ff(x): if x: print sys.exit else: print sys.copyright _=attr_freeze.Ref() gg=attr_freeze.freeze_attrs(ff, _.sys.exit,sys.exit, _.sys.copyright,sys.copyright) === Added File Products/PythonMethod/zbytecodehacks/tests/utils.py === import dis,tempfile,sys,os def diff_funcs(f1,f2): file1 = tempfile.mktemp() file2 = tempfile.mktemp() svstdout = sys.stdout try: sys.stdout = open(file1, 'w') dis.dis(f1) sys.stdout = open(file2, 'w') dis.dis(f2) sys.stdout = svstdout os.system("diff -y %s %s"%(file1,file2)) finally: sys.stdout = svstdout os.unlink(file1) os.unlink(file2) === Added File Products/PythonMethod/zbytecodehacks/tests/utils.pyo === From sidnei at x3ng.com.br Fri May 30 11:17:45 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/PortalBase - CHANGES.txt:1.1 Documents.py:1.1 MemberFolder.gif:1.1 MemberFolder.py:1.1 MemberFolder.py.old:1.1 MemberFolder.py2:1.1 Membership.py:1.1 User.gif:1.1 ZopeSite.py:1.1 __init__.py:1.1 Message-ID: <200305301517.h4UFHjX20257@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PortalBase In directory cvs.zope.org:/tmp/cvs-serv19195/PortalBase Added Files: CHANGES.txt Documents.py MemberFolder.gif MemberFolder.py MemberFolder.py.old MemberFolder.py2 Membership.py User.gif ZopeSite.py __init__.py Log Message: Adding products needed for migration of NZO === Added File Products/PortalBase/CHANGES.txt === PortalBase Changes PortalBase 1.0.0 Initial release === Added File Products/PortalBase/Documents.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Enhanced document object base classes""" __version__='$Revision: 1.1 $'[11:-2] from ComputedAttribute import ComputedAttribute from DocumentTemplate.DT_String import String from OFS.DTMLDocument import DTMLDocument from OFS.DTMLMethod import DTMLMethod from ExtensionClass import Base import Globals class DocumentHooks(Base): """ """ def __get_name__(self): return getattr(self, '__name__') id=ComputedAttribute(__get_name__) def manage_edit(self,data,title,SUBMIT='Change',dtpref_cols='50', dtpref_rows='20',REQUEST=None): """ """ self.onEditBegin() r=DTMLMethod.manage_edit(self, data, title, SUBMIT=SUBMIT, dtpref_cols=dtpref_cols, dtpref_rows=dtpref_rows, REQUEST=REQUEST) self.onEditComplete() return r def manage_upload(self,file='', REQUEST=None): """ """ self.onEditBegin() r=DTMLMethod.manage_upload(self, file, REQUEST) self.onEditComplete() return r def PUT(self, REQUEST, RESPONSE): """ """ self.onEditBegin() r=DTMLMethod.PUT(self, REQUEST, RESPONSE) self.onEditComplete() return r def onEditBegin(self): """ """ pass def onEditComplete(self): """ """ pass class HTMLDocument(DocumentHooks, DTMLDocument): """ """ _state_name={'raw':1, 'globals':1, '__name__':1, '_vars':1, '_proxy_roles':1, 'title':1, 'subject':1, 'description':1, 'date':1, 'content':1, 'reviewed':1, }.has_key class HTMLMethod(DocumentHooks, DTMLMethod): """ """ _state_name={'raw':1, 'globals':1, '__name__':1, '_vars':1, '_proxy_roles':1, 'title':1, 'subject':1, 'description':1, 'date':1, 'content':1, 'reviewed':1, }.has_key Globals.default__class_init__(HTMLDocument) Globals.default__class_init__(HTMLMethod) === Added File Products/PortalBase/MemberFolder.gif === === Added File Products/PortalBase/MemberFolder.py === (449/549 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 449 lines omitted -=- -=- -=-] _login_html=""" Login

Name
Password
""" _logout_html=""" Logout

You have been logged out of the system.
""" === Added File Products/PortalBase/MemberFolder.py.old === (422/522 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 422 lines omitted -=- -=- -=-] _login_html=""" Login

Name
Password
""" _logout_html=""" Logout

You have been logged out of the system.
""" === Added File Products/PortalBase/MemberFolder.py2 === (433/533 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 433 lines omitted -=- -=- -=-] _login_html=""" Login

Name
Password
""" _logout_html=""" Logout

You have been logged out of the system.
""" === Added File Products/PortalBase/Membership.py === # This module implements various external methods used # by our Membership and registration objects. import sys, os, string, time, random from DateTime import DateTime # Registration methods # -------------------- def added_props(self): """ """ stdprops=('name','email','last_visit','prev_visit','full_name','company') c=self.Control_Panel.Products.ZopeSite.MemberFolder c=c.propertysheets.methods._getOb('Member') ps=c.propertysheets.common.CommonProperties ids=ps.propertyIds() set=[] for id in ids: if not (id in stdprops): set.append(id) return set chars=string.letters+string.digits def gen_password(choose=random.choice, chars=chars, join=string.join): result=[] for n in range(8): result.append(choose(chars)) return join(result, '') def register(self, username='', fullname='', company='', email='', REQUEST=None): """ """ register_html=getattr(self, 'register.html') if not username or not email: return register_html(self, REQUEST, error='You must enter a value for Name and a valid Email ' \ 'Address.') user=self.acl_users.getUser(username) if user is not None: return register_html(self, REQUEST, error='The login name you selected is already in use. Please ' \ 'choose another.') password=gen_password() # Add the member self.acl_users.addUser(username, password, ['Member'], []) user=self.acl_users.getUser(username) for ps in user.propertysheets: ps.manage_changeProperties(REQUEST) # Here we add a new Folder for this user in Members, # giving the user the local role 'Owner' in his Folder. members=self.Members members.manage_addFolder(username) folder=getattr(members, username) if REQUEST: name=REQUEST['AUTHENTICATED_USER'].getUserName() folder.manage_delLocalRoles([name]) folder.manage_setLocalRoles(username, ['Owner']) # Generate email notification self.notify(self, REQUEST, password=password) return getattr(self, 'success.html')(self, REQUEST) def updateMember(self, REQUEST): """ """ user=REQUEST['AUTHENTICATED_USER'] name=user.getUserName() if hasattr(user, 'propertysheets'): for ps in user.propertysheets: ps.manage_changeProperties(REQUEST) return self.index_html(self, REQUEST, message='Your changes have been saved.') else: return self.index_html(self, REQUEST, message='Cannot set non-member %s' % user) # MemberFolder methods # -------------------- def fixup_user(user): if hasattr(user, 'last_visit'): if not user.last_visit.isCurrentDay(): user.prev_visit=user.last_visit user.last_visit=DateTime().earliestTime() return user def addMemberFolder(self, REQUEST=None): if hasattr(self.aq_base, 'acl_users'): return MessageDialog( title ='Item Exists', message='This object already contains a User Folder', action ='%s/manage_main' % REQUEST['URL1']) dest=self.Destination() ob=self.MemberFolder() #'acl_users', REQUEST) dest._setObject('acl_users', ob) dest.__allow_groups__=dest.acl_users if REQUEST: return dest.manage_main(dest, REQUEST, update_menu=1) def addUser(self, name, password, roles, domains, REQUEST=None): """ """ # zclass=self.Control_Panel.Products.ZopeSite.MemberFolder.Member._zclass_ user=self.Member(name, password, roles, domains) user.id=name self.data[name]=user if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def getUser(self, name): """ """ if self.data.has_key(name): user=self.data[name].__of__(self) user=fixup_user(user) return user return None def changeUser_Form(self, name, REQUEST=None): """ """ user=self.data[name].__of__(self) return self.changeUserForm(self, REQUEST=REQUEST, user=user, password=user._getPassword()) def changeUser(self, name, password, roles, domains, REQUEST=None): """ """ user=self.data[name] user._pw_=password user.roles=roles user.domains=domains if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def changeUserPassword(self, name, password, domains, REQUEST=None): """ """ user=self.data[name] user._pw_=password user.domains=domains if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def delUser(self, names, REQUEST=None): """ """ # Delete and clean up after a user members=self.Members for name in names: if self.data.has_key(name): del self.data[name] if hasattr(members.aq_base, name): members._delObject(name) if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) === Added File Products/PortalBase/User.gif === === Added File Products/PortalBase/ZopeSite.py === import sys, os, string, time, random from DateTime import DateTime def getOwners(self, join=string.join): dict=self.__ac_local_roles__ or {} list=[] for key, val in dict.items(): if 'Owner' in val: list.append(key) return join(list, ', ') def approveNewsItem(self, REQUEST=None): """ """ for ps in self.propertysheets.values(): ps.manage_changeProperties(REQUEST=REQUEST) # Add to catalog here... self.title=title def ReturnFindableAttributes(self): """ Should be bound to an objects 'ZopeCatalogAttributes' method """ fas = () for x in self.__class__.__bases__: if hasattr(x, 'findableAttributes'): if x.findableAttributes: for i in x.findableAttributes: (n, a, t, i) = string.split(i) fas.append({'name' : n, 'attr' : a, 'type' : t, 'index' : i}) if self.findableAttributes: for i in self.findableAttributes: (n, a, t, i) = string.split(i) fas.append({'name' : n, 'attr' : a, 'type' : t, 'index' : i}) return fas def DelObjects(self, ids, REQUEST): """ Deletes an list of objects from the catalog """ urls = [] for n in ids: urls.append(getattr(self, n).absolute_url()) self.Catalog.manage_catalogRemove(urls=urls) self.manage_delObjects(ids) return self.manage_main(self, REQUEST) # Registration methods # -------------------- chars=string.letters+string.digits def gen_password(choose=random.choice, chars=chars, join=string.join): result=[] for n in range(8): result.append(choose(chars)) return join(result, '') def register(self, username='', fullname='', company='', email='', REQUEST=None): """ """ register_html=getattr(self, 'register.html') if not username or not email: return register_html(self, REQUEST, error='You must enter a value for Name and a valid Email ' \ 'Address.') user=self.acl_users.getUser(username) if user is not None: return register_html(self, REQUEST, error='The login name you selected is already in use. Please ' \ 'choose another.') password=gen_password() # Add the member self.acl_users.addUser(username, password, ['Member'], []) # Here we add a new Folder for this user in Members, # giving the user the local role 'Owner' in his Folder. members=self.Members members.manage_addFolder(username) folder=getattr(members, username) folder.manage_setLocalRoles(username, ['Owner']) # Generate email notification self.notify(self, REQUEST, password=password) return getattr(self, 'success.html')(self, REQUEST) # MemberFolder methods # -------------------- def fixup_user(user): if hasattr(user, 'last_visit'): if not user.last_visit.isCurrentDay(): user.last_visit=DateTime().earliestTime() return user def addMemberFolder(self, REQUEST=None): if hasattr(self.aq_base, 'acl_users'): return MessageDialog( title ='Item Exists', message='This object already contains a User Folder', action ='%s/manage_main' % REQUEST['URL1']) dest=self.Destination() __traceback_info__=(hasattr(dest.aq_base, 'acl_users'),) ob=self.MemberFolder('acl_users', REQUEST) dest.__allow_groups__=dest.acl_users if REQUEST: return dest.manage_main(dest, REQUEST, update_menu=1) def addUser(self, name, password, roles, domains, REQUEST=None): """ """ zclass=self.Control_Panel.Products.ZopeSite.MemberFolder.Member._zclass_ user=zclass(name, password, roles, domains) user.id=name self.data[name]=user # Here we add a new Folder for this user in Members, # giving the user the local role 'Owner' in his Folder. members=self.Members members.manage_addFolder(name) folder=getattr(members, name) if REQUEST is not None: user=REQUEST.get('AUTHENTICATED_USER', None) if user is not None: folder.manage_delLocalRoles([user.getUserName()]) folder.manage_setLocalRoles(name, ['Owner']) if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def getUser(self, name): """ """ if self.data.has_key(name): user=self.data[name].__of__(self) user=fixup_user(user) return user return None def changeUser_Form(self, name, REQUEST=None): """ """ user=self.data[name].__of__(self) return self.changeUserForm(self, REQUEST=REQUEST, user=user, password=user._getPassword()) def changeUser(self, name, password, roles, domains, REQUEST=None): """ """ user=self.data[name] user.__=password user.roles=roles user.domains=domains if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def delUser(self, names, REQUEST=None): """ """ # Delete and clean up after a user members=self.Members for name in names: if self.data.has_key(name): del self.data[name] if hasattr(members.aq_base, name): members._delObject(name) if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) === Added File Products/PortalBase/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Portal services base objects""" __version__='$Revision: 1.1 $'[11:-2] from ImageFile import ImageFile import MemberFolder, Documents # This is the new way to initialize products. It is hoped # that this more direct mechanism will be more understandable. def initialize(context): ## perm='Add Member Folder' ## context.registerClass( ## MemberFolder.MemberFolder, ## permission=perm, ## constructors=(MemberFolder.addForm, Membership.add,), ## icon='MemberFolder.gif', ## ) context.registerBaseClass(MemberFolder.MemberFolder) context.registerBaseClass(MemberFolder.Member) context.registerBaseClass(Documents.HTMLDocument, 'HTML Document') context.registerBaseClass(Documents.HTMLMethod, 'HTML Method') # context.registerBaseClass(AccessControl.User.User) # context.registerZClass(ZClasses.ObjectManager.ZObjectManager) ## __ac_permissions__=( ## ('Add Subscription Dbs', ('manage_addSubscriptionDbForm', ## 'manage_addSubscriptionDb')), ## ('Change Subscription Dbs', ()), ## ) From sidnei at x3ng.com.br Fri May 30 11:17:54 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/Redirector/www - RedirectorIcon.gif:1.1 Message-ID: <200305301517.h4UFHsC20622@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Redirector/www In directory cvs.zope.org:/tmp/cvs-serv19195/Redirector/www Added Files: RedirectorIcon.gif Log Message: Adding products needed for migration of NZO === Added File Products/Redirector/www/RedirectorIcon.gif === From sidnei at x3ng.com.br Fri May 30 11:17:53 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/Redirector - README.txt:1.1 Redirector.py:1.1 VERSION.txt:1.1 __init__.py:1.1 addRedirector_form.dtml:1.1 manageRedirector.dtml:1.1 Message-ID: <200305301517.h4UFHrs20607@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Redirector In directory cvs.zope.org:/tmp/cvs-serv19195/Redirector Added Files: README.txt Redirector.py VERSION.txt __init__.py addRedirector_form.dtml manageRedirector.dtml Log Message: Adding products needed for migration of NZO === Added File Products/Redirector/README.txt === Redirector Copyright © 1999 "Alexander Staubo":mailto:alex@mop.no. Extended 1999 "Dylan Jay":mailto:djay@slarken.org.au.
  ANY USE BY YOU OF THE SOFTWARE IS AT YOUR OWN RISK. THE SOFTWARE IS PROVIDED
  FOR USE "AS IS" WITHOUT WARRANTY OF ANY KIND. TO THE MAXIMUM EXTENT
  PERMITTED BY LAW, THE AUTHOR (ALEXANDER STAUBO) DISCLAIMS ALL WARRANTIES OF
  ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED
  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. THE AUTHOR (ALEXANDER STAUBO) IS NOT OBLIGATED TO PROVIDE
  ANY UPDATES TO THE SOFTWARE. SO THERE.
  
What it Does Redirector is an experimental folder product for redirecting object requests. Any request to a subobject (whether it exists or not) in the folder is redirected to a designated target URL. A flexible mechanism for mapping specific URLs is also provided. For example, you might have an URL such as *http: //oldserver/foo* (running Zope, of course) which you've moved to your brand new server *http://newserver/bar* (Zope not required). Once you have deleted or moved the foo folder or object out of the way, create a Redirector object called *foo*, set its Target property to *http://newserver/bar*, following which requests for *http://oldserver/foo* will then be redirected to *http://newserver/bar*. Given this, if a user then requests *http://oldserver/foo/fnargh*, the request will simply be redirected to *http://newserver/bar/fnargh*. In fact a call such as *http://oldserver/foo/fnargh/something/doSomething?param=blah* will also correctly redirect to *http://newserver/bar/fnargh/something/doSomething?param=blah* The Redirector object also supports exceptions to this rule: For example, if the old server had a subobject called *milk*, which now exists on the new server under the name of *honey*, then you can create a mapping which simply maps the old object to the new object. Mappings support (or rather, require) regular expressions to be used, so you could also map any object starting with the letter *M* to a specific object. Regular expression groups are supported. A \n where n is an integer in the replacement field will be replaced by the corresponding group in the FROM: field. See the python regular expression syntax for clarification on this. Added bonus feature: If you set the Redirector to "hard mapping" mode, it will fall back to the default target URL if none of the mappings match the requested URL. That means -- if you're like me, converting a dull old Netscape server to a new Zope site with lots of magic fairy dust added -- that you can create mappings for all the old documents that should be redirected to their Zopefied counterpart URLs, but for all the documents that are deprecated on the new server, the redirection will be set to the server's root folder. Documentation File under "self-explanatory". In short, what you're seeing here is what you get. Bugs and Such This being an experimental Zope Product, I can't promise that it will work as promised. Indeed, I won't promise anything. I can only give the typical excuse that "it works here". Please report problems to "me":mailto:alex@mop.no. If you include the line "This is important and you're just one dandy programmer, Alex!" I'll promise to give you lots of priority. Future Improvements === Added File Products/Redirector/Redirector.py === # Redirector 1.1 Copyright (c) 1999 Alexander Staubo # Extended 9/1999 Dylan Jay # See README.txt for more information about this Zope product. # $Header: /var/cvs-zopeorg/Products/Redirector/Redirector.py,v 1.1 2003/05/30 15:17:52 sidnei Exp $ __version__ = '$Revision: 1.1 $'[11:-2] from Globals import Persistent, HTMLFile, HTML, MessageDialog from AccessControl.Role import RoleManager import Acquisition import sys import string import OFS import Globals import time import copy import re manage_addRedirectorForm = HTMLFile('addRedirector_form', globals()) def manage_addRedirector(self, id, title = '', Target = '', Mappings = {}, HardMap = 0, REQUEST = None): '''Add a Redirector into the system''' Obj = Redirector() Obj.id = id Obj.title = title Obj._init(Target, Mappings, HardMap) self._setObject(id, Obj) if REQUEST: return self.manage_main(self, REQUEST) class RedirectorBase(Acquisition.Implicit, OFS.Folder.Folder, RoleManager): '''Redirector base class''' meta_type = 'Redirector' icon = 'misc_/Redirector/icon' manage = manage_main = HTMLFile('manageRedirector', globals()) manage_options = ( {'icon': '', 'label': 'Edit', 'action': 'manage_main', 'target': 'manage_main'}, {'icon': '', 'label': 'Security', 'action': 'manage_access', 'target': 'manage_main'}, ) __ac_permissions__ = OFS.Folder.Folder.__ac_permissions__ + ( ('View management screens', ('manage',)), ('Change configuration', ('manage_makeChanges',)), ('Use Redirector services',('',)), ) def __init__(self): '''Initialize''' self.Target = '' self.Mappings = {} self.HardMap = 0 def _init(self, Target, Mappings = {}, HardMap = 0): '''Initialize with configuration''' self.Mappings = copy.copy(Mappings) self.Target = Target self.HardMap = HardMap def manage_makeChanges(self, title = '', Target = '', HardMap = 0, MapFrom = [], MapTo = [], REQUEST = None): '''Perform changes''' self.title = title NewMap = {} i = 0 while i < len(MapFrom): NewMap[MapFrom[i]] = MapTo[i] i = i + 1 for k in NewMap.keys(): if not (k and NewMap[k]): del NewMap[k] self._init(Target, NewMap, HardMap) if REQUEST: return MessageDialog( title = 'Changed %s' % self.id, message = '%s has been updated' % self.id, action = REQUEST['URL1'] + '/manage_main', target = 'manage_main') def __bobo_traverse__(self, REQUEST, Name = ''): if Name[:6] != 'manage': import ExtensionClass class doTraverse(ExtensionClass.Base): def __init__(self, path, Mappings, Target, HardMap): self.path = path self.Mappings = Mappings self.Target = Target self.HardMap = HardMap def __bobo_traverse__(self, REQUEST, Name = ''): self.path = self.path + '/' + Name return self.__class__(self.path, self.Mappings, self.Target, self.HardMap) def __call__(self, REQUEST): path = self.path if REQUEST['QUERY_STRING']: path = path + "?" + REQUEST['QUERY_STRING'] for k in self.Mappings.keys(): if re.match(k, path): path = re.sub(k, self.Mappings[k], path) break else: if self.HardMap: raise 'Redirect', self.Target def Merge(Target, Url): if Url[:5] == 'http:' or Url[:4] == 'ftp:': return Url else: return Target + Url raise 'Redirect', Merge(self.Target , path) return doTraverse(Name, self.Mappings, self.Target, self.HardMap) if hasattr(self, 'aq_base'): b = self.aq_base if hasattr(b, Name): return getattr(self, Name) try: return self[Name] except: return getattr(self, Name) def index_html(self): raise 'Redirect', self.Target class Redirector(RedirectorBase, Persistent): '''Redirector product''' === Added File Products/Redirector/VERSION.txt === 1.1 === Added File Products/Redirector/__init__.py === # Redirector 1.0 Copyright (c) 1999 Alexander Staubo # See README.txt for more information about this Zope product. # $Header: /var/cvs-zopeorg/Products/Redirector/__init__.py,v 1.1 2003/05/30 15:17:52 sidnei Exp $ __version__ = '$Revision: 1.1 $'[11:-2] __doc__='''Redirector Product Initialization''' import Redirector def initialize(context): context.registerClass( Redirector.Redirector, permission = 'Add Redirector objects', constructors = ( Redirector.manage_addRedirectorForm, Redirector.manage_addRedirector), icon = 'www/RedirectorIcon.gif', legacy = ( ('manage_addRedirector', Redirector.manage_addRedirector), ('manage_addRedirector_form', Redirector.manage_addRedirectorForm), ) ) === Added File Products/Redirector/addRedirector_form.dtml === Add Redirector

Add Redirector

A redirector object transparently redirects all sub-requests to another URL.

For example, if the redirector object is /Zope and the target is set to http://www.zope.org, then any request for /Zope/foo.html will be redirected to http://www.zope.org/foo.html.

Target must be an absolute or relative URL. If it denotes a folder, it must end with a slash, thus: http://www.zorg.org/Projects/.

Id
Title
Target
 
=== Added File Products/Redirector/manageRedirector.dtml === Edit Redirector

Target must be an absolute or relative URL. If it denotes a folder, it must end with a slash, thus: http://www.zope.org/Projects/.

Mappings is a list of URL mappings. The "From" part is compared against the requested sub-URL (including query string if any) and, if matching, translated into the "To" part. If the "To" part starts with http: or ftp:, the URL is preserved; otherwise, it is appended to the URL in Target. Groups matched in the "From" part will replace "\n" type strings in the "To" part, where "n" is an integer.

Id
Title
Target (absolute or relative URL)
Hard mapping mode checked value="1"> If checked, mappings are required to match. If a match fails, Target is used by default, ignoring the requested URL.
Mappings
From (regular expression)   To
 
  ">

From sidnei at x3ng.com.br Fri May 30 11:17:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ZDBase - README.txt:1.1 ZDiscussions.py:1.1 __init__.py:1.1 Message-ID: <200305301517.h4UFHwq20798@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZDBase In directory cvs.zope.org:/tmp/cvs-serv19195/ZDBase Added Files: README.txt ZDiscussions.py __init__.py Log Message: Adding products needed for migration of NZO === Added File Products/ZDBase/README.txt === Z Discussions Base Classes Contents About this release What is ZDBase? License and support About this release This is the first public release of ZDBase. It is very much beta. It is likely to work, but it may not work in the way you'd like it to. Please feel free to submit bug reports and feature requests to Mike Pelleter at mike@digicool.com. What is ZDBase? Unlike most Products, this one doesn't add anything to your Add menu. ZDBase contains two classes which are the base classes for the ZDConfera and ZDiscussions discussion objects. To get any use out of ZDBase, you will need to install one of those (and vice versa). ZDBase provides these services: o Body searches o Interesting searches such as new since last visit, replies to an author, most popular posts, etc. o Thread management o RSS channels (erm, next release.) License and support Z Discussions and ZDConfera have been released under the Zope Public License (ZPL). Please see http://www.zope.org/Resources/License. This release is officially unsupported. It is presently under the care of Mike Pelletier ( mike@digicool.com ) who will be happy to offer unofficial support. === Added File Products/ZDBase/ZDiscussions.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## # Not only that, but this software is NOT supported by Digital Creations. # Send comments and questions to mike@digicool.com __doc__ = "ZDiscussions Base Classes" __version__ = "0.2.0" import Globals, OFS, Products, AccessControl from Products.ZCatalog import ZCatalog from Acquisition import Implicit from Globals import HTMLFile, Persistent from DateTime import DateTime def manage_addZDTopic(self, id, title, REQUEST=None): """Add a ZDTopic object""" topic = ZDTopic(id, title) self._setObject(id, topic) if REQUEST is not None: return self.manage_main(self, REQUEST) class ZDItem(OFS.SimpleItem.SimpleItem, OFS.PropertyManager.PropertyManager, Persistent, Implicit, AccessControl.Role.RoleManager): """ZDItem object""" meta_type = "Z Discussions Item Base Class" _properties = ( {'id':'title', 'type':'string', 'mode':'w'}, {'id':'author', 'type':'string', 'mode':'w'}, {'id':'email', 'type':'string', 'mode':'w'}, {'id':'body', 'type':'text', 'mode':'w'}, {'id':'in_reply_to', 'type':'string', 'mode':''} ) manage_options = ( {'label':'Properties', 'action':'manage_propertiesForm'} ) __ac_permissions__ = ( ('Manage properties', ('manage_addProperty', 'manage_editProperties', 'manage_delProperties', 'manage_changeProperties',)), ) def __init__(self, id, title, body, author, email, in_reply_to): self.id = id self.title = title self.author = author self.email = email self.body = body self.in_reply_to = in_reply_to self.created = self.modified = DateTime() def ancestors(self): """Return a list of ancestral posts""" ancestors = [] irp = self.in_reply_to while irp: parent = getattr(self.aq_parent, irp) ancestors = ancestors + [parent] irp = parent.in_reply_to return ancestors def children(self, REQUEST=None): """Return a list of replies to this item""" if REQUEST is None: REQUEST = self.REQUEST children = [] results = self.searchResults(in_reply_to=self.id) #, sort_on="created") children = map(lambda x, self=self, REQUEST=REQUEST: self.getobject(x.data_record_id_, REQUEST), results) return children def manage_addReply(self, id, title, body, author, email, REQUEST=None): """Add a ZDItem to this ZDTopic""" item = ZDItem(id, title, body, author, email, self.id) self.aq_parent._setObject(id, item) if REQUEST is not None: return self.manage_main(self, REQUEST) def manage_afterAdd(self, item, container): OFS.SimpleItem.SimpleItem.manage_afterAdd(self, item, container) self.catalog_object(self, self.absolute_url(1)) # Am thinkink this is bad - # I seem to recall 'self' is not part of the acquisition hierarchy when # afterClone is called, resulting in error. Test. def manage_afterClone(self, item, container): OFS.SimpleItem.SimpleItem.manage_afterClone(self, item, container) self.catalog_object(self, self.absolute_url(1)) def manage_beforeDelete(self, item, container): # Prevent orphans for child in self.children(): child.in_reply_to = self.in_reply_to OFS.SimpleItem.SimpleItem.manage_beforeDelete(self, item, container) try: self.uncatalog_object(self.absolute_url(1)) except ValueError: pass class ZDTopic(ZCatalog.ZCatalog): """ZDTopic object""" meta_type = 'Z Discussions Topic Base Class' manage_options=( {'label': 'Contents', 'action': 'manage_main', 'target': 'manage_main'}, {'label': 'Cataloged Objects', 'action': 'manage_catalogView', 'target': 'manage_main'}, {'label': 'MetaData Table', 'action': 'manage_catalogSchema', 'target':'manage_main'}, {'label': 'Indexes', 'action': 'manage_catalogIndexes', 'target':'manage_main'}, {'label': 'Status', 'action': 'manage_catalogStatus', 'target':'manage_main'}, ) def __init__(self, id, title=''): # Initialise ZCatalog ZCatalog.ZCatalog.__init__(self, id, title) # Set up the indexes self._catalog.addIndex('body', 'TextIndex') self._catalog.addIndex('author', 'FieldIndex') self._catalog.addIndex('email', 'FieldIndex') self._catalog.addIndex('in_reply_to', 'FieldIndex') self._catalog.addIndex('created', 'FieldIndex') self._catalog.addIndex('modified', 'FieldIndex') # Set up meta-data columns self._catalog.addColumn('body') self._catalog.addColumn('author') self._catalog.addColumn('email') self._catalog.addColumn('in_reply_to') self._catalog.addColumn('created') self._catalog.addColumn('modified') def manage_editZDTopic(self, title, REQUEST=None): """Set properties of ZDTopic. Presently just title.""" self.title = title if REQUEST: return self.manage_main(self, REQUEST, manage_tabs_message = "ZDTopic changed.") def posts(self, REQUEST=None): """Return the top-level posts""" if REQUEST is None: REQUEST=self.REQUEST posts = [] for res in self.searchResults(in_reply_to=''): #, sort_on='created'): posts.append(self.getobject(res.data_record_id_, REQUEST)) return posts children = posts def generate_id(self): """Find an available ID""" id = 0 fmt = "%08d" while hasattr(self, fmt % id): id = id + 1 return fmt % id def manage_addZDItem(self, id, title, body, author, email, in_reply_to='', REQUEST=None): """Add a ZDItem to this ZDTopic""" item = ZDItem(id, title, body, author, email, in_reply_to) self._setObject(id, item) if REQUEST is not None: return self.manage_main(self, REQUEST) === Added File Products/ZDBase/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import ZDiscussions __doc__ = ZDiscussions.__doc__ __version__ = ZDiscussions.__version__ def initialize(context): context.registerBaseClass(ZDiscussions.ZDTopic) context.registerBaseClass(ZDiscussions.ZDItem) From sidnei at x3ng.com.br Fri May 30 11:17:29 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/DOM - Core.py:1.1 Exceptions.py:1.1 ExpatBuilder.py:1.1 LoadSave.py:1.1 SAXBuilder.py:1.1 Traversal.py:1.1 XMLExtended.py:1.1 __init__.py:1.1 Message-ID: <200305301517.h4UFHTh19346@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/DOM In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/DOM Added Files: Core.py Exceptions.py ExpatBuilder.py LoadSave.py SAXBuilder.py Traversal.py XMLExtended.py __init__.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/DOM/Core.py === (2243/2343 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 2243 lines omitted -=- -=- -=-] return oldNode def _delFromParentList(self, attrs, i): "workhorse for __delitem__; remove ith item from attrs" del attrs[i] #XXX ownerElement needs to be updated in other refs self._parent._changed() def _addToParentList(self, attrs, node): if self._parent._attributes: self._parent._attributes.append(node._item) else: self._parent.__dict__['_attributes'] = [node._item] self._parent._changed() def _key_helper(self, itemSource): "given an item source, return an appropriate key for our mapping" return itemSource[_ATTR_NAME] # Utility functions for Attrs, used by more than the Attr class. def _attr_item_match_name(item, name, _ATTR_NAME=_ATTR_NAME): "utility function for AttributeMap; return true if name matches item" return item[_ATTR_NAME] == name def _attr_item_match_ns(item, (namespaceURI, localName), _ATTR_NS=_ATTR_NS, _ATTR_LOCALNAME=_ATTR_LOCALNAME): "utility function for AttributeMap; return true if name matches item" return (item[_ATTR_LOCALNAME] == localName and item[_ATTR_NS] == namespaceURI) def _attr_get_value(nodes): "utility function to get attr value; concatenate values of list of nodes" L = [] for node in nodes: L.append(node.nodeValue) return _string.join(filter(None, L), '') def _attr_set_value(item, value): "utility function to safely set shared value of attr item" newChild = Text(value) del newChild.__dict__['_in_tree'] while item[_ATTR_VALUE]: item[_ATTR_VALUE].pop() item[_ATTR_VALUE].append(newChild) # no longer needed del ComputedAttribute === Added File Products/ParsedXML/DOM/Exceptions.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Replacement DOM exceptions to be used if the xml.dom package is not available. """ """ Why does this module exist? The Python DOM API defines exceptions that DOM implementations should use to allow DOM client code to detect errors that can occur during processing. Since not all client code knows about the DOM implementation used, all implementations must use shared exceptions. These are defined in the xml.dom package (in the package's __init__.py). The xml.dom package is provided as part of PyXML and Python 2.0. Since ParsedXML may be used from Python 1.5.2 without having PyXML or a more recent version of Python available, we need to provide an alternate implementation. However, DOM client code that works on DOM instances created elsewhere will still expect to get the exception classes from xml.dom. Since the code may be part of third-party packages that know nothing of ParsedXML or Zope, we need to provide an implementation of xml.dom if it doesn't already exist. So how does this module solve the problem? This module defines the required exception objects and constants and 'installs' the values in the xml.dom module if they are not already present. Since the xml.dom module may not exist, or may pre-date the addition of these exceptions to the standard implementation (Python 2.0 or PyXML 0.6.2), the modules xml and xml.dom are created by surgically adding them to sys.modules if needed, and inserting the required values into an existing xml.dom module if needed. This works because of the way the module import machinery works in Python. sys.modules is a mapping from module name to module object; sys.modules['sys'] evaluates to the sys module object. When an import statement is executed, the Python runtime first looks in sys.modules to retrieve an already-loaded module. The set of built-in modules and the filesystem are only consulted if the module has not already been loaded. For modules in packages (xml.dom), each level of enclosing package is checked before attempting to load the module; i.e., xml is checked before xml.dom. This machinery is invoked each time an import is attempted. When ParsedXML.DOM is imported, it imports this module. This first attempts to load the standard xml.dom package. If that fails (which it is likely to do for Python 1.5.2 without PyXML installed), this module is an acceptable implementation of xml.dom, but we still need the xml package. This is created artificially using the new.module() function and inserted in sys.modules. Once this is done, this module may be inserted for the key 'xml.dom', after which attempts to import xml.dom will provide this module. If xml.dom is already available, but older than the introduction of DOMException and its specializations, the implementations defined here are inserted into it, so that it is extended to match the more recent version of the interface definition. What are the limitations of this approach? Some versions of PyXML may have defined DOMException without defining the subclasses. The specialized versions of DOMException were added in PyXML version 0.6.3 (XXX ??). Versions which contain DOMException but not the specializations will not be compatible with this module. This should not be a substantial limitation in the context of Zope. There is no way to protect against code that imports xml.dom before ParsedXML.DOM has been imported. Such code will receive an ImportError. Reloading that code after ParsedXML.DOM is imported will cause it to work properly. """ # These have to be in order: _CODE_NAMES = [ "INDEX_SIZE_ERR", "DOMSTRING_SIZE_ERR", "HIERARCHY_REQUEST_ERR", "WRONG_DOCUMENT_ERR", "INVALID_CHARACTER_ERR", "NO_DATA_ALLOWED_ERR", "NO_MODIFICATION_ALLOWED_ERR", "NOT_FOUND_ERR", "NOT_SUPPORTED_ERR", "INUSE_ATTRIBUTE_ERR", "INVALID_STATE_ERR", "SYNTAX_ERR", "INVALID_MODIFICATION_ERR", "NAMESPACE_ERR", "INVALID_ACCESS_ERR", ] for i in range(len(_CODE_NAMES)): globals()[_CODE_NAMES[i]] = i + 1 del i class DOMException(Exception): """Base class for exceptions raised by the DOM.""" def __init__(self, code, *args): self.code = code self.args = (code,) + args Exception.__init__(self, g_errorMessages[code]) if self.__class__ is DOMException: self.__class__ = g_realExceptions[code] def _derived_init(self, *args): """Initializer method that does not expect a code argument, for use in derived classes.""" if not args: args = (self, g_errorMessages[self.code]) else: args = (self,) + args apply(Exception.__init__, args) try: from xml.dom import DOMException except ImportError: pass import string _EXCEPTION_NAMES = ["DOMException"] template = """\ class %s(DOMException): code = %s __init__ = _derived_init """ g_realExceptions = {} for s in _CODE_NAMES: words = string.split(string.lower(s), "_") ename = string.join(map(string.capitalize, words), "") exec template % (ename, s) g_realExceptions[globals()[s]] = globals()[ename] _EXCEPTION_NAMES.append(ename) del s, words, ename, string, template try: import xml.dom except ImportError: # We have to define everything, which we've done above. # This installs it: import sys try: mod = __import__("xml") except ImportError: import new mod = new.module("xml") del new sys.modules["xml"] = mod import Exceptions mod.dom = Exceptions sys.modules["xml.dom"] = Exceptions del mod, sys del Exceptions from Core import Node else: # The exception classes may not have been defined, so add any # that are needed. import Exceptions for s in _CODE_NAMES + _EXCEPTION_NAMES: if not hasattr(xml.dom, s): setattr(xml.dom, s, getattr(Exceptions, s)) if not hasattr(xml.dom, "Node") or type(xml.dom.Node) is type(Exceptions): # We need to provide the Node class so the .nodeType constants # are in the right place. import Core xml.dom.Node = Core.Node del Core del s, Exceptions del _CODE_NAMES, _EXCEPTION_NAMES g_errorMessages = { INDEX_SIZE_ERR: "Index error accessing NodeList or NamedNodeMap", DOMSTRING_SIZE_ERR: "DOMString exceeds maximum size.", HIERARCHY_REQUEST_ERR: "Node manipulation results in invalid parent/child relationship.", WRONG_DOCUMENT_ERR: "", INVALID_CHARACTER_ERR: "", NO_DATA_ALLOWED_ERR: "", NO_MODIFICATION_ALLOWED_ERR: "Attempt to modify a read-only attribute.", NOT_FOUND_ERR: "", NOT_SUPPORTED_ERR: "DOM feature not supported.", INUSE_ATTRIBUTE_ERR: "Illegal operation on an attribute while in use by an element.", INVALID_STATE_ERR: "", SYNTAX_ERR: "", INVALID_MODIFICATION_ERR: "", NAMESPACE_ERR: "Namespace operation results in malformed or invalid name or name declaration.", INVALID_ACCESS_ERR: "", } # To be sure that unused alternate implementations of the DOM # exceptions are not used by accessing this module directly, import # the "right" versions over those defined here. They may be the same, # and they may be from an up-to-date PyXML or Python 2.1 or newer. # This causes alternate implementations to be discarded if not needed. from xml.dom import * === Added File Products/ParsedXML/DOM/ExpatBuilder.py === (840/940 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 840 lines omitted -=- -=- -=-] def default_handler(self, s): self.subset.append(s) def parse(file, namespaces=1): """Parse a document, returning the resulting Document node. 'file' may be either a file name or an open file object. """ if namespaces: builder = ExpatBuilderNS() else: builder = ExpatBuilder() if isinstance(file, type('')): fp = open(file, 'rb') result = builder.parseFile(fp) fp.close() else: result = builder.parseFile(file) return result def parseFragment(file, context, namespaces=1): """Parse a fragment of a document, given the context from which it was originally extracted. context should be the parent of the node(s) which are in the fragment. 'file' may be either a file name or an open file object. """ if namespaces: builder = FragmentBuilderNS(context) else: builder = FragmentBuilder(context) if isinstance(file, type('')): fp = open(file, 'rb') result = builder.parseFile(fp) fp.close() else: result = builder.parseFile(file) return result def makeBuilder(options): """Create a builder based on an Options object.""" if options.namespaces: return ExpatBuilderNS(options) else: return ExpatBuilder(options) === Added File Products/ParsedXML/DOM/LoadSave.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Implementation of the DOM Level 3 'Load' feature.""" import Core import ExpatBuilder import copy import string import xml.dom __all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"] class DOMBuilder(Core.AttributeControl): entityResolver = None errorHandler = None filter = None def __init__(self): self.__dict__['_options'] = ExpatBuilder.Options() def _get_entityResolver(self): return self.entityResolver def _set_entityResolver(self, entityResolver): self.__dict__['entityResolver'] def _get_errorHandler(self): return self.errorHandler def _set_errorHandler(self, errorHandler): self.__dict__['errorHandler'] = errorHandler def _get_filter(self): return self.filter def _set_filter(self, filter): self.__dict__['filter'] = filter def setFeature(self, name, state): if self.supportsFeature(name): try: settings = self._settings[(_name_xform(name), state)] except KeyError: raise xml.dom.NotSupportedErr( "unsupported feature: " + `name`) else: for name, value in settings: setattr(self._options, name, value) else: raise xml.dom.NotFoundErr("unknown feature: " + `name`) def supportsFeature(self, name): return hasattr(self._options, _name_xform(name)) def canSetFeature(self, name, state): key = (_name_xform(name), state and 1 or 0) return self._settings.has_key(key) _settings = { ("namespaces", 0): [("namespaces", 0)], ("namespaces", 1): [("namespaces", 1)], ("namespace_declarations", 0): [("namespace_declarations", 0)], ("namespace_declarations", 1): [("namespace_declarations", 1)], ("validation", 0): [("validation", 0)], ("external_general_entities", 0): [("external_general_entities", 0)], ("external_general_entities", 1): [("external_general_entities", 1)], ("external_parameter_entities", 0): [("external_parameter_entities", 0)], ("external_parameter_entities", 1): [("external_parameter_entities", 1)], ("validate_if_cm", 0): [("validate_if_cm", 0)], ("create_entity_ref_nodes", 0): [("create_entity_ref_nodes", 0)], ("create_entity_ref_nodes", 1): [("create_entity_ref_nodes", 1)], ("entity_nodes", 0): [("create_entity_ref_nodes", 0), ("entity_nodes", 0)], ("entity_nodes", 1): [("entity_nodes", 1)], ("white_space_in_element_content", 0): [("white_space_in_element_content", 0)], ("white_space_in_element_content", 1): [("white_space_in_element_content", 1)], ("cdata_nodes", 0): [("cdata_nodes", 0)], ("cdata_nodes", 1): [("cdata_nodes", 1)], ("comments", 0): [("comments", 0)], ("comments", 1): [("comments", 1)], ("charset_overrides_xml_encoding", 0): [("charset_overrides_xml_encoding", 0)], ("charset_overrides_xml_encoding", 1): [("charset_overrides_xml_encoding", 1)], } def getFeature(self, name): try: return getattr(self._options, _name_xform(name)) except AttributeError: raise xml.dom.NotFoundErr() def parseURI(self, uri): if self.entityResolver: input = self.entityResolver.resolveEntity(None, uri) else: input = DOMEntityResolver().resolveEntity(None, uri) return self.parseDOMInputSource(input) def parseDOMInputSource(self, input): options = copy.copy(self._options) options.filter = self.filter options.errorHandler = self.errorHandler fp = input.byteStream if fp is None and options.systemId: import urllib fp = urllib.urlopen(input.systemId) builder = ExpatBuilder.makeBuilder(options) return builder.parseFile(fp) class DOMEntityResolver(Core.DOMImplementation): def resolveEntity(self, publicId, systemId): source = DOMInputSource() source.publicId = publicId source.systemId = systemId if systemId: import urllib self.byteStream = urllib.urlopen(systemId) # Should parse out the content-type: header to # get charset information so that we can set the # encoding attribute on the DOMInputSource. return source class DOMInputSource(Core.AttributeControl): byteStream = None characterStream = None encoding = None publicId = None systemId = None def _get_byteStream(self): return self.byteStream def _set_byteStream(self, byteStream): self.__dict__['byteStream'] = byteStream def _get_characterStream(self): return self.characterStream def _set_characterStream(self, characterStream): self.__dict__['characterStream'] = characterStream def _get_encoding(self): return self.encoding def _set_encoding(self, encoding): self.__dict__['encoding'] = encoding def _get_publicId(self): return self.publicId def _set_publicId(self, publicId): self.__dict__['publicId'] = publicId def _get_systemId(self): return self.systemId def _set_systemId(self, systemId): self.__dict__['systemId'] = systemId class DOMBuilderFilter: """Element filter which can be used to tailor construction of a DOM instance. """ # There's really no need for this class; concrete implementations # should just implement the endElement() method as appropriate. def endElement(self, element): # Why this method is supposed to return anything at all # is a mystery; the result doesn't appear to be used. return 1 def _name_xform(name): return string.replace(string.lower(name), '-', '_') === Added File Products/ParsedXML/DOM/SAXBuilder.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Constructor for ParsedXML.DOM, based on a SAX parser.""" import os import urllib import xml.sax class SAXBuilder(xml.sax.ContentHandler): _locator = None document = None documentElement = None def __init__(self, documentFactory=None): self.documentFactory = documentFactory self._ns_contexts = [{}] # contains uri -> prefix dicts self._current_context = self._ns_contexts[-1] def install(self, parser): parser.setContentHandler(self) def setDocumentLocator(self, locator): self._locator = locator def startPrefixMapping(self, prefix, uri): self._ns_contexts.append(self._current_context.copy()) self._current_context[uri] = prefix or None def endPrefixMapping(self, prefix): self._current_context = self._ns_contexts.pop() def _make_qname(self, uri, localname, tagname): # When using namespaces, the reader may or may not # provide us with the original name. If not, create # *a* valid tagName from the current context. if uri: if tagname is None: prefix = self._current_context.get(uri) if prefix: tagname = "%s:%s" % (prefix, localname) else: tagname = localname else: tagname = localname return tagname def startElementNS(self, name, tagName, attrs): uri, localname = name tagName = self._make_qname(uri, localname, tagName) if not self.document: factory = self.documentFactory self.document = factory.createDocument(uri or None, tagName, None) node = self.document.documentElement else: if uri: node = self.document.createElementNS(uri, tagName) else: node = self.document.createElement(localname) self.curNode.appendChild(node) self.curNode = node for aname, value in attrs.items(): a_uri, a_localname = aname if a_uri: qname = "%s:%s" % (self._current_context[a_uri], a_localname) node.setAttributeNS(a_uri, qname, value) else: attr = self.document.createAttribute(a_localname) node.setAttribute(a_localname, value) def endElementNS(self, name, tagName): self.curNode = self.curNode.parentNode def startElement(self, name, attrs): if self.documentElement is None: factory = self.documentFactory self.document = factory.createDocument(None, name, None) node = self.document.documentElement self.documentElement = 1 else: node = self.document.createElement(name) self.curNode.appendChild(node) self.curNode = node for aname, value in attrs.items(): node.setAttribute(aname, value) def endElement(self, name): self.curNode = self.curNode.parentNode def comment(self, s): node = self.document.createComment(s) self.curNode.appendChild(node) def processingInstruction(self, target, data): node = self.document.createProcessingInstruction(target, data) self.curNode.appendChild(node) def ignorableWhitespace(self, chars): node = self.document.createTextNode(chars) self.curNode.appendChild(node) def characters(self, chars): node = self.document.createTextNode(chars) self.curNode.appendChild(node) def parse(file, namespaces=1, dom=None, parser=None): if not parser: parser = xml.sax.make_parser() parser.setFeature(xml.sax.handler.feature_namespaces, namespaces) if not dom: import Core dom = Core.theDOMImplementation if isinstance(file, type('')): try: fp = open(file) except IOError, e: if e.errno != errno.ENOENT: raise fp = urllib.urlopen(file) systemId = file else: # Ugh! Why doesn't urllib.pathname2url() do something useful? systemId = "file://" + os.path.abspath(file) else: source = xml.sax.InputSource() fp = file try: systemId = file.name except AttributeError: systemId = None source = xml.sax.InputSource(file) source.setByteStream(fp) source.setSystemId(systemId) builder = SAXBuilder(documentFactory=dom) builder.install(parser) parser.parse(source) if fp is not file: fp.close() return builder.document === Added File Products/ParsedXML/DOM/Traversal.py === """Implementation of DOM Level 2 Traversal. Based on the W3C recommendation at: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ """ # This code could be sped up. # - uses DOM methods, could use implementation internals, esp. childNodes # - if we had mutation events, NodeIterator could build an array as it # iterated, and move over that, only updating on mutation import xml.dom __all__ = [ "NodeFilter", "NodeIterator", "TreeWalker", ] class NodeFilter: # Constants returned by acceptNode(): FILTER_ACCEPT = 1 FILTER_REJECT = 2 FILTER_SKIP = 3 # Constants for whatToShow: SHOW_ALL = 0xFFFFFFFF SHOW_ELEMENT = 0x00000001 SHOW_ATTRIBUTE = 0x00000002 SHOW_TEXT = 0x00000004 SHOW_CDATA_SECTION = 0x00000008 SHOW_ENTITY_REFERENCE = 0x00000010 SHOW_ENTITY = 0x00000020 SHOW_PROCESSING_INSTRUCTION = 0x00000040 SHOW_COMMENT = 0x00000080 SHOW_DOCUMENT = 0x00000100 SHOW_DOCUMENT_TYPE = 0x00000200 SHOW_DOCUMENT_FRAGMENT = 0x00000400 SHOW_NOTATION = 0x00000800 def acceptNode(self, node): # Just accept everything by default: return NodeFilter.FILTER_ACCEPT _whatToShow_bits = ( (xml.dom.Node.ELEMENT_NODE, NodeFilter.SHOW_ELEMENT), (xml.dom.Node.ATTRIBUTE_NODE, NodeFilter.SHOW_ATTRIBUTE), (xml.dom.Node.TEXT_NODE, NodeFilter.SHOW_TEXT), (xml.dom.Node.CDATA_SECTION_NODE, NodeFilter.SHOW_CDATA_SECTION), (xml.dom.Node.ENTITY_REFERENCE_NODE, NodeFilter.SHOW_ENTITY_REFERENCE), (xml.dom.Node.ENTITY_NODE, NodeFilter.SHOW_ENTITY), (xml.dom.Node.PROCESSING_INSTRUCTION_NODE, NodeFilter.SHOW_PROCESSING_INSTRUCTION), (xml.dom.Node.COMMENT_NODE, NodeFilter.SHOW_COMMENT), (xml.dom.Node.DOCUMENT_NODE, NodeFilter.SHOW_DOCUMENT), (xml.dom.Node.DOCUMENT_TYPE_NODE, NodeFilter.SHOW_DOCUMENT_TYPE), (xml.dom.Node.DOCUMENT_FRAGMENT_NODE, NodeFilter.SHOW_DOCUMENT_FRAGMENT), (xml.dom.Node.NOTATION_NODE, NodeFilter.SHOW_NOTATION), ) class AccessorBase: def __init__(self, root, whatToShow, filter, entityReferenceExpansion): if root is None: raise xml.dom.NotSupportedErr( "root of traversal object can't be None") d = self.__dict__ d['root'] = root d['whatToShow'] = whatToShow d['filter'] = filter d['expandEntityReferences'] = entityReferenceExpansion # # Decode the whatToShow flags for faster tests; the W3C # reserves the first 200 NodeType values, but the whatToShow # flags have to fit in 32 bits (leave slot 0 empty since it's # not a valid NodeType). # d['_whatToShow'] = what = [0] * 33 for nodeType, bit in _whatToShow_bits: what[nodeType] = whatToShow & bit def __setattr__(self, name, value): setter = getattr(self, '_set_' + name, None) if setter is None: getter = getattr(self, '_get_' + name, None) if getter: raise xml.dom.NoModificationAllowedErr( "read-only attribute: " + `name`) else: raise AttributeError, "no such attribute: " + `name` setter(value) def _get_root(self): return self.root def _get_whatToShow(self): return self.whatToShow def _get_filter(self): return filter def _get_expandEntityReferences(self): return self.expandEntityReferences def _should_show(self, node): if not self._whatToShow[node.nodeType]: return NodeFilter.FILTER_SKIP else: if ( node.nodeType == xml.dom.Node.ENTITY_REFERENCE_NODE and not self.expandEntityReferences): return NodeFilter.FILTER_REJECT elif self.filter is not None: return self._filterNode(node) return NodeFilter.FILTER_ACCEPT def _nextInTree(self, node): """Return first visible node in node's subtree, or None.""" # check given node first if self._should_show(node) == NodeFilter.FILTER_ACCEPT: return node elif self._should_show(node) == NodeFilter.FILTER_REJECT: return None for c in node.childNodes: child = self._nextInTree(c) if child: return child if c.isSameNode(self.root): # don't leave root subtree return None return None def _lastInTree(self, node): """Return last visible node in node's subtree, or None.""" if self._should_show(node) == NodeFilter.FILTER_REJECT: return None childNodes = node.childNodes childNums = range(childNodes.length) childNums.reverse() for c in childNums: childNode = childNodes[c] child = self._lastInTree(childNode) if child: return child if childNode.isSameNode(self.root): # don't leave root subtree return None # subtree exhausted, check given node if self._should_show(node) == NodeFilter.FILTER_ACCEPT: return node return None # we don't do any visibilty tests here, _nextInTree does. def _nextNode(self, startNode): """Return next visible node after startNode, or None.""" # check children for child in startNode.childNodes: node = self._nextInTree(child) if node: return node if child.isSameNode(self.root): # don't leave root subtree return None # check next siblings sib = startNode.nextSibling while sib: node = self._nextInTree(sib) if node: return node if sib.isSameNode(self.root): # don't leave root subtree return None sib = sib.nextSibling # check ancestors' next siblings; don't visit ancestors ancestor = startNode.parentNode while ancestor: sib = ancestor.nextSibling while sib: node = self._nextInTree(sib) if node: return node if sib.isSameNode(self.root): # don't leave root subtree return None sib = sib.nextSibling # no visible nodes in siblings or subtrees of this ancestor if ancestor.isSameNode(self.root): # don't leave root subtree return None ancestor = ancestor.parentNode return None # we *do* a visibilty test here, _lastInTree does too. def _previousNode(self, startNode): """Return the previous visible node after startNode, or None.""" # check previous siblings sib = startNode.previousSibling while sib: node = self._lastInTree(sib) if node: return node if sib.isSameNode(self.root): # don't leave root subtree return None sib = sib.previousSibling # check ancestors, then ancestors' previous siblings ancestor = startNode.parentNode while ancestor: if self._should_show(ancestor) == NodeFilter.FILTER_ACCEPT: return ancestor sib = ancestor.previousSibling while sib: node = self._lastInTree(sib) if node: return node if sib.isSameNode(self.root): # don't leave root subtree return None sib = sib.previousSibling if ancestor.isSameNode(self.root): # don't leave root subtree return None ancestor = ancestor.parentNode return None # Since we don't need to know about structure, we could probably be a lot # faster if we kept a list of nodes in document order and updated # it when we got a mutation event - once we have mutation events. class NodeIterator(AccessorBase): BEFORE_NODE = 1 # iterator crossed reference node moving forward AFTER_NODE = 0 # iterator crossed reference node moving backward def __init__(self, root, whatToShow=NodeFilter.SHOW_ALL, filter=None, entityReferenceExpansion=1): AccessorBase.__init__(self, root, whatToShow, filter, entityReferenceExpansion) self.__dict__['_refNode'] = None self.__dict__['_refPos'] = NodeIterator.BEFORE_NODE def detach(self): self.__dict__['root'] = None def nextNode(self): if self.root is None: raise xml.dom.InvalidStateErr( "can't iterate using a detached NodeIterator") if self._refNode == None: self.__dict__['_refNode'] = self.root self.__dict__['_refPos'] = NodeIterator.AFTER_NODE if self._should_show(self._refNode) == NodeFilter.FILTER_ACCEPT: return self._refNode elif self._refPos == NodeIterator.BEFORE_NODE: if self._should_show(self._refNode) == NodeFilter.FILTER_ACCEPT: self.__dict__['_refPos'] = NodeIterator.AFTER_NODE return self._refNode node = AccessorBase._nextNode(self, self._refNode) if node: self.__dict__['_refNode'] = node self.__dict__['_refPos'] = NodeIterator.AFTER_NODE return node def previousNode(self): if self.root is None: raise xml.dom.InvalidStateErr( "can't iterate using a detached NodeIterator") if self._refNode == None: self.__dict__['_refNode'] = self.root self.__dict__['_refPos'] = NodeIterator.BEFORE_NODE elif self._refPos == NodeIterator.AFTER_NODE: if self._should_show(self._refNode) == NodeFilter.FILTER_ACCEPT: self.__dict__['_refPos'] = NodeIterator.BEFORE_NODE return self._refNode node = AccessorBase._previousNode(self, self._refNode) if node: self.__dict__['_refNode'] = node self.__dict__['_refPos'] = NodeIterator.BEFORE_NODE return node def __getitem__(self, index): node = self.nextNode() if node is None: raise IndexError, "NodeIterator index out of range" return node def _filterNode(self, node): """Return what the filter says to do with node, translating reject into skip""" filterAction = self.filter.acceptNode(node) if filterAction == NodeFilter.FILTER_REJECT: return NodeFilter.FILTER_SKIP return filterAction class TreeWalker(AccessorBase): def __init__(self, root, whatToShow=NodeFilter.SHOW_ALL, filter=None, entityReferenceExpansion=1): AccessorBase.__init__(self, root, whatToShow, filter, entityReferenceExpansion) self.__dict__['currentNode'] = root def _get_currentNode(self): return self.currentNode def _set_currentNode(self, node): if node is None: raise xml.dom.NotSupportedErr("can't set current node to None") self.__dict__['currentNode'] = node def parentNode(self): if self.root.isSameNode(self.currentNode): return None node = self.currentNode.parentNode while node is not None and ( self._should_show(node) != NodeFilter.FILTER_ACCEPT): if node.isSameNode(self.root): # can't step any further up return else: node = node.parentNode if node is not None: self.__dict__['currentNode'] = node return node def firstChild(self): node = self.currentNode.firstChild while node is not None and ( self._should_show(node) != NodeFilter.FILTER_ACCEPT): node = node.nextSibling if node is not None: self.__dict__['currentNode'] = node return node def lastChild(self): node = self.currentNode.lastChild while node is not None and ( self._should_show(node) != NodeFilter.FILTER_ACCEPT): node = node.previousSibling if node is not None: self.__dict__['currentNode'] = node return node # the rec doesn't say that *Sibling should pay attention to root! def previousSibling(self): node = self.currentNode.previousSibling while node is not None and ( self._should_show(node) != NodeFilter.FILTER_ACCEPT): node = node.previousSibling if node is not None: self.__dict__['currentNode'] = node return node def nextSibling(self): node = self.currentNode.nextSibling while node is not None and ( self._should_show(node) != NodeFilter.FILTER_ACCEPT): node = node.nextSibling if node is not None: self.__dict__['currentNode'] = node return node # TreeWalkers don't move if there is no visible next or previous, # so we do nothing for a None return. def nextNode(self): node = AccessorBase._nextNode(self, self.currentNode) if node: self.__dict__['currentNode'] = node return node def previousNode(self): node = AccessorBase._previousNode(self, self.currentNode) if node: self.__dict__['currentNode'] = node return node def _filterNode(self, node): """Return what the filter says to do with node.""" return self.filter.acceptNode(node) === Added File Products/ParsedXML/DOM/XMLExtended.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Acquisition-based implementation of the DOM 'XML' feature classes.""" import Core import xml.dom from ComputedAttribute import ComputedAttribute class CDATASection(Core.Text): nodeName = "#cdata-section" nodeType = Core.Node.CDATA_SECTION_NODE class Identified: """Mix-in class that supports the publicId and systemId attributes.""" def _identified_mixin_init(self, publicId, systemId): d = self.__dict__ d['publicId'] = publicId d['systemId'] = systemId def _get_publicId(self): return self.publicId def _get_systemId(self): return self.systemId class Entity(Identified, Core.Parentless, Core.Node): nodeType = Core.Node.ENTITY_NODE _readonly = 1 _in_tree = 0 _allowed_child_types = (Core.Node.ELEMENT_NODE, Core.Node.PROCESSING_INSTRUCTION_NODE, Core.Node.COMMENT_NODE, Core.Node.TEXT_NODE, Core.Node.CDATA_SECTION_NODE, Core.Node.ENTITY_REFERENCE_NODE) def __init__(self, name, publicId, systemId, notationName): self._identified_mixin_init(publicId, systemId) d = self.__dict__ d['nodeName'] = name d['notationName'] = notationName def _cloneNode(self, deep, mutable, document): # force children to not to acquire mutability: return Core.Node._cloneNode(self, deep, 0, document) def _get_notationName(self): return self.notationName # DOM Level 3 (Working Draft, 01 Sep 2000) # I expect some or all of these will become read-only before the # recommendation is finished. actualEncoding = None encoding = None version = None def _get_actualEncoding(self): return self.actualEncoding def _set_actualEncoding(self, value): self.__dict__['actualEncoding'] = value def _get_encoding(self): return self.encoding def _set_encoding(self, value): self.__dict__['value'] = value def _get_version(self): return self.version def _set_version(self, value): self.__dict__['version'] = value class EntityReference(Core.Node): nodeType = Core.Node.ENTITY_REFERENCE_NODE _readonly = 1 _allowed_child_types = (Core.Node.ELEMENT_NODE, Core.Node.PROCESSING_INSTRUCTION_NODE, Core.Node.COMMENT_NODE, Core.Node.TEXT_NODE, Core.Node.CDATA_SECTION_NODE, Core.Node.ENTITY_REFERENCE_NODE) def __init__(self, name): self.__dict__['_in_tree'] = 0 self.__dict__['nodeName'] = name class Notation(Identified, Core.Childless, Core.Parentless, Core.Node): nodeType = Core.Node.NOTATION_NODE _readonly = 1 def __init__(self, name, publicId, systemId): self._identified_mixin_init(publicId, systemId) d = self.__dict__ d['_in_tree'] = 0 d['nodeName'] = name def _cloneNode(self, deep, mutable, document): # force children to not to acquire mutability: return Core.Node._cloneNode(self, deep, 0, document) # DOM Level 3 (working draft, 5 June 2001) def _get_textContent(self): return '' textContent = '' class ProcessingInstruction(Core.Childless, Core.Node): nodeType = Core.Node.PROCESSING_INSTRUCTION_NODE def __init__(self, target, data): d = self.__dict__ d['_in_tree'] = 0 d['nodeName'] = target d['target'] = target d['nodeValue'] = data d['data'] = data def _get_data(self): return self.data def _set_data(self, data): if self._readonly: raise xml.dom.NoModificationAllowedErr() d = self.__dict__ if d['data'] != data: d['data'] = data d['nodeValue'] = data self._changed() _set_nodeValue = _set_data def _get_target(self): return self.target target = ComputedAttribute(_get_target, 1) # DOM Level 3 (working draft, 5 June 2001) def _get_textContent(self): return self.nodeValue textContent = ComputedAttribute(_get_textContent, 1) class DocumentType(Identified, Core.Childless, Core.Node): nodeType = Core.Node.DOCUMENT_TYPE_NODE nodeValue = None internalSubset = None def __init__(self, qualifiedName, publicId, systemId): self._identified_mixin_init(publicId, systemId) d = self.__dict__ d['name'] = qualifiedName d['nodeName'] = qualifiedName d['_entities'] = [] d['_notations'] = [] d['_in_tree'] = 0 def _get_internalSubset(self): return self.internalSubset def _get_name(self): return self.name _get_nodeName = _get_name def _set_nodeValue(self, data): return def _get_entities(self): return OwnedEntityMap(self, '_entities') entities = ComputedAttribute(_get_entities, 1) def _get_notations(self): return OwnedEntityMap(self, '_notations') notations = ComputedAttribute(_get_notations, 1) def isSupported(self, feature, version): doc = self.ownerDocument if doc: impl = doc.implementation else: impl = Core.theDOMImplementation return impl.hasFeature(feature, version) # DOM Level 3 (working draft, 5 June 2001) def _get_textContent(self): return '' textContent = '' class OwnedEntityMap(Core.MapFromParent): """ NamedNodeMap that works on the entity or notation structure of a DocumentType. """ def __init__(self, parent, listName): Core.MapFromParent.__init__(self, parent) self.__dict__['_parentListName'] = listName def _item_helper(self, itemSource): "used by item; create an Attribute from the item and return it" # XXX is ownerDocument ok with this? #itemSource.__dict__['ownerDocument'] = self._parent return itemSource.__of__(self._parent) def _nameMatcher(self, itemSource, name): return itemSource.nodeName == name def _nsMatcher(self, itemSource, namespaceURI, localName): return (itemSource.namespaceURI == namespaceURI and itemSource.localName == localName) def _set_named_item(self, name, matcher, node): raise xml.dom.NoModificationAllowedErr() def _delFromParentList(self, entities, i): raise xml.dom.NoModificationAllowedErr() def _addToParentList(self, entities, node): raise xml.dom.NoModificationAllowedErr() def _key_helper(self, itemSource): "Given an item source, return an appropriate key for our mapping" if itemSource.prefix: return "%s:%s" % (itemSource.prefix, itemSource.localName) else: return itemSource.localName # no longer needed del ComputedAttribute === Added File Products/ParsedXML/DOM/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Digital Creation's light-weight, acquisition-based DOM implementation.""" __version__ = '$Revision: 1.1 $' # Work around the possible lack of a decent XML package; the # Exceptions module will masquerade as xml.dom if it needs to. # See the comments in Exceptions for a full explanation. # import Exceptions from Core import theDOMImplementation From sidnei at x3ng.com.br Fri May 30 11:17:33 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests/domapi - Base.py:1.1 CoreLvl1.py:1.1 CoreLvl2.py:1.1 CoreLvl3.py:1.1 Load3.py:1.1 TraversalLvl2.py:1.1 XMLLvl1.py:1.1 XMLLvl2.py:1.1 __init__.py:1.1 Message-ID: <200305301517.h4UFHXd19505@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests/domapi In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests/domapi Added Files: Base.py CoreLvl1.py CoreLvl2.py CoreLvl3.py Load3.py TraversalLvl2.py XMLLvl1.py XMLLvl2.py __init__.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/domapi/Base.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import xml.dom from xml.dom import Node import sys import unittest # Namespace URI for namespace tests TEST_NAMESPACE = 'uri:namespacetests' # Convenience map for assert messages TYPE_NAME = { Node.ATTRIBUTE_NODE: 'Attribute', Node.CDATA_SECTION_NODE: 'CDATA Section', Node.COMMENT_NODE: 'Comment', Node.DOCUMENT_FRAGMENT_NODE: 'Document Fragment', Node.DOCUMENT_NODE: 'Document', Node.DOCUMENT_TYPE_NODE: 'DocumentType', Node.ELEMENT_NODE: 'Element', Node.ENTITY_NODE: 'Entity', Node.ENTITY_REFERENCE_NODE: 'Entity Reference', Node.NOTATION_NODE: 'Notation', Node.PROCESSING_INSTRUCTION_NODE: 'Processing Instruction', Node.TEXT_NODE: 'Text', } def checkAttribute(node, attribute, value): """Check that an attribute holds the expected value, and that the corresponding accessor method, if provided, returns an equivalent value.""" # v1 = getattr(node, attribute) if v1 != value: raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if v2 != value: raise AssertionError( "accessor result does not match\n expected: %s\n found: %s" % (`value`, `v2`)) if v1 != v2: raise AssertionError( "attribute & accessor result don't compare equal\n" " attribute: %s\n accessor: %s" % (`v1`, `v2`)) def checkAttributeNot(node, attribute, value): """Check that an attribute doesn't hold a specific failing value, and that the corresponding accessor method, if provided, returns an equivalent value.""" # v1 = getattr(node, attribute) if v1 == value: raise AssertionError( "attribute value should not match\n found: %s" % `v1`) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if v2 == value: raise AssertionError( "accessor result should not match\n found: %s" % `v2`) if v1 != v2: raise AssertionError( "attribute & accessor result don't compare equal\n" " attribute: %s\n accessor: %s" % (`v1`, `v2`)) def checkAttributeSameNode(node, attribute, value): v1 = getattr(node, attribute) if value is None: if v1 is not None: raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) else: if not isSameNode(value, v1): raise AssertionError( "attribute value does not match\n expected: %s\n found: %s" % (`value`, `v1`)) if hasattr(node, "_get_" + attribute): v2 = getattr(node, "_get_" + attribute)() if value is None: if v2 is not None: raise AssertionError( "accessor result does not match\n" " expected: %s\n found: %s" % (`value`, `v2`)) elif not isSameNode(value, v2): raise AssertionError( "accessor result does not match\n" " expected: %s\n found: %s" % (`value`, `v2`)) def checkReadOnly(node, attribute): try: setattr(node, attribute, "don't set this!") except xml.dom.NoModificationAllowedErr: pass else: raise AssertionError("write-access to the '%s' attribute not blocked" % attribute) if hasattr(node, "_set_" + attribute): # setter implemented; make sure it won't allow update try: getattr(node, "_set_" + attribute)("don't set this!") except xml.dom.NoModificationAllowedErr: pass else: raise AssertionError("_set_%s() allowed attribute update" % attribute) def checkLength(node, value): checkAttribute(node, "length", value) if len(node) != value: raise AssertionError("broken support for __len__()") checkReadOnly(node, "length") def isSameNode(node1, node2): """Compare two nodes, returning true if they are the same. Use the DOM lvl 3 Node.isSameNode method if available, otherwise use a simple 'is' test. """ if hasattr(node1, 'isSameNode'): return node1.isSameNode(node2) else: return node1 is node2 class TestCaseBase(unittest.TestCase): def createDocumentNS(self): self.document = self.implementation.createDocument( TEST_NAMESPACE, 'foo:bar', None) return self.document def createDocument(self): self.document = self.implementation.createDocument(None, 'root', None) return self.document def buildCases(modName, feature, level): cases = [] add = cases.append objects = sys.modules[modName].__dict__ for obj in objects.keys(): if obj[-8:] != 'TestCase': continue add((objects[obj], feature, level)) return list(cases) === Added File Products/ParsedXML/tests/domapi/CoreLvl1.py === (2331/2431 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 2331 lines omitted -=- -=- -=-] "setNamedItem store seems to have failed, can't retrieve.") def checkSetNamedItemReplacingExistingNode(self): newAttr = self.document.createAttribute('someAttr') self.map.setNamedItem(newAttr) anotherAttr = self.document.createAttribute('someAttr') anotherAttr.value = 'eggs' retVal = self.map.setNamedItem(newAttr) assert retVal is not None, "setNamedItem returned None" assert isSameNode(retVal, newAttr), ( "setNamedItem didn't return replaced Node.") checkLength(self.map, 2) def checkSetNamedItemWrongDocument(self): newDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = newDoc.createAttribute('someAttr') try: self.map.setNamedItem(foreignAttr) except xml.dom.WrongDocumentErr: pass else: assert 0, "Was allowed to add foreign Node to NamedNodeMap." def checkSetNamedItemAlreadyInUse(self): el = self.document.createElement('someElement') attr = self.document.createAttribute('someAttribute') el.setAttributeNode(attr) try: self.map.setNamedItem(attr) except xml.dom.InuseAttributeErr: pass else: assert 0, ( "Was allowed to add attribute already in use to NamedNodeMap.") def checkSetNamedItemHierarchyRequestErr(self): # See DOM erratum core-4. textNode = self.document.createTextNode('text node') try: self.map.setNamedItem(textNode) except xml.dom.HierarchyRequestErr: pass else: assert 0, ( "Was allowed to add a Node Type not belonging in this " "NamedNodeMap (a Text Node to a map of attributes).") cases = buildCases(__name__, 'Core', None) === Added File Products/ParsedXML/tests/domapi/CoreLvl2.py === (1624/1724 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 1624 lines omitted -=- -=- -=-] 'qname:someAttr') self.map.setNamedItemNS(newAttr) anotherAttr = self.document.createAttributeNS(self.TEST_NAMESPACE, 'anotherQN:someAttr') anotherAttr.value = 'eggs' retVal = self.map.setNamedItemNS(newAttr) assert retVal is not None, "setNamedItemNS returned None" assert isSameNode(retVal, newAttr), ( "setNamedItemNS didn't return replaced Node.") checkLength(self.map, 2) def checkSetNamedItemNSWrongDocument(self): newDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = newDoc.createAttributeNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) try: self.map.setNamedItem(foreignAttr) except xml.dom.WrongDocumentErr: pass else: assert 0, "Was allowed to add foreign Node to NamedNodeMap." def checkSetNamedItemNSAlreadyInUse(self): el = self.document.createElement('someElement') attr = self.document.createAttributeNS(self.TEST_NAMESPACE, self.TEST_QUALIFIED_NAME) el.setAttributeNode(attr) try: self.map.setNamedItem(attr) except xml.dom.InuseAttributeErr: pass else: assert 0, ( "Was allowed to add attribute already in use to NamedNodeMap.") def checkSetNamedItemNSHierarchyRequestErr(self): # See DOM erratum core-4. element = self.document.createElementNS(TEST_NAMESPACE, 'foo:bar') try: self.map.setNamedItemNS(element) except xml.dom.HierarchyRequestErr: pass else: assert 0, ( "Was allowed to add a Node Type not belonging in this " "NamedNodeMap (an Element Node to a map of attributes).") cases = buildCases(__name__, 'Core', '2.0') === Added File Products/ParsedXML/tests/domapi/CoreLvl3.py === """Test cases for DOM Core Level 3.""" import xml.dom import Base class WhitespaceInElementContentTestCase(Base.TestCaseBase): def checkWhiteSpaceInElementContent(self): TEXT = """ ]> """ doc = self.parse(TEXT) for node in doc.documentNode.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: if not node.isWhitespaceInElementContent: self.fail("founc whitespace node not identified" " as whitespace-in-element-contnet") def checkWhiteSpaceInUnknownContent(self, subset=""): TEXT = """ """ % subset doc = self.parse(TEXT) for node in doc.documentNode.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: if node.isWhitespaceInElementContent: self.fail("founc whitespace node in mixed content marked" " as whitespace-in-element-contnet") def checkWhiteSpaceInMixedContent(self): assert 0 self.checkWhiteSpaceInUnknownContent("""[ ]""") cases = Base.buildCases(__name__, 'Core', '3.0') === Added File Products/ParsedXML/tests/domapi/Load3.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Tests for the 'Load' part of the Load/Save component from DOM Level 3. Note that the Load/Save component is a working draft and not a final recommendation. """ import xml.dom import Base from Products.ParsedXML.DOM import LoadSave from Products.ParsedXML.StrIO import StringIO class BuilderTestCaseBase(Base.TestCaseBase): def createBuilder(self): return self.implementation.createDOMBuilder() class BuilderFeatureConformanceTestCase(BuilderTestCaseBase): """Test that the DOMBuilder has the defaults and allows setting all features required by the W3C specification. The features are not exercised, but every value that is required to be supported is tested and set. """ FEATURES = { # feature-name: (default, must-support-true, must-support-false) "namespaces": (1, 1, 0), "namespace-declarations": (1, 1, 0), "validation": (0, 0, 1), "external-general-entities": (1, 1, 0), "external-parameter-entities": (1, 1, 0), "validate-if-cm": (0, 0, 1), "create-entity-ref-nodes": (1, 1, 0), "entity-nodes": (1, 1, 0), "white-space-in-element-content": (1, 1, 0), "cdata-nodes": (1, 1, 0), "comments": (1, 1, 1), "charset-overrides-xml-encoding": (1, 1, 1), } def checkFeatureDefaults(self): for item in self.FEATURES.items(): feature, (default, xxx, xxx) = item b = self.createBuilder() value = b.getFeature(feature) and 1 or 0 self.assert_(value == default, "default feature value not right") def checkRequiredFeatureSettings(self): for item in self.FEATURES.items(): feature, (xxx, require_true, require_false) = item b = self.createBuilder() if require_true: self.assert_(b.canSetFeature(feature, 1), "builder indicates feature cannot be enabled") b.setFeature(feature, 1) self.assert_(b.getFeature(feature), "enabling feature failed") if require_false: self.assert_(b.canSetFeature(feature, 0), "builder indicates feature cannot be disabled") b.setFeature(feature, 0) self.assert_(not b.getFeature(feature), "disabling feature failed") def checkSupportsFeatures(self): b = self.createBuilder() for feature in self.FEATURES.keys(): self.assert_(b.supportsFeature(feature), "builder reports non-support for required feature") def checkEntityNodesFeatureSideEffect(self): b = self.createBuilder() b.setFeature("entity-nodes", 0) self.assert_(not b.getFeature("create-entity-ref-nodes"), "setting entity-nodes to false should turn off" " create-entity-ref-nodes") def checkUnknownFeature(self): b = self.createBuilder() self.assertRaises(xml.dom.NotFoundErr, b.setFeature, "non-existant-feature", 0) self.assertRaises(xml.dom.NotFoundErr, b.getFeature, "non-existant-feature") self.assert_(not b.supportsFeature("non-existant-feature"), "expected non-existant-feature to raise" " xml.dom.NotFoundErr") self.assert_(not b.canSetFeature("non-existant-feature", 0), "builder allows setting of non-existant feature" " to false") self.assert_(not b.canSetFeature("non-existant-feature", 1), "builder allows setting of non-existant feature" " to true") def checkWhiteSpaceInElementContentDiscarded(self): TEXT = """ ]> """ doc = self._parse(TEXT, {"white-space-in-element-content": 0}) for node in doc.documentElement.childNodes: if node.nodeType == xml.dom.Node.TEXT_NODE: self.fail("founc whitespace-in-element-content node which" " should bave been excluded") def checkCommentsOmitted(self): doc = self._parse("", {"comments": 0}) self.assert_(doc.documentElement.childNodes.length == 0, "comment node was returned as part of the document") def checkCDATAAsText(self): doc = self._parse(">]]>", {"cdata-nodes": 0}) self.assert_(doc.documentElement.childNodes[0].data == "<>") self.assert_(doc.documentElement.childNodes.length == 1) def checkWithoutNamespaces(self): doc = self._parse("" " " "", {"namespaces": 0}) docelem = doc.documentElement self.assert_(docelem.namespaceURI is None) self.assert_(docelem.prefix is None) self.assert_(docelem.getAttributeNode("xmlns").namespaceURI is None) self.assert_(docelem.getAttributeNode("xmlns").prefix is None) self.assert_(docelem.getAttributeNode("tal:attr").namespaceURI is None) self.assert_(docelem.getAttributeNode("tal:attr").prefix is None) elem = docelem.firstChild self.assert_(elem.namespaceURI is None) self.assert_(elem.prefix is None) def checkWithoutNamespaceDeclarations(self): doc = self._parse("" "" "", {"namespace-declarations": 0}) docelem = doc.documentElement self.failIf(docelem.hasAttribute("xmlns")) self.failIf(docelem.hasAttribute("xmlns:tal")) self.assert_(docelem.attributes.length == 1) # We can't just name this parse(), since the framework overwrites # that name on the actual instances. # def _parse(self, source, flags={}): b = self.createBuilder() for feature, value in flags.items(): b.setFeature(feature, value) fp = StringIO(source) inpsrc = LoadSave.DOMInputSource() inpsrc.byteStream = fp return b.parseDOMInputSource(inpsrc) cases = Base.buildCases(__name__, "Load", "3.0") === Added File Products/ParsedXML/tests/domapi/TraversalLvl2.py === (543/643 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 543 lines omitted -=- -=- -=-] walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_TEXT, SkipBFilter(), 0) self.iterate(walker, "firstChild", "parentNode", [self.document, self.G]) def checkWalkerNoFilterNextSiblingPreviousSibling(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) assert walker.previousSibling() is None, ( "previousSibling on a fresh walker did not return None.") # move to B to make more interesting walker.firstChild() # doctype walker.nextSibling() # A walker.firstChild() # B self.iterate(walker, "nextSibling", "previousSibling", [self.B, self.C, self.F, self.G]) def checkWalkerNoFilterLastChild(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) # move to A to make more interesting walker.firstChild() # doctype walker.nextSibling() # A retNode = walker.lastChild() assert isSameNode(retNode, walker.currentNode) assert isSameNode(self.G, walker.currentNode) def checkWalkerPreviousNode(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) assert walker.previousNode() is None, ( "previousNode on a fresh walker did not return None.") def checkCurrentNodeNoneNotSupported(self): walker = self.document.createTreeWalker(self.document, NodeFilter.SHOW_ALL, None, 0) try: walker.currentNode = None except xml.dom.NotSupportedErr: pass else: assert 0, "Was allowed to set currentNode to None." cases = buildCases(__name__, 'Traversal', '2.0') === Added File Products/ParsedXML/tests/domapi/XMLLvl1.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * from CoreLvl1 import NodeReadTestCaseBase, NodeWriteTestCaseBase from CoreLvl1 import TextReadTestCase, TextWriteTestCase TextReadTestCaseBase = TextReadTestCase TextWriteTestCaseBase = TextWriteTestCase del TextReadTestCase del TextWriteTestCase import xml.dom from xml.dom import Node # --- DocumentType class DocumentTypeReadTestCase(NodeReadTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo', None, None) self.expectedType = Node.DOCUMENT_TYPE_NODE doc = self.parse(""" ]> """) self.doctypeInternalSubset = doc.doctype def checkName(self): checkAttribute(self.doctype, 'name', 'foo') checkReadOnly(self.doctype, 'name') def checkEmptyEntities(self): assert self.doctype.entities.length == 0 def checkEntitiesInternalSubset(self): checkLength(self.doctypeInternalSubset.entities, 3) entity = self.doctypeInternalSubset.entities.getNamedItem( 'internalParsedE') def checkEntitiesRemoveReadOnly(self): try: self.doctypeInternalSubset.entities.removeNamedItem( 'internalParsedE') except xml.dom.NoModificationAllowedErr: pass else: assert 0, 'Was allowed to remove entity.' def checkEntitiesSetReadOnly(self): entity = self.doctypeInternalSubset.entities.item(0) try: self.doctypeInternalSubset.entities.setNamedItem(entity) except xml.dom.NoModificationAllowedErr: pass else: assert 0, 'Was allowed to set entity.' def checkEmptyNotations(self): assert self.doctype.notations.length == 0 def checkNotationsInternalSubset(self): checkLength(self.doctypeInternalSubset.notations, 1) notation = self.doctypeInternalSubset.notations.getNamedItem( 'aNotation') def checkNotationsRemoveReadOnly(self): try: self.doctypeInternalSubset.notations.removeNamedItem( 'aNotation') except xml.dom.NoModificationAllowedErr: pass else: assert 0, 'Was allowed to remove notation.' def checkNotationsSetReadOnly(self): notation = self.doctypeInternalSubset.notations.item(0) try: self.doctypeInternalSubset.notations.setNamedItem(notation) except xml.dom.NoModificationAllowedErr: pass else: assert 0, 'Was allowed to set notation.' def checkCloneNode(self): # TODO: Implementation dependent, what should we test? pass class DocumentTypeWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.createDocument() # Needed for Node tests self.doctype = self.node = self.implementation.createDocumentType( 'foo', None, None) # --- ProcessingInstruction class ProcessingInstructionReadTestCase(NodeReadTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi self.expectedType = Node.PROCESSING_INSTRUCTION_NODE def checkGetTarget(self): checkAttribute(self.pi, "target", "pit") def checkGetData(self): checkAttribute(self.pi, "data", "pid") def checkCloneNode(self): clone = self.pi.cloneNode(0) deepClone = self.pi.cloneNode(1) assert not isSameNode(self.pi, clone), "Clone is same as original." assert not isSameNode(self.pi, deepClone), "Clone is same as original." checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.pi.nodeType) checkAttribute(deepClone, 'nodeType', self.pi.nodeType) checkAttribute(clone, 'data', self.pi.data) checkAttribute(deepClone, 'data', self.pi.data) checkAttribute(clone, 'target', self.pi.target) checkAttribute(deepClone, 'target', self.pi.target) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class ProcessingInstructionWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi def checkSetData(self): self.pi._set_data("uggg") checkAttribute(self.pi, "data", "uggg") # --- CDATASection class CDATASectionReadTestCase(TextReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") self.expectedType = Node.CDATA_SECTION_NODE class CDATASectionWriteTestCase(TextWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") # --- EntityReference class EntityReferenceReadTestCase(NodeReadTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") self.expectedType = Node.ENTITY_REFERENCE_NODE self.expectedNodeName = 'eref' def checkCloneNode(self): pass # TODO: Fill in meaningful test here. class EntityReferenceWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") # TODO: An ENTITY_REFERENCE_NODE Node will have childNodes when the # entity it refers to has childNodes. We need entities first before we write # tests for that. # --- Entity class EntityReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = self.internalParsed = doc.doctype.entities.getNamedItem( 'internalParsedE') self.publicUnparsed = doc.doctype.entities.getNamedItem( 'publicUnparsedE') self.systemUnparsed = doc.doctype.entities.getNamedItem( 'systemUnparsedE') self.expectedNodeName = 'internalParsedE' self.expectedType = Node.ENTITY_NODE def checkPublicIdReadOnly(self): checkReadOnly(self.node, 'publicId') def checkPublicIdInternalParsed(self): checkAttribute(self.internalParsed, 'publicId', None) def checkPublicIdPublicUnparsed(self): checkAttribute(self.publicUnparsed, 'publicId', 'uri:public') def checkPublicIdSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'publicId', None) def checkSystemIdReadOnly(self): checkReadOnly(self.node, 'systemId') def checkSystemIdInternalParsed(self): checkAttribute(self.internalParsed, 'systemId', None) def checkSystemIdPublicUnparsed(self): checkAttribute(self.publicUnparsed, 'systemId', 'uri:system') def checkSystemIdSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'systemId', 'uri:system') def checkNotationNameReadOnly(self): checkReadOnly(self.node, 'notationName') def checkNotationNameInternalParsed(self): checkAttribute(self.internalParsed, 'notationName', None) def checkNotationNamePublicUnparsed(self): checkAttribute(self.publicUnparsed, 'notationName', 'aNotation') def checkNotationNameSystemUnparsed(self): checkAttribute(self.systemUnparsed, 'notationName', 'aNotation') def checkSubTreeInternalParsed(self): entity = self.internalParsed assert entity.hasChildNodes(), ( 'Internal Parsed Entity has no subtree representing the value.') checkAttribute(entity.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(entity.firstChild, 'data', 'Entity text') checkReadOnly(entity.firstChild, 'data') def checkSubTreePublicUnparsed(self): assert not self.publicUnparsed.hasChildNodes(), ( 'An unparsed entity should not have a sub-tree.') def checkSubTreeSystemUnparsed(self): assert not self.systemUnparsed.hasChildNodes(), ( 'An unparsed entity should not have a sub-tree.') class EntityWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') # --- Notation class NotationReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = self.publicExternal = doc.doctype.notations.getNamedItem( 'publicExternalN') self.systemExternal = doc.doctype.notations.getNamedItem( 'systemExternalN') self.public = doc.doctype.notations.getNamedItem('publicN') self.expectedNodeName = 'publicExternalN' self.expectedType = Node.NOTATION_NODE def checkPublicIdReadOnly(self): checkReadOnly(self.node, 'publicId') def checkPublicIdPublicExternal(self): checkAttribute(self.publicExternal, 'publicId', 'uri:public') def checkPublicIdSystemExternal(self): checkAttribute(self.systemExternal, 'publicId', None) def checkPublicIdPublic(self): checkAttribute(self.public, 'publicId', 'uri:public') def checkSystemIdReadOnly(self): checkReadOnly(self.node, 'systemId') def checkSystemIdPublicExternal(self): checkAttribute(self.publicExternal, 'systemId', 'uri:system') def checkSystemIdSystemExternal(self): checkAttribute(self.systemExternal, 'systemId', 'uri:system') def checkSystemIdPublic(self): checkAttribute(self.public, 'systemId', None) class NotationWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') cases = buildCases(__name__, 'XML', '1.0') === Added File Products/ParsedXML/tests/domapi/XMLLvl2.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import CoreLvl2 TextReadTestCaseBase = CoreLvl2.TextReadTestCase TextWriteTestCaseBase = CoreLvl2.TextWriteTestCase NodeReadTestCaseBase = CoreLvl2.NodeReadTestCaseBase NodeWriteTestCaseBase = CoreLvl2.NodeWriteTestCaseBase del CoreLvl2 import xml.dom from xml.dom import Node # --- DocumentType class DocumentTypeReadTestCase(NodeReadTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo:bar', 'uri:foo', 'uri:bar') def checkInternalSubset(self): # The DOM Level 2 recommendation is not clear on the value of the # internalSubset attribute when there isn't one; this test relies # on a clarification from Joe Kesselman: # # http://lists.w3.org/Archives/Public/www-dom/2001AprJun/0009.html # checkAttribute(self.doctype, 'internalSubset', None) checkReadOnly(self.doctype, 'internalSubset') def checkPublicId(self): checkAttribute(self.doctype, 'publicId', 'uri:foo') checkReadOnly(self.doctype, 'publicId') def checkSystemId(self): checkAttribute(self.doctype, 'systemId', 'uri:bar') checkReadOnly(self.doctype, 'systemId') def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) try: foreignDoc.importNode(self.doctype, 0) except xml.dom.NotSupportedErr: pass else: assert 0, "Was allowed to import a Document Type Node." class DocumentTypeWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.doctype = self.node = self.implementation.createDocumentType( 'foo:bar', 'uri:foo', 'uri:bar') # --- ProcessingInstruction class ProcessingInstructionReadTestCase(NodeReadTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi def checkImportNode(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) clone = foreignDoc.importNode(self.pi, 0) deepClone = foreignDoc.importNode(self.pi, 1) assert not isSameNode(self.pi, clone), "Clone is same as original." assert not isSameNode(self.pi, deepClone), "Clone is same as original." checkAttributeSameNode(clone, 'ownerDocument', foreignDoc) checkAttributeSameNode(deepClone, 'ownerDocument', foreignDoc) checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.pi.nodeType) checkAttribute(deepClone, 'nodeType', self.pi.nodeType) checkAttribute(clone, 'data', self.pi.data) checkAttribute(deepClone, 'data', self.pi.data) checkAttribute(clone, 'target', self.pi.target) checkAttribute(deepClone, 'target', self.pi.target) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class ProcessingInstructionWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.pi = self.createDocument().createProcessingInstruction("pit", "pid") self.node = self.pi # --- CDATASection class CDATASectionReadTestCase(TextReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") class CDATASectionWriteTestCase(TextWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createCDATASection( "com") # --- EntityReference class EntityReferenceReadTestCase(NodeReadTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") def checkImportNode(self): pass # TODO: Fill in meaningful test here. class EntityReferenceWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.entref = self.node = self.createDocument().createEntityReference( "eref") # --- Entity class EntityReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') class EntityWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.entities.getNamedItem('internalParsedE') # --- Notation class NotationReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') class NotationWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.document = self.parse(""" ]> """) self.node = doc.doctype.notations.getNamedItem('aNotation') cases = buildCases(__name__, 'XML', '2.0') === Added File Products/ParsedXML/tests/domapi/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """A suite of unit tests for the Python DOM API. This suite will test a DOM API for compliance with the DOM API, level 2. It assumes that the DOM tested supports at least both the Core and XML features. It requires PyUnit; see http://pyunit.sourceforge.net/. Example for the python minidom (which is an incomplete implementation): from xml.dom.minidom import DOMImplementation, parseString from domapi import DOMImplementationTestSuite def MiniDomParseString(self, xml): return parseString(xml) def test_suite(): '''Return a test suite for the Zope testing framework.''' return DOMImplementationTestSuite(DOMImplementation(), MiniDomParseString) if __name__ == '__main__': import unittest unittest.TextTestRunner().run(test_suite()) """ import unittest import CoreLvl1, CoreLvl2, CoreLvl3, XMLLvl1, XMLLvl2, TraversalLvl2, Load3 cases = ( CoreLvl1.cases + CoreLvl2.cases + CoreLvl3.cases + XMLLvl1.cases + XMLLvl2.cases + TraversalLvl2.cases + Load3.cases ) def DOMImplementationTestSuite(implementation, parseMethod, verbose=0): """ Create a testsuite for DOM lvl 2 compliance, given a DOM Implementation. To test a DOM implementation, hand in a DOMImplementation object, and a method that will take a string holding an XML document and returns a Document Node created from the XML. Then run the returned unittest testsuite. Note that the signature of the parse method is (self, xmlString) and should parse the xml string with namespaces turned on. It will be used to create Nodes which normally cannot be created using the DOM API, like Notations and Entities. """ # First test for minimal feature support assert (implementation.hasFeature('Core', '2.0') and implementation.hasFeature('XML', '2.0')), ( "This DOMImplementation doesn't feature the level 2 Core and XML API.") suite = unittest.TestSuite() # The minimal set of features that should return 1 on hasFeature. # ('Core', '1.0') was never defined for DOM level 1, it was implicit. Most # DOM level 2 implementations return true, but this is a courtesy. supportedFeatures = { ('Core', None): 1, ('Core', '2.0'): 1, ('XML', None): 1, ('XML', '1.0'): 1, ('XML', '2.0'): 1, } for case, feature, version in cases: if implementation.hasFeature(feature, version): case.implementation = implementation case.parse = parseMethod suite.addTest(unittest.makeSuite(case, 'check')) supportedFeatures[(feature, version)] = 1 supportedFeatures[(feature, None)] = 1 else: if verbose: print ("Test %s skipped: DOM feature not supported.\n" % case.__name__) # Record supported features. CoreLvl1.DOMImplementationReadTestCase.supportedFeatures = ( supportedFeatures.keys()) CoreLvl2.NodeReadTestCaseBase.supportedFeatures = ( supportedFeatures.keys()) return suite From sidnei at x3ng.com.br Fri May 30 11:17:28 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML - AdaptableStorage.py:1.1 CHANGES.txt:1.1 CREDITS.txt:1.1 DOMProxy.py:1.1 Example.zexp:1.1 ExtraDOM.py:1.1 INSTALL.txt:1.1 LICENSE.Fourthought:1.1 LICENSE.txt:1.1 ManageableDOM.py:1.1 ParsedXML.py:1.1 PrettyPrinter.py:1.1 Printer.py:1.1 README.DOMProxy:1.1 README.parseprint:1.1 README.txt:1.1 StrIO.py:1.1 TransPubDOMProxy.py:1.1 __init__.py:1.1 main.dtml:1.1 version.txt:1.1 Message-ID: <200305301517.h4UFHSE19308@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML Added Files: AdaptableStorage.py CHANGES.txt CREDITS.txt DOMProxy.py Example.zexp ExtraDOM.py INSTALL.txt LICENSE.Fourthought LICENSE.txt ManageableDOM.py ParsedXML.py PrettyPrinter.py Printer.py README.DOMProxy README.parseprint README.txt StrIO.py TransPubDOMProxy.py __init__.py main.dtml version.txt Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/AdaptableStorage.py === ############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (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 # ############################################################################## """Serializers for Shane's AdaptableStorage The properties must be deserialized prior the actual xml. $Id: AdaptableStorage.py,v 1.1 2003/05/30 15:17:26 sidnei Exp $ """ from types import StringType from cStringIO import StringIO from Products.AdaptableStorage.mapper.public import IAspectSerializer,\ FieldSchema, RowSequenceSchema from ParsedXML import ParsedXML, createDOMDocument class ParsedXMLSerializer: """Serializer for ParsedXML Documents. Only the raw XML is stored in the filesystem. """ __implements__ = IAspectSerializer schema = FieldSchema('data', 'string') attributes = ( ) def getSchema(self): return self.schema def canSerialize(self, object): return isinstance(object, ParsedXML) def serialize(self, object, event): encoding = 'utf-8' data = object.writeStream(encoding=encoding).getvalue().encode(encoding) event.ignoreAttributes([ '_node', '_persistentDoc', '_lenCache', '_lenCorrect', '_container']) return data def deserialize(self, object, event, state): assert isinstance(state, StringType) object._persistentDoc = object object._lenCache = 0 object._lenCorrect = 0 object.initFromDOMDocument(createDOMDocument(state, not object.noNamespaces)) class ParsedXMLPropertiesSerializer: """Serialize parsed xml's properties""" __implements__ = IAspectSerializer schema = RowSequenceSchema() schema.addField('id', 'string', 1) schema.addField('type', 'string') schema.addField('data', 'string') attributes = { 'title': str, 'contentType': str, 'noNamespaces': int, } def getSchema(self): return self.schema def canSerialize(self, object): return isinstance(object, ParsedXML) def serialize(self, object, event): res = [] for attribute, factory in self.attributes.items(): if not hasattr(object, attribute): continue value = getattr(object, attribute) t = factory.__name__ if value is None: if factory in (int, long): value = 0 else: value = '' value = str(value) event.ignoreAttribute(attribute) res.append((attribute, t, value)) return res def deserialize(self, object, event, state): for attribute, t, value in state: factory = self.attributes.get(attribute) if factory is None: continue value = factory(value) setattr(object, attribute, value) assert getattr(object, attribute) == value === Added File Products/ParsedXML/CHANGES.txt === ParsedXML changes ParsedXML 1.3.1 Bugs Fixed - Bugfix/performance improvement. Do not rely on getPersistentDocument() but instead use acquisition parent. This fixes a memory leak triggered when doing 'document.documentElement', and also likely improves performance when accessing the DOM through the ManageableDOM wrappers. - The Zope Find tab should now not give an error anymore when searching with ids. - Use the One True Way to import expat now ('from xml.parsers import expat'). ParsedXML 1.3.0 Features - All element nodes now have a _element_id id. This id is guaranteed to be unique in the document, though which id an element has may change in a reparse. - NodePath system for creating various paths to nodes. This can be based on 'child' (child node index), 'element_id', or 'robust', which is not very robust as yet in some ways, but should be resistent to quite a few changes to the document. - added pretty printing feature. A pretty print button renders the document in pretty printed form, but does not save this changed version (you can do so yourself). Bugs Fixed - Removed ParsedXML's Expat, introduced dependency on PyXML's pyexpat instead (or just compile your own). This gets rid of lots of install hassles, especially on Windows. Just install PyXML. - An ongoing attempt to bring sanity to the unit test story. - Avoid XML-garbling bug in Printer by using PrettyPrinter. - various bugfixes in the DOM. ParsedXML 1.2.1 Features - pyexpat.c is now in sync with Python's and PyXML's version. ParsedXML 1.2.0 Bugs Fixed - Tests are now more conformant with Zope unit testing guidelines. - Should work with Python 2.1/Zope 2.4, but not all the way there yet (parser segfault..) - new version of PyExpat Features - Access to DOM from Zope environment sped up by new DOMProxy implementation ParsedXML 1.1b1 Bugs Fixed - Fixed an ExpatBuilder bug that caused a DOM reference to be leaked when parsing occured at the document. There is still a leak for fragment parsing that we're looking into. Features - ZCatalog support added - ZCache support added ParsedXML 1.1a1 Bugs Fixed - Version numbers make more sense :) Features - The value returned by get_size() is cached, which will often speed up the management view of an instance's container. ParsedXML 1.0 Bugs Fixed - Problems with Attr Node manipulation not being reflected by the getAttribute methods of their Elements and vice versa fixed. - Erroneous position information for parse error output on subnodes fixed. - Default attributes are noticed by the parser and printer, and the relevent DOM methods work. Features - ManageableDOM Nodes can find the persistent Document wrapper when it has been installed in a Zope ObjectManager. This object, rather than a newly created ManageableDocument wrapper, is returned when available by OwnerDocument calls. This allows Zopish navigation and discovery out of the Document, helps shorten acquisition paths, and fixes some bugs with manipulation at the Document. - ManageableDOM's usage of namespaces for parsing is now optional and settable. - The DOM 2 Traversal interface has been fleshed out, although support for visiblity and roots is not complete. ParsedXML 0.1b3 Bugs Fixed - Yet a few more DOM bugs fixed. - Fixed a distribution error that was causing build problems under Solaris. ParsedXML 0.1b2 Bugs Fixed - Many bugs found and fixed as we hammered out new DOM tests, especially in namespace usage, attribute printing, and attribute children. Features - Several speedups throughout the code. - ManageableDOM refactored into several base classes to make extension easier. === Added File Products/ParsedXML/CREDITS.txt === Current Maintainer: Martijn Faassen The Zope Corporation Parsed XML team: Karl Anderson Fred Drake Todd Corum Martijn Pieters External Contributor: Martijn Faassen Much test and implementation help was provided by Chris McDonough Shane Hathaway Guido van Rossum Parsed XML also contains code from versions of the original XMLDocument, written by Amos Latteier and Fourthought Inc. ParsedXML contains software derived from works by Fourthought Inc; see LICENSE.Fourthought for their license. === Added File Products/ParsedXML/DOMProxy.py === (505/605 lines abridged) import DOM import xml.dom from ComputedAttribute import ComputedAttribute import string _DOM_PROXY_FEATURES = () class DOMImplementationProxy: def __init__(self): self._domimplementation = DOM.theDOMImplementation def hasFeature(self, feature, version): feature = string.lower(feature) if (feature, version) in _DOM_PROXY_FEATURES: return 1 return self._domimplementation.hasFeature(feature, version) def _createDOMDocumentType(self, qualifiedName, publicId, systemId): return self._domimplementation.createDocumentType( qualifiedName, publicId, systemId) def _createDOMDocument(self, namespaceURI, qualifiedName, docType=None): return self._domimplementation.createDocument( namespaceURI, qualifiedName, docType) class DOMProxy: def __init__(self, node, persistentDoc=None): self._node = node self._persistentDoc = persistentDoc def getDOMObj(self): """Return the node without wrappers. """ return self._node def getPersistentDoc(self): """Return a reference to a security friendly persistent document if we can, or None. This can be None when OwnerDocument, if it exsists, is not None. If you don't need to reach the document through the security checks, you don't need to use this method. """ # We do this because the userfolder container needs to be in the aq # context of the unwrapped returned object. if self._persistentDoc and getattr( self._persistentDoc, "_container", None): try: [-=- -=- -=- 505 lines omitted -=- -=- -=-] class EntityReferenceProxy(NodeProxy): pass class NotationProxy(NodeProxy): _DOMAttrs = NodeProxy._DOMAttrs + ("publicId", "systemId") def _get_publicId(self): return self._node._get_publicId() publicId = ComputedAttribute(_get_publicId) def _get_systemId(self): return self._node._get_systemId() systemId = ComputedAttribute(_get_systemId) class DocumentTypeProxy(NodeProxy): _DOMAttrs = NodeProxy._DOMAttrs + ("publicId", "systemId", "name", "entities", "notations", "internalSubset") def _get_entities(self): return self.wrapNamedNodeMap(self._node._get_entities()) entities = ComputedAttribute(_get_entities) def _get_internalSubset(self): return self._node._get_internalSubset() internalSubset = ComputedAttribute(_get_internalSubset) def _get_name(self): return self._node._get_name() name = ComputedAttribute(_get_name) def _get_notations(self): return self.wrapNamedNodeMap(self._node._get_notations()) notations = ComputedAttribute(_get_notations) def _get_publicId(self): return self._node._get_publicId() publicId = ComputedAttribute(_get_publicId) def _get_systemId(self): return self._node._get_systemId() systemId = ComputedAttribute(_get_systemId) === Added File Products/ParsedXML/Example.zexp === ZEXP ((U OFS.FolderqUFolderqtqNt.}q(UidqUExampleqUtreeq(U¶q(hUFolderq ttQU_objectsq (}q (U meta_typeq UFolderq UidqUslidequ}q(h h hUtreequtU__ac_local_roles__q}qUkarlq]qUOwnerqasUtitleqUh(U q(hUFolderqttQU_ownerq(]qU acl_usersqahtu.¶Q((U OFS.FolderqUFolderqtqNt.}q(UtitleqUUidqUtreeqUtreeq(Uq (UOFS.DTMLDocumentq U DTMLDocumentq ttQU_objectsq (}q (U meta_typeqU DTML DocumentqUidqUtreequ}q(hU Parsed XMLqhUTreequtqUTreeq(U»q(UProducts.ParsedXML.ParsedXMLqU ParsedXMLqttQU__ac_local_roles__q}qUkarlq]qUOwnerqasu. 6((U OFS.FolderqUFolderqtqNt.}q(U nextSlideq(U±q(U#Products.PythonScripts.PythonScriptqU PythonScriptqttQUidq Uslideq U__ac_local_roles__q }q Ukarlq ]qUOwnerqasU_objectsq(}q(U meta_typeqU DTML Documentqh Uslidequ}q(U meta_typeqU Parsed XMLqUidqUSlidesqu}q(U meta_typeqU DTML MethodqUidqU viewSlidequ}q(U meta_typeq UScript (Python)q!Uidq"hu}q#(h h!h"U previousSlideq$u}q%(h h!h"UdomURLq&u}q'(h h!h"UgetColorq(utq)h(Uq*(UOFS.DTMLDocumentq+U DTMLDocumentq,ttQU_ownerq-(]q.U acl_usersq/aUkarlq0tq1USlidesq2(U q3(UProducts.ParsedXML.ParsedXMLq4U ParsedXMLq5ttQU viewSlideq6(U®q7(UOFS.DTMLMethodq8U DTMLMethodq9ttQh((Uµq:(hU PythonScriptq;ttQUtitleqttQUdomURLq?(U´q@(hU PythonScriptqAttQu.à((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqU tree tag demoqUrawqT)

The dtml-tree tag will show the ParsedXML DOM tree. We use it in the DOM tree view, too.

qU__ac_local_roles__q }q Ukarlq ]q UOwnerq asUglobalsq}qU__name__qUtreeqU_varsq}qu.»:((UProducts.ParsedXML.ParsedXMLqU ParsedXMLqtqNt.}q(UidqUTreeqU_persistentDocq(U»q(hU ParsedXMLq ttQU _containerq NU__ac_local_roles__q }q Ukarlq ]qUOwnerqasUtitleqUU contentTypeqUtext/xmlqU noNamespacesqKU_nodeqcProducts.ParsedXML.DOM.Core Document qNRq}q(U _childrenq]qcProducts.ParsedXML.DOM.Core Element qNRq}q(h]q(cProducts.ParsedXML.DOM.Core Text qNRq}q (U nodeValueq!U q"Udataq#h"ubhNRq$}q%(U localNameq&Nh]q'(hNRq(}q)(h!U q*h#h*ubhNRq+}q,(h&Nh]q-(hNRq.}q/(h!U q0h#h0ubhNRq1}q2(UtagNameq3Uhairq4UnodeNameq5h4h&NUprefixq6NU namespaceURIq7NubhNRq8}q9(h!U q:h#h:ubeh3Uheadq;h5h;h6Nh7NubhNRq<}q=(h!U q>h#h>ubhNRq?}q@(h3UbodyqAh5hAh&Nh6Nh7NubhNRqB}qC(h!U qDh#hDubhNRqE}qF(h&Nh]qG(hNRqH}qI(h!U qJh#hJubhNRqK}qL(h3UtoesqMh5hMh&Nh6Nh7NubhNRqN}qO(h!U qPh#hPubeh3UfeetqQh5hQh6Nh7NubhNRqR}qS(h!U h#U ubeh3UthingqTh5hTh6Nh7NubhNRqU}qV(h!U qWh#hWubhNRqX}qY(h&Nh]qZ(hNRq[}q\(h!U q]h#h]ubhNRq^}q_(h3Ufirstq`h5h`h&Nh6Nh7NubhNRqa}qb(h!U qch#hcubhNRqd}qe(h&Nh]qf(hNRqg}qh(h!U qih#hiubhNRqj}qk(h3Uthirdqlh5hlh&Nh6Nh7NubhNRqm}qn(h!U qoh#houbeh3Usecondqph5hph6Nh7NubhNRqq}qr(h!U h#U ubeh3hTh5hTh6Nh7NubhNRqs}qt(h!U quh#huubeh3Uthingsqvh5hvubaUvalueqwNU _elem_infoqx}qyUversionqzU1.0q{U _attr_infoq|}q}ubu.±5((U#Products.PythonScripts.PythonScriptqU PythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature FuncCode qoq}q(U co_varnamesq (Unodeq U $loop_watcherq U $read_guardq U $write_guardq U$guardqtU co_argcountqKubUidqU nextSlideqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(KKKKU‘t}|ƒt}t}t} |tƒi} xL |oA ||ƒidjo  |Sn ||ƒi}|ƒq:WtSdSq(NUslideqtq(UcontextqU nextSiblingqUnodeqUnodeNameqUNoneqU $loop_watcherq U $read_guardq!U $write_guardq"U$guardq#tq$(hh h!h"h#tq%UScript (Python)q&hKU   q')tN}q(tq)U_bodyq*T›# return the next sibling with a nodeName of 'slide', or None. # We need to do this because the parser doesn't treat whitespace text # nodes specially; they're parsed into DOM text nodes just like # everything else. # Acquire this from the slide node that wants to find the next slide. node = context.nextSibling while node: if node.nodeName == 'slide': return node node = node.nextSibling return Noneq+U _bind_namesq,(cShared.DC.Scripts.Bindings NameAssignments q-oq.}q/U_asgnsq0}q1(Uname_containerq2U containerq3U name_subpathq4Utraverse_subpathq5U name_contextq6Ucontextq7U name_m_selfq8Uscriptq9usbU Python_magicq:U™N q;U func_defaultsq

  1. /viewSlide">
qU__ac_local_roles__q }q Ukarlq ]q UOwnerq asUglobalsq}qU__name__qUslideqU_varsq}qu. Ã((UProducts.ParsedXML.ParsedXMLqU ParsedXMLqtqNt.}q(UidqUSlidesqU_persistentDocq(U q(hU ParsedXMLq ttQU _containerq NU__ac_local_roles__q }q Ukarlq ]qUOwnerqasUtitleqUU contentTypeqUtext/xmlqU noNamespacesqKU_nodeqcProducts.ParsedXML.DOM.Core Document qNRq}q(U _childrenq]qcProducts.ParsedXML.DOM.Core Element qNRq}q(U _attributesq]q]q(NUcolorq NNUgrayq!KeaUtagNameq"Uslidesq#UnodeNameq$h#h]q%(cProducts.ParsedXML.DOM.Core Text q&NRq'}q((U nodeValueq)U q*Udataq+h*ubhNRq,}q-(h]q.]q/(NUtitleq0NNU first slideq1KeaU localNameq2Nh]q3(h&NRq4}q5(h)U q6h+h6ubhNRq7}q8(h2Nh]q9h&NRq:}q;(h)U This is the first slide Here are some points, that I want to make: * one thing * another thing qNU namespaceURIq?Nubh&NRq@}qA(h)U qBh+hBubeh"UslideqCh$hCh>Nh?Nubh&NRqD}qE(h)U qFh+hFubhNRqG}qH(h]qI]qJ(Nh0NNU second slideqKKeah2Nh]qL(h&NRqM}qN(h)U qOh+hOubhNRqP}qQ(h2Nh]qRh&NRqS}qT(h)U˜ This is the second slide Here are some points, that I want to make: 1. one thing 2. another thing 3. final point qUh+hUubah"h=h$h=h>Nh?Nubh&NRqV}qW(h)U qXh+hXubeh"hCh$hCh>Nh?Nubh&NRqY}qZ(h)U q[h+h[ubhNRq\}q](h]q^(]q_(Nh0NNU the red slideq`Ke]qa(Nh NNUredqbKeeh2Nh]qc(h&NRqd}qe(h)U qfh+hfubhNRqg}qh(h2Nh]qih&NRqj}qk(h)U¥ This slide is red because it has a color attribute. All the others are gray because they didn't have a color attribute, but their parent did. qlh+hlubah"h=h$h=h>Nh?Nubh&NRqm}qn(h)U qoh+houbeh"hCh$hCh>Nh?Nubh&NRqp}qq(h)U qrh+hrubeubaUvalueqsNU _elem_infoqt}quUversionqvU1.0qwU _attr_infoqx}qyubu.®Ã((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUUrawqT

next: /viewSlide"> previous: /viewSlide">
qU__ac_local_roles__q}q Ukarlq ]q UOwnerq asUglobalsq }qU__name__qU viewSlideqU_varsq}qu.µ{((U#Products.PythonScripts.PythonScriptqU PythonScriptqtqNt.}q(U func_codeq(cShared.DC.Scripts.Signature FuncCode qoq}q(U co_varnamesq (Unodeq U $loop_watcherq U $read_guardq U $write_guardq U$guardqtU co_argcountqKubUidqUgetColorqU__ac_local_roles__q}qUkarlq]qUOwnerqasU_tq(hN(KKKKU—t}|ƒt}t}t }t}x[|oP||ƒidƒo||ƒidƒSn||ƒi}|ƒq1W tSdSq(NUcolorqtq(UcontextqUnodeqU hasAttributeqU getAttributeqU parentNodeqUNoneq U $loop_watcherq!U $read_guardq"U $write_guardq#U$guardq$tq%(hh!h"h#h$tq&UScript (Python)q'hKU  q()tN}q)tq*U_bodyq+UÌ# return a color attribute value from context or ancestors, or None. node = context while node: if node.hasAttribute('color'): return node.getAttribute('color') node = node.parentNode return Noneq,U _bind_namesq-(cShared.DC.Scripts.Bindings NameAssignments q.oq/}q0U_asgnsq1}q2(Uname_containerq3U containerq4U name_subpathq5Utraverse_subpathq6U name_contextq7Ucontextq8U name_m_selfq9Uscriptq:usbU Python_magicq;U™N qNu.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ === Added File Products/ParsedXML/ExtraDOM.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ Non-DOM helper functions useful when working with either of our DOM implementations, but not specific to any instantiation. """ from xml.dom import Node import DOM.ExpatBuilder import PrettyPrinter from StrIO import StringIO def parseFile(node, file, namespaces = 1): """ Parse XML file, replace node with the resulting tree, return replacement. Node must be in an existing DOM tree if not a Document. """ if node.nodeType == Node.DOCUMENT_NODE: return DOM.ExpatBuilder.parse(file, namespaces) elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: raise Exception, "replacing a document fragment doesn't make sense" else: fragment = DOM.ExpatBuilder.parseFragment( file, node.parentNode, namespaces) #if fragment.childNodes.length != 1: # # we could do this, actually, if we wanted # raise Exception, "replacing a Node with less or more " + \ # "than one tree of Nodes is not implemented" sib = node.nextSibling parent = node.parentNode parent.removeChild(node) #print fragment.childNodes.length #for child in fragment.childNodes: # print child.nodeType, node.nodeName # if child.nodeType == Node.TEXT_NODE: # print repr(child.data) return parent.insertBefore(fragment.firstChild, sib) # frag.firstChild def writeStream(node, stream = None, encoding = None, html = 0, contentType = None, prettyPrint = 0): "Write the XML representation of node to stream." if stream is None: stream = StringIO() PrettyPrinter.PrintVisitor(node, stream, encoding, html, contentType, prettyPrint=prettyPrint)() return stream === Added File Products/ParsedXML/INSTALL.txt === Requirements This release requires Zope 2.4.x and later. You also need PyXML 0.7.x or later installed, or at least a recent version of pyexpat. Installation Unpack the ParsedXML tarball in the Products directory of your Zope installation (usually this is lib/python/Products). Rename the unpacked directory to "ParsedXML" so that Python can import it. Restart Zope. There should be a ParsedXML product in your Products folder, and a ParsedXML option for available objects to add in the root folder. === Added File Products/ParsedXML/LICENSE.Fourthought === Copyright (c) 2000 Fourthought Inc, USA All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of FourThought LLC not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. FOURTHOUGHT LLC DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FOURTHOUGHT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. === Added File Products/ParsedXML/LICENSE.txt === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## === Added File Products/ParsedXML/ManageableDOM.py === (655/755 lines abridged) ############################################################################# # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations [-=- -=- -=- 655 lines omitted -=- -=- -=-] def _get_implementation(self): return self.implementation #block set of implementation, since we don't proxy it the same def __setattr__(self, name, value): if name == "implementation": raise xml.dom.NoModificationAllowedErr() ManageableDocument.inheritedAttribute('__setattr__')(self, name, value) # DOM extended interfaces class ManageableEntityReference(ManageableWrapper, DOMProxy.EntityReferenceProxy, ManageableNode): "A wrapper around a DOM EntityReference." meta_type = "Manageable Entity Reference" class ManageableEntity(ManageableWrapper, DOMProxy.EntityProxy, ManageableNode): "A wrapper around a DOM Entity." meta_type = "Manageable Entity" class ManageableNotation(ManageableWrapper, DOMProxy.NotationProxy, ManageableNode): "A wrapper around a DOM Notation." meta_type = "Manageable Notation" class ManageableDocumentType(ManageableWrapper, DOMProxy.DocumentTypeProxy, ManageableNode): "A wrapper around a DOM DocumentType." meta_type = "Manageable Document Type" Node = xml.dom.Node WRAPPER_TYPES = { Node.ELEMENT_NODE: ManageableElement, Node.ATTRIBUTE_NODE: ManageableAttr, Node.TEXT_NODE: ManageableText, Node.CDATA_SECTION_NODE: ManageableCDATASection, Node.ENTITY_REFERENCE_NODE: ManageableEntityReference, Node.ENTITY_NODE: ManageableEntity, Node.PROCESSING_INSTRUCTION_NODE: ManageableProcessingInstruction, Node.COMMENT_NODE: ManageableComment, Node.DOCUMENT_NODE: ManageableDocument, Node.DOCUMENT_TYPE_NODE: ManageableDocumentType, Node.DOCUMENT_FRAGMENT_NODE: ManageableDocumentFragment, Node.NOTATION_NODE: ManageableNotation, } del Node === Added File Products/ParsedXML/ParsedXML.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ Zope Product creation for Parsed XML. """ from OFS.SimpleItem import SimpleItem from AccessControl.Role import RoleManager from Persistence import Persistent from Acquisition import Implicit from OFS.Cache import Cacheable import Globals from ManageableDOM import ManageableDocument, DOMManageable, \ theDOMImplementation from StrIO import StringIO from xml.parsers import expat import DOM, ExtraDOM from types import FileType, StringType from urllib import quote from NodePath import registry _marker = [] # dummy default object for cache return parserr=('Sorry, an XML parsing error occurred. Check ' 'your XML document for well-formedness and try ' 'to upload it again after modification.

') def manage_addParsedXML(self,id,title='',file='', useNamespaces = 1, contentType = "text/xml", REQUEST=None,submit=None): "Add a Parsed XML instance with optional file content." if not file or not isinstance(file, StringType): file ='' try: ob = ParsedXML(id, file, useNamespaces, contentType) except expat.error, e: if REQUEST is not None: err = "%s%s" % (parserr, '%s' % getattr(e, 'args', '')) return Globals.MessageDialog( title= 'XML Parsing Error', message = err, action='manage_main') raise ob.title = str(title) id = self._setObject(id, ob) if REQUEST is not None: try: u=self.DestinationURL() except: u=REQUEST['URL1'] if submit==" Add and Edit ": u="%s/%s" % (u,quote(id)) REQUEST.RESPONSE.redirect(u+'/manage_main') manage_addParsedXMLForm = Globals.DTMLFile('dtml/documentAdd', globals()) def createDOMDocument(XMLstring = None, namespaces = 1): "Helper function to create a DOM document, without any proxy wrappers." if XMLstring: XMLstring=StringIO(XMLstring) # more efficient to not use ExtraDOM here return DOM.ExpatBuilder.parse(XMLstring, namespaces) # we use DOM.theDOMImplementation, not ManageableDOMs, for efficiency return DOM.theDOMImplementation.createDocument( None, "mydocument", None) contentTypes = ['text/html', 'application/html', 'text/xml'] class ParsedXML(SimpleItem, ManageableDocument, Cacheable): "The Parsed XML top object, and the persistent head of the tree." meta_type = 'Parsed XML' manage_editForm = Globals.HTMLFile('dtml/persEdit',globals()) manage_options = (DOMManageable.manage_options + RoleManager.manage_options + Cacheable.manage_options) __ac_permissions__ = (('View management screens', ('manage_main',), ('Manager',)), ('View DOM hierarchy', ('manage_DOMTree',), ('Manager',)), ('Edit ParsedXML', ('manage_editForm',), ('Manager',)), ('View source', ('index_html',), ('Manager',)), ('Access contents information', ('objectIds', 'objectValues', 'objectItems', ''), ('Manager',)),) icon = 'misc_/ParsedXML/pxml.gif' def __init__(self, id, XMLstring = None, namespaces = 1, contentType = "text/xml"): "Initialize a Parsed XML object" self.id = id self._persistentDoc = self # used by transient proxies self.noNamespaces = not namespaces if contentType not in contentTypes: import string raise RuntimeError, ( "Bad content type %s; valid types are %s" % (str(contentType), string.join(contentTypes))) self.contentType = contentType self.initFromDOMDocument(createDOMDocument(XMLstring, namespaces)) if XMLstring: self._lenCache = len(XMLstring) else: self._lenCache = len(str(self)) self._lenCorrect = 1 initFromDOMDocument__roles__ = () # Private def initFromDOMDocument(self, DOMdoc): "Initialize a Parsed XML from a DOM Document" # inherit from ManageableDocument ParsedXML.inheritedAttribute('__init__')(self, DOMdoc, self) def manage_afterAdd(self, object, container): """Store the container that we're being added to. This is used to traverse back to the persistent document.""" self._container = container # # methods that deal with persistence # # DOM nodes use __changed__ because its acquirable # Setting _p_changed is equivalent. def __changed__(self, *args): """Override the acquired __changed__ method used by the non-DB DOM nodes, update length cache, and mark this object as dirty.""" if getattr(self, '_v_lenCorrect', None): self._lenCorrect = 1 else: self._lenCorrect = 0 self.ZCacheable_invalidate() self._p_changed = 1 # wrap DOMIO to provide cacheing def index_html(self, REQUEST = None, RESPONSE = None): "Returns publishable source according to content type" if RESPONSE: RESPONSE.setHeader('Content-type', self.contentType) data = self.ZCacheable_get(default = _marker) if data is not _marker: return data # inherit from DOMIO data = ParsedXML.inheritedAttribute('index_html')(self, REQUEST, RESPONSE) self.ZCacheable_set(data) return data def get_size(self): "Length of the XML string representing this node in characters." if not getattr(self, '_lenCorrect', 0): self._lenCache = len(str(self)) self._lenCorrect = 1 return self._lenCache # methods that override ZDOM methods that are incorrect # def getElementsByTagName(self, tagName): return self.__getattr__("getElementsByTagName")(tagName) def hasChildNodes(self): return self.__getattr__("hasChildNodes")() # # methods that override SimpleItem; sigh, multiple inheritance. # def objectValues(self, spec=None): """ Returns a list of actual subobjects of the current object. If 'spec' is specified, returns only objects whose meta_type match 'spec'. """ return ManageableDocument.objectValues(self, spec) def objectIds(self, spec=None): """ Returns a list of subobject ids of the current object. If 'spec' is specified, returns objects whose meta_type matches 'spec'. """ return ManageableDocument.objectIds(self, spec) def objectItems(self, spec=None): """ Returns a list of (id, subobject) tuples of the current object. If 'spec' is specified, returns only objects whose meta_type match 'spec' """ return ManageableDocument.objectItems(self, spec) def tpValues(self): "Return a list of immediate subobjects. Used by the dtml-tree tag." return ManageableDocument.tpValues(self) # override ManageableDocument's method; we can't persist new DOM node by # hanging off of parents def parseXML(self, file): "parse file as XML, replace DOM node with resulting tree, return self" namespaces = not self.noNamespaces node = ExtraDOM.parseFile(self.getDOMObj(), file, namespaces) self.initFromDOMDocument(node) self.__changed__(1) return self def getDOM(self): """Get the Document node of the DOM tree. """ return self def getNodePath(self, scheme_name, node): """Create the node path for a particular node in the tree. """ # if we're asking for node of this document itself if node is self: return 'scheme_name' # otherwise ask for nodepath of node return node.getNodePath(scheme_name) def resolveNodePath(self, path): """Resolve node path from top of the tree to node. """ # start resolving from the document node doc = self._persistentDoc._earlyAqChain() # FIXME: could use raw DOM instead of management wrappers return registry.resolve_path(doc, path) def __getitem__(self, s): """Handle node paths. """ # backwards compatibility -- handle classic 0/1/2 paths try: return self.childNodes[int(s)].__of__(self) except ValueError: pass # start resolving from the document node doc = self._persistentDoc._earlyAqChain() # FIXME: could use raw DOM instead of management wrappers result = registry.resolve_path(doc, s) # FIXME: does this convince ZPublisher to show NotFound? if result is None: raise KeyError, "Could not resolve node path." return result Globals.default__class_init__(ParsedXML) # activate perms === Added File Products/ParsedXML/PrettyPrinter.py === import re import string from DOM.Core import Node, XMLNS_NS, XML_NS import sys from StrIO import StringIO # an XML printer which: # * can do pretty printing, optionally # * as opposed to the one defined in Printer.py, actually should # be less buggy class PrintVisitor: def __init__(self, root, stream=sys.stdout, encoding=None, html=0, contentType=None, entityReferenceExpansion=1, prettyPrint=0, indentLevel=2): self.namePrint = lambda s: s # identity if contentType and html: if contentType == 'html': self.namePrint = string.upper elif contentType == 'xml': self.namePrint = string.lower self.root = root self.stream = stream self.encoding = encoding self.html = html self.contentType = contentType self.entityReferenceExpansion = entityReferenceExpansion self.prettyPrint = prettyPrint self.indent = 0 self.indentLevel = indentLevel self.nodeType2method = { Node.ELEMENT_NODE: self.renderElement, Node.ATTRIBUTE_NODE: self.renderAttr, Node.TEXT_NODE: self.renderText, Node.CDATA_SECTION_NODE: self.renderCDATASection, Node.ENTITY_REFERENCE_NODE: self.renderEntityReference, Node.ENTITY_NODE: self.renderEntity, Node.PROCESSING_INSTRUCTION_NODE:\ self.renderProcessingInstruction, Node.COMMENT_NODE: self.renderComment, Node.DOCUMENT_NODE: self.renderDocument, Node.DOCUMENT_TYPE_NODE: self.renderDocumentType, Node.DOCUMENT_FRAGMENT_NODE: self.renderDocumentFragment, Node.NOTATION_NODE: self.renderNotation, } def renderAll(self): return self.render(self.stream, self.root) __call__ = renderAll def render(self, f, node): self.nodeType2method[node.nodeType](f, node) def renderElement(self, f, node): if self.prettyPrint: f.write(" " * self.indent * self.indentLevel) f.write("<") f.write(self.namePrint(node.tagName)) for attribute in node.attributes.values(): self.renderAttr(f, attribute) if not node.hasChildNodes(): if self.html: if node.tagName.upper() not in HTML_FORBIDDEN_END: f.write('>') else: f.write(' />') else: f.write('/>') if self.prettyPrint: f.write("\n") else: f.write('>') prettyPrint = self.prettyPrint stream = f if prettyPrint: f.write("\n") no_indentation = 0 for child in node.childNodes: if (child.nodeType == Node.TEXT_NODE and child.data.strip() != ''): no_indentation = 1 break if no_indentation: stream = StringIO() self.prettyPrint = 0 self.indent += 1 for child in node.childNodes: self.render(stream, child) self.prettyPrint = prettyPrint if prettyPrint: if no_indentation: f.write(indentBlock( stream.getvalue().strip(), self.indent * self.indentLevel, 70)) f.write('\n') self.indent -= 1 f.write(" " * self.indent * self.indentLevel) f.write("" % self.namePrint(node.tagName)) if self.prettyPrint: f.write("\n") def renderAttr(self, f, node): if not node.specified: return text, delimiter = _translateCdataAttr(node.value, encoding=self.encoding) f.write(" %s=%s%s%s" % (self.namePrint(node.name), delimiter, text, delimiter)) def renderText(self, f, node): data = node.data if self.prettyPrint: data = node.data.strip() if data == "": return data = indentBlock(data, self.indent * self.indentLevel, 70) f.write(_translateCdata(data, self.encoding)) if self.prettyPrint: f.write('\n') def renderCDATASection(self, f, node): f.write("", "]]]>")) f.write("]]>") def renderEntityReference(self, f, node): f.write('&') f.write(node.nodeName) f.write(';') def renderEntity(self, f, node): st = "\n') def renderProcessingInstruction(self, f, node): f.write('') def renderComment(self, f, node): f.write('') def renderDocument(self, f, node): if not self.html: f.write('\n') for child in node.childNodes: self.render(f, child) f.write('\n') def renderDocumentType(self, f, node): if (not node.entities.length and not node.notations.length and not node.systemId): return f.write("\n') def renderNotation(self, f, node): st = "\n') def renderDocumentFragment(self, f, node): for child in node.childNodes: self.render(f, child) # regexps used by _translateCdata(), # made global to compile once. # see http://www.xml.com/axml/target.html#dt-character ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]' SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]' ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]' # Note: Prolly fuzzy on this, but it looks as if characters from the # surrogate block are allowed if in scalar form, which is encoded in UTF8 the # same was as in surrogate block form XML_ILLEGAL_CHAR_PATTERN = re.compile( '%s|%s' % (ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS)) # the characters that we will want to turn into entrefs # We must do so for &, <, and > following ]]. # The xml parser has more leeway, but we're not the parser. # http://www.xml.com/axml/target.html#dt-chardata # characters that we must *always* turn to entrefs: g_cdataCharPatternReq = re.compile('[&<]|]]>') g_charToEntityReq = { '&': '&', '<': '<', ']]>': ']]>', } # characters that we must turn to entrefs in attr values: g_cdataCharPattern = re.compile('[&<>"\']|]]>') g_charToEntity = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', ']]>': ']]>', } # HTML nodes to always be minimzied, else never minimize # from PyXML's xml.dom.html # http://www.w3.org/TR/xhtml1/#guidelines HTML_FORBIDDEN_END = ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME', 'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM'] def _translateCdata(characters, allEntRefs = None, encoding='UTF-8'): """Translate characters into a legal format.""" if not characters: return '' if allEntRefs: # translate all chars to entrefs; for attr value if g_cdataCharPattern.search(characters): new_string = g_cdataCharPattern.subn( lambda m, d=g_charToEntity: d[m.group()], characters)[0] else: new_string = characters else: # translate only required chars to entrefs if g_cdataCharPatternReq.search(characters): new_string = g_cdataCharPatternReq.subn( lambda m, d=g_charToEntityReq: d[m.group()], characters)[0] else: new_string = characters if XML_ILLEGAL_CHAR_PATTERN.search(new_string): new_string = XML_ILLEGAL_CHAR_PATTERN.subn( lambda m: '&#%i;' % ord(m.group()), new_string)[0] #new_string = utf8_to_code(new_string, encoding) # XXX ugh return new_string def _translateCdataAttr(characters, encoding='UTF-8'): """ Translate attribute value characters into a legal format; return the value and the delimiter used. """ if not characters: return '', '"' if '"' not in characters or "'" in characters: delimiter = '"' new_chars = _translateCdata(characters, allEntRefs = 1, encoding=encoding) new_chars = re.sub("'", "'", new_chars) else: delimiter = "'" new_chars = _translateCdata(characters, allEntRefs = 1, encoding=encoding) new_chars = re.sub(""", '"', new_chars) return new_chars, delimiter def indentBlock(text, indent, line_length): words = text.split() lines = [] i = 0 while i < len(words): line = [] while i < len(words) and indent + len(" ".join(line)) < line_length: line.append(words[i]) i += 1 if len(line) > 1 and indent + len(" ".join(line)) >= line_length: i -= 1 line.pop() lines.append(" " * indent + " ".join(line)) return '\n'.join(lines) === Added File Products/ParsedXML/Printer.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## # # Specifically, most of this code is from PyXML's xml.dom.ext.Printer. # See LICENSE.Fourthought. # """ Printing and XML generating support for DOM classes. """ import re import string # regexps used by _translateCdata(), # made global to compile once. # see http://www.xml.com/axml/target.html#dt-character ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]' SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]' ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]' #Note: Prolly fuzzy on this, but it looks as if characters from the surrogate block are allowed if in scalar form, which is encoded in UTF8 the same was as in surrogate block form XML_ILLEGAL_CHAR_PATTERN = re.compile('%s|%s'%(ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS)) # the characters that we will want to turn into entrefs # We must do so for &, <, and > following ]]. # The xml parser has more leeway, but we're not the parser. # http://www.xml.com/axml/target.html#dt-chardata # characters that we must *always* turn to entrefs: g_cdataCharPatternReq = re.compile('[&<]|]]>') g_charToEntityReq = { '&': '&', '<': '<', ']]>': ']]>', } # characters that we must turn to entrefs in attr values: g_cdataCharPattern = re.compile('[&<>"\']|]]>') g_charToEntity = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', ']]>': ']]>', } # HTML nodes to always be minimzied, else never minimize # from PyXML's xml.dom.html # http://www.w3.org/TR/xhtml1/#guidelines HTML_FORBIDDEN_END = ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME', 'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM'] from DOM.Core import Node, XMLNS_NS, XML_NS from DOM import Traversal import sys class Visitor: """A class to visit an entire tree according to a TreeWalker.""" # These are both used for html mode. These aren't the types that # the server returns; 'html' covers '*/html', etc. contentTypes = ['html', 'xml'] def __init__(self, root, stream = sys.stdout, encoding = None, html = 0, contentType = None, whatToShow = Traversal.NodeFilter.SHOW_ALL, filter = None, entityReferenceExpansion = 1): if root.ownerDocument: doc = root.ownerDocument else: doc = root self.tw = doc.createTreeWalker(root, whatToShow, filter, entityReferenceExpansion) self.stream = stream self.encoding = encoding self.html = html if contentType and contentType not in self.contentTypes: raise RuntimeError, ( "Bad content type %s; valid types are 'html', 'xml'" % contentType) self.contentType = contentType # elt/attr names: html */html upcase, html */xml lowercase. # http://www.w3.org/TR/xhtml1/#guidelines self.namePrint = lambda string: string # identity if self.contentType and self.html: if self.contentType == 'html': self.namePrint = string.upper elif self.contentType == 'xml': self.namePrint = string.lower # maps node type to visitor method self.NODE_TYPES = { Node.ELEMENT_NODE: self.visitElement, Node.ATTRIBUTE_NODE: self.visitAttr, Node.TEXT_NODE: self.visitText, Node.CDATA_SECTION_NODE: self.visitCDATASection, Node.ENTITY_REFERENCE_NODE: self.visitEntityReference, Node.ENTITY_NODE: self.visitEntity, Node.PROCESSING_INSTRUCTION_NODE: \ self.visitProcessingInstruction, Node.COMMENT_NODE: self.visitComment, Node.DOCUMENT_NODE: self.visitDocument, Node.DOCUMENT_TYPE_NODE: self.visitDocumentType, Node.DOCUMENT_FRAGMENT_NODE: self.visitDocumentFragment, Node.NOTATION_NODE: self.visitNotation, } # methods to drive the walker def visitWhole(self): curNode = self.tw.currentNode self.visit(curNode, start = 1) self.visitChildren() self.visit(curNode, start = 0) __call__ = visitWhole def visitChildren(self): if self.tw.firstChild(): self.visitWhole() while (self.tw.nextSibling()): self.visitWhole() self.tw.parentNode() # methods that do stuff once we're there, without moving the walker def visitElement(self, node, start): self.visitGeneric(node) def visitAttr(self, node, start): self.visitGeneric(node) def visitText(self, node, start): self.visitGeneric(node) def visitCDATASection(self, node, start): self.visitGeneric(node) def visitEntityReference(self, node, start): self.visitGeneric(node) def visitEntity(self, node, start): self.visitGeneric(node) def visitProcessingInstruction(self, node, start): self.visitGeneric(node) def visitComment(self, node, start): self.visitGeneric(node) def visitDocument(self, node, start): self.visitGeneric(node) def visitDocumentType(self, node, start): self.visitGeneric(node) def visitDocumentFragment(self, node, start): self.visitGeneric(node) def visitNotation(self, node, start): self.visitGeneric(node) def visitGeneric(self, node): self.stream.write("visit %s node %s\n"%(node.nodeType, node.nodeName)) def visit(self, node, start): "Find the element type and call the appropriate visit method" visitMethod = self.NODE_TYPES.get(node.nodeType, None) if visitMethod is None: raise TypeError, ( "Cannot print unknown nodeType: %s" % node.nodeType) else: return visitMethod(node, start) # we'll want hooks to generalize this for prettyprinting etc: # add formatting, named constants for < etc so we can < etc. class PrintVisitor(Visitor): """A class to generate XML for a tree according to a TreeWalker""" def visitElement(self, node, start): if start: self.stream.write('<' + self.namePrint(node.tagName)) st = '' for item in node.attributes.values(): self.visitAttr(item, start=1) if not node.hasChildNodes(): if self.html: if string.upper(node.tagName) not in HTML_FORBIDDEN_END: self.stream.write('>') else: self.stream.write(' />') else: self.stream.write('/>') else: self.stream.write('>') else: if node.hasChildNodes(): self.stream.write('') def visitAttr(self, node, start): if start and node.specified: text, delimiter = _translateCdataAttr(node.value) self.stream.write(" %s=%s%s%s" % (self.namePrint(node.name), delimiter, text, delimiter)) def visitText(self, node, start): if start: self.stream.write(_translateCdata(node.data, self.encoding)) def visitCDATASection(self, node, start): if start: self.stream.write('", "]]]>")) self.stream.write(']]>') def visitEntityReference(self, node, start): if start: self.stream.write('&') self.stream.write(node.nodeName) self.stream.write(';') def visitEntity(self, node, start): if start: st = "\n') def visitNotation(self, node, start): if start: st = "\n') def visitProcessingInstruction(self, node, start): if start: self.stream.write('') def visitComment(self, node, start): if start: self.stream.write('') def visitDocument(self, node, start): if start: if not self.html: self.stream.write('\n') else: self.stream.write('\n') # Add a final newline def visitDocumentType(self, node, start): if start: if not node.entities.length and not node.notations.length and \ not node.systemId: return self.stream.write("\n') def visitDocumentFragment(self, node, start): pass # we're just here for the children def _translateCdata(characters, allEntRefs = None, encoding='UTF-8'): """Translate characters into a legal format.""" if not characters: return '' if allEntRefs: # translate all chars to entrefs; for attr value if g_cdataCharPattern.search(characters): new_string = g_cdataCharPattern.subn( lambda m, d=g_charToEntity: d[m.group()], characters)[0] else: new_string = characters else: # translate only required chars to entrefs if g_cdataCharPatternReq.search(characters): new_string = g_cdataCharPatternReq.subn( lambda m, d=g_charToEntityReq: d[m.group()], characters)[0] else: new_string = characters # This was never used, & I never got it anyway - prettyprinting? #if prev_chars[-2:] == ']]' and characters[0] == '>': # new_string = '>' + new_string[1:] # Note: use decimal char entity rep because some browsers are broken # FIXME: This will bomb for high characters. # Should, for instance, detect the UTF-8 for 0xFFFE # and put out ￾ if XML_ILLEGAL_CHAR_PATTERN.search(new_string): new_string = XML_ILLEGAL_CHAR_PATTERN.subn( lambda m: '&#%i;' % ord(m.group()), new_string)[0] #new_string = utf8_to_code(new_string, encoding) # XXX ugh return new_string def _translateCdataAttr(characters): """ Translate attribute value characters into a legal format; return the value and the delimiter used. """ if not characters: return '', '"' if '"' not in characters or "'" in characters: delimiter = '"' new_chars = _translateCdata(characters, allEntRefs = 1) new_chars = re.sub("'", "'", new_chars) else: delimiter = "'" new_chars = _translateCdata(characters, allEntRefs = 1) new_chars = re.sub(""", '"', new_chars) #FIXME: There's more to normalization #Convert attribute new-lines to character entity # characters is possibly shorter than new_chars (no entities) # I think this was a prettyprinting issue, newlines aren't illegal # http://www.xml.com/axml/target.html#NT-AttValue #if "\n" in characters: # new_chars = re.sub('\n', ' ', new_chars) return new_chars, delimiter === Added File Products/ParsedXML/README.DOMProxy === How and why we are proxying DOM nodes. Parsed XML consists of two DOM interfaces. Our DOM is a tight and fast implementation. Our ManageableDOM (of which the ParsedXML object that is instantiated acts as the top object) contains an instance of a DOM tree, proxies its DOM interface, and also provides Zope support such as management interfaces. A Parsed XML object can be created from scratch, in which case its DOM document will be created with it, or it can be wrapped around an existing DOM document. Parsed XML objects should be able to provide some management support for any compliant DOM document, since it proxies DOM calls. However, since it uses our builder, which is optimized for our DOM storage, parsing will not work on storages other than our DOM. Why are we proxying? Our DOM implementation is fast and scalable, and we didn't want to compromise this with our extras. Some users won't want or need the Zopish features to be married to the DOM implementation. When should the proxy be used, and when should the simple DOM be used? There's no reason to use the proxies when you don't need their features. If all that you need is a DOM storage, then the proxies aren't necessary, and you can create and use a DOM document without the proxy wrappers. However, you will have to know what you are doing; some Zope machinery won't be taken care of for you: - The DOM storage doesn't keep track of any non-DOM attributes. For example, namespace usage and content type are stored by the proxy Document, and if you're not using this, you'll have to keep track of these attributes yourself, since the DOM doesn't keep track of them. - The DOM storage doesn't know about Zope permissions, so your containing object must handle this. - The DOM storage doesn't provide any persistence machinery, although it will acquire and call the persistence triggering methods when available, so storing it in a persistent container will suffice to persist the DOM. To create a DOM Document without any proxy wrappers, see createDOMDocument() in ParsedXML.py. When should the proxy not be used? When you reference the proxied DOM object through a different persistent object, *and* change the DOM through that reference, *and* rely on get_size() or use a ZCache, *and* the ParsedXML Document isn't notified when the change occurs. The DOM objects persist by acquiring persistence methods from their containers. The proxy objects update certain cached values when these methods are called. That means that if a DOM Document is referenced by a different persistent object, and changes are made through that reference, the ParsedXML proxy won't know to update its cached values. ParsedXML caches the result of get_size(), and provides support for a ZCache to cache index_html. If you use a ZCache with a ParsedXML instance, or rely on the result of get_size(), you will need to make sure that these values are updated if the DOM is modified through a reference other than the ParsedXML Document. This can be done by calling __changed__() on the ParsedXML Document. How are we proxying? Our DOM implementation is in the DOM subdirectory. The baseclasses for the DOMImplementation is in DOMProxy.py. These define the machinery for proxying our DOM tree. The basic proxying is defined here, except for methods to create the proxy nodes, which we'll describe soon. The base proxy class is DOMProxy. It contains a reference to the actual DOM node it is proxying for. NodeProxy, ElementProxy, etc. all specialize DOMProxy for the appropriate DOM classes. These proxy classes all lack the ability to actually create instances of the proxy nodes. This is because they are designed to be subclassed, and they don't yet know what class to wrap a DOM node into when they want a proxy object. Subclasses should define the methods wrapDOMObj(), wrapNodeList() and wrapNamedNodeMap(). wrapDOMObj() and it should take a DOM Node and return the appropriate proxy node; wrapNodeList() and wrapNamedNodeMap() should take a NodeList and NamedNodeMap object respectively and returned proxied versions. Because these methods are undefined, these baseclasses cannot be instantiated, they must be subclassed. A simple example of a working implementation is in TransPubDOMProxy.py. The actual proxy classes that Parsed XML uses are in ManageableDOM.py, and the basic DOM baseclass is ManageableNode, which corresponds to a DOM node. It mixes DOMProxy.NodeProxy with ManageableWrapper, which provides the needed methods that return ManageableNode, ManageableNodeList and ManageableNamedNodeMap subclasses. ManageableNode also mixes in DOMManageable, which provides our management and publishing support, and an Acquisition class. When a Parsed XML product is added to a Zope installation, a ParsedXML object is instantiated, which is a subclass of ManageableDocument. It is important to note that none of the other proxy nodes are persistent! wrapDOMObj() wraps a new proxy node around an existing DOM node whenever it is called. It never reuses existing proxy nodes, or even knows of their existence. So although you can do things like assign non-DOM attributes to a ManageableNode, re-navigating to the ManageableNode corresponding to the same place in the DOM tree won't get you a node with those attributes, since it's a whole new instance. This also means that navigating with DOM calls is slower, because of all that instantiating and wrapping. It's more efficient to work through the proxied DOM objects when you can and wrap the result when you must. There are ways to make persistent proxy objects if you're developing your own proxy classes based on ours, by inheriting a wrapDOMObj() method that makes persistent proxy objects and returns existing ones when appropriate. === Added File Products/ParsedXML/README.parseprint === DOM objects, XML, printing, and parsing ParsedXML doesn't store any XML. It stores a DOM tree, which is an object representation of the data in an XML document; or perhaps it is more accurate to say that an XML document is a serial representation of some data, and the corresponding DOM tree is a hierarchical representation of the same data. The primary way of accessing and manipulating that data is with DOM API calls. When a ParsedXML object is viewed as XML, the DOM tree is serialized into the XML which is viewed. This is what is seen in the Edit management view. When XML is inputted into a ParsedXML object, it is parsed to create DOM objects which are inserted into the DOM tree. This is what happens when XML is edited or uploaded in the Edit management view. It is important to note that the DOM is not the XML because the information that each stores is not the same. The XML specification states what information can be expressed by a well-formed XML document, and some of this information is not preserved by the parser, printer, and DOM storage. For example, whitespace in attribute strings isn't significant. The Infoset specification at "http://www.w3.org/TR/xml-infoset/" states what can be lost; parsers are also allowed certain liberties with their input. Our parser, printer, and DOM keep more information than the Infoset requires, such as attribute order. Entities and entity references are an example of how the parser and printer manipulate XML. Currently, entity references are expanded to their entities by the parser; it never adds entity reference nodes to the document. This is legal, if annoying, behavior. Because of this, when an XML file containing "&" in a text node is parsed, the node will contain a literal "&" where the "&" was in the XML. It is legal for a DOM text node to contain a literal "&" character. However, it is not legal for an XML text node to contain a literal "&", so when that node is printed, the "&" will be converted back into a "&" entity reference. === Added File Products/ParsedXML/README.txt === README for Parsed XML. What is it? Parsed XML allows you to use XML objects in the Zope environment. You can create XML documents in Zope and leverage Zope to format, query, and manipulate XML. Parsed XML consists of a DOM storage, a builder that uses PyExpat to parse XML into the DOM, and a management proxy product that provides Zope management features for a DOM tree. It also includes a system to create paths to nodes in Zope URLs (NodePath). Requirements, Installation See INSTALL.txt. Feedback, discussion, more information The latest released version can be found at the "product":http://www.zope.org/Members/faassen/ParsedXML site. For more information, see the Parsed XML "wiki":http://www.zope.org/Wikis/DevSite/Projects/ParsedXML. Bug reports and status is kept by the the Parsed XML "tracker":http://www.zope.org/Members/karl/ParsedXML/ParsedXMLTracker. There is a "mailing list":http://mail.zope.org/mailman/listinfo/parsed-xml-dev with archives. The latest version is available through "CVS":http://www.zope.org/Wikis/DevSite/Projects/ParsedXML/Releases. Features The Parsed XML product parses XML into a Zopish DOM tree. The elements of this tree support persistence, acquisition, etc.. The document and subnodes are editable and manageable through management proxy objects, and the underlying DOM tree can be directly manipulated via DTML, Python, etc.. DOM and ManageableDOM We're implementing a lean, mean DOM tree for pure DOM access, and a tree of proxy shells to handle management and take care of the conveniences like publishing and security. The ManageableNodes are the proxy objects. These are what you see in the management interface, and the top object that gets put in the ZODB. Note that only the top proxy object is persistent, the others are transient. The Nodes are pure DOM objects. From a ManageableNode, the DOM Node is retrieved with the getDOMObj() call. See README.DOMProxy for information about the proxy objects. DOM API support The DOM tree created by Zope aims to comply with the DOM level 2 standard. This allows you to access your XML in DTML or External Methods using a standard and powerful API. We are currently supporting the DOM level 2 Core and Traversal specifications. The DOM tree is not built with the XML-SIG's DOM package, because it requires significantly different node classes. DOM attributes are made available according to the Python language mapping for the IDL interfaces described by the DOM recommendation; see the "mapping":http://cgi.omg.org/cgi-bin/doc?ptc/00-04-08. URL traversal Parsed XML implements a 'NodePath' system to create references to XML nodes (most commonly elements). FIXME include examples here Currently, traversal uses an element's index within its parent as an URL key. For example, 'http://server/myDoc/0/2/mymethod' This URL traverses from an XML Document object with id 'myDoc' to it's first sub-element, to that element's second sub-element to an acquired method with id 'myMethod' DOM methods can also be used in URLs, for example, 'http://server/myDoc/firstChild/nextSibling/mymethod' Editing XML with the management interface XML Documents and subnodes are editable via the management interface. Documents and subtrees can be replaced by uploading XML files. Security Security is handled at the document level. DOM attributes and methods are protected by the "Access contents information" permission. Subnodes will acquire security settings from the document. Developing with Parsed XML We like to think that Parsed XML provides a flexible platform for using a DOM storage and extending that storage to do interesting things. See README.DOMProxy for an explanation of how we're using this for Parsed XML. We've included a comprehensive unit test suite to make testing for DOM compliance easier. See tests/README for details. If you want to submit changes to Parsed XML, please use the test suite to make sure that your changes don't break anything. Bugs There are bugs in how multiple node references reflect the hierarchy above the node: - A reference to a subnode of a DOM document won't reflect some hierarchy changes made on other references to the same node. If two references to a node are created, and one is then reparented, the other reference won't reflect the new parent. The parentNode attribute will be incorrect, for example, as well as the ownerDocument and ownerElement attributes. - A reference to a subnode of a DOM document can't be properly stored as a persistent attribute of a ZODB object; it will lose hierarchy information about its parent as well. Entity reference handling is not complete: - Entity references do not have child nodes that mirror the child nodes of the referenced entity; they do not have child nodes at all. - TreeWalker.expandEntityReferences has no effect, because of the above bug. Unicode support is still incomplete. It appears to work with Python 2.1 and Zope 2.4, but there are still some issues with the parser. Traversal support for visibility and roots is not complete. Credits see CREDITS.txt and LICENSE.Fourthought. === Added File Products/ParsedXML/StrIO.py === """Module which selects the right version of StringIO.""" # Python 2.1 and up is now a requirement, so we don't need to # do anything special here from StringIO import StringIO === Added File Products/ParsedXML/TransPubDOMProxy.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ A simple example implementation of DOMProxy. Provide a class to implement wrapDOMObj(), mix that and the DOMProxy proxy classes, and add whatever you want to make it interesting. """ import DOMProxy import Acquisition class TransPubWrapper: """ Mixin class to go alongside DOMProxy classes. Provides the wrapDOMObj function to create TransPubNode classes. This is what makes TransPubNodes transient - we never re-use proxies, but create new ones when we need them. """ # In the future we may want to return different proxy types based # on non-DOM node types, such as DB/nonDB. Probably map # the same way that the DOM classes will map. def wrapDOMObj(self, node): """ Return the appropriate manageable class wrapped around the Node. We never create Nodes ourselves, only wrap existing ones. Wrapped node can be single DOM object, a non-DOM object, or a container that contains only non-DOM objects - DOM objects in containters aren't wrapped. """ from xml.dom import Node import types if node == None: return None elif isinstance(node, types.InstanceType) \ and node.__class__.__name__ == "ChildNodeList": # XXX impl detail return TransPubNodeList(node) elif isinstance(node, types.InstanceType) \ and node.__class__.__name__ == "AttributeMap": # XXX impl detail return TransPubNamedNodeMap(node) elif not hasattr(node, "nodeType"): return node # not DOM, don't wrap. elif node.nodeType == Node.ELEMENT_NODE: return TransPubElement(node) elif node.nodeType == Node.ATTRIBUTE_NODE: return TransPubAttr(node) elif node.nodeType == Node.TEXT_NODE: return TransPubText(node) elif node.nodeType == Node.CDATA_SECTION_NODE: return TransPubCDATASection(node) elif node.nodeType == Node.ENTITY_REFERENCE_NODE: return TransPubEntityReference(node) elif node.nodeType == Node.ENTITY_NODE: return TransPubEntity(node) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: return TransPubProcessingInstruction(node) elif node.nodeType == Node.COMMENT_NODE: return TransPubComment(node) elif node.nodeType == Node.DOCUMENT_NODE: return TransPubDocument(node) elif node.nodeType == Node.DOCUMENT_TYPE_NODE: return TransPubDocumentType(node) elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE: return TransPubDocumentFragment(node) elif node.nodeType == Node.NOTATION_NODE: return TransPubNotation(node) else: raise TypeError _TRANS_PUB_DOM_PROXY_FEATURES = ( ("org.zope.dom.acquisition", None), ("org.zope.dom.acquisition", "1.0"), ) class TransPubDOMImplementation(DOMProxy.DOMImplementationProxy): """ A DOMImplementation proxy that implements createDocument to produce TransPubDocument instances. """ def hasFeature(self, feature, version): feature = string.lower(feature) if (feature, version) in _TRANS_PUB_DOM_PROXY_FEATURES: return 1 return self._domimplementation.hasFeature(feature, version) def createDocument(self, namespaceURI, qualifiedName, docType=None): DOMDocument = self._createDOMDocument(namespaceURI, qualifiedName, docType) return TransPubDocument(DOMDocument.aq_base) # XXX check aq theDOMImplementation = TransPubDOMImplementation() #DOMIO, DOMManageable, DOMPublishable, class TransPubNode(TransPubWrapper, DOMProxy.NodeProxy, Acquisition.Implicit): "The core of the TransPub DOM proxies." pass class TransPubNodeList(TransPubWrapper, DOMProxy.NodeListProxy): "A TransPubWrapper mixer with NodeListProxy." pass class TransPubNamedNodeMap(TransPubWrapper, DOMProxy.NamedNodeMapProxy): "A TransPubWrapper mixer with NamedNodeMapProxy." pass class TransPubDocumentFragment(DOMProxy.DocumentFragmentProxy, TransPubNode): "A TransPubWrapper mixer with DocumentFragmentProxy." pass class TransPubElement(DOMProxy.ElementProxy, TransPubNode): "A TransPubWrapper mixer with ElementProxy." pass class TransPubCharacterData(DOMProxy.CharacterDataProxy, TransPubNode): "A TransPubWrapper mixer with CharacterDataProxy." pass class TransPubCDATASection(DOMProxy.CDATASectionProxy, TransPubNode): "A TransPubWrapper mixer with CDATASectionProxy." pass class TransPubText(TextProxy, DOMProxy.TransPubCharacterData): "A TransPubWrapper mixer with TextProxy." pass class TransPubComment(CommentProxy, DOMProxy.TransPubCharacterData): "A TransPubWrapper mixer with CommentProxy." pass class TransPubProcessingInstruction(DOMProxy.ProcessingInstructionProxy, TransPubNode): "A TransPubWrapper mixer with ProcessingInstructionProxy." pass class TransPubAttr(DOMProxy.AttrProxy, TransPubNode): "A TransPubWrapper mixer with AttrProxy." pass class TransPubDocument(DOMProxy.DocumentProxy, TransPubNode): """ A TransPubWrapper mixer with DocumentProxy. Provides and protects the implementation attribute. """ implementation = theDOMImplementation #block set of implementation, since we don't proxy it the same def __setattr__(self, name, value): if name == "implementation": raise xml.dom.NoModificationAllowedErr() # wacky ExtensionClass inheritance TransPubDocument.inheritedAttribute('__setattr__')(self, name, value) # DOM extended interfaces class TransPubEntityReference(DOMProxy.EntityReferenceProxy, TransPubNode): "A TransPubWrapper mixer with EntityReferenceProxy." pass class TransPubEntity(DOMProxy.EntityProxy, TransPubNode): "A TransPubWrapper mixer with EntityProxy." pass class TransPubNotation(DOMProxy.NotationProxy, TransPubNode): "A TransPubWrapper mixer with NotationProxy." pass class TransPubDocumentType(DOMProxy.DocumentTypeProxy, TransPubNode): "A TransPubWrapper mixer with DocumentTypeProxy." pass === Added File Products/ParsedXML/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ Parsed XML product """ def initialize(context): import ParsedXML context.registerClass( ParsedXML.ParsedXML, permission = 'Add Documents, Images, and Files', icon='www/pxml.gif', constructors = (ParsedXML.manage_addParsedXMLForm, ParsedXML.manage_addParsedXML) ) context.registerHelp() context.registerHelpTitle('Parsed XML Help') #context.registerHelpTopic('ParsedXML_Edit', ParsedXML_Edit()) === Added File Products/ParsedXML/main.dtml === hello world === Added File Products/ParsedXML/version.txt === ParsedXML 1.3.1 From sidnei at x3ng.com.br Fri May 30 11:17:34 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/ParsedXML/tests - README:1.1 __init__.py:1.1 domloader.py:1.1 domtester.py:1.1 profParse.py:1.1 profPrinter.py:1.1 profPyXMLParse.py:1.1 profPyXMLPrinter.py:1.1 test_ODB.py:1.1 test_acquisition.py:1.1 test_all.py:1.1 test_aqpain.py:1.1 test_collection.py:1.1 test_dom.py:1.1 test_elementid.py:1.1 test_parser.py:1.1 test_persistence.py:1.1 test_prettyprinter.py:1.1 test_printer.py:1.1 test_pyxmldom.py:1.1 test_truthable.py:1.1 test_wrappeddom.py:1.1 test_zopeinterface.py:1.1 Message-ID: <200305301517.h4UFHYi19518@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ParsedXML/tests In directory cvs.zope.org:/tmp/cvs-serv19195/ParsedXML/tests Added Files: README __init__.py domloader.py domtester.py profParse.py profPrinter.py profPyXMLParse.py profPyXMLPrinter.py test_ODB.py test_acquisition.py test_all.py test_aqpain.py test_collection.py test_dom.py test_elementid.py test_parser.py test_persistence.py test_prettyprinter.py test_printer.py test_pyxmldom.py test_truthable.py test_wrappeddom.py test_zopeinterface.py Log Message: Adding products needed for migration of NZO === Added File Products/ParsedXML/tests/README === Parsed XML test README Using the test suite This directory holds our test suite. Usually, it can be invoked with "python domtester.py". Appending an -h argument will return a usage string. To run the domtester, you need to be able to find Zope's unit testing framework and mount the ZODB, so you need to make sure Zope's lib/python can be found. Adding Zope's lib/python to your python path, either going through sys.path or adding it to the PYTHONPATH environment variable. For instance, if you're running bash, all you have to type is this:: export PYTHONPATH=/path/to/Zope/lib/python The ZODB must also be mountable, so if you're not running ZEO, the server must be stopped while the tests run. Upon completion, the tester will report how many tests failed, and put more detailed output in out.txt. Running tests individually You can also run each test individually, for instance:: python test_dom.py Again you have to make sure Zope's lib/python can be found. There's also a very simple test_all.py that runs all the individual tests in a row; doing the same thing as domtester.py does but without some of the conveniences. Debugging with the test suite If you want to contribute changes to ParsedXML, please run the test suite to make sure that your changes don't break anything. The tests themselves are in test_domapi.py. The test suite checks for compliance with the Python IDL mapping with the DOM specification. As of this writing nearly all of DOM level 2 is tested, along with a few level 3 interfaces. Some Parsed XML specific tests are run as well, if the implementation supports those features, such as persistence, parsing, and printing. The suite is very useful for testing extensions to Parsed XML that provide full DOM capabilities. We run the tests on both our ManageableDOM and DOM layers - if it works for DOM, it should work for ManageableDOM, which proxies the entire DOM interface. === Added File Products/ParsedXML/tests/__init__.py === # make this a package === Added File Products/ParsedXML/tests/domloader.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Products.ParsedXML.DOM import ExpatBuilder def main(): import getopt import sys namespaces = 0 opts, args = getopt.getopt(sys.argv[1:], "n") if opts: namespaces = 1 if args: file = args[0] else: file = sys.stdin doc = ExpatBuilder.parse(file, namespaces=namespaces) print doc for node in doc.documentElement.childNodes: print (node.nodeType, node.nodeName, (node.namespaceURI, node.localName), node.nodeValue) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/domtester.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## USAGE = '''\ %(program)s -- Test script for DOM implementations. usage: %(program)s [-h] [implementations...] Parameters: -g Use the Tkinter GUI from unittestgui, if available. -h Print this help text. -x Treat the list of tests as tests to exclude rather than include. tests List of tests to execute. By default, all known testcases are run. Known tests include: - DOM the basic DOM - ParsedXML the persistent/wrapped Zope DOM - Printer the DOM-to-XML Printer - Parser the Expat parser and DOM builder - Persistence persistence of the managed DOM - Truthable checks for truth tests - Acquisition checks for acquisition-related integrity failure ''' import getopt import os import sys import imp import unittest import Products.ParsedXML impls = ( ('DOM', 'test_dom'), ('ParsedXML', 'test_wrappeddom'), ('Printer', 'test_printer'), ('Parser', 'test_parser'), ('Persistence', 'test_persistence'), ('Truthable', 'test_truthable'), ('UserAcquisition', 'test_acquisition'), # known parenting bug, also causes errors in DOM tests ('Acquisition', 'test_aqpain'), ('ZopeInterface', 'test_zopeinterface'), # FIXME: this is causing a segfault with debian's python 2.1, though # not with a manually compiled python.. need to look into this # ('Refcounts', 'test_collection'), ('ODB', 'test_ODB'), ('elementId', 'test_elementid'), ) def main(): program = os.path.basename(sys.argv[0]) impls_to_exclude = None gui = 0 try: opts, impls_to_test = getopt.getopt( sys.argv[1:], "dghx", ["disable-gc", "gui", "help", "exclude"]) except getopt.error: sys.stdout = sys.stderr print USAGE % {"program": program} sys.exit(2) for opt, arg in opts: if opt in ("-x", "--exclude"): impls_to_exclude = impls_to_test impls_to_test = [] elif opt in ("-d", "--disable-gc"): try: import gc except ImportError: # nothing to disable pass else: gc.disable() elif opt in ("-g", "--gui"): gui = 1 elif opt in ("-h", "--help"): print USAGE % {"program": program} sys.exit() # Make a backup, so you can see differences between runs. if os.path.exists('out.txt'): if os.path.exists('out.txt.bak'): os.unlink('out.txt.bak') os.rename('out.txt', 'out.txt.bak') if gui: run_tests = run_tests_gui else: run_tests = run_tests_text if run_tests(impls_to_test, impls_to_exclude): sys.exit(1) def run_tests_gui(include, exclude): try: import unittestgui except ImportError: sys.stderr.write( "unittestgui module not installed; install that module from\n" "PyUNIT and try again.\n") return 1 else: unittestgui.main("__main__.all_suites") return 0 def run_tests_text(include, exclude): errs = 0 outf = open("out.txt", "w") stdout = sys.stdout for implname, filename in impls: if include and implname not in include: continue elif exclude and implname in exclude: continue sys.stdout = outf print "===== %s =====\n" % implname try: # Import test file and retrieve test suite. testSuite = load_suite(filename) errs = errs + run_suite(testSuite, implname, outf) finally: sys.stdout = stdout outf.close() return errs def load_suite(filename): path = os.path.join(sys.modules['Products.ParsedXML'].__path__[0], 'tests') file, pathname, desc = imp.find_module(filename, [path]) module = imp.load_module(filename, file, pathname, desc) file.close() return module.test_suite() def all_suites(): suite = unittest.TestSuite() for name, module in impls: suite.addTest(load_suite(module)) return suite def run_suite(testSuite, implname, outf=None): if outf is None: outf = sys.stdout if hasattr(unittest, 'JUnitTextTestRunner'): # Prefer the non-verbose version. runner = unittest.JUnitTextTestRunner(outf) else: runner = unittest.TextTestRunner(outf) result = runner.run(testSuite) print "\n\n" if result.errors: print "Errors:" map(print_error, result.errors) print if result.failures: print "Failures:" map(print_error, result.failures) print newerrs = len(result.errors) + len(result.failures) if newerrs: sys.stderr.write("%s: %d errors, %d failures\n" % (implname, len(result.errors), len(result.failures))) return newerrs def print_error(info): testcase, (type, e, tb) = info print " %s.%s.%s" % (testcase.__class__.__module__, testcase.__class__.__name__, tb.tb_frame.f_code.co_name) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/profParse.py === #! /usr/bin/env python1.5 import getopt import os import profile import pstats import sys from Products.ParsedXML.DOM import Core, ExpatBuilder FILE = os.path.join(sys.modules['Products.ParsedXML'].__path__[0], 'tests', 'xml', '4ohn4ktj.xml') PROFILEDATA = "@parsefile.prof" def parsefile(filename, namespaces): ExpatBuilder.parse(filename, namespaces=namespaces) _getattr_counts = {} def main(): namespaces = 1 profiledata = None proflines = 20 filename = FILE opts, args = getopt.getopt(sys.argv[1:], "nd:p:") for opt, arg in opts: if opt == "-n": namespaces = not namespaces elif opt == "-p": proflines = int(arg) elif opt == "-d": profiledata = arg if len(args) >= 2: print "One file at a time, please!" sys.exit(2) elif args: filename = args[0] profile.run('parsefile(%s, %s)' % (`filename`, namespaces), profiledata or PROFILEDATA) p = pstats.Stats(profiledata or PROFILEDATA) p.strip_dirs().sort_stats('time').print_stats(proflines) #p.print_callers(proflines) #p.strip_dirs().sort_stats('cum').print_stats(proflines) if not profiledata: os.unlink(PROFILEDATA) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/profPrinter.py === import getopt import os import profile import pstats import sys from Products.ParsedXML.DOM import Core, ExpatBuilder from Products.ParsedXML.ExtraDOM import writeStream FILE = os.path.join(sys.modules['Products.ParsedXML'].__path__[0], 'tests', 'xml', '4ohn4ktj.xml') PROFILEDATA = "@parsefile.prof" def parsefile(filename, namespaces): return ExpatBuilder.parse(filename, namespaces=namespaces) def printDOM(document): writeStream(document) _getattr_counts = {} def main(): namespaces = 1 profiledata = None proflines = 20 filename = FILE opts, args = getopt.getopt(sys.argv[1:], "nd:p:") for opt, arg in opts: if opt == "-n": namespaces = not namespaces elif opt == "-p": proflines = int(arg) elif opt == "-d": profiledata = arg if len(args) >= 2: print "One file at a time, please!" sys.exit(2) elif args: filename = args[0] doc = parsefile(filename, namespaces) profiler = profile.Profile() profiler.runctx('printDOM(doc)', locals(), globals()) profiler.dump_stats(profiledata or PROFILEDATA) p = pstats.Stats(profiledata or PROFILEDATA) p.strip_dirs().sort_stats('time').print_stats(proflines) #p.print_callers(proflines) #p.strip_dirs().sort_stats('cum').print_stats(proflines) if not profiledata: os.unlink(PROFILEDATA) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/profPyXMLParse.py === import getopt import os import profile import pstats import sys import Products.ParsedXML from xml.dom.ext.reader import PyExpat FILE = os.path.join(sys.modules['Products.ParsedXML'].__path__[0], 'tests', 'xml', '4ohn4ktj.xml') PROFILEDATA = "@parsefile.prof" def parsefile(filename, namespaces): if not namespaces: print "PyXML reader only parses with namespaces" sys.exit(2) reader = PyExpat.Reader() return reader.fromUri(filename) _getattr_counts = {} def main(): namespaces = 1 profiledata = None proflines = 20 filename = FILE opts, args = getopt.getopt(sys.argv[1:], "nd:p:") for opt, arg in opts: if opt == "-n": namespaces = not namespaces elif opt == "-p": proflines = int(arg) elif opt == "-d": profiledata = arg if len(args) >= 2: print "One file at a time, please!" sys.exit(2) elif args: filename = args[0] profile.run('parsefile(%s, %s)' % (`filename`, namespaces), profiledata or PROFILEDATA) p = pstats.Stats(profiledata or PROFILEDATA) p.strip_dirs().sort_stats('time').print_stats(proflines) #p.print_callers(proflines) #p.strip_dirs().sort_stats('cum').print_stats(proflines) if not profiledata: os.unlink(PROFILEDATA) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/profPyXMLPrinter.py === import getopt import os import profile import pstats import sys from Products.ParsedXML.ExtraDOM import writeStream FILE = os.path.join(sys.modules['Products.ParsedXML'].__path__[0], 'tests', 'xml', '4ohn4ktj.xml') PROFILEDATA = "@parsefile.prof" def parsefile(filename, namespaces): from xml.dom.ext.reader import PyExpat reader = PyExpat.Reader() return reader.fromUri(filename) def printDOM(document): writeStream(document) _getattr_counts = {} def main(): namespaces = 1 profiledata = None proflines = 20 filename = FILE opts, args = getopt.getopt(sys.argv[1:], "nd:p:") for opt, arg in opts: if opt == "-n": namespaces = not namespaces elif opt == "-p": proflines = int(arg) elif opt == "-d": profiledata = arg if len(args) >= 2: print "One file at a time, please!" sys.exit(2) elif args: filename = args[0] doc = parsefile(filename, namespaces) profiler = profile.Profile() profiler.runctx('printDOM(doc)', locals(), globals()) profiler.dump_stats(profiledata or PROFILEDATA) p = pstats.Stats(profiledata or PROFILEDATA) p.strip_dirs().sort_stats('time').print_stats(proflines) #p.print_callers(proflines) #p.strip_dirs().sort_stats('cum').print_stats(proflines) if not profiledata: os.unlink(PROFILEDATA) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_ODB.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## "Test some ODB interactions." import unittest import ZODB # for Persistent from Products.ParsedXML import ParsedXML class ODBTestCase(unittest.TestCase): def setUp(self): self.document = ParsedXML.ParsedXML('foo') def shotgunTpStuff(self, node): "assert that the Tp* functions work" children = node.childNodes tpVals = node.tpValues() for i in range(children.length): assert children.item(i).isSameNode(tpVals[i]) for i in range(children.length): assert children.item(i).tpURL() == str(i) assert children.item(i).tpId() == str(i) for node in tpVals: self.shotgunTpStuff(node) def checkTpStuff(self): "check that the Tp* functions work" self.document.documentElement.appendChild( self.document.createElement('zero')) self.document.documentElement.appendChild( self.document.createElement('one')) self.document.documentElement.firstChild.appendChild( self.document.createElement('zero-zero')) self.document.documentElement.firstChild.appendChild( self.document.createElement('zero-one')) self.shotgunTpStuff(self.document.documentElement) def test_suite(): """Return a test suite for the Zope testing framework.""" return unittest.makeSuite(ODBTestCase, 'check') def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_acquisition.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## "test that the ParsedXML DOM object acquire implicitly" # this suite isn't done that well. We could probably just mount a db. # We currently have to have a Zope instance # to mount; we need a persistent container & Zope traversal to acquire # properly, because we don't want to acquire through the transient # proxy objects. import unittest import ZODB # for Persistent from Products.ParsedXML import ParsedXML def checkAcquire(aqer, aqee, name): "check that acquisition of name from aqee to aqer happens" assert hasattr(aqer, name) assert getattr(aqer, name) == getattr(aqee, name) assert getattr(aqer, name) is getattr(aqee, name) def checkAcquireNot(aqer, aqee, name): "check that acquisition of name from aqee to aqer doesn't happen" assert getattr(aqer, name) != getattr(aqee, name) assert getattr(aqer, name) is not getattr(aqee, name) class WrappedAcquisitionTestCase(unittest.TestCase): def setUp(self): # we need a doc in a container that supports # restrictedTraverse and getPhysicalPath to have a proper # acquisition chain. import OFS.Application self.app = OFS.Application.Application() self.tmpId = 'TempParsedXMLUnitTestInstance' self.app._setObject(self.tmpId, ParsedXML.ParsedXML(self.tmpId)) self.doc = getattr(self.app, self.tmpId) self.app.string = 'a string' self.app.firstChild = "a string that shouldn't be acquired" elt1 = self.doc.createElement('eggs') elt2 = self.doc.createElement('ham') self.doc.documentElement.appendChild(elt1) self.doc.documentElement.appendChild(elt2) self.doc.documentElement.setAttribute('color', 'green') def _acquisitionTest(self, DOMObj): checkAcquire(DOMObj, self.app, 'string') checkAcquireNot(DOMObj, self.app, 'firstChild') def checkTraversalAcquisition(self): "make sure we can acquire through DOM traversal" self._acquisitionTest(self.doc) self._acquisitionTest(self.doc.documentElement) self._acquisitionTest(self.doc.documentElement.firstChild) self._acquisitionTest(self.doc.documentElement.firstChild.nextSibling) self._acquisitionTest(self.doc.documentElement.ownerDocument) self._acquisitionTest(self.doc.documentElement.getAttributeNode( 'color')) def checkMethodAcquisition(self): "make sure we acquire through proxied DOM methods" elt = self.doc.createElement('foo') self._acquisitionTest(self.doc.documentElement.appendChild(elt)) def checkNodeListAcquisition(self): "make sure we can acquire through a NodeList" self._acquisitionTest(self.doc.documentElement.childNodes.item(0)) def checkNamedNodeMapAcquisition(self): "make sure we can acquire through a NamedNodeMap" self._acquisitionTest( self.doc.documentElement.attributes.getNamedItem('color')) def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(WrappedAcquisitionTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_all.py === import unittest from Products.ParsedXML.tests import test_dom from Products.ParsedXML.tests import test_wrappeddom from Products.ParsedXML.tests import test_printer from Products.ParsedXML.tests import test_parser from Products.ParsedXML.tests import test_persistence from Products.ParsedXML.tests import test_truthable from Products.ParsedXML.tests import test_acquisition from Products.ParsedXML.tests import test_aqpain from Products.ParsedXML.tests import test_zopeinterface from Products.ParsedXML.tests import test_collection from Products.ParsedXML.tests import test_ODB from Products.ParsedXML.tests import test_elementid def test_suite(): suite = unittest.TestSuite() suite.addTest(test_dom.test_suite()) suite.addTest(test_wrappeddom.test_suite()) suite.addTest(test_printer.test_suite()) suite.addTest(test_parser.test_suite()) suite.addTest(test_persistence.test_suite()) suite.addTest(test_truthable.test_suite()) suite.addTest(test_acquisition.test_suite()) suite.addTest(test_aqpain.test_suite()) suite.addTest(test_zopeinterface.test_suite()) suite.addTest(test_collection.test_suite()) suite.addTest(test_ODB.test_suite()) suite.addTest(test_elementid.test_suite()) return suite def main(): if hasattr(unittest, 'JUnitTextTestRunner'): unittest.JUnitTextTestRunner().run(test_suite()) else: unittest.TextTestRunner(verbosity=0).run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_aqpain.py === """Test that checks the fragility of using acquistion wrappers to indicate tree hierarchy. The current implementation of the DOM uses acquisition wrappers to store references to a node's parent node. While this allows very efficient access to the parent, it is fragile in the case of multiple wrappers referring to the same node. If client code holds two wrappers for a node and modifies the node's position in the tree using one of them, the other will store incorrect information on the shape of the tree. For acquisition to be used to adequately be used to present the containment hierarchy for a node, a complete chain of wrappers would need to be constructed each time a node is reparented, starting from the outermost node in the ancestor chain. Application code would need to be wary that old references to a node are replaced by the new wrapper. The Python DOM API makes no such requirement at the present time, nor should it need to. This script shows a contrived example that exercises this DOM bug. While this particular code is unlikely in real applications, the ease with which multiple acquisition wrappers can be produced in more complex application code is easy to see. """ import unittest from Products.ParsedXML.DOM.ExpatBuilder import ExpatBuilder from Products.ParsedXML.Printer import PrintVisitor class AcquisitionPain(unittest.TestCase): def setUp(self): self.doc = ExpatBuilder().parseString("") self.printer = PrintVisitor(self.doc) def checkParentReferenceIntegrity(self): e1a = self.doc.documentElement.firstChild e1b = self.doc.documentElement.firstChild e2 = e1b.nextSibling e2.appendChild(e1b) assert e1a.parentNode.isSameNode(e1b.parentNode), \ "Two references to the same node return different parent nodes." def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(AcquisitionPain, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_collection.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## "Tests for garbage collection." import unittest import ZODB # for Persistent import os import string import sys from Products.ParsedXML import ParsedXML, DOM import App.ApplicationManager class ReferenceTestCase(unittest.TestCase): def setUp(self): self.dbman = App.ApplicationManager.DebugManager() def getRefcounts(self, ob): "return number of refcounts for instances of ob's class" name = '%s.%s' % (ob.__module__, ob.__class__.__name__) for i in self.dbman.refcount(): if i[1] == name: return i[0] return 0 def checkParsedXMLCollect(self): "see if refcounts from ParsedXML product init are released" doc = ParsedXML.ParsedXML('foo') refcounts1 = self.getRefcounts(doc) doc = ParsedXML.ParsedXML('foo') refcounts2 = self.getRefcounts(doc) assert refcounts2 == refcounts1, ( "ParsedXML leaked %d refcounts" % (refcounts2 - refcounts1)) def checkDOMParseCollect(self): "see if refcounts from DOM parse creation are released" testDir = os.path.join( sys.modules['Products.ParsedXML'].__path__[0], 'tests') filename = os.path.join(testDir, 'xml', '4ohn4ktj.xml') doc = DOM.ExpatBuilder.parse(filename) refcounts1 = self.getRefcounts(doc) doc = DOM.ExpatBuilder.parse(filename) refcounts2 = self.getRefcounts(doc) assert refcounts2 == refcounts1, ( "DOM parse leaked %d refcounts" % (refcounts2 - refcounts1)) def checkDOMCreateCollect(self): "see if refcounts from DOM creation are released" doc = DOM.theDOMImplementation.createDocument(None, 'doc', None) refcounts1 = self.getRefcounts(doc) doc = DOM.theDOMImplementation.createDocument(None, 'doc', None) refcounts2 = self.getRefcounts(doc) assert refcounts2 == refcounts1, ( "DOM parse leaked %d refcounts" % (refcounts2 - refcounts1)) def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ReferenceTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_dom.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest from Products.ParsedXML import DOM from Products.ParsedXML.DOM import ExpatBuilder from Products.ParsedXML.StrIO import StringIO from domapi import DOMImplementationTestSuite def DOMParseString(self, xml): file = StringIO(xml) return ExpatBuilder.parse(file) def test_suite(): """Return a test suite for the Zope testing framework.""" return DOMImplementationTestSuite(DOM.theDOMImplementation, DOMParseString) def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_elementid.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest from Products.ParsedXML import DOM from Products.ParsedXML.DOM import ExpatBuilder from Products.ParsedXML.StrIO import StringIO from domapi import DOMImplementationTestSuite def DOMParseString(xml): file = StringIO(xml) return ExpatBuilder.parse(file) def get_element_ids(node): result = [] if node.nodeType == node.ELEMENT_NODE: result.append(node.elementId) for child in node.childNodes: result.extend(get_element_ids(child)) return result def check_unique_ids(node): element_ids = get_element_ids(node) element_ids.sort() last = element_ids[0] for element_id in element_ids[1:]: assert last != element_id,\ 'Found at least one double element_id: %s' % element_id last = element_id class ElementIdTestCase(unittest.TestCase): def setUp(self): self.doc = DOMParseString('''

Test

Another test

Foohey

''') def checkElementIdsAfterParse(self): element_ids = get_element_ids(self.doc) for i in xrange(len(element_ids)): assert i == element_ids[i] def checkElementIdsAfterAppend(self): element = self.doc.createElement('foo') self.doc.documentElement.appendChild(element) check_unique_ids(self.doc) def checkElementIdsAfterAppend2(self): element = self.doc.createElement('foo') self.doc.documentElement.insertBefore( element, self.doc.documentElement.childNodes[0]) check_unique_ids(self.doc) def checkCloneNodeShallow(self): cloned = self.doc.documentElement.cloneNode(0) self.doc.documentElement.appendChild(cloned) check_unique_ids(self.doc) def checkCloneNodeDeep(self): cloned = self.doc.documentElement.cloneNode(1) self.doc.documentElement.appendChild(cloned) check_unique_ids(self.doc) def checkImportNodeShallow(self): otherdoc = DOMParseString(''' ''') imported = self.doc.importNode( otherdoc.documentElement, 0) self.doc.documentElement.appendChild(imported) check_unique_ids(self.doc) def checkImportNodeDeep(self): otherdoc = DOMParseString(''' ''') imported = self.doc.importNode( otherdoc.documentElement, 1) self.doc.documentElement.appendChild(imported) check_unique_ids(self.doc) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ElementIdTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_parser.py === (451/551 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 451 lines omitted -=- -=- -=-] def checkXMLNSPrefixParse(self): "check that xmlns prefix attrs are parsed properly" inStr = '' doc = ParsedXML.ParsedXML('foo', inStr) attr = doc.documentElement.attributes.item(0) checkAttribute(attr, 'prefix', 'xmlns') checkAttribute(attr, 'localName', 'spamNS') checkAttribute(attr, 'namespaceURI', 'http://www.w3.org/2000/xmlns/') checkAttribute(attr, 'value', 'uri:test_namespace') def checkXMLNSParse(self): "check that xmlns attrs are parsed properly" inStr = '' doc = ParsedXML.ParsedXML('foo', inStr) attr = doc.documentElement.attributes.item(0) checkAttribute(attr, 'prefix', 'xmlns') checkAttribute(attr, 'localName', None) checkAttribute(attr, 'namespaceURI', 'http://www.w3.org/2000/xmlns/') checkAttribute(attr, 'value', 'uri:test_namespace') def checkNoNSParse(self): """check that attrs parsed with no NS but with NS aware parse can be retrieved with NS of None""" inStr = '' doc = ParsedXML.ParsedXML('foo', inStr) assert doc.documentElement.getAttributeNS(None, 'version'), ( "NS-free attribute not gotten by NS-free getAttributeNS") def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ParseOasisXMLTestSaTestCase, 'check')) suite.addTest(unittest.makeSuite(ParseTestCase, 'check')) suite.addTest(unittest.makeSuite(Lvl2ParseTestCase, 'check')) return suite def main(): unittest.TextTestRunner(verbosity=3).run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_persistence.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## # DB stuff copied from testBTrees.py import unittest import ZODB # for Persistent import glob import os import sys from Products.ParsedXML import ParsedXML from Products.ParsedXML.StrIO import StringIO import unittest class PersistenceTestCase(unittest.TestCase): implementation = ParsedXML.theDOMImplementation def openDB(self): from ZODB.FileStorage import FileStorage from ZODB.DB import DB storage = FileStorage(self.dbName) db = DB(storage) self.db = db.open().root() def closeDB(self): get_transaction().commit() self.document = None self.db._p_jar._db.close() self.db = None def getAppDocument(self): "put the document that startup put in the db in self.document" self.document = self.db['doc'] def cycleDB(self): """close and open the db and replace self.document. Any nonpersistent changes to self.document should be lost.""" self.closeDB() self.openDB() self.getAppDocument() def delDB(self): map(os.unlink, glob.glob("fs_tmp__*")) def setUp(self): """open db, create a document in the db, set self.document to it""" self.dbName = 'fs_tmp__%s' % os.getpid() self.openDB() self.db['doc'] = ParsedXML.ParsedXML('foo') get_transaction().commit() self.document = self.db['doc'] def tearDown(self): self.closeDB() self.delDB() def checkIDPersistence(self): "assert that changing the ID persists over transactions" self.document._setId('newId') self.cycleDB() assert self.document.getId() == 'newId' def checkParsedXMLDOMPersistence(self): "assert that a Parsed XML DOM edit persists over transactions" elt = self.document.createElement('elt') self.document.firstChild.appendChild(elt) self.cycleDB() childLen = self.document.firstChild.childNodes.length assert childLen == 1, "DOM edit didn't persist" def checkDOMPersistence(self): "assert that a DOM edit persists over transactions" doc = ParsedXML.createDOMDocument() import OFS.SimpleItem si = self.db['si'] = OFS.SimpleItem.SimpleItem() si.doc = doc elt = si.doc.createElement('elt') si.doc.firstChild.appendChild(elt) self.cycleDB() # not using the normal db document, must grab ourselves si = self.db['si'] childLen = si.doc.firstChild.childNodes.length assert childLen == 1, "DOM edit didn't persist" def checkParsePersistence(self): "assert that a parse persists over transactions" testDir = os.path.join( sys.modules['Products.ParsedXML'].__path__[0], 'tests') filename = os.path.join(testDir, 'xml', '4ohn4ktj.xml') file = open(filename) self.document.parseXML(filename) file.close() childLen = self.document.firstChild.childNodes.length self.cycleDB() childLen1 = self.document.firstChild.childNodes.length assert childLen == childLen1, "parse didn't persist" def checkSubnodeParsePersistence(self): "assert that a subnode parse persists over transactions" docString = '' subNodeString = 'bar' self.document.documentElement.parseXML(StringIO(subNodeString)) self.cycleDB() childLen = self.document.documentElement.childNodes.length assert childLen == 1, "parse on subnode didn't persist" # right now it's too annoying to get parsing to work at a transient # document proxy, but it could be less aggravating if we had a better # way to get at the persistent document. #def checkTransientDocumentParsePersistence(self): # """assert that a parse of a transient proxy of the document # persists over transactions""" # docStringBefore = '' # docStringAfter = 'bar' # self.document.documentElement.ownerDocument.parseXML( # StringIO(docStringAfter)) # self.cycleDB() # childLen = self.document.documentElement.childNodes.length # assert childLen == 1, "parse on subnode didn't persist" # def checkTheseDamnTests(self): # "assert that I understand how these tests should work" # docString = 'fff' # self.document.parseXML(StringIO(docString)) # get_transaction().commit() # # db and doc length now 1 # self.document.documentElement.removeChild( # self.document.documentElement.firstChild) # # doc length 0, db length 1 # # do what closeDB and openDB do, but *don't commit* # # so the above edit shouldn't stay. # #closeDB but don't commit # #get_transaction().commit() # self.document = None # self.db._p_jar._db.close() # self.db = None # #openDB # from ZODB.FileStorage import FileStorage # from ZODB.DB import DB # storage = FileStorage(self.dbName) # db = DB(storage) # self.db = db.open().root() # self.getAppDocument() # get_transaction().commit() # assert self.document.documentElement.childNodes.length == 1, ( # "these tests are faulty") def test_suite(): """Return a test suite for the Zope testing framework.""" return unittest.makeSuite(PersistenceTestCase, 'check') def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_prettyprinter.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest import ZODB # for Persistent import string # FIXME: could test with Core DOM instead, do we want to? from Products.ParsedXML import ParsedXML, PrettyPrinter from Products.ParsedXML.StrIO import StringIO def printElement(element, encoding = None, html = 0, contentType = None): output = StringIO() PrettyPrinter.PrintVisitor(element, output, encoding, html, contentType)() return output.getvalue() def checkOutput(wanted, got, message="Bad output"): assert wanted == got, \ ("%s. Wanted:\n%s[[EOF]]\nGot:\n%s[[EOF]]\n" % (message, wanted, got)) class PrintTestBase(unittest.TestCase): implementation = ParsedXML.theDOMImplementation def parse(self, xml): return ParsedXML.ParsedXML('foo', xml) class PrintTestCase(PrintTestBase): def checkAttrOrder(self): inStr = '\n\n' doc = self.parse(inStr) output = printElement(doc) checkOutput(inStr, output, "attribute order not preserved") def checkDefaultAttrSkipped(self): inStr = '' \ ']>' outStr = '\n\n' doc = self.parse(inStr) output = printElement(doc) checkOutput(outStr, output, "default attribute printed") def checkAttrEntRefExpansion(self): "entity references must be expanded in attributes" doc = self.implementation.createDocument(None, 'root', None) attr = doc.createAttribute("attrName") # this is a text string; &test; is not an entity reference, # so its & should be converted to the proper ref on printing, # as should the & and < and >. attr.value = "&test; &<>" # this reference should be expanded to the empty string attr.appendChild(doc.createEntityReference('foo')) doc.documentElement.setAttributeNode(attr) outStr = '' output = printElement(doc.documentElement) checkOutput(outStr, output, "improper attr entity expansion") def checkTextEntRefExpansion(self): "only some entity references should be expanded in text" doc = self.implementation.createDocument(None, 'root', None) # &< must be converted to the proper reference; > should not. text = doc.createTextNode("&<>]]>") outStr = '&<>]]>' output = printElement(text) checkOutput(outStr, output, "improper text entity expansion") #TODO: check for expansion of entity refs in other contexts; #currently we're expanding aggressively, but it's not a priority #because the parser gets to play around with refs too class HTMLPrintTestCase(PrintTestBase): def checkMinimize(self): inStr = ('



' + '

') outStr = ('



' + '

\n') doc = self.parse(inStr) output = printElement(doc, encoding = None, html = 1) checkOutput(outStr, output, "improper HTML minimization") def checkCapitalize(self): inStr = ('
\n') doc = self.parse(inStr) output = printElement(doc, encoding = None, html = 1, contentType = 'html') checkOutput(string.upper(inStr), output, "improper HTML contenttype HTML capitalization") output = printElement(doc, encoding = None, html = 1, contentType = 'xml') checkOutput(string.lower(inStr), output, "improper XML contenttype HTML capitalization") class Lvl2PrintTestCase(PrintTestBase): def checkNamespacePrint(self): outStr = '\n' \ '\n' \ '\n' doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkNamespaceAttrOrder(self): inStr = ('\n' '' ' ' '\n') doc = self.parse(inStr) output = printElement(doc) checkOutput(inStr, output, "attribute order not preserved") def checkHierarchicalElementNamespacePrint(self): # print new ns, don't print ns printed by ancestor outStr = ('\n' '' ' ' ' ' ' ' ' ' ' ' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkDefaultNamespacePrint(self): outStr = ('\n' '' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkDefaultAndPrefixNamespacePrint(self): # try and tickle a namespace printing bug outStr = ('\n' '' ' ' ' ' ' ' ' ' ' ' ' ' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(PrintTestCase, 'check')) suite.addTest(unittest.makeSuite(HTMLPrintTestCase, 'check')) suite.addTest(unittest.makeSuite(Lvl2PrintTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_printer.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest import ZODB # for Persistent import string # FIXME: could test with Core DOM instead, do we want to? from Products.ParsedXML import ParsedXML, Printer from Products.ParsedXML.StrIO import StringIO def printElement(element, encoding = None, html = 0, contentType = None): output = StringIO() Printer.PrintVisitor(element, output, encoding, html, contentType)() return output.getvalue() def checkOutput(wanted, got, message="Bad output"): assert wanted == got, \ ("%s. Wanted:\n%s[[EOF]]\nGot:\n%s[[EOF]]\n" % (message, wanted, got)) class PrintTestBase(unittest.TestCase): implementation = ParsedXML.theDOMImplementation def parse(self, xml): return ParsedXML.ParsedXML('foo', xml) class PrintTestCase(PrintTestBase): def checkAttrOrder(self): inStr = '\n\n' doc = self.parse(inStr) output = printElement(doc) checkOutput(inStr, output, "attribute order not preserved") def checkDefaultAttrSkipped(self): inStr = '' \ ']>' outStr = '\n\n' doc = self.parse(inStr) output = printElement(doc) checkOutput(outStr, output, "default attribute printed") def checkAttrEntRefExpansion(self): "entity references must be expanded in attributes" doc = self.implementation.createDocument(None, 'root', None) attr = doc.createAttribute("attrName") # this is a text string; &test; is not an entity reference, # so its & should be converted to the proper ref on printing, # as should the & and < and >. attr.value = "&test; &<>" # this reference should be expanded to the empty string attr.appendChild(doc.createEntityReference('foo')) doc.documentElement.setAttributeNode(attr) outStr = '' output = printElement(doc.documentElement) checkOutput(outStr, output, "improper attr entity expansion") def checkTextEntRefExpansion(self): "only some entity references should be expanded in text" doc = self.implementation.createDocument(None, 'root', None) # &< must be converted to the proper reference; > should not. text = doc.createTextNode("&<>]]>") outStr = '&<>]]>' output = printElement(text) checkOutput(outStr, output, "improper text entity expansion") #TODO: check for expansion of entity refs in other contexts; #currently we're expanding aggressively, but it's not a priority #because the parser gets to play around with refs too class HTMLPrintTestCase(PrintTestBase): def checkMinimize(self): inStr = ('



' + '

') outStr = ('



' + '

\n') doc = self.parse(inStr) output = printElement(doc, encoding = None, html = 1) checkOutput(outStr, output, "improper HTML minimization") def checkCapitalize(self): inStr = ('
\n') doc = self.parse(inStr) output = printElement(doc, encoding = None, html = 1, contentType = 'html') checkOutput(string.upper(inStr), output, "improper HTML contenttype HTML capitalization") output = printElement(doc, encoding = None, html = 1, contentType = 'xml') checkOutput(string.lower(inStr), output, "improper XML contenttype HTML capitalization") class Lvl2PrintTestCase(PrintTestBase): def checkNamespacePrint(self): outStr = '\n' \ '\n' \ '\n' doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkNamespaceAttrOrder(self): inStr = ('\n' '' ' ' '\n') doc = self.parse(inStr) output = printElement(doc) checkOutput(inStr, output, "attribute order not preserved") def checkHierarchicalElementNamespacePrint(self): # print new ns, don't print ns printed by ancestor outStr = ('\n' '' ' ' ' ' ' ' ' ' ' ' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkDefaultNamespacePrint(self): outStr = ('\n' '' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def checkDefaultAndPrefixNamespacePrint(self): # try and tickle a namespace printing bug outStr = ('\n' '' ' ' ' ' ' ' ' ' ' ' ' ' '\n') doc = self.parse(outStr) output = printElement(doc) checkOutput(outStr, output) def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(PrintTestCase, 'check')) suite.addTest(unittest.makeSuite(HTMLPrintTestCase, 'check')) suite.addTest(unittest.makeSuite(Lvl2PrintTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_pyxmldom.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest from domapi import DOMImplementationTestSuite from xml.dom import ext, implementation from xml.dom.ext.reader import PyExpat def DOMParseString(self, xml): reader = PyExpat.Reader() return reader.fromString(xml) def test_suite(): """Return a test suite for the Zope testing framework.""" return DOMImplementationTestSuite(implementation, DOMParseString) def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_truthable.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## "tests to make sure that DOM objects support truth testing" import unittest import ZODB # for Persistent from Products.ParsedXML import ParsedXML, DOM from operator import truth class WrappedTruthableTestCaseBase(unittest.TestCase): def setUp(self): self.document = doc = ParsedXML.ParsedXML('foo') self.floating_element = doc.createElement("per") self.attached_element = doc.documentElement class DOMTruthableTestCaseBase(unittest.TestCase): def setUp(self): self.document = doc = DOM.theDOMImplementation.createDocument( None, 'root', None) self.floating_element = doc.createElement("per") self.attached_element = doc.documentElement class TruthableTestCaseTests: def checkFloatingTruthable(self): assert truth(self.floating_element) == 1 def checkDOMTruthable(self): assert truth(self.document) == 1 assert truth(self.document.documentElement.parentNode) == 1 def checkAttachedTruthable(self): assert truth(self.attached_element) == 1 class DOMTruthableTestCase(DOMTruthableTestCaseBase, TruthableTestCaseTests): pass class WrappedTruthableTestCase(WrappedTruthableTestCaseBase, TruthableTestCaseTests): pass def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(DOMTruthableTestCase, 'check')) suite.addTest(unittest.makeSuite(WrappedTruthableTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() === Added File Products/ParsedXML/tests/test_wrappeddom.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## import unittest import ZODB # for Persistent from Products.ParsedXML import ParsedXML from domapi import DOMImplementationTestSuite def ParsedXMLParseString(self, xml): return ParsedXML.ParsedXML('foo', xml) def test_suite(): """Return a test suite for the Zope testing framework.""" return DOMImplementationTestSuite(ParsedXML.theDOMImplementation, ParsedXMLParseString) def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == '__main__': main() === Added File Products/ParsedXML/tests/test_zopeinterface.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Test that some Zope interfaces are supported properly.""" import unittest import ZODB # for Persistent from Products.ParsedXML import ParsedXML from Products.ParsedXML.StrIO import StringIO def assertSize(doc): "assert that the document size what's reported by len" gs = doc.get_size() l = len(str(doc)) assert gs == l, "get_size reports %d while len reports %d" % (gs, l) class GetSizeTestCase(unittest.TestCase): "test that get_size works. We only test on the persistent Document." def setUp(self): self.document = ParsedXML.ParsedXML('foo') def checkGetSize(self): "assert that get_size works" assertSize(self.document) def checkGetSizeParse(self): "assert that get_size works after a parse" inStr = 'text' self.document.parseXML(StringIO(inStr)) assertSize(self.document) self.document.documentElement.parseXML(StringIO(inStr)) assertSize(self.document) def checkGetSizeDOMMethods(self): "assert that get_size works after some DOM method manipulations" self.document.documentElement.appendChild( self.document.createElement('spam')) assertSize(self.document) self.document.documentElement.appendChild( self.document.createTextNode('spam')) assertSize(self.document) self.document.documentElement.appendChild( self.document.createTextNode('spam')) assertSize(self.document) self.document.normalize() assertSize(self.document) self.document.documentElement.setAttribute('eggs', 'ham') assertSize(self.document) def checkgetSizeDOMAttributess(self): "assert that get_size works after some DOM attribute manipulations" self.document.documentElement.appendChild( self.document.createTextNode('spam')) self.document.documentElement.firstChild.data = "spamspamspam" assertSize(self.document) self.document.documentElement.setAttribute('eggs', 'ham') self.document.documentElement.attributes.item(0).value = 'spam' assertSize(self.document) def test_suite(): """Return a test suite for the Zope testing framework.""" suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(GetSizeTestCase, 'check')) return suite def main(): unittest.TextTestRunner().run(test_suite()) if __name__ == "__main__": main() From sidnei at x3ng.com.br Fri May 30 11:17:55 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:12 2008 Subject: [zopeorg-checkins] CVS: Products/TrackerBase - CHANGES.txt:1.1 LICENSE.txt:1.1 Noodging.py:1.1 README.txt:1.1 Tracker.zexp:1.1 TrackerBase.py:1.1 TrackerMethods.py:1.1 TrackerMisc.py:1.1 __init__.py:1.1 addTrackerForm.dtml:1.1 age.py:1.1 envsetup.py:1.1 issue.gif:1.1 item.gif:1.1 tracks.gif:1.1 Message-ID: <200305301517.h4UFHtw20682@cvs.baymountain.com> Update of /cvs-zopeorg/Products/TrackerBase In directory cvs.zope.org:/tmp/cvs-serv19195/TrackerBase Added Files: CHANGES.txt LICENSE.txt Noodging.py README.txt Tracker.zexp TrackerBase.py TrackerMethods.py TrackerMisc.py __init__.py addTrackerForm.dtml age.py envsetup.py issue.gif item.gif tracks.gif Log Message: Adding products needed for migration of NZO === Added File Products/TrackerBase/CHANGES.txt === 21-Feb-2000 Mon 1.02+ * TrackerMethods send_posting(): Refined header origin and destination addresses - still WAGs, tho: - Made the From a bit more self-explanatory, with the tracker-admin's address as the origin. - Using an empty '<>' for the destinations - seems to work... I have to consult the RFC to find out the right way (if there is one) to not provide destination addresses. Changed some more to deal with sites with large membership (editStateYikes). Removed WRAP=hard everywhere - it wraps URLs in the middle!! === Added File Products/TrackerBase/LICENSE.txt === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## === Added File Products/TrackerBase/Noodging.py === (509/609 lines abridged) """Tracker rules processor mixin.""" from types import * import time, whrandom import Acquisition from Persistence import Persistent from DateTime import DateTime DEBUG = 0 BIZDAYSTART = 9.0 # 9:00 am BIZDAYEND = 18.0 # 6:00 pm REGULAR_HOLIDAYS = {'Independence Day': '07/04', 'Christmas Day': '12/25', 'Thanksgiving': '11/25', 'New Years Day': '01/01', 'Easter': '04/04', } RULES_USER = '.rules.' class TransactionAbort(Exception): pass BadForm = "BadForm" # String exception, needs to be caught elsewhere. class Noodge(Acquisition.Implicit, Persistent, ): """Maintain and process the tracker's rule base. Rules are applied only to active issues - ie, those that are not in the completed, rejected, or deferred stage.""" def __init__(self, rules=None): self.init_expr_tables() self.set_rules(rules) def set_rules(self, rules): self._rules = rules def init_expr_tables(self): # Map non-builtin conditions to method names. self._conditions = {'state': "state_condition", 'value': "issue_value", } self._actions = {'notify': "notify_action", } def execute_rules(self, issues=None): [-=- -=- -=- 509 lines omitted -=- -=- -=-] if extremed == 0: ztime = extremed = (ztime + shift).earliestTime() else: ztime = extremed = ztime + shift else: if extremed == 0: ztime = extremed = (ztime + shift).latestTime() else: ztime = ztime + shift return ztime class HoliDatesOff: """A cache for "regular" holidays, ie those determined by a month/day. '.add()' registers new month/day holidays. '.get()' takes a year and returns all the registered holiday dates, as DateTime objects, for that year - shifting any that fall on a weekend to the nearest subsequent non-holiday weekday. The HoliDatesOff class economizes on the DateTime object creation process by caching assortments for any encountered year. The cache is invalidated any time a new date is entered.""" def __init__(self, monthdaylist=[]): self._cache = {} # {year: [dates]} self.monthdaylist = [] self.add(monthdaylist) def add(self, dates): if type(dates) == type(""): dates = [dates] mdl = self.monthdaylist for i in dates: if i in mdl: continue mdl.append(i) self._cache = {} def get(self, year): year = str(year) if self._cache.has_key(year): print "from cache" return self._cache[year] got = [] for i in self.monthdaylist: d = nearest_bizday(DateTime("%s/%s" % (year, i)), 1, got) got.append(DateTime(d.Date())) got = tuple(got) self._cache[year] = got return got def getHolidayRegistry(): return HoliDatesOff(REGULAR_HOLIDAYS.values()) === Added File Products/TrackerBase/README.txt === ZCatalog Notes for Zope 2.0 (this will not work pre Zope 2). This is the TrackerBase product for the Zope. It also contains the Tracker ZClass, in Tracker.zexp. Installation To install the tracker from CVS: o Checkout the product into the lib/python/Products folder of your site, and use the Control_Panel "Restart" button to restart your Zope site. (Note that the 'forms' subdirectory contains all the dtml used in the Tracker ZClass - i like to have version control for all my code. Until ZClasses provide that version control - which may not be as long as you think - i do it myself.) o Create a symlink in your site's Extensions directory (creating the dir if necessary) to ../lib/python/Products/TrackerBase/TrackerMethods.py If you're on a platform without symlinks, copy TrackerMethods.py to the Extensions directory. (You'll have to remember to update the copies when the original file changes.) o Copy Tracker.zexp to your site's import dir (creating the dir if necessary) o From the Zope Control_Panel/Products folder, import 'Tracker.zexp'. (If you're updating an existing tracker install, you'll have to delete the Tracker product before doing the import.) You should now be able to create and use trackers in your zope. Follow the "help" and "details" links from the setup pages for help on configuring the tracker, and the TrackerHelp tab from anywhere in the tracker for an overview of the system. (See also: http://www.zope.org/Members/klm/SoftwareCarpentry -- the Software Carpentry tracker submission, including similar help documentation, some design specs, a cover letter describing desired futures, etc. http://www.zope.org/Members/klm/Tracker -- The "Tracker tracker" for bug reports, feature and documentation requests, and so forth. This is the place to go to report tracker bugs - after first searching for issues where the bug is already reported, of course...-) === Added File Products/TrackerBase/Tracker.zexp === (6078/6178 lines abridged) ZEXP ùíØ((U App.ProductqUProductqtqNt.}q(UidqUTrackerqU__ac_local_roles__q}qUklmq ]q UOwnerq asU_objectsq (}q (U meta_typeqUZ ClassqUidqUTrackerqu}q(hUExternal MethodqhU addTrackerqu}q(hU DTML MethodqhUaddTrackerFormqu}q(hUZope PermissionqhUaddTrackerPermqu}q(hU Zope FactoryqhUfTrackerqu}q(U meta_typeqU Product Helpq Uidq!UHelpq"utUtitleq#Uh(U ùîq$(U App.Factoryq%UFactoryq&ttQU addTrackerq'(U ùïq((U&Products.ExternalMethod.ExternalMethodq)UExternalMethodq*ttQh(U ùðq+(UApp.Permissionq,U Permissionq-ttQh(U ùñq.(UOFS.DTMLMethodq/U DTMLMethodq0ttQh(U ùòq1(UZClasses.ZClassq2UZClassq3ttQh"(U jÏq4(UHelpSys.HelpSysq5U ProductHelpq6ttQu. ùîT((U App.FactoryqUFactoryqtqNt.}q(UidqUfTrackerqU__ac_local_roles__q}qUklmq ]q UOwnerq asUinitialq UaddTrackerFormq U_permissionMapperqcAccessControl.PermissionMapping PM qNRq}qU_Use_Factories_PermissionqU_Add_Tracker_PermissionqsbU permissionqU Add TrackerqUtitleqUTracker FactoryqU object_typeqUTrackerqu. ùï((U&Products.ExternalMethod.ExternalMethodqUExternalMethodqtqNt.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq (Uselfq Uidq UREQUESTq Uinstq UdestqUtrackerqUuserqUroleqUpsqtqU co_argcountqKubh U addTrackerqU__ac_local_roles__q}qUklmq]qUOwnerqasUtitleqUU _functionqU addTrackerqU func_defaultsq(NtqU_moduleq UTrackerMethodsq!u. ùð–((UApp.PermissionqU PermissionqtqNt.}q(UtitleqUUidqUaddTrackerPermqUnameqU Add Trackerq U__ac_local_roles__q }q Uklmq ]q UOwnerqasu. ùñ—((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUU__name__qUaddTrackerFormqU__ac_local_roles__q}q Uklmq ]q UOwnerq asUglobalsq }qUrawqTê

Add A Tracker

=== Added File Products/TrackerBase/forms/catalog.dtml === Catalog info (see Updates Maintenance for catalog reassessment):
  • :
=== Added File Products/TrackerBase/forms/configActivities.dtml === The configuration activities (details) proceed from one to the next.
Id
Title
 
[-=- -=- -=- 6078 lines omitted -=- -=- -=-] FuncCode qoq}q(U co_varnamesq(Uselfq tq U co_argcountq KubUidq U index_objectq U__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqU index_objectqU func_defaultsqNU_moduleqUZopeSitequ. ú’(cProducts.ExternalMethod.ExternalMethod ExternalMethod qNtq.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq(Uselfq Uftypeq Ufhostq Uurlq Utypeq UuriqUhostqU script_nameqtqU co_argcountqKubUidqUurlqU__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqUurlqU func_defaultsq(curllib splittype qcurllib splithost qtq U_moduleq!UZopeSiteq"u. ú€j(cProducts.ExternalMethod.ExternalMethod ExternalMethod qNtq.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq(Uselfq Uitemq U containerq Uobjectq Ustq U co_argcountqKubUidqUmanage_beforeDeleteqU__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqUmanage_beforeDeleteqU func_defaultsqNU_moduleqUZopeSitequ. úG(cOFS.DTMLMethod DTMLMethod qNtq.}q(UtitleqUU__name__qUwaaaqUglobalsq}qUrawq UÚ

This is the Document in the Folder.

q U_varsq }q u. ú‚b(cProducts.ExternalMethod.ExternalMethod ExternalMethod qNtq.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq(Uselfq Uitemq U containerq Uobjectq Ustq U co_argcountqKubUidqUmanage_afterAddqU__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqUmanage_afterAddqU func_defaultsqNU_moduleqUZopeSitequ. úƒ>(cProducts.ExternalMethod.ExternalMethod ExternalMethod qNtq.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq(Uselfq tq U co_argcountq KubUidq Uunindex_objectq U__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU func_defaultsqNU _functionqUunindex_objectqU_moduleqUZopeSitequ. ú„Y(cProducts.ExternalMethod.ExternalMethod ExternalMethod qNtq.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq(Uselfq Uitemq Uobjectq Ustq U co_argcountq KubUidqUmanage_afterCloneqU__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqUmanage_afterCloneqU func_defaultsqNU_moduleqUZopeSitequ. ú…b((U&Products.ExternalMethod.ExternalMethodqUExternalMethodqtqNt.}q(U func_codeq(cApp.Extensions FuncCode qoq}q(U co_varnamesq (Uselfq U first_onlyq Uusersq Uuserq UrolesqtqU co_argcountqKubUidqUcreatorqU__ac_local_roles__q}qUbrianq]qUOwnerqasUtitleqUU _functionqUcreatorqU func_defaultsq(KtqU_moduleqUZopeSitequ.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ === Added File Products/TrackerBase/TrackerBase.py === """Issue tracking system implementation classes.""" __version__ = '$Revision: 1.1 $' import time import string from types import * from string import atoi from Noodging import Noodge, BadForm, TransactionAbort, age import Acquisition import AccessControl.Role import OFS.SimpleItem from Globals import HTMLFile, default__class_init__ from Persistence import Persistent from IOBTree import BTree # Setting to 1 leave an entry in audit history for each rules run. # Setting to 2 also produces debug flags on stderr. DEBUG = 0 class TrackerBase(Noodge, Acquisition.Implicit, Persistent, AccessControl.Role.RoleManager, ): """Issue tracking system central implementation.""" meta_class = 'TrackerIssue' isPrincipiaFolderish = 1 __ac_permissions__ = ( ('Browse', ('__getitem__', '__getattr__', 'owners', 'keys', 'items', 'values', 'has_key', 'update', 'get', 'length', '__len__', '__del__', '__delitem__', '__setitem__', ), ['Anonymous']), ('Create Issues', ('add_issue'), ['Anonymous']), ('Configure Tracker', (), ['TrackerOwner']), ('Supporter', (), ['TrackerOwner', 'Supporter']), ) IMATRACKER = 1 def __init__(self, id): __traceback_info__ = ("TrackerBase __init__ in", `id`) self.id = id self._notifier = Notifier() Noodge.__init__(self) self._issues = BTree() def __repr__(self): return ("<%s %s (%d issues) at 0x%s>" % (self.__class__.__name__, `self.id`, self.length(), hex(id(self))[2:])) def add_issue(self, issue): """Add a new issue, and return the generated id.""" if self._issues: id = self._issues.keys()[-1] + 1 else: id = 1 self._issues[id] = issue issue.id = str(id) return id def keys(self): """Return all issue keys, regardless of viewability of value.""" return self._issues.keys() def items(self): """Return all keys and issues which we are privileged to view.""" got = [] for k, v in self._issues.items(): got.append((k, v.__of__(self))) return got def values(self): """Return all issues which we are privileged to view.""" got = [] for i in self.items(): got.append(i[1]) return got def has_key(self, id): """True if item exists for key, regardless of privilege to view it.""" if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id return self._issues.has_key(id) def get(self, id, failobj=None): """Like generic sequence get, including failover.""" if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id if self._issues.has_key(id): return self._issues[id] else: return failobj def length(self): """Number of all issues.""" return self._issues.__len__() def __len__(self): """Number of all issues.""" return self._issues.__len__() ## def __del__(self): ## """ """ ## for k in tuple(self.keys()): ## del self._issues[k] def __delitem__(self, id): """ """ if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id del self._issues[id] def __setitem__(self, id, issue): """ """ __traceback_info__ = ("TrackerBase.__setitem__", `id`, `issue`) if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id self._issues[id] = issue def __getitem__(self, id): """ """ if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id __traceback_info__ = ("TrackerBase.__getitem__", `id`) return self._issues[id].__of__(self) __getattr__ = __getitem__ def owners(self): # Modelled on Extensions/ZopeSite.py:getOwners() got = [] for k, v in self.__ac_local_roles__.items(): if 'Owner' in v: got.append(k) return got default__class_init__(TrackerBase) class TrackerIssueBase(Acquisition.Implicit, Persistent, AccessControl.Role.RoleManager, ): """Implement Issue state-change auditing, item-containment, permissions. See audited_state, add_state, register_state_changes for auditing features. The ZClass inheritor does the rest...""" # If we need to enable access to unprotected attributes. __allow_access_to_unprotected_attributes__ = 1 isPrincipiaFolderish = 1 IMATRACKERISSUE = 1 meta_class = 'TrackerIssueBase' # XXX Permissions are going to have to be worked out! __ac_permissions__ = ( ('Public Issue Interaction', ['add_item', '__getitem__', '__getattr__', 'owners', 'keys', 'items', 'values', 'has_key', 'update', 'get', 'length', 'length', '__len__', '__delitem__', '__setitem__', 'history', 'numid', 'add_state', 'register_state_changes', 'statecond', 'promotes', # XXX XXX Expediency, permissions broke ], ['Anonymous']), ('Privileged Issue Interaction', [], # ['promotes'], ['Requester', 'IssueOwner', 'Supporter', 'TrackerOwner'], ), ('Tracker Staff', [], # ['promotes'], ['IssueOwner', 'Supporter', 'TrackerOwner'], ), ('Issue Overrides', [], ['IssueOwner', 'TrackerOwner'], ) ) def __init__(self, REQUEST=None): self.id = (REQUEST and REQUEST.get('id', '')) or '' self._messages = BTree() self._promoted = [] self.audited_state = AuditedState() self.state_tick = 1 def __repr__(self): return ("<%s %s (%d messages, %d promoted) at 0x%s>" % (self.__class__.__name__, `self.id`, self.length(), len(self.promotes()), hex(id(self))[2:])) def add_item(self, item, user): """Add a new item, returning generated id and item acquired.""" items = self._messages if items: id = items.keys()[-1] + 1 else: id = 1 item.id = str(id) items[id] = item self.audited_state.set('newitem', id, user) return (id, item.__of__(self)) def numid(self): """Return the numeric version of the id.""" if type(self.id) == StringType: return atoi(self.id) else: return self.id def promotes(self, itemid=None, user=None, demote=None): """Return list of promoted items, or promote/demote one. Without an itemid, return the list of promoted items. With just the itemid and user, add the itemid to the list - or remove it, if demote is set.""" if itemid is None: return self._promoted[:] if type(itemid) == StringType: try: itemid=atoi(itemid) except: raise AttributeError, itemid if demote is None: pubs = self._promoted if itemid not in pubs: pubs.append(itemid) self._promoted = pubs self.audited_state.set('promote', itemid, user) else: pubs = self._promoted if itemid in pubs: pubs.remove(itemid) self._promoted = pubs self.audited_state.set('demote', itemid, user) def execute_rules(self): """Invoke tracker rules on just this issue.""" return self.aq_parent.execute_rules(issues=[self]) def statecond(self, var=None, value=None, priorcount=None): """Expose Noodge.state_condition() method to dtml.""" return self.state_condition(self, var=var, value=value, priorcount=priorcount) def tick(self): """Tick used to identify "volatile" settings of current transaction.""" return self.state_tick def increment_tick(self): """Increment ticker by which audited state volitility is recognized.""" self.state_tick = self.state_tick + 1 def add_state(self, additions, REQUEST=None): """Institute the state settings that are to be audited.""" # Create the audit trail: user = (REQUEST and `REQUEST.AUTHENTICATED_USER`) or '' setstate = self.audited_state.set for varname, value in additions: setstate(varname, value, user) def register_state_changes(self, REQUEST=None): """Check for tracked-attribute changes and register any found. Call this whenever the state of the issue has changed.""" state = self.audited_state user = (REQUEST and `REQUEST.AUTHENTICATED_USER`) or '' for a, v in state.items(): if not hasattr(self, a): # Event state vars, like 'newitem', are ephemeral... continue current = getattr(self, a) if current != v: state.set(a, current, user) return self.execute_rules() def history(self): """History of audited items.""" return self.audited_state.history() def __getitem__(self, id): """ """ if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id return self._messages[id].__of__(self) __getattr__ = __getitem__ def keys(self, reverse=0): """ """ got = list(self._messages.keys()) if reverse: got.reverse() return got def items(self, reverse=0): """Return all keys and issues which we are privileged to view.""" items = self._messages got = [] for k, v in items.items(): got.append((k, v.__of__(self))) if reverse: got.reverse() return got def values(self, reverse=0): """Return all items which we are privileged to view.""" got = [] for i in self.items(reverse=reverse): got.append(i[1]) return got def has_key(self, id): """True if item exists for key, regardless of privilege to view it.""" if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id return self._messages.has_key(id) def get(self, id, failobj=None): """Like generic sequence get, including failover.""" if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id items = self._messages if items.has_key(id): return items[id].__of__(self) else: return failobj def length(self): """Number of message items.""" return self._messages.__len__() def __len__(self): """Number of message items.""" return self._messages.__len__() ## def __del__(self): ## """ """ ## for k in tuple(self._messages.keys()): ## del self._messages[k] ## # XXX any other cleanup... def __delitem__(self, id): """ """ # XXX is there any special stuff to do for ZClass deletion? if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id del self._messages[id] def __setitem__(self, id, issue): """ """ __traceback_info__ = ("TrackerIssueBase.__setitem__", `id`, `issue`) if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id self._messages[id] = issue def __getitem__(self, id): """ """ if type(id) == StringType: try: id=atoi(id) except: raise AttributeError, id __traceback_info__ = ("TrackerIssueBase.__getitem__", `id`) return self._messages[id].__of__(self) def owners(self): lr = self.__ac_local_roles__ or {} got = [] for k, v in lr.items(): if 'TrackerOwner' in v: got.append(k) return got default__class_init__(TrackerIssueBase) class AuditedState(Acquisition.Explicit): # If we need to enable access to unprotected attributes. __allow_access_to_unprotected_subobjects__ = 1 def __init__(self): self._state = {} self._hist = [] def set(self, varname, value, user): """Set current state and record old value in history.""" self._state[varname] = value # self.tick() is got by acquisition. self._hist.insert(0, (varname, value, user, time.time(), self.aq_parent.tick())) def get(self, varname, failobj=None): if not self._state.has_key(varname): return failobj return self._state[varname] def keys(self): return self._state.keys() def items(self): return self._state.items() def in_state(self, varname, value): return value == self.get(varname) def age(self): if not self._hist: return 0 return age(self._hist[-1][-2], business=1) def history(self, varname=None, value=None, user=None, max=None, after=None, tick=None): """Return list of (name, val, oldval, user, time, tick) tuples. Order is more recent entries first. Optional parameters constrain the search. varname, value, and user constrain entries to ones that contain that field. (value and user can be lists of eligible candidates.) max specifies an upper limit to the number of entries returned. after specifies a cutoff time.time(), entries logged before that time are excluded.""" if varname != None and not self._state.has_key(varname): raise AttributeError, "Undefined varname '%s'" % varname got = [] if varname == value == max == after == tick == None: __traceback_info__ = (`self`,) return self._hist[:] if value is not None and type(value) == StringType: user = [user] if user is not None and type(user) == StringType: user = [user] for n, v, u, t, i in self._hist: if after and t < after: break if varname and (n != varname): continue if value and (v not in value): continue if user and (u not in user): continue if tick: if i != tick: return [] return [(n, v, u, t, i)] got.append((n, v, u, t, i)) if len(got) == max: break return got class Notifier: def notify(self, issue, who, subj, msg): if DEBUG >= 2: Note("** Issue notify: %s, Notify: to: %s, subj:%s\nmsg: %s\n", issue, who, subj, msg) def sample(): """Evolving test that returns a populated tracker.""" tracker = TrackerBase('sample') tracker.abbrev = 'SAMP' issue = TrackerIssueBase() i = tracker.add_issue(issue) issue = tracker[i] audit = issue.audited_state user = 'test' class PseudoItem(Acquisition.Implicit): def __init__(self, title="", description=""): self.title = title self.description = description self.IMATRACKERITEM = 1 item = PseudoItem("sample title", "sample description") issue.add_item(item, user) item = issue[1] additions = [('newitem', '0'), ('stage', 'pending'), ('punctuality', 'ok'), ('correspondence', 'caught-up'), ('priority', 'normal'), ('urgency', 'normal'), ('window', 'soon'), ] class x: AUTHENTICATED_USER = 'test' issue.add_state(additions, x()) return tracker, issue, item === Added File Products/TrackerBase/TrackerMethods.py === (2193/2293 lines abridged) """External methods for Tracker-related ZClasses and Products.""" #import Products.TrackerBase.TrackerMisc # DEBUG #reload(Products.TrackerBase.TrackerMisc) # DEBUG from Products.TrackerBase.TrackerMisc import * import OFS.Image import sys, time TRACKER_DATA_VERSION = 1 ISSUE_DATA_VERSION = 1 ITEM_DATA_VERSION = 1 def addTracker(self, id, REQUEST=None): """ """ # self = Factory - actually, FactoryDispatcher # Destination() = the folder in which the obj is being created. if not id: raise ValueError, "You must specify an id." inst = self.Tracker(id) dest = self.Destination() dest._setObject(id, inst) tracker = getattr(dest, id) tracker.DATA_VERSION = TRACKER_DATA_VERSION user = (REQUEST and `REQUEST.AUTHENTICATED_USER`) or '' tracker.manage_addLocalRoles(user, ['TrackerOwner']) for role in unique(ROLE_CATEGORIES['open'] + ROLE_CATEGORIES['dedicated']): if not tracker._has_user_defined_role(role): tracker._addRole(role) setTrackerRules(tracker) tracker.smtphost = socket.gethostname() tracker.smtpport = 25 for ps in tracker.propertysheets: ps.manage_changeProperties(REQUEST) tracker.supporters = [] tracker.clients = [] tracker.peers = [] tracker.open_subscribe = tracker.default_open_subscribe trackerInitCatalog(tracker) [-=- -=- -=- 2193 lines omitted -=- -=- -=-] ## (INCLUDE, 'overdue', 'ownership')))), ( # Clear up ownership pending state when suitable. (CONDITION, (NOT, (STATE, 'stage', 'pending'))), ( (CONDITION, (CONTAINS, 'due', 'ownership')), (ACTIONS, (REMOVE, 'due', 'ownership'))), ( (CONDITION, (CONTAINS, 'overdue', 'ownership')), (ACTIONS, (REMOVE, 'overdue', 'ownership')))), ( # Clear up rsvp pending state when suitable. (CONDITION, (AND, (OR, (CONTAINS, 'due', 'rsvp'), (CONTAINS, 'overdue', 'rsvp')), (NOT, (STATE, 'msgfromrole', 'Requester', 0)))), ( (CONDITION, (CONTAINS, 'due', 'rsvp')), (ACTIONS, (REMOVE, 'due', 'rsvp'))), ( (CONDITION, (CONTAINS, 'overdue', 'rsvp')), (ACTIONS, (REMOVE, 'overdue', 'rsvp')))), ( # Alert to languishing reply. (CONDITION, # The last correspondence is from the requester: (AND, (OR, ('<', (STATE, 'msgfromrole', ['Requester', 'TrackerOwner'], 0), (STATE, 'msgfromrole', 'Supporter', 0)), ('>', (STATE, 'msgfromrole', 'Requester', 0), 3*ADAY)))), # Send daily alerts to issue owner, after initial grace period: ( (CONDITION, (OR, (NOT, (STATE, 'alert', 'rsvp due', 0)), ('>', (STATE, 'alert', 'rsvp due', 0), 1*ADAY))), (ACTIONS, (SET, 'alert', 'rsvp due'), (NOTIFY, 'IssueOwner', "Issue %[var title]s %[var id]s correspondence pending", "Issue %[var issueIdentity]s requester is owed" " correspondence.") )), # This has been going on too long - alert the tracker owner once: ( (CONDITION, (AND, ('>', (STATE, 'alert', 'rsvp due', 0), 7*ADAY), (NOT, (STATE, 'alert', 'rsvp overdue', 0)))), (ACTIONS, (SET, 'alert', 'rsvp overdue'), (NOTIFY, 'TrackerOwner', "Issue %[var title]s %[var id]s correspondence WAY pending", "Issue %[var issueIdentity]s requester has been owed" " correspondence for more than 7 days.")))) ] return standard === Added File Products/TrackerBase/TrackerMisc.py === (697/797 lines abridged) # General stuff ========================================================== import string from DocumentTemplate.html_quote import html_quote import smtplib, socket from DateTime import DateTime import urllib from AccessControl.PermissionRole import rolesForPermissionOn from Products.ZCatalog.ZCatalog import Catalog RELEVANCE_DEBUG = 1 RULES_DEBUG = 0 EMBLEM_DEBUG = 1 # Privacy stuff ========================================================== # Role categories - map abstract tracker role names to tracker-specific zope # security roles. Use tracker_role() to do the translation from tracker dtml. INVOLVED_ROLES = ['IssueOwner', 'Requester', 'TrackerOwner'] STAFF_ROLES = ['TrackerOwner', 'IssueOwner', 'Supporter', 'Researcher'] DEDICATED_ROLES = STAFF_ROLES + ['TrackerClient', 'Subscriber', 'Requester'] OPEN_ROLES = DEDICATED_ROLES + ['Anonymous', 'Member'] # XXX SupporterHelp would be a good place for exposition about the categories. # Some details would be good for TrackerElementsHelp, as well - see # set_privacy for related notes. ROLE_CATEGORIES = { # staff: View any items, become issue owner, and do other state changes. # Not shown other-correspondence items, but has access to them, # including private ones. 'staff': STAFF_ROLES, # observer: View correspondence beyond summary, private issues. Does not # enable followup privileges or access to private items. 'observer': (['Subscriber'] + INVOLVED_ROLES), # involved: Like observer but can submit followups. 'involved': INVOLVED_ROLES, # dedicated: Can enter dedicated tracker. 'dedicated': DEDICATED_ROLES, # open: Can enter open tracker. 'open': OPEN_ROLES, } def elementEmblem(self, issue_id=None, item_id=None, nolink=0, complete=0, forcelink=0, REQUEST=None): """Return a terse link specifying a particular issue, item, or tracker. If REQUEST.AUTHENTICATED_USER is not authorized to view the target element (or no REQUEST was passed in), then only the textual, unlinked version of the emblem is returned. This serves as the cue that the element is unviewable, and prevents the user from trying to prevent the element and [-=- -=- -=- 697 lines omitted -=- -=- -=-] else: return (text[:prior], text[prior+1:]) def pedigree(self): """Investigation utility showing the base class hierachy of a class.""" __traceback_info__ = (`self`) structure = pedigree_structure(self.__class__) got = indented(structure, depth=0) return ("" + ("

%s Instance Inherited Classes

\n" % got[0]) + "\n('...' abbreviates already elaborated classes)" + "\n
\n" + string.join(got[1:], '\n') + "\n
\n" + "") def indented(nesting, depth=0): """Indicate list nesting with indentation instead of containment. Ellipses appreviate already elaborated classes, and single-element inheritance is shown on the same line as the inheritor.""" got = [] for i in nesting: if type(i) == type(''): got.append((depth * ' ') + i) ## elif len(i) == 2 and len(i[1]) == 1: ## got.append((depth+1) * ' ' + "%s %s" % (i[0], i[1][0])) else: got = got + indented(i, depth + 1) return got def pedigree_structure(klass, already_seen=None): """Return nested lists reflecting inheritance structure of self.""" __traceback_info__ = (`klass`) bases = klass.__bases__ seen = "" if already_seen is None: already_seen = [] elif bases and klass in already_seen: seen = " ..." if hasattr(klass, '__module__') and klass.__module__: got = ["%s (%s)%s" % (klass.__name__, klass.__module__, seen)] else: got = [klass.__name__ + seen] if not seen: already_seen.append(klass) for i in bases: got.append(pedigree_structure(i, already_seen)) return got === Added File Products/TrackerBase/__init__.py === """Tracker base-objects product.""" __version__='$Revision: 1.1 $'[11:-2] import TrackerBase def initialize(context): ## perm='Add Whatever' context.registerBaseClass(TrackerBase.TrackerBase, "TrackerBase") context.registerBaseClass(TrackerBase.TrackerIssueBase, "TrackerIssueBase") ## context.registerBaseClass(TrackerBase.TrackerItemBase) === Added File Products/TrackerBase/addTrackerForm.dtml ===

Add A Tracker

Id
Title
 
... three configuration steps remaining ...
=== Added File Products/TrackerBase/age.py === from DateTime import DateTime BIZDAYSTART = 9.0 # 9:00 am BIZDAYEND = 18.0 # 6:00 pm def age(since, until=None, business=0, holidates=None, bizdaystart=BIZDAYSTART, bizdayend=BIZDAYEND): """Return age in decimal (float) number of days. Optional end time 'until', defaults to current moment. Optional flag 'business' means compute according to business time - excluding non-business hours, weekends, and specified holidays. Optional holidates is a list of DateTimes.Dates() format dates designating holidays to be excluded from business hours. \(Holidates falling on a weekend day are shifted to next non-exempted weekday before being exempted.) Optional bizdaystart is the start time of a business day, expressed *as a decimal number*: the integral hour, then the decimal portion thereof. Optional bizdayend is the companion day-end time for bizdaystart.""" now = DateTime() if type(since) != type(now): since = DateTime(since) if not until: until = now elif type(until) != type(now): until = DateTime(until) if not business: return until - since # Business-hours computation onwards. # factor to normalize number of business hours/day: daylenfactor = 24/(bizdayend - bizdaystart) if daylenfactor < 0: raise 'DateTimeError', ('business day end (%s) is before start (%s)?? ' % (bizdayend, bizdaystart)) # Shift the endpoints to nearest contained business days: since = nearest_bizday(since, forwards=1, holidates=holidates) until = nearest_bizday(until, forwards=0, holidates=holidates) if not since.lessThan(until): return 0 # Nail down the amount of time in the head & tail days: head = tail = 0 sincetod = since - since.earliestTime() if sincetod < (bizdaystart/24): # Increment the time to the start of the business day: since = since + ((bizdaystart/24) - sincetod) sincetod = since - since.earliestTime() untiltod = until - until.earliestTime() if untiltod > (bizdayend/24): # Decrement the time to the end of the business day: until = until - (untiltod - (bizdayend/24)) untiltod = until - until.earliestTime() if not since.lessThan(until): return 0 if since.Date() == until.Date(): return (until - since) * daylenfactor else: subtotal = (((bizdayend/24 - sincetod) + (untiltod - bizdaystart/24)) * daylenfactor) # Ok, now we just need to deal with intervening days. since = since.latestTime() until = until.earliestTime() # Num of intervening days, sans head/tail interdays = int(until - since) if interdays == 0: return subtotal # Omit saturdays and sundays. dow_count = since.dow() + interdays weekend_days = dow_count/7 + (dow_count+1)/7 interdays = interdays - weekend_days if holidates: # Omit intervening holidays. # Increment to the first non-weekend, non-considered day if necessary. exempted = [] for htime in holidates: if since <= htime <= until: interdays = interdays - 1 if interdays <= 0: return subtotal return interdays + subtotal def nearest_bizday(ztime, forwards, holidates): """Return the nearest business day to specified time. If we must shift forward, return the beginning of the soonest day. If backward, return the end of the most recent day. holidates are DateTime objects representing holiday dates to exclude.""" # Each time around we concentrate on *either* the weekend *or* holiday... doingweekend = 0 # ... so we can process the shifts consistently at the bottom. Thus # we retraverse the loop after any shift to assess the newly found date. shift = 1 # We only need to do the (relatively expensive) earliest/latest shifts # the first time - 'extremed' marks that. extremed = 0 while shift: shift = 0 if not doingweekend: if ztime.dow() == 6: if forwards: shift = 2 else: shift = -1 doingweekend = 1 elif ztime.dow() == 0: if forwards: shift = 1 else: shift = -2 doingweekend = 1 else: doingweekend = 0 if not doingweekend and holidates: thisDate = ztime.Date() for h in holidates: if thisDate == h.Date(): if forwards: shift = 1 else: shift = -1 if shift: if shift > 0: if extremed == 0: ztime = extremed = (ztime + shift).earliestTime() else: ztime = extremed = ztime + shift else: if extremed == 0: ztime = extremed = (ztime + shift).latestTime() else: ztime = ztime + shift return ztime class HoliDatesOff: """A cache for "regular" holidays, ie those determined by a month/day. '.add()' registers new month/day holidays. '.get()' takes a year and returns all the registered holiday dates, as DateTime objects, for that year - shifting any that fall on a weekend to the nearest subsequent non-holiday weekday. The HoliDatesOff class economizes on the DateTime object creation process by caching assortments for any encountered year. The cache is invalidated any time a new date is entered.""" def __init__(self, monthdaylist=[]): self._cache = {} # {year: [dates]} self.monthdaylist = [] self.add(monthdaylist) def add(self, dates): if type(dates) == type(""): dates = [dates] mdl = self.monthdaylist for i in dates: if i in mdl: continue mdl.append(i) self._cache = {} def get(self, year): year = str(year) if self._cache.has_key(year): print "from cache" return self._cache[year] got = [] for i in self.monthdaylist: d = nearest_bizday(DateTime("%s/%s" % (year, i)), 1, got) got.append(DateTime(d.Date())) got = tuple(got) self._cache[year] = got return got REGULAR_HOLIDAYS = {'Independence Day': '07/04', 'Christmas Day': '12/25', 'Thanksgiving': '11/25', 'New Years Day': '01/01', 'Easter': '04/04', } def getHolidayRegistry(): return HoliDatesOff(REGULAR_HOLIDAYS.values()) === Added File Products/TrackerBase/envsetup.py === """Command sequence to prime for interaction with a sample tracker.""" try: envsetup envsetup.seek(0) except NameError: envsetup = open('./envsetup.py', 'r') import sys sys.path.insert(0, '.') sys.path.insert(0, '../..') import ZODB import TrackerBase, TrackerMethods, Noodging # or reload(TrackerBase); reload(TrackerMethods); reload(Noodging) tracker, issue, item = TrackerBase.sample(); rules = TrackerMethods.setTrackerRules(tracker) state = issue.audited_state print "tracker, issue, item, rules, and state prepared" print "(exec(envsetup.read()) to reinit env)" === Added File Products/TrackerBase/issue.gif === === Added File Products/TrackerBase/item.gif === === Added File Products/TrackerBase/tracks.gif === From sidnei at x3ng.com.br Fri May 30 11:17:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/TrackerBase/forms - ActivityReports.dtml:1.1 HelpComposite.html:1.1 HelpConfiguration.dtml:1.1 HelpIssues.dtml:1.1 HelpItems.dtml:1.1 HelpSupporter.dtml:1.1 HelpTrackerOverview.dtml:1.1 addTrackerForm.dtml:1.1 allIssuesView.dtml:1.1 attachmentsFormRow.dtml:1.1 catalog.dtml:1.1 configActivities.dtml:1.1 configAssignmentsForm.dtml:1.1 configBasicForm.dtml:1.1 configMemberSettings.dtml:1.1 configTraitValuesForm.dtml:1.1 configUpdatesMaint.dtml:1.1 currentStateView.dtml:1.1 date_widget.dtml:1.1 doSetConfig.dtml:1.1 editIssueStatus.dtml:1.1 editStateYikes.dtml:1.1 elementSummaryRows.dtml:1.1 index_html.dtml:1.1 issue-attachments.dtml:1.1 issue-index_html.dtml:1.1 issueAllIssues.dtml:1.1 issueBanner.dtml:1.1 issueCurrentIssues.dtml:1.1 issueHistory.dtml:1.1 issueStatusRows.dtml:1.1 issueSummaryRows.dtml:1.1 item-attachments.dtml:1.1 item-index_html.dtml:1.1 itemBanner.dtml:1.1 itemForm.dtml:1.1 itemIssueView:1.1 itemIssuesIndexView.dtml:1.1 itemSubmitNewIssu! e.dtml:1.1 itemSummaryRows.dtml:1.1 login.dtml:1.1 relogin.dtml:1.1 searchFormComplex.dtml:1.1 searchFormSimple.dtml:1.1 setIssueState.dtml:1.1 standard_tracker_footer.dtml:1.1 standard_tracker_header.dtml:1.1 submitIssueForm.dtml:1.1 Message-ID: <200305301517.h4UFHwB20817@cvs.baymountain.com> Update of /cvs-zopeorg/Products/TrackerBase/forms In directory cvs.zope.org:/tmp/cvs-serv19195/TrackerBase/forms Added Files: ActivityReports.dtml HelpComposite.html HelpConfiguration.dtml HelpIssues.dtml HelpItems.dtml HelpSupporter.dtml HelpTrackerOverview.dtml addTrackerForm.dtml allIssuesView.dtml attachmentsFormRow.dtml catalog.dtml configActivities.dtml configAssignmentsForm.dtml configBasicForm.dtml configMemberSettings.dtml configTraitValuesForm.dtml configUpdatesMaint.dtml currentStateView.dtml date_widget.dtml doSetConfig.dtml editIssueStatus.dtml editStateYikes.dtml elementSummaryRows.dtml index_html.dtml issue-attachments.dtml issue-index_html.dtml issueAllIssues.dtml issueBanner.dtml issueCurrentIssues.dtml issueHistory.dtml issueStatusRows.dtml issueSummaryRows.dtml item-attachments.dtml item-index_html.dtml itemBanner.dtml itemForm.dtml itemIssueView itemIssuesIndexView.dtml itemSubmitNewIssue.dtml itemSummaryRows.dtml login.dtml relogin.dtml searchFormComplex.dtml searchFormSimple.dtml setIssueState.dtml standard_tracker_footer.dtml standard_tracker_header.dtml submitIssueForm.dtml Log Message: Adding products needed for migration of NZO === Added File Products/TrackerBase/forms/ActivityReports.dtml === A prototype tracker activity report presentation. 1">
        <!--#var meta_type-->   Tracker Activity Reports
Site:
For: -
... plus: Identify trackers to be included in the report, relative to / (e.g. )

 
 

Per-Tracker Ticket Quotas
  This presents the current status of issues opened within the service period of the respective trackers. (See here for info about the different kids of service periods.)
 
/ +
Tracker Plan Active Resolved Other
Closed
Balance Allotted Period
open
=>
Plan
Support-level plan, one of Bronze, Silver, Gold, or Platinum for Dedicated trackers, or Open for Open trackers.
Active
Number of requests currently in Pending or Accepted stage
Resolved
Number of closed issues that count against a dedicated tracker's allotment of request tickets - those issue completed by the resolve supporter action.
Other Closed
Number of other closed issue, which wouldn't count against a request ticket allotment, ie those closed with the reject, defer, or divert actions.
Balance
Number of new tickets available within the allotment, deducting the number of active and resolved tickets. Not applicable to open trackers or dedicated trackers with unlimited ticket allotment.
Period
The specified dates of service for a dedicated tracker, or the period from a year ago to today for an open one.
 

Per-Supporter Ticket Assignments
 
/ +
bgcolor="#eeeeee">
Supporter Platinum Gold Silver Bronze None Total
bgcolor="#eeeeee"> , , -
Each entry indicates the number of Accepted , Resolved , and (Other - rejected deferred or diverted) requests the supporter has chalked up across the subject trackers and within their respective periods of service. (See the Ticket Quotas table for the service periods).
 

Active Issues Maturity
  This presents the current ages of all incomplete issues across the collection subject trackers, and then within each tracker individually.
 
  < align="center"> - >
/ +
/

=== Added File Products/TrackerBase/forms/HelpComposite.html === (968/1068 lines abridged) Tracker Users Guide

Tracker Overview

The Zope Tracker conducts web-based support and development dialogues, organizing the flow and artifacts of the correspondence. This page presents a user-oriented overview.

Introduction to the Tracker

Any number of distinct trackers can be created within a single Zope site. Each Tracker has its own administrator, with overriding configuration privileges including, among other things, the ability to designate specific supporters - tracker staff responsible for satisfying requests - and the mode by which site users are allowed to submit (request) and browse existing issues. In Open operating mode, trackers admit all Zope site users. In Dedicated mode, the tracker only admits browsing and requests from designated users.

The process of tracker issues.

Individual tracker dialogues are known as issues. An issue is basically a container for messages, known as items, between the issue requester and suporters. When submitting an issue, the requester selects traits which characterize it. The ranges of traits are configured by the tracker administrator, tailored for the tracker's [-=- -=- -=- 968 lines omitted -=- -=- -=-]

Traits that have many values have a special first entry - <Invert>. Selecting <Invert> means that the supporter is disqualified by the selected values, rather than qualified by them. This makes it easy to disqualify a supporter for just a few values of some extensive trait.

Member Info Settings (See the form...)

The tracker needs an email address for all issue participants, for correspondence about the issues. On sites with membership, that information is already available. Elsewhere, you may need to fill in this data yourself. The Member Settings form enables the tracker administrator to specify the email addresses when they assign new supporters or clients. It is automatically visited on submission of the Values Configuration form if there are supporters lacking an email address. Also, there is a link to this form from that page, which you can use at any time.

On the form, supporter IDs are highlighted with either a green or a red font - red to alert you to the lack of an email address for the supporter. The email-lacking supporter entries are also distinguished with a pair of ** asterisks, to make it easy to search for such entries amid a large collection of users.


Ken Manheimer
Last modified: Sun Mar 26 13:52:37 EST 2000 === Added File Products/TrackerBase/forms/HelpConfiguration.dtml ===

Tracker Configuration Instructions

Overview

The user creating a tracker get the TrackerOwner, with configuration and other special privileges. (You can use the Zope management Security tab/local roles to transfer or share those privileges after the tracker is created, if necessary.)

Tracker configuration is a three-step process. The tracker owner is brought to it upon creating the tracker, and can reenter it at any time via the configuration tab (which only the tracker owner sees) at the top of the main tracker page.

Stage Details

Basic Configuration (See the form...)

Here is where you set the fundamental tracker operation settings, and you name the trait categories by which requesters qualify their issues.

  • Id - the object management id for the tracker - you can change it from the management interface of the folder containing the tracker, not from inside the tracker itself.
  • Title - A terse descriptive title for the tracker.
  • Abbreviation - An extremely terse distinctive abbreviation for the tracker. Email notifications will use this at the beginning of the message subject lines to identify the tracker, so as brief as possible while providing some cue is in order here.
  • Description - Brief presentation of the tracker's purpose - this will be displayed at the top of the issues overview page.
  • Admin Address - Where to send email for tracker administrative business, including notifications gone awry, public contact, etc.
  • SMTP Host / Port - The host and inet socket port where SMTP email for this tracker is dispatched.
  • Mode - Trackers operate in open or dedicated access mode. The access mode determines whether the tracker is open to all comers or only to designated clients.
    • In an open tracker anyone with site membership can submit issues, and anyone at all can review existing ones. Open trackers are convenient for fielding requests in a diverse community, particularly with community-staffed trackers.
    • A dedicated tracker is intended to serve specific clients, so that only they (and tracker staff) can review existing issues and submit new ones. Dedicated trackers provide dedicated support to the clients.
  • Trait Fields - The categories of attributes by requesters qualify their issues. The ranges of values within each category you designate are set in the Values Configuration stage. Note that if there's a trait named "priority", "urgency", "importance", or "need", with values the same as the trackers priority_range property (as shipped: "normal", "high", "low", and "critical"), then the value of that trait will be used to set the issue's initial priority state. This state is separate from the trait - it has a reserved report column, showing settings when different than 'normal', and it will be useful for sorting, once that's implemented.

Values Configuration (See the form...)

This is where you enumerate a variety of tracker settings. This includes special member roles - identifying supporters, and, if the tracker is running in dedicated mode, clients - and issue trait values. (From here you can get to a form to specify user account's email and name settings, as well.)

  • Supporters - Identify the users responsible for (and privileged to) handle issues. If you designate any supporters that do not have an email address registered for them, you will wind up at the Member Info Settings form before proceeding to the next stage, to fill in the addresses.
  • Clients and Request Quota (Dedicated tracker only) - Designate:
    • Members with privileges to access a dedicated tracker.
    • Support level - Support policy level.
    • Allotted number - Total number of requests available to the customer within the service period. Specify a negative number for no limit.
    • Service Start/End - The dates within which the customer's quota of requests is available.
  • Traits Elaboration - Here you enumerate the trait values associated with the traits identifed on the basic config form. You also set checkboxes to identify those fields to be used for routing new issue notifications to supporters - the actual routing choices are made on the next form.

Supporter Assignments (See the form...)

This is where you associate specific supporters with specific issue trait values, for new issue notifications. (There is nothing to do here if you did not check any of the Traits Elaboration text-boxes in the Values Configuration form.)

By assigning specific request trait values to a supporter, that supporter receives notifications about new issues having those settings. If no supporters are identified as relevant for a particular request, the notices for that request are directed to the tracker administrator.

Selecting traits is a way of narrowing the range of issues for which supporter receives new-request email notices. Not selecting any of a supporter's values for a particular trait means that trait is ignored when figuring routing for the supporter. (Thus, its equivalent to selecting all the values for that trait, and less work...)

Traits that have many values have a special first entry - <Invert>. Selecting <Invert> means that the supporter is disqualified by the selected values, rather than qualified by them. This makes it easy to disqualify a supporter for just a few values of some extensive trait.

Member Info Settings (See the form...)

The tracker needs an email address for all issue participants, for correspondence about the issues. On sites with membership, that information is already available. Elsewhere, you may need to fill in this data yourself. The Member Settings form enables the tracker administrator to specify the email addresses when they assign new supporters or clients. It is automatically visited on submission of the Values Configuration form if there are supporters lacking an email address. Also, there is a link to this form from that page, which you can use at any time.

On the form, supporter IDs are highlighted with either a green or a red font - red to alert you to the lack of an email address for the supporter. The email-lacking supporter entries are also distinguished with a pair of ** asterisks, to make it easy to search for such entries amid a large collection of users.

=== Added File Products/TrackerBase/forms/HelpIssues.dtml === === Added File Products/TrackerBase/forms/HelpItems.dtml === === Added File Products/TrackerBase/forms/HelpSupporter.dtml ===

Supporter Actions

Most supporter actions are done through posting followups to an issue. The supporter chooses the particular action from among the "Action" radio buttons on the message submit form. The available choices are tailored to the visitor's role in the issue - see the table, below.

Among other things, the message action determines whether or not the item will be included in the issue summary. For regular (non-confidential) issues, the summary is visible to the general public. It includes synopses of all those messages whose actions change the stage of an issue, and also messages that were submitted with the "Note" action. Other correspondence - the default action, "Plain" - is not included in the summary, and is just between the supporters and requester.

See the topic concerning issue corresondence for more details about who receives what correspondence.

Action From/To Stage Who? * To Summary? Purpose / Notes

Plain

Any


No change

Involved

No

Correspond with parties to issue / Not distinguished in issue summary

Accept

Pending, Deferred


Accepted

Staff

Yes

Claim ownership of an issue / Other supporters exempted from further issue correspondence

Kibitz / Subscribe

Pending, Deferred, Accepted


No change

Anyone

No

Join in an issue / Only when not already involved

Resign

Any but pending


No change

Owners

No

Abandon ownership of issue you own / Not offered when not involved or only supporter

Note

Any


No change

Involved

Yes

Item for summary that doesn't affect stage

Resolve

Accepted, Pending


Resolved

Staff

Yes

Conclude issue satisfying requester / If accepted, only owners (acceptor or staff subscribers) can resolve

Reject

Accepted, Pending


Rejected

Staff

Yes

Dismiss issue without resolution / Same as note as for resolve

Defer

Accepted, Pending


Deferred

Staff

Yes

Table this issue until whenever / Same as resolve note

Reframe

Any


No change

Staff

No

Change any of title/description and/or change traits / For when the requester wasn't quite clear or accurate

Divert

Any


Diverted

Staff

Yes

Include the subsuming issue as the first of the references / Same as resolve note

(
* Who? column is one of: Anyone - anyone able to visit the issue, Involved - requester or tracker staff, Owners - supporter(s) who have accepted responsibility for the issue, Staff - supporters and tracker owner.)

(Occasionally supporters need to send messages that are not exposed the requester or to the public at large. This is done by checking the "Staff eyes only?" box (beside the message subject input field). You must also check the "don't-post-to-summary box, since summary items can't be private.)

The stage, traits, privacy, and other issue settings can be forced using the entries on the issue's "Edit State" tab. (Some state transitions may be inhibited.) The Edit State form is included as part of the Reframe item action.

=== Added File Products/TrackerBase/forms/HelpTrackerOverview.dtml === (631/731 lines abridged)

Zope Tracker Overview

The Zope Tracker conducts web-based support and development dialogues, organizing the flow and artifacts of the correspondence. This page presents a general purpose client-oriented overview:

(Tracker administrators may want to visit the tracker configuration help, and supporters may be seeking support-specific help.)

Tracker Elements

Any number of distinct trackers can be created within a single Zope site. Each Tracker has its own administrator, with overriding configuration privileges including, among other things, the ability to designate specific supporters - tracker staff responsible for satisfying requests - and the mode by which site users are allowed to submit (request) and browse existing issues. In Open operating mode, trackers admit all Zope site users. In Dedicated mode, the tracker only admits browsing and requests from designated users.

Tracker Issues

Individual tracker dialogues are known as issues. An issue is basically a container for messages between the issue requester and suporters about the issue, known as items. When submitting an issue, the requester selects issue traits which characterize their request. The ranges of traits are configured by the tracker administrator, tailored for the tracker's subject domain.

See also the discussion about browsing the issue overview page, below.

The process of tracker issues.

[-=- -=- -=- 631 lines omitted -=- -=- -=-]
  • Following the links in the email notifications.
  • Visiting the tracker index, finding the issue in question, and using the Last Msg shortcut to get to the most recent item.
  • Visiting the containing issue (eg, from the index) and using the Most recent message shortcut located on the upper right corner of the page.
  • When dealing with other than the most recent item, using the other links in the issue summary (or the links in the "Other Correspondence" section, below the summary).
  • Using the URL - the item's is that of the tracker, followed by a '/' and the serial number of the issue, then another '/' and the serial number of the item.

When you followup to an item your new message follows the original in its correspondence thread. You can also start a new thread by using one of the "Start a New Thread" links, found in the issue summary and in the items.

The forms for submitting new items are similar to those for submitting new issues, with a few additions:

  • When replying, the title and text of the original item are cited.
  • Parties to an issue can select actions beyond just sending correspondence. The choice is made using the Action radio-button selection on the item form. Requesters have just a few choices:
    Plain
    The default action, plain items are not registered in the summary, hence are not visible to the general public.
    Note
    Note items are included in the summary, along with the landmark items (see above). This action is useful for posting key developments, like intermediate results.
    Cancel - only until issue is accepted
    The requester can withdraw an issue from consideration up until a supporter has accepted responsibility for it. After the issue has been accepted, however, this option is not offered, and the requester must negotiate with the supporter to reject it.

Supporters can invoke several other actions with their issues - they should consult the support-specific help for details.

=== Added File Products/TrackerBase/forms/addTrackerForm.dtml ===

Add A Tracker

Id
Title
 
... three configuration steps remaining ...
=== Added File Products/TrackerBase/forms/allIssuesView.dtml ===

All "> Tracker Issues

Issues Total

To visit an issue, click on its ID.

Zero zilch no issues. === Added File Products/TrackerBase/forms/attachmentsFormRow.dtml === Some table rows providing form file input fields.
References:
Include (issue)[item] and/or absolute url references, one per line (no HTML). When diverting, include the target issue as the first reference.
Attachments: >
File     Title (if different than file name)
   
Activity Description  
Basic Configuration Pending! Tracker configuration incomplete until this is finished. Set fundamental tracker operation settings and name the trait categories by which requesters qualify their issues. Help
Traits and Supporters Pending! Tracker configuration incomplete until this is finished. Enumerate values of a variety of tracker settings, including designating the supporters and specifying the ranges of issue trait values. Help
Request Routing Assignments Associate specific supporters with specific issue trait values, for new issue notifications. (There is nothing to do here if none of the traits were selected for notification routing in the Traits and Supporters activity.) Help
Other
Member Settings Adjust tracker personnel (supporter and requester) email and fullname settings.
Updates Maintenance Adjust tracker issue indexes and other structural assessments, in the face of upgrades or unexpected drift.
Catalog Management Assess and interact with tracker's catalog structure.
=== Added File Products/TrackerBase/forms/configAssignmentsForm.dtml ===

Category/Supporter Assignments

Assign specific request trait values to each supporter. The supporter will receive notifications about new issues that have those settings. If no supporters are identified as relevant for a particular request, the notices for that request are directed to the tracker administrator.

No traits or supporters selected for assignment. No traits selected for assignment. All supporters will receive all new-request notices. No supporters selected for assignment. The tracker admin will receive all requests.

If this is not what you intended, you can return to the Basic Configuration form or the Trait/Values form and check the boxes of the traits you want to use. Otherwise, you can just proceed to the configured tracker.

Selecting traits is a way of narrowing the range of issues for which supporter receives new-request email notices. Not selecting any of a supporter's values for a particular trait means the supporter's relevance for receiving notices disregards that trait. Furthermore, not selecting any values for any of a supporter's traits means that supporter will receive notices for all new requests.

Traits that have many values have a special first entry - <Invert>. Selecting <Invert> means that the supporter is disqualified by the selected values, rather than qualified by them. This makes it easy to disqualify a supporter for just a few values of some extensive trait.

For more details on the tracker configuration process in general, see here . See here for some more explanation of this configuration stage.

Who Requesters

 
 
Submit proceeds to main page.
Prior config step: Traits and Members
Before that: Basic
=== Added File Products/TrackerBase/forms/configBasicForm.dtml ===

This begins a three-step tracker configuration process , with fundamental tracker identity attributes and naming of characteristic request traits. See here for details on this stage.


Identity
Id:
Title:
Abbreviation: (Very brief - to distinguish email subjects among trackers on this host.)
Description:

Email Connection
Admin Address: >
SMTP Host: > Port: 25 >

Open vs Dedicated Mode
  In an open tracker, any site members can submit issues, and anyone at all can review existing ones. In a dedicated tracker, only designated visitors can review and submit issues (details).
Mode: CHECKED >  Open Open CHECKED >  Dedicated Dedicated

Issue Subscribers
  Non-supporter tracker visitors can participate in issues without being the requester if you allow an open subscription policy. The policy can be overrident for individual issues from within those issues.
Subscribing: CHECKED> Disabled > Disable CHECKED> Enabled > Enable - Are regular visitors by default allow to subscribe to issues?
Posting: CHECKED> Prohibited > Prohibit CHECKED> Allowed > Allow - Can subscribers by default post messages, or just get notified about new ones?

Noisy mode
  Regular trackers cut non-subscribing supporters out of the correspondence loop once one of them accepts an issue. "Noisy" trackers continue to notify all supporters about all correspondence. Toggle this setting to change the behavior of all issues, even already existing ones. (details).
Broadcast: CHECKED > Regular Regular CHECKED > Noisy Noisy

Request Trait Fields
  Use your own, and/or the sample ones. On the next form you'll fill in the candidate values. (The samples have example candidates.)
Trait Fields:

 
   
Submit proceeds to next step: Traits
Which is followed by: Assignments ...
=== Added File Products/TrackerBase/forms/configMemberSettings.dtml === A kludge to make it easy to assign email addresses to staff and clients that are new site members - particularly in the absence of membership, where the fields may be unset.

A supporter or supporters are missing email settings. Such entries will be marked with a '**' flag and a user ID in red.

Bonafide managers can assign member settings here. You create new users using the /manage_main"> acl_users management interface. The IDs of supporters will be either green or red - red to alert you to the lack of an email address for the supporter.

If you were in the midst of configuring the tracker and are done setting supporter email and full name settings, you can continue with the final tracker configuration step new issue routing assignments.

">
ID Fullname Email
Invalid user ''


Barring invalid entries, submit proceeds to ">the next configuration step
... or you can instead return to the Return to the
Trait/Values form

=== Added File Products/TrackerBase/forms/configTraitValuesForm.dtml ===

Trait/Values Configuration

Specify dedicated tracker attributes - members privileged to submit and browse as clients requests, their collective quota of requests, and the time span within which that quota applies. (For tracker operation without these restrictions, return to the basic config form and select 'open' access mode, instead of 'dedicated'.)

Here you select the members who field the requests as support staff, the members to whom this tracker is dedicated, and the range of values for each of your request trait fields - one value per line. See here for help.


Tracker Supporters
  Specify supporters - members responsible for fielding requests.
Supporters: 100"> (Visit configMemberSettings to assign supporter fullnames and email addresses.)

Tracker
  If this were a dedicated tracker, you would designate here those members privileged to submit and browse as clients requests, their collective quota of requests, and the time span within which that quota applies. In open trackers, no such restrictions apply. To switch to dedicated mode, return to the basic config form and select 'dedicated' access mode, instead of 'open'.
Clients and Request Quota: Clients 100">
Service Request Quota
Support Level: CHECKED>
Allotted Number:
... requests to resolve
within service period
Negative for no limit.
Service Start:
Service End:

Traits Elaboration
  Fill or adjust trait values, and check the boxes by traits you will use to distinguish which supporters are notified for which requests. In the next form you will use those traits to target supporter notifications about new requests depending on the request trait settings.

Requester Check the Requester box if you wish to target request notifications according to who submitted the request. This is disabled until Supporter Assignments form handles large site membership.
:
CHECKED>

 
   
Submit proceeds to last config step: Supporter Assignments
One preceeding step: Basic ...
=== Added File Products/TrackerBase/forms/configUpdatesMaint.dtml ===
Reestablish traits and values
Reinstate Catalog
   
 
All Configuration Activities
=== Added File Products/TrackerBase/forms/currentStateView.dtml ===

Issue Current Status (internal view)

:
=== Added File Products/TrackerBase/forms/date_widget.dtml === Invoke this with namespace settings for: thedate - a string for the initial date setting, defaults to now, month_var, day_var, year_var - var names to get the chosen month, day, and year settings. "> === Added File Products/TrackerBase/forms/doSetConfig.dtml === === Added File Products/TrackerBase/forms/editIssueStatus.dtml === <!--#var title_or_id-->
stages No value for stages
urgencies No value for urgencies
punctualities No value for punctualities
correspondences No value for correspondences
=== Added File Products/TrackerBase/forms/editStateYikes.dtml ===
<!--#var meta_type--> -

Override Issue Attributes
  Tracker staff can force new settings for issue attributes here. (To reformulate the issue text, submit a message in the issue with the 'reframe' action; the last step will include this form.)
Private: CHECKED > Public > Public
CHECKED > Private > Private
Allow Subscribers: CHECKED > Subscribing Disabled > Disable Subscribing
CHECKED > Subscribing Enabled > Enable Subscribing
:
Requester: Subscribers:
Supporters: ">
Traits:
:
 

 
  Recompute the stage settings for this issue, to catch up with tracker architectural changes.
=== Added File Products/TrackerBase/forms/elementSummaryRows.dtml === Generalized synopsis presentation of tracker element (issues and items) sequences as a bunch of table rows. It requires the sequence to be bound to be (using eg a '#with') to the variable 'element', and a list of the desired fields to be bound to 'summary_fields'. Several fields are specially handled, in particular: - 'emblem' is presented as a short sign for the element that links to it. - 'date' is presented so current day is just the am/pm time, and current years are shown without the year. - Lists are unrolled with ',' commas between the pieces. - 'in_reply_to' and 'replies' entries are turned into the emblem links for the elements. BGCOLOR="#ccffcc"> ID Item only Action Issue only Supporter - Last
Msg Re   >   > issues only  

,
"left" "center"> "left" "center"> * ,   === Added File Products/TrackerBase/forms/index_html.dtml === Tracker index_html We do massive preparation of search criteria. We may be coming in from elsewhere - a fresh start - or we may be cycling back one of the search buttons at the bottom. Then there's some massaging of traits, etc. Prime search settings with refine_defaults, according to whether we're: - coming in from elsewhere - fresh, init from defaults - doing simple search - retain simple settings, default the others - doing elaborate search - retain all settings - "default" search button was hit - reinit from defaults Prime search criteria with batch settings. Prime search criteria with date info. Prime search criteria with trait settings. Check for proper tracker configuration and report prospective problems. DO THE SEARCH.
        <!--#var meta_type-->   Issue Tracker
Purpose:

Below are existing issues, filtered according to the search settings at the bottom of the page.
  To visit one of the existing issues, click on the ID or title. To go directly to the most recent message in the issue (for details, or to respond to it), click on the identifier in the last-message column.
  To submit a new issue, click here, or use the tab at the top of the page.
  For more background and instructions, visit the Tracker overview .

NOTE! This tracker is incompletely configured, which may lead to malfunction. The following needs to be configured (by tracker staff): Basic Config and Traits Config

 

Matching Issue of Matching Issues ( Total - = 0"> remaining tickets of allotted through service scheduled through )
">
( Retain batch size as personal default)
Zero zilch no matching issues.
   
=== Added File Products/TrackerBase/forms/issue-attachments.dtml === Enumerate all the attachments for the current issue, with icon/link format. If there's a binding for 'attachments_delimiter', it's put between the item entries. ... of item. === Added File Products/TrackerBase/forms/issue-index_html.dtml ===
=> This issue has been diverted to ">
<!--#var meta_type-->

Issue Summary (Most recent message: , )
"> Reframe Request :
">
Traits:

Item Refs:
Attachments:
Description:
 
:
From: ,
Item Refs:
Attachments:
Description:

 
Subscriptions: Issue subscribibility: CHECKED > Disabled >Disable   CHECKED > Enabled >Enable
Subscriptions disabled for this issue Non-member cannot subscribe Issue subscription: CHECKED > Remain Unsubscribed >Unsubscribe   CHECKED > Remain Subscribed >Subscribe
Note: subscriptions are disabled, so no resubscribing if you unsubscribe
Subscribing includes you among those notified about and posting new issue items.
  Issue subscriber posting: CHECKED > Disabled >Disable   CHECKED > Enabled >Enable
   
Other Issue Correspondence
To followup or for For item details, select an item by clicking an Action[ID] header, above, or an ID/title, below OR start a new thread for this issue supplement discussion in this closed issue here. (See here for help.)
All correspondence is covered in the summary
=== Added File Products/TrackerBase/forms/issueAllIssues.dtml === === Added File Products/TrackerBase/forms/issueBanner.dtml === Handy presentation of the current issue id - including link to current tracker Tracker. Issue === Added File Products/TrackerBase/forms/issueCurrentIssues.dtml === === Added File Products/TrackerBase/forms/issueHistory.dtml ===


Change History (internal view)

Which What Who When Tick
=== Added File Products/TrackerBase/forms/issueStatusRows.dtml === issueStatusRows From: , Supporter1">s: Not assigned Stage: => , "> Priority: CHECKED > > Issue Refs: Subscribers: 10"> (+ more) Private: Yes No Item Private: Correspondence: "> === Added File Products/TrackerBase/forms/issueSummaryRows.dtml === This is the place to set the standard format for an issue summary row, and the thing to use to generate them. If 'doheader' is set, only the header is shown, otherwise only the body is shown. Convenience for displaying an issue synopsis as a bunch of columns. It expects a list of issues to be displayed to be bound to 'elements', the number of elements in the list to be bound to 'totmatches', and the amount of elements in the previous batch to be bound to 'numpriors'. Binding 'summary_header_only' around a call here will emit a table header of the field names, instead of the values. ID
# Title
Description Request Last
Msg Stage Priority Traits bgcolor="eeeeee"
>
=>
(+)
XXX instead, eg: date.strftime("%b %e %I:%M %P")) BUT, %b, ..., get caught by dtml processing!
XXX See other XXX, above.
 

- ,
bgcolor="eeeeee" >   54> Diverted to to "> - References: bgcolor="eeeeee" > / >  
=== Added File Products/TrackerBase/forms/item-attachments.dtml === Enumerate all the attachments for the item, with icon/link format. "> " alt="" border="0"> [<!--#var meta_type-->] , === Added File Products/TrackerBase/forms/item-index_html.dtml === Content-Type: text/HTML Multi-perspective home page for items. When visited without arguments, it shows the current-item details and a form for followup in the thread, and also a link to a form for starting a new thread in the issue. That "starting a new thread" form is actually the same index_html, but it doesn't show the section with the details of the current item, or any other signs that there *is* a current item.
=> This issue has been diverted to ">
<!--#var meta_type--> of

Message Details  
Subject:
From: , Action: (Overridden by )
In reply to: Replies:
Item Refs:
Attachments:
Description:

 
CHECKED > PublicPublic
CHECKED > PrivatePrivate
... to change the item privacy setting, alone.
... to promote this item to the issue summary with the few actions that don't change the issue state. (Visit /editStateYikes"> here for stage-altering actions.) NOTE - to promote it you must unset privacy.
  This item is an issue summary '' message. You can demote it to only be part of the requester/staff correspondence. (Note that demoting it will make the issue phrasing go back to that of the request.)

Followup to this message below... OR Start a new thread for this issue. Supplement discussion in this closed issue.
(No subscriber posting in this issue tracker)
=== Added File Products/TrackerBase/forms/itemBanner.dtml === Handy presentation of the current item identifier - including links to current tracker and issue Tracker. Issue Item === Added File Products/TrackerBase/forms/itemForm.dtml === Tracker item itemForm
/addIssueItem" ENCTYPE="multipart/form-data" method="post"> ">
<!--#var meta_type-->
Note! This item is closed. Further correspondence may be unwelcome -
consider " >submitting a new issue instead.
 

New Item Reply Form
Subject: value="Re: "> Staff eyes only? (details)
From:
(details)
: ">    Full Name:    Email:
Action:
"HelpSupporter#actions""HelpTrackerOverview#followacts">(details)
*** Supporter Action Options *** 'request' is never overt - always implicit in request submission. Plain corresondence is always an option. Plain Can only 'accept' from active or deferred stages. It's 'kibitzing' when there's already an owner. It's also "reactivating" when done from deferred stage. Accept Reactivate/Kibitz Accept Can 'subscribe' when not involved. Subscribe Can 'defer' anytime it's not already deferred. Defer Can 'resign' when an owner and there is at least one other. 1)"> Resign Can complete (besides divert) when issue is pending, or it's active and you're an owner. > Anything else is fair game. >
( But don't post to summary, even if non-plain?) Plain Note Cancel

Description:
Signature:
( Retain as personal default.)


 
value="Submit New Message" value="Submit Reply" >
=== Added File Products/TrackerBase/forms/itemIssueView === === Added File Products/TrackerBase/forms/itemIssuesIndexView.dtml === === Added File Products/TrackerBase/forms/itemSubmitNewIssue.dtml === === Added File Products/TrackerBase/forms/itemSummaryRows.dtml === This is the place to set the standard format for an item summary row, and the thing to use to generate them. Convenience for displaying an item synopsis as a bunch of columns. It expects the current item to be bound to 'element', and binding 'summary_header_only' around a call here will emit a table header of the field names, instead of the values. ID Title /
Description ( / Incidentals ) Date Action From Re Replies
Refs:
   
=== Added File Products/TrackerBase/forms/login.dtml === === Added File Products/TrackerBase/forms/relogin.dtml === Call this from other methods to force user reauthentication before redirecting back to the calling script. (This script leaves traces before raising "Unauthorized" so that it recognizes the return after the authentication, and avoids repeating. At that point the cookie used to recognize the return is removed, enabling the process for the next invocation.) (Interim - the raise value only shows when the user login fails.) Refresh this page to get the login prompt. === Added File Products/TrackerBase/forms/searchFormComplex.dtml ===
Advanced Issues Search (details)
Title/Description (details)
value="" >
Stage
Requester
Supporter
Priority
Issue activity (details)
Since: CHECKED >
Until: CHECKED >
Access: CHECKED > Public
CHECKED > Private
Issue Traits:
=== Added File Products/TrackerBase/forms/searchFormSimple.dtml ===
Issues Search (details)
Title/Description (details)
value="" >
Stage
Requester
Supporter
Priority
=== Added File Products/TrackerBase/forms/setIssueState.dtml === ?manage_tabs_message= XXX We don't currently participate right in site findability! The following old call isn't right, but holds the place for when we get the right thing. !--#call "propertysheets.Findables.manage_changeProperties(REQUEST)" === Added File Products/TrackerBase/forms/standard_tracker_footer.dtml ===

(Re-login)
=== Added File Products/TrackerBase/forms/standard_tracker_header.dtml === === Added File Products/TrackerBase/forms/submitIssueForm.dtml ===

Service Contract Exhausted
      Please contact your tracker administrator for further info.

NOTE - You are using the Anonymous User account, which means you don't have a verified identity. Since the anonymous account is unregulated, the support staff cannot reliably identify who they're dealing with, so we will not be able to offer you the ability to post followups to your issue, or submit attachments with your request. To have these capabilities you must login.

Click here to login.








/addTrackerIssue" ENCTYPE="multipart/form-data" method="POST">
<!--#var meta_type-->   Issue Tracker

Submit a New Issue (details)
Subject: CHECKED> Confidential?
From: "> - Name:    Email:
(... anonymous can't post followups)

Traits:
:

Description:
Signature:
( Retain as personal default.)


 
 
From sidnei at x3ng.com.br Fri May 30 11:17:51 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks/doc/diagrams - Makefile:1.1 active.dia:1.1 active.eps:1.1 active.jpg:1.1 cyclic.dia:1.1 cyclic.eps:1.1 cyclic.jpg:1.1 cyclicref.dia:1.1 cyclicref.eps:1.1 cyclicref.jpg:1.1 inert.dia:1.1 inert.eps:1.1 inert.jpg:1.1 Message-ID: <200305301517.h4UFHpr20542@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks/doc/diagrams In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks/doc/diagrams Added Files: Makefile active.dia active.eps active.jpg cyclic.dia cyclic.eps cyclic.jpg cyclicref.dia cyclicref.eps cyclicref.jpg inert.dia inert.eps inert.jpg Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/Makefile === SCALE=75% all: active.jpg cyclic.jpg cyclicref.jpg inert.jpg %.jpg: %.eps convert -geometry $(SCALE) $*.eps $*.jpg === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/active.dia === ‹íZÝ“Ú6¿¿Âã›é“’eKvd¦i;}h'ižaëÀ­±¨-àî%{×à0„³ñå’š™cÆÒÞþ´f?~ëõÛw÷ËØØÈ4‹T26 Âæ»ÉÍÛ0oàožŠ¥I–_Í…Ö«7Ãáv»EñC&´JQ­Q&‡ŸE‹! ÍÉaì+…ùZµ*´N£ÙZK#K96g"øgžªuš¥T%¨X¥ÆFÄcóö®ø˜ÃJÍð@O7¬,ÔÄâA¦ÔÏ;(ceÑ,†E®¥¹w>5û[ÚÐ+ØüôçÆÀøKÚÜÝ%lQ86?àÃ?µ 4MW*û"T‰­T”èÒ°‹Æ”Y.rmÏ¡ÖÚxg6{ “‚"™Çrå–P¨F”3DZ|DIchËå4Pi"ÓÎÍ,°¶Q¨ǦŠ¸Dr‘o3¯…þ…Œæ }€"î4S¯åý‘Þ@-ÁA")Ýí‰Ì M\&ó¹J²Ü™ÜþFZ€w¿W¡¼-Ymíë®?üIØ;•è:Ð|½ù]Æ©£@ìnQ¤£¡æ‡ÀÈkr™µnk#F™Ï,†;pÛ&xE>«CÜOt¸ø´q4O–²þÇ’ÉzYb‘ QÊ/žÚÄõ3-S©r¥W6 ×ûL }MåõKÅh  qöáÙ"<]DŠªâ!çÇ OüráeSèhsK3¥b)’ò@w"Îd³Ò—-ÔvZ.fg1 .Öb¹Žu´ŠÛ›P.–$°+$×`…Äñ©E ŠlìvÌ YÅ9vGQ‡Rß"PûxSèËYa{3/a…ò±Gíi!AÞëg…Ÿ’»Xf 9/üX¬öå§qù!ˆ0̹EòÙ¾ûöì°g‡mcµË¦q áè%Åé áwO[`|Fø‹\É$”IðPC íÖ´"ßæŒC¿ãÚô)×e´Ð6˜Cq(m5`DIUìšóB•êÅ´°¨™gdýò ge ösdÛQðÜ^•F‡±}®Òž‹ùÓÿ÷œ3…©€ÐKSµí¨Ë¿¯Xv¯Â•$àáÙQý~Ü1" ó1 ­Š>ÎØíÖÜï#¥í[GÚ:G0ä¹FN—É! ¨;"ðÅ<Ïrñ;íÛYuY‹HrSþ÷“ƒßúñšóÎÁ­,`¤Nßöíá5‡ýä E`2(\Vþ¨³oû™Á«é+ lßq9¸¶ëaÒ-$NŽ%Žb2‚~‰{娜òæ/²\Öž²òŒ¨ƒØW[ÉÇiÿsdÛ½·Ó·‡ßq{ˆ»h?B…" !Uü•S…ã$á¶NÄFØ&ž•Oüx·ÓEé€QP˜BHq{4àˆqŸ»À‰ó%ÿõwD?ý»Vz”.T½²Q®¼$ýz¯Ö&ÒîÉé~jvÊûú¶¨SrÁ®“7xÌœÙÄé6qØÈÿ°9<î¹.P ŸØ2‹Ó&ž¶‘ÍÏ O¯¥¾Mè©@T€Rúl*P^¯ªOnÞeŸÜüçZ¢/ === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/active.eps === %!PS-Adobe-2.0 EPSF-2.0 %%Title: active.dia %%Creator: Dia v0.41 %%CreationDate: Sat May 29 14:42:38 1999 %%For: a user %%Magnification: 1.0000 %%Orientation: Portrait %%BoundingBox: 0 0 559 362 %%Pages: 1 %%BeginSetup %%EndSetup %%EndComments [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def /Times-Roman-latin1 /Times-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Italic-latin1 /Times-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Bold-latin1 /Times-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-BoldItalic-latin1 /Times-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Book-latin1 /AvantGarde-Book findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-BookOblique-latin1 /AvantGarde-BookOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Demi-latin1 /AvantGarde-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-DemiOblique-latin1 /AvantGarde-DemiOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Light-latin1 /Bookman-Light findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-LightItalic-latin1 /Bookman-LightItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Demi-latin1 /Bookman-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-DemiItalic-latin1 /Bookman-DemiItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-latin1 /Courier findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Oblique-latin1 /Courier-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Bold-latin1 /Courier-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-BoldOblique-latin1 /Courier-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-latin1 /Helvetica findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Oblique-latin1 /Helvetica-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Bold-latin1 /Helvetica-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-BoldOblique-latin1 /Helvetica-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-latin1 /Helvetica-Narrow findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Oblique-latin1 /Helvetica-Narrow-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Bold-latin1 /Helvetica-Narrow-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-BoldOblique-latin1 /Helvetica-Narrow-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Roman-latin1 /NewCenturySchoolbook-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Italic-latin1 /NewCenturySchoolbook-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Bold-latin1 /NewCenturySchoolbook-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-BoldItalic-latin1 /NewCenturySchoolbook-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Roman-latin1 /Palatino-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Italic-latin1 /Palatino-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Bold-latin1 /Palatino-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-BoldItalic-latin1 /Palatino-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Symbol-latin1 /Symbol findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfChancery-MediumItalic-latin1 /ZapfChancery-MediumItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfDingbats-latin1 /ZapfDingbats findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /cp {closepath} bind def /c {curveto} bind def /f {fill} bind def /a {arc} bind def /ef {eofill} bind def /ex {exch} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth pop} bind def /tr {translate} bind def /ellipsedict 8 dict def ellipsedict /mtrx matrix put /ellipse { ellipsedict begin /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc savematrix setmatrix end } def /colortogray { /rgbdata exch store rgbdata length 3 idiv /npixls exch store /rgbindx 0 store 0 1 npixls 1 sub { grays exch rgbdata rgbindx get 20 mul rgbdata rgbindx 1 add get 32 mul rgbdata rgbindx 2 add get 12 mul add add 64 idiv put /rgbindx rgbindx 3 add store } for grays 0 npixls getinterval } bind def /mergeprocs { dup length 3 -1 roll dup length dup 5 1 roll 3 -1 roll add array cvx dup 3 -1 roll 0 exch putinterval dup 4 2 roll putinterval } bind def /colorimage { pop pop {colortogray} mergeprocs image } bind def 28.346000 -28.346000 scale 16.363750 -12.670500 translate %%EndProlog 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n -5.600360 5.528430 m -5.600360 9.268430 l 0.326440 9.268430 l 0.326440 5.528430 l f 0.000000 0.000000 0.000000 srgb n -5.600360 5.528430 m -5.600360 9.268430 l 0.326440 9.268430 l 0.326440 5.528430 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (EditableCode) dup sw 2 div -2.636960 ex sub 6.668430 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n -5.100360 6.828430 m -0.173560 6.828430 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n -5.600360 7.328430 m 0.326440 7.328430 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (co_code) -5.100360 8.468430 m gs 1 -1 sc sh gr 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n -5.614930 10.820500 m -5.614930 12.620500 l 3.293390 12.620500 l 3.293390 10.820500 l f 0.000000 0.000000 0.000000 srgb n -5.614930 10.820500 m -5.614930 12.620500 l 3.293390 12.620500 l 3.293390 10.820500 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (Unfleshed CodeString) dup sw 2 div -1.160770 ex sub 11.960500 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n -5.114930 12.120500 m 2.793390 12.120500 l s 0.100000 slw [1.000000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -3.927675 8.813683 m -3.927675 9.963683 l -1.160770 9.963683 l -1.160770 10.820500 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -1.410770 10.020500 m -1.160770 10.820500 l -0.910770 10.020500 l s /Courier-latin1 ff 0.800000 scf sf 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n -6.850000 0.400000 m -6.850000 4.140000 l 1.306880 4.140000 l 1.306880 0.400000 l f 0.000000 0.000000 0.000000 srgb n -6.850000 0.400000 m -6.850000 4.140000 l 1.306880 4.140000 l 1.306880 0.400000 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (Fleshed CodeString) dup sw 2 div -2.771560 ex sub 1.540000 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n -6.350000 1.700000 m 0.806880 1.700000 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n -6.850000 2.200000 m 1.306880 2.200000 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (code) -6.350000 3.340000 m gs 1 -1 sc sh gr 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -5.294570 3.580100 m -5.294570 4.613683 l -2.636960 4.613683 l -2.636960 5.528430 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -2.886960 4.728430 m -2.636960 5.528430 l -2.386960 4.728430 l s /Courier-latin1 ff 0.800000 scf sf /Courier-latin1 ff 1.000000 scf sf 0.000000 0.000000 0.000000 srgb ("code.co_code") dup sw 2 div -12.021750 ex sub 0.777050 m gs 1 -1 sc sh gr 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -12.027675 0.762145 m -12.027675 2.270000 l -6.850000 2.270000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -7.650000 2.520000 m -6.850000 2.270000 l -7.650000 2.020000 l s /Courier-latin1 ff 0.800000 scf sf showpage === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/active.jpg === ÿØÿàJFIFÿþ6 Image generated by GNU Ghostscript (device=ppmraw) ÿÛC    $.' ",#(7),01444'9=82<.342ÿÀ ¤ÿÄÿÄP !1AV"QSUa“”•ÑÒ#27RTqt‘’¢²á6u³3BbÁ$5r¡±%Ccñ4sðÿÚ?ïr$1:äIy¶YAen8¢JR]ó3ØB4jÍ.käÄZ”7Þ4q„ÛO¥J4üìçQ4‹rã;%ØÍÈir"7JÈÔ‚=Ù-å‘쇌Yq¦°OÄÓí™,”“2ß´‡°*£ šLÉ‘ã©åihžu(5Ÿy9=§´·:„*‹Jv ¸ò›J´šØp–D}ì‘ï@S]”S¸­:¥!*Ò¹q–Ú8î±Üäð{3©Z<•·vD«‘%fŠÔ%%.šµ>GÝž ¾. 8ÿÀÙ•>¯S¬K‹K8±¡ÃY4ì™ -Å8朚R’4– )Éäúv “S©Ò¨U •Æ™qØÊ>+’%DO§JtàŒÌÈÍFeþǃ’®h4åT¥•9ÒGÂ; ”©&†÷«÷J"ÉãIgÈ$OªN“U‹M£›)RÙåOÉ}µ--´g„‘$Œ²¥zK“´©5¯J›u„0\š‰L¤Ð‡›5¬óƒ3ÒeŒdûý" Wœ©ñ;!§JŽ‡0¶!Ief£FÍ‹q*Á(öîI‘d·¶‡TMn‰¤†–ÑHl”m¬Œ¸Ëiã#ÛÒ,¼SëZ¤¶©Š‹ G •HÊÜS®¨’œ¤‰$gŒäòdc.ÊUiVôÉ•˜ì»-…šDB2KùÒ”`¶™”xò'¥ÜtÈRœtçÚlõȌ“i¬åJJÌÏY¥;q¤³´ldd¤’‹q–H|qÄ´ÒÜYá#R¼D5¨rîz½?²QUN†ÓÉ'#F}…­jFvÕ©:LË 'Œô‰jÕHð)Q›ŠÉÖ§$’¤,ÕÅ2dN)FYîR{³´Ì‹=#4L«SªØ©®$˜òŒÛ) 6mnã$“Aš²G…mÎÎðŽSk•i•¥¹,H«Tv—%…¸oºŸŒ{(%w9Û“#T›‰t›BmR¡“ÉUIÖŽ6²Á:§tž;œíÏ{n+¼eSù3ïÔ©µ”¤¢C1c:‡©DZ‘µZȲfe‚<—{Y¥uT­¹'ƒE2y>ê³IxÉã“=IG{¤eÁÝžvedeùïH$¥z‰(3 &Yø©N|¹p`uûö·wÜ4Ú´f¢ÒŸC_ñm,Ô­IÉm#ò™ÄpµôÛg̹í#…¯¦Û>eÏhq-}6Ùó.{Cˆáké¶Ï™sÚG _M¶|ËžÐâ8Zúm³æ\ö‡Â×ÓmŸ2ç´8Ž¾›lù—=¡ÄpµôÛg̹í#…¯¦Û>eÏhq-}6Ùó.{Cˆáké¶Ï™sÚG _M¶|ËžÐâ8Zúm³æ\ö‡Â×ÓmŸ2ç´8Ž¾›lù—=¡ÄpµôÛg̹í#…¯¦Û>eÏhq-}6Ùó.{Cˆáké¶Ï™sÚ"U$ð«J¥K¨=.ÛSQšSªJYs&I,ž6ÖÒª?[´i5ID‚~\T:á °! œ™dðBäQ;D¨üêEI1Ó%D¹¤´o4¥ã“…$Ò{ 8<7DÑḑM‹Z¨*YJÙ†QÄ¥’ÎÍ3Ql<™žÒQ*Ò¢&Ÿ2´K‡„¥km¼’Þ•¯Q§ºÜxIoèõ +îTcÔ©s ¦›âV•¶kiÖ¶™%H#-Æy###,ŸAˆðh5k®ÔçTÚ–râgˆ4 ’JQ¤ZÏOÆÛœçȨ•jT>CJª²Q’d¦GSËdºJ%§).Œäü¢ê+Oµ ?$ß|“…þ a »j‘S£ÃÍR¶íYÇ$-Ô:ãDƒm&yÓ°÷ÿØ*‰>JDºEM,5%fãÑd²o7¬÷©RM&}%œy|˜©2Ê‘RÔÈ3R·’ÒÊ:ã)&FÙ4‚3=†Dy3=¥ý÷hµI±Ñ }].B#N¾*>‡_I•jÔe…téIgÈBTŠÊã>¶SG©:H<Úm•}YQŒÕNk¥Ê=E¤:F•-æÒI"ÇI’ŒÄ(ÔJÝ2*¡SklœD§Lr™Þq’Û‚%Ó¨‹f5žÍæ$É »&,UNAT!,ÖÜÂ"#QŸÆJ’]ɤËa—±ƒ,Œ™¥N~£eR{ormFÓÙ6ÚÔej#RŒÔE’-¸,îÕC©Ã—5Ê=U¨ìK3qLI`Þ&<êZ;´àŒöšO%»2cÊ-¤i£Í¦Lžãí½%RY’4<Ó†­zµdòd­¥‚"",`ÈJä7 ñmf*ZJ‹S‰…ð«IwÌÖiÉô™'ê"`9í‰ò…ÂÛcÿlÇAR’„š”dI"É™ô×û|´ ñÛ=?moÚ.ãÌ-O&<†6\âÝ$(•¡x#ÒxÜx2ÙåÀg‚Éî1eǹQmøî¤:Ò‰IQwÈËxö<Opñ‹.<è­ÊˆûoÇpµ!Ö”JJ‹¾F[Ä:ÅE¢­ªU ÂS™4&CélÕŽöOÊ'´ëo²‡™Z\mi%!i<’ˆ÷Ìx®\f¥³ÇÛL‡‰Ji¥(‰K$ãQ‘tã%Ÿ¬{ š•Ï@£É(Õ:Õ>æ’Q7"B¬N Å¢‡[K¨–…)*I䌤‡œ¹q ErT·Ûb;e©nº¢JR]ó3Ü=ˆÈË%¸Q^ŸÁÏ°»úLEàëäâÝû_¤†Î[¨BK—Ý"YÑúšŽêJ¢O|ÿ“GN®ÿ@Ù=±>P¸Aûlí˜ÞªòÙ_þ•ÿàÇ.°*qŽÑ·â®Ä¨¿˜Í æòF µl"דVqÓœdzÐVœ¾iqDë÷£2·Ìɦ֦›Â–dFzKg‚3 „¹¯ÕæRü+…þ@¹‘^¦4¦ˆÖ‚<²¢QžÓÁ`Ë¿¸N²ï •ÁSS.ÕéØ\U:ë ´¸ò"/æšg¯y‘žÌcÊ),º¥ÍE´¬ç×&œºDÙ-ALT°®5)Y« 75c;3#:÷ ²˜¨UW«GˆÕ1Õ²Tém¸¹ÔÚŒ—…'b3Œ'ãyp,¼.«ÂD§­V`ƃ.¸ÝAn<ëˆ'8²4«¹-&E¨úzÁÁny±·ó°ù)äÅW”z]~Ø‘ZªGQŸV}åK[È'4‘-I&‹9ÂR’Ø^QçÿhE§ÚÖ”¶¦I¨O–—-d¶à6’%­I—ÅÉa;7žà›{WmØ•Ê}^‚TP,hÖ]ÔCMUö§0­m¨áñkNRxI“ƒéÁô`Oºî‹¡§.õÂr”TÚµðRc)Õ½­´¨Ò}ÑO~ߨ]Uª·L»ÍÊ M63mÓ˜nJaNµ-iÒDF[I}^Q]ó¸kTKR<‡±X'ÖûëhÖËHdÌ–dDffzpYé1sdV«õõúu˜e*™!¶R¨©2JÒ¦ÉZ¶™ïÉ:3izW>Âïé1ƒ¯“‹wì ~’8 n Â}Ò:l÷Tˆî‘LmÃ&ÏùVÆgÐ6@ÏlO”.~Ûûf7J¼Ø0iή¡-¨¬8Fßâ°DfXå½^µ­ûvŸHEÇ äÃa,“†á$Õ¤±œg`¡™Ò—¦ÚnèìÈ•T*«ZsâJR†xQw=;ò$Å™GTiè«p€Ü×äÆ\fÝhÛŒL%[Ô”£f¼ãº>ð‰JM=f N¯~Å©½¥µàšgI-:U¨Ë&½˜Þ{öxåiÇ·-ê9]qš4¦¤¥ÝI˦ƒQàË;3¨FR(ñçN:_mA§N¹DJqD¥ÿ‰¡ÅmNvŸÌePjßr«&eüj–‰±Û5¤hwŽ$’Q)G”¯IãVÓØ]á{lÖ­[jÚFnä„ú!µÅ“ªp’jÛ¿ÚbQiu²-®[¤Æ˜âv¥·ÚKŠ<šJÆ‘”Šežš5:56ñnJ £˜š——qÕ5‘ž •Ò[¶Ì Ú©µ†ëƒ5•QÛ³ÔâP¦Ò“ËdÚ bI*î¶tí {tT\Q+5ŽXª=3±PÚÛIв,üSß°ò};;Ãå)ª=-1 '„V×DŒ²6 ’[JÉ <¥ñwFE°¼¤XÝ"™Q¨?np‰—{ç%èªe§ÒNŸÆRuc{6 …n±H¦3N½âµQƒ9ÊÌ{C†ûËJ‰f¤çG¨÷nªI´ê1®†UuÄAW³Y’’|N„%6íÎœôoŒÖ-Vn·k¥rÂ5¹¸\WX"JÔ­YÏú± Ñë3-ª;]ˆw+¨~šä‚n«´¼L“†j4¸ÎLÔ•g,àÒ]ñ{Á]^$ÚÍÆïeÕ9Ù²¶^‚iÇÉ T¢l¾*s°‹ˆn—§ðEsì.þ“x:ù8·~À×é!³€Öê)lïÊBŒê¼aGwOžKþOõw†È5<%ÚÐ. Z…C‘JeD“9-šYàb÷tž,ȳ™KÑ$4ûJÚKid¢?êCD±>P¸Aûlí˜è BN•¡*.ò‹#KÀ5ø9,×à ä±ü_€ƒ’Çð ~KÀ5ø9,×à ä±ü_€ƒ’Çð ~KÀ5ø9,×à ä±ü_€ƒ’Çð ~KÀ5ø9,×à ä±ü_€ƒ’Çð ~KÀ5ø9,×à!õ 2Úµ!¤%]òI¦½?‚+Ÿawô˜‹Á×ÉÅ»ö¿I œ vV™-é5—"He…¶Üu–¨ëZ·)iéÀÇ’ÝiÌ‘"]¨nœRêt÷‰+TÃCDã?åJ{Ê.“&áÉš%U)ÆñN5­DÁàãt ¿×åH‰v©™DÅNž—8—ÔÁ™"7J¾¯(K‰v­5nIS§ ÜqOÖÁŸŸóþqŸ@Îd[©nÕN%Jm¸Ò žKdÌÚ^ÍF¿œG·ãÑ.Ãyój¥OKgÑ)ƒ3L®•Ÿú<ƒëqn’‘ܨÀ6J ¡ä“'•IÆÅ—y9èĉv!ÊiË©SÜBp¦’27<è4wˆ¶d†£rTâÁ‰Mx×-ÇÔÛŽvA…ÆÖ·P¦“.‘ÊaQësÖÛ¶:­W(Z—1Q¢©£ø¤IYï.“ÿ°Ø¬{.æ¯]·!Vni¥Åu¤Íä.i7–i<K°‹¼:5nõÖæô¿Ø9«w®·7¥þÁÍ[½u¹½/öjÝë­Íé°sVï]noKýƒš·zësz_ìÕ»×[›Òÿ`æ­ÞºÜÞ—û5nõÖæô¿Ø9«w®·7¥þÁÍ[½u¹½/öjÝë­Íé°sVï]noKýƒš·zësz_ìÕ»×[›Òÿ`æ­ÞºÜÞ—û5nõÖæô¿Ø9«w®·7¥þÁÍ[½u¹½/öjÝë­Íé°ª¹¸5r¯T”w}Äñ5ÅñNÊÊW„™àˆåÁ×ÉŽö¿HÙÀQ¦Í· ²ý\èñP}ZÜ}ÆÉJ3Æ2YÝ» ]‘A}b|¡pƒöØÿÛ1Ѐ:­VšõB{¼TVq­zMXÉ’KamÞd&¢½?‚+Ÿawô˜‹Á×ÉÅ»ö¿I œ=±>P¸Aûlí˜Ø¯zÔ‹zÍ©Õ"K-‘4kø©R”I#?!³ Õ«*º,ª\ÚÙÜiªFL­qæID÷ùTÖ”—rF{Hó°fK¸íIÖü¹×ÖªÊn¨î¶„% s&KdÒY",n<ä»ÃP¯*ã¯ðs6è~ã2‰*_ü«‹I¶†IâI •ZÈÒG‘e\ºëõ½léò+ñ•MäXŒSi|¡‡VÞܺá‘çQìÁcIwÇN¶jS*öÕ>¡P†påÈd–ìs#- é-»E¨ +Óø"¹öIˆ¼|œ[¿`kôÙÀsÛå „¶ÇþÙâ¥N‹V¦I§Íh‹%µ4ê¥&X1­Aàâ‹Å.Sõ ™òeElªMÒeµH-šr[22¡ðuF¡M‹)Ô&ª Ñ:IºˆÄ{ø´ã ñÌU5¹Øi 5gŒ&ú6ÿM¢Ægô¹U9SZU„SÆJbšeõn3RK¤Ëaã; 5;l0Ú[i¤’„– )"ÁAèŠôþ®}…ßÒb/_'ïØý$6pöÄùBáí±ÿ¶c¡ qÔ\ ¹#±‰'“Ù<¸Óî¿ÃÑœã§8 +Óø"¹öIˆ¼|œ[¿`kôÙÀs‰5Ùè­U¨,H-UK®4ìN0ÈÒœÓ?¬zv»Âg]iþ® íw„κÓý\AÚï u§ú¸†¾‹K„r¿—ÙؤéÁ$vK‘ƒ-_áéÎþœàl®ð™×Z«ˆ;]á3®´ÿWv»Âg]iþ® íw„κÓý\AÚï u§ú¸ƒµÞ:ëOõqk¼&uÖŸêâ×xLë­?ÕÄ®ð™×Z«ˆ;]á3®´ÿWv»Âg]iþ® íw„κÓý\AÚï u§ú¸ƒµÞ:ëOõqk¼&uÖŸêâ×xLë­?ÕÄ#δ8E¨À‘ MçLHmM¸’§‘e&X=¹µµHUÙ¦ÒVé:¨qÐɸE‚V’Æp-@jrZz5øõAšEEóìr’O¦A 2<“dž}ñ*%ÁVí9[RØL¨î:ò”êO“-9Âß5`·wÇÈ— ^BiFí±1ƒ˜µ¦A)ÔŸ$"Ü¥wóäǸ«G€ã–´Æ—"Z˜u u&qÛ-Ϋ¾GÞ-£áÜu‚lÕÚ¬Ìö@¢éãSþÿïÿÒ]íã)7]–ª nטò£IK,¥.¤ŽB{‰ïwŒ|rU!·Xp­¹N&Ä„”²WÆ4™îÓÓ‘&-rs÷c—Gq˜¼/žœ(̲i$ï<Ã=Âå§[yÚq'v¤žHfŠó¢•ÅgU©F]Ôˆê$y[Sÿr!Ì)—RÑfCºž£¥riôw¢9Q7p¦ŸIè&´täðy÷TUи?¥Çx”<ß)xÏy­Îèó÷Û€›¯²Á¼ëm‘îÖ¢,ýãϲ¾—δ;! éqüá{C²¾—δ;! éqüá{C²¾—δ;! éqüá{C²¾—δ~g­ÛÑÏ…Ç-”c’ͨ"R]'¾ 1ÕÝ­8ݼ·ùéd΂„’S.9¸ÄŒ»! éqüá{C²¾—δ;! éqüá{C²¾—δ;! éqüá{C²¾—δfÔ–3&^mÃ-úG¸z€æ<(ÓbV.«&›=®6$‰Î¡ÖõuŽùµævÃñzSÞøs;aøˆ½)ï|9°üD^”÷¾ÎØ~"/J{ßgl?¥=ï‡3¶ˆ‹Òž÷ÙÛÄEéO{â*¸²N¦Ü’¥™0–”…1Ç»…(ÌŒ•YØDeÛD®gl?¥=ï‡3¶ˆ‹Òž÷ÙÛÄEéO{áÌí‡â"ô§½ðævÃñzSÞøs;aøˆ½)ï|9°üD^”÷¾)lj%>Ýánç¦RØäðÛƒIkZ•ƒ33=ª31ÔÀsËûøöÁþ`ïöÇC•Vî©F¹Ÿ¢R­·ªŽÇŒÜ‡V™m²I%šˆ‹»ßñL[PêUZƒoª«B]$ÐdM¥r[{Œ#ÎO¸Ý/|yK¸”ÍÀý<É”Šj§·‡ $æ ›Éî3>“Ø&"³ê‘éOµQz)Êâ ³„’UÝ͆¢!?%œd…UºÝz<ÇPÊ™(Ó^†d¥gQ¶­&¯êÊëu*Õfš–…Sm¥,Õ’s[d¼‘tc8¹#ÜcH‘ §˜‘6…kÏ«Ó#­H\¶ÜCd³IáFÚTz–Eß"è1´Q+p.,jµ9î6$”êBŒ°{ðdeÐdddP°Éc=§³­ÛØe\g!å¼v­˜ã4iǤ[d³Œ€ç”–û¯ù|_÷! <¿¿læÿlt1̪MÔ\á^­ØûŠ=Ê—ZŸŽ‡xÎíÜjQcî1¼iY-Cª\‰¨F“TŽÄùÙKFÔež A«H‹?êÀ×'Òè”K‚ñ‹@}FÁZ-M%ÓZYžä™îÉíÞbÞLjCW½§QFÖ\‚u+2Y)ŒvíQ$Õ¬A%BÑ©³N‹Nqú›$\ß•%µçW‚,™íÙœ ´úE2-é:±S[58µIf•”¥!pþF…4EÒg·aLxíVáÙ×4÷V¶jO;KnRœQ´¢%²ÒW•c(Øg•toè´Z¬+‘©1i´è²iÒ•-URÎNd…žRZTJRK9,ämœÝvúx=€Âæņí2)36;‹JÊÐFJ5”ÈÏ=93%Ñ®jݯ¢Ë´»jdy/± yŽÔ—ÉÒÓ¯##N\"†’³u ºJÉsø#2Û´Åm" Q3­Ú­%ªd9²d¶§æ&´©.ÍC›\J›4àó´ÿÓÞ‡< ü·ÝËâÿ¸è`9åýü{`ÿ0wûc¡+:OIž6©@¨V¦rª—mM|’H'd>kV’ÜY6¼£äZ FP¢ÙVË1e†[|Éãv¢â°aƒQ‚Ó­D²­–y¥0â[|ÒKmG“Iá­¤}áë*“Y&‰6¾ãðÈŠ3Š–­Mt$ø½…äÜ žê¤·aÚÍêRTfÛæ“ÉHòMdŒŒHrÝœôÔÍrȶ).¤òŸÊ‰fzYâ·çnDõG¸—Ë5[rܬËQñØNžëàöìÙ· xRiušØ›F݃ÆãŒäòM±»8kh6Ü›R˜s'Xö¼‰'ŒºëÚ”ÔÚêp+•¨ÍǪZ–üÆ[=HmùF´¤ñŒ‘[0k©¤v!6¥¾TãNŽJR‹ÓÞÓÅ`ySiz2ÍtË>܆£A¶fÄ“AšLòe±­ÙÚ1§Ðêt™«›N³-¨²–FJy™…™ÓÚMtá“uL6o%(tÒF´¤òD¬m">’þƒòßuÿ/‹þã¡€æ)U!Ñn«"¥=Þ*$y®­ÅàÏIhïÑeÏ5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï! 5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¡Ï5‡ã²ó{¢žÄ®Ó®Nîz•*Gpc¥.i4äÈÌaíT;¿ÒJ¿,¨ˆÈç»’2ÿãÿ&cÀ·øH93¿ÂAɘð-þLÇoðrf< „ƒ“1à[ü$™ßá äÌxÿ &cÀ·øH93¿ÂAɘð-þLÇoðrf< „ƒ“1à[ü$™ßá!Ïíä¥6ÝIJI%Øø»±ß<¿¿læÿlt1A&÷¶bVI~³dß¨Ï 3Æ“Ql#ÏA˜Uïkjƒ90ªuˆÑä™›j33I0jÁ’ÛÓ|…¥Ä%hQ)*,’ˆòF]ñ ­Y¦Ð¡ʤƢÇ#Ó­ÃÆO¼E¼Ïaì!^Ýím;Dr²šÌ^Ƕ³mO)Zp¿›ƒÛ«ÉŒ˜÷¦]:Å2EJI‡¡ÇÏît“x,ž¢<lÛ´k¬p‡M­]ô*m¥\y\£•’Rz’Il”ƒ,àȳ¢î%émÏ­*¯ÙéR“ĤÏj“¼ˆñƒ2ï‹àòƒòßuÿ/‹þã¡€ç—÷ñíƒüÁß펆9 6d:] }«X¶&U*jª:¾NQ–¦¥šÔ‡ ÓN’"I–Ó=šD”ÔâÚ×-ݳoΚíIÒ~;ŒDSé’ÊIK¢,'G°öm•‡J›D²)Tê‚I™hÉh%êÑ•’sä#"þ‚ªü× ·k׈ôªu>S¼¥ ¶§Ù­Pæ„‘™é2?¼jÕ™0æO‡tÄ´¦&-Xœ˜gÉÙ†m©$÷e¨É 2Þ_PÆ·]Þ»ª³C¥Èb#Ô´EøfÔÂç:‡ Å ËWÄ#FL¶ç†5 ,\×%íÚÈ«f•69¼¸‹ŽM©L6ÖT’Üg°÷mtšDŠôJÚ¥hŸ„û.ª!ÑQ1”Ž£{I‘mÜ£5d·ŽòžP~[î¿åñÜt0òþþ=°˜;ý±ÐÀDŠ㯪«SlŒÍf”I2Jzv6[A—L)´Ú“õ¯¨ô<릿Šf“"Ï”Œ[€ç”–û¯ù|_÷ 7áC/kù/6Ë(žé©ÇIJKGIžá¸ö×nøú™éhö‡mvï©ž–hv×nøú™éhöŒº­ãidší/&“Æ©HÇõÚ*­{Ž•ߎÍB·o&JMzÊ „%ª3-%žö3åȸí®Ýñõ3ÒÑíÚíßS=-Ðí®Ýñõ3ÒÑíÚíßS=-Ðí®Ýñõ3ÒÑíÚíßS=-Ðí®Ýñõ3ÒÑíÚíßS=-Ðí®Ýñõ3ÒÑíÚíßS=-ѦZÓ"Ïážé‘CR8ˆœid¤™–zHt u›rp¡¤V)±¦¥£3lŸA+Ižü žm,ž«Ó<Á6–OUéž`ƒ›K'ªôÏ0C85²ÒÚ6½/Q™e‚ÆEe¹Áý³:†ÄŠ¥­A)Š5ë(h%µ±FEƒéÙŒùr-y´²z¯LóÚY=W¦y‚m,ž«Ó<Á6–OUéž`ƒ›K'ªôÏ0AÍ¥“Õzg˜ æÒÉê½3Ìsidõ^™æ9´²z¯LóÚY=W¦y‚tkVƒo8ë”zLXKt‰.)†É&¢-Äbܦ\-ò“-9Ævn5±tQ(vĨÓ"&ˆºJ–BF·Š>µ™§º"=Z³™ÆEû× ‡f4äÓ%ÈS_.)g¥“,’·mú‹hváBåG->3‘rüqKÿÕ»½Ñ¿È ^4)*„–¦šŽlUËcà–ZÚOÆVíŸQí"^tÇK(ógT×ÈþeÆiøÛËf<¸±{[òQmN5&¡!Q£²ÖâvnÙõž{[Êa/ÿƒTîÇ‘›+/‡ù»¼›÷yDúevXzkPdq«„ñ± N…—FÒ,ýd,ÉDFFFG¸È}æl2­Yi¯ãe%Ý}`l4ffm ÍE¤û’Ú]á÷‰k9â‘:s¤·w¾¡ð˜h´á¤’Áw%°»ÀL28i£âá%Üý@L2ZpÒ Iå=Él>ù G„ÚÕ¸>ª5‰,'•²h,´wYÙÓ‚1¢Í¼¢&Ú©\±SQLù”V[#Æ"›Ë=GúÉFyòé¶Mt.“NqJSÍGO¥LÖ{Uÿs1~>‘o2 ÖŸœ_xkOÎ/¼5§çÞÓó‹ï iùÅ÷†´üâûÃZ~q}á­?8¾ðÖŸœ_xkOÎ/¼b¾-hRi4¨°d}$?3Ò(³—Âs#²å.™¦¹GJË)e?“"ïžqýH~šÔŸœ_xkOÎ/¼5§çÞÓó‹ï iùÅ÷†´üâûÃZ~q}á­?8¾ðÖŸœ_xkOÎ/¼5§çÞˆúH}ËøE¥G¯p‰fÒ&©îG$¥q¨iÕ6jÒÞ¢ÚGäBÙ›?ÁT}`ï¼ÌÙþ £ë}àæfÏðUX;ï36‚¨úÁßx9™³üGÖûÁÌÍŸàª>°wÞflÿQõƒ¾ðs3gø*¬÷ƒ™›?ÁT}`ï¼ÌÙþ £ë}àæfÏðUX;ïHà6ÔM]Éf™¼J™J ¾Væ¢VO*Õœí,<‚o36‚¨úÁßx9™³üGÖûÁÌÍŸàª>°wÞflÿQõƒ¾ðs3gø*¬÷ƒ™›?ÁT}`ï¼ÌÙþ £ë}àæfÏðUX;ï36‚¨úÁßx9™³üGÖûÁÌÍŸàª>°wÞþ4™õútW^(ÑjŽ4Ñ-Õ(É$„`²g‘ú=ºþW¬OªgöŒt!WN®1R«Õ©Í´â\¦:Ûn©XÂh%–?¡ô°klN®Õi-´â]¦ñ©ŸÚ1І—k¼ÚoÛݵ8‚s•EV“Qgœw†¡t<§—~È…)imÉt¦S&3˜Â‰HJÉ*.’νÒ-™ E£_zìΙ!¥?:Uq·[–—>28œ‘s°ˆˆËA>¦oE®Í®OTÙ1ªéMfQ2äÈ%’x•Æ=‡¤ÏA™Üçi‰u;~RµÂ4ù.K'a! `™”ãIJÊ"TJÂL²{ ~wõ9ÕZõFGr$š¤r¡Gž¸íTŠuYI©kÞ²,Â2ÁžLFiUçmº}·9Ø´ù!ã™”NºÜrI©-)ä5k"FLl–M.… ¢¯Éa¨QL’û¦á±•8®,”{L¶çoΩÕ4îîµ¥‰sbÅT%¼¢"q´¤Ò¤ ÌþAyDºívœÌû„©õÃŒ·U%¶‰ZwšRˆó«$J$÷†žLE Ðí«Ž‹pL›YŸ%–Ü7d©âœN(¸Ô›yÁi,žRE;EÚTi|CºeÖg*³2¨×(io«‹RÎA±Å™à‰:r]=ȼ¯vVæ»®ÇM—=ºbÊì[/=«ã 2ÊM*<éQ©LËÿ¡*Kõ4T§Ð.NÅÔeH¢H[UI6^&ÒDF•§'‚5HÈðx=„*¨ôrãðwI7æ¢ ºT‰j[‰ãm²x3#ÉOqc zÎ7ûL®Ånd¦‰7j"¡Ä<¢ZãšN­å°Ä[£²¦Üðé ±¢;Jˆâé+w‰7$KZMFfG§'¿x¼ƒB…np¥o±J©Ër,¸\r+²ÖêII$8D£3-Yú»ƒ¨ ÇñÓüáßÐÞ€sÛ¯åzÄú¦hÇ@pÔ–ÔhN¥‘¥9ÆO½‘¡V¨ònõZÀ§Ëu„¸¹ÉÕŽöI92ÍÁ¨3EE»)ÈRT˜éž’I(”Gñwê"1)nW\¨*zìèÇ)Lctê)É·œéø»³´xDT€äeŲb4¨Ñ¹#&š‚{†rG »Ù"û„u¾ºEO²TþiÑæwFN¢rrYߎçý.[|m]UW8:¦®j×Æ)ÕMAêW|ËN3ý¡•dΠ}¦EÍD±/ÿPOÃ{Ÿ›°A©ÑdVbÄQ° Hf Ò¹éø4à‹xÎ0D=ž>E 47lH*¦$ˆ“ç#A`òXîwç¤cF¦Í·–âé$(jq…›SÒF¢#3,÷;v™Œ«P'Üm¶Ýbă0›< Ýœƒ4ýG§$3£Æ©Ð!.*Ç…:ÔjZžœ(Ϥû¢*€å¢séœÓãK22ã[œœ‘üw;? òr×KÕg¹ÁÍ5R_·9rrjÉ+V퇒#ÕzµéÉ›TàúŸ*JRIãW=92-Äx-¿ÔJ«C¨W!7§b@•¬qh\äwô÷;7á“E‘CnJ)– É”hžœ­=ã3,ãi´ªLÊ''ìuŽLn©ñ\f5’r[ô—Ü$*5Ml<¬˜†ÓÒŠc‰ì‚p§‰D­g³~RGýZü[ž©jáÚЩIŽ˜Ç!ùHu*l•«B’eµ'•h£¡Zw"ëVgÒ)ìFeÖÔÔ9¹SŠsI”¥â$ì/)÷Ç]â;§ùÿ¡½æ< U`Ñ8L²j)(¢—­ÕîN[ÁÜÈ^ó­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö:Ö/Yaþo`s­bõ–æö]J§U¸¦Ây/F~¬êÛq;”“B6ÿÙ === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclic.dia === ‹íZM“â6½Ï¯pyªrò˲½,lU6©Ê!©=lr¦„­%Â"²€™K~{Z¶çƒÁ°ŒI*1UXzÓOm«»_üô°Ö–©‚Ë|bcäÚŸ¦73N?ÀßBÑ•€¼0G{©õúÃh´Ûíx,¨– ¾AýE… #ìée½6QMÍX=JµV|¾ÑÌÊéŠMì9MÿX(¹É3»BÕ¸T ©¬-ûö¾|Ù£ÚÌhÏNÉ7j ,ÍúÈTMõý •µåŸ ÔjÃìWë“óßYª-ý¸†Éß~ùÙº³¾À¶_Î’k[<›Ø_Üý¿õ ,ÍÖ²xÕ°µä¹®s áðɵFçNÌçoí+X>Í‚=sŠ1AÄ#±¡$hÇÆ[ÍR©r¦ús©$ÙñL/Ý¢¢¢Qžt°¿d|±ÔÇ |µšêKZ¬Ž¯ž©„d9DfûÈÄPD \¹ÿ±¸t¯—¼˜ÑTóíAÍ¥ŒæÕ‚î©(X»rW,ånV '9J‘ÕŠbµš¯EwªÁJݵ“{¸«Ü PâÄ(éSí( Ç»»;Øk-fÎ|Ýœ:Oïácï/øŒÐûZ~ŠJÛ¢¡ Câ@x¸ƒàßEß öÚfˆcjoP{WU{?°5Ë3–§ ’Ïë*ù<ûö ñ1ñûT~%±a"( À4Ž‘ï™J— –·Ê¤ÒËYéJ+CaeäЧ2ý.hkam•Šïó©êz*Èÿß{Ö”) ±¦”Üõiæý‚¥ö"Š •y›"°8¨ÙO3֒晹omK˲+³^fÎ÷Ñ ¥¿kj È/Ã:4— ÇÔ- ñÇE‘ Ñ1bHºŸ•Žúxê#Ÿ†‚N0ØwAQø­DRß >Ùᇛ+eœ!Sý›2•ÛG¦ú žQ•AºúÕ42‡‰*蚨î qD‰8òúT0w"Iä•!h²Å#ìÇÞ°}¢ºæšïþÜH=6`õíšíàg¹„¢úoqß­à‘ý6Ü£éµÕ /‘&HÇ&\{îuî0T`CŸe³Ÿ8êSË÷ï– ×;,—ØýSBb(úW(úþ»‹~u\>Æ4½Ù{Îizó7™‰Y¾% === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclic.eps === %!PS-Adobe-2.0 EPSF-2.0 %%Title: cyclic.dia %%Creator: Dia v0.41 %%CreationDate: Sat May 29 14:24:05 1999 %%For: a user %%Magnification: 1.0000 %%Orientation: Portrait %%BoundingBox: 0 0 422 379 %%Pages: 1 %%BeginSetup %%EndSetup %%EndComments [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def /Times-Roman-latin1 /Times-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Italic-latin1 /Times-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Bold-latin1 /Times-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-BoldItalic-latin1 /Times-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Book-latin1 /AvantGarde-Book findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-BookOblique-latin1 /AvantGarde-BookOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Demi-latin1 /AvantGarde-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-DemiOblique-latin1 /AvantGarde-DemiOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Light-latin1 /Bookman-Light findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-LightItalic-latin1 /Bookman-LightItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Demi-latin1 /Bookman-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-DemiItalic-latin1 /Bookman-DemiItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-latin1 /Courier findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Oblique-latin1 /Courier-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Bold-latin1 /Courier-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-BoldOblique-latin1 /Courier-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-latin1 /Helvetica findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Oblique-latin1 /Helvetica-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Bold-latin1 /Helvetica-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-BoldOblique-latin1 /Helvetica-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-latin1 /Helvetica-Narrow findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Oblique-latin1 /Helvetica-Narrow-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Bold-latin1 /Helvetica-Narrow-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-BoldOblique-latin1 /Helvetica-Narrow-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Roman-latin1 /NewCenturySchoolbook-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Italic-latin1 /NewCenturySchoolbook-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Bold-latin1 /NewCenturySchoolbook-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-BoldItalic-latin1 /NewCenturySchoolbook-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Roman-latin1 /Palatino-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Italic-latin1 /Palatino-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Bold-latin1 /Palatino-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-BoldItalic-latin1 /Palatino-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Symbol-latin1 /Symbol findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfChancery-MediumItalic-latin1 /ZapfChancery-MediumItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfDingbats-latin1 /ZapfDingbats findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /cp {closepath} bind def /c {curveto} bind def /f {fill} bind def /a {arc} bind def /ef {eofill} bind def /ex {exch} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth pop} bind def /tr {translate} bind def /ellipsedict 8 dict def ellipsedict /mtrx matrix put /ellipse { ellipsedict begin /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc savematrix setmatrix end } def /colortogray { /rgbdata exch store rgbdata length 3 idiv /npixls exch store /rgbindx 0 store 0 1 npixls 1 sub { grays exch rgbdata rgbindx get 20 mul rgbdata rgbindx 1 add get 32 mul rgbdata rgbindx 2 add get 12 mul add add 64 idiv put /rgbindx rgbindx 3 add store } for grays 0 npixls getinterval } bind def /mergeprocs { dup length 3 -1 roll dup length dup 5 1 roll 3 -1 roll add array cvx dup 3 -1 roll 0 exch putinterval dup 4 2 roll putinterval } bind def /colorimage { pop pop {colortogray} mergeprocs image } bind def 28.346000 -28.346000 scale 2.697240 -14.066400 translate %%EndProlog 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 0.650000 4.150000 m 0.650000 7.890000 l 6.576800 7.890000 l 6.576800 4.150000 l f 0.000000 0.000000 0.000000 srgb n 0.650000 4.150000 m 0.650000 7.890000 l 6.576800 7.890000 l 6.576800 4.150000 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (EditableCode) dup sw 2 div 3.613400 ex sub 5.290000 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 1.150000 5.450000 m 6.076800 5.450000 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n 0.650000 5.950000 m 6.576800 5.950000 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (co_code) 1.150000 7.090000 m gs 1 -1 sc sh gr 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 4.900000 8.950000 m 4.900000 12.690000 l 10.051120 12.690000 l 10.051120 8.950000 l f 0.000000 0.000000 0.000000 srgb n 4.900000 8.950000 m 4.900000 12.690000 l 10.051120 12.690000 l 10.051120 8.950000 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (CodeString) dup sw 2 div 7.475560 ex sub 10.090000 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 5.400000 10.250000 m 9.551120 10.250000 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n 4.900000 10.750000 m 10.051120 10.750000 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (code) 5.400000 11.890000 m gs 1 -1 sc sh gr 0.100000 slw [1.000000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 2.834120 7.316350 m 2.834120 8.366350 l 7.475560 8.366350 l 7.475560 8.950000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 7.225560 8.150000 m 7.475560 8.950000 l 7.725560 8.150000 l s /Courier-latin1 ff 0.800000 scf sf 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 6.334120 12.066400 m 6.334120 13.216400 l 11.334100 13.216400 l 11.334100 1.566350 l 3.613400 1.566350 l 3.613400 4.150000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 3.363400 3.350000 m 3.613400 4.150000 l 3.863400 3.350000 l s /Courier-latin1 ff 0.800000 scf sf /Courier-latin1 ff 1.000000 scf sf 0.000000 0.000000 0.000000 srgb ("code") dup sw 2 div -0.779240 ex sub 2.250000 m gs 1 -1 sc sh gr 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -0.765880 2.516350 m -0.765880 6.020000 l 0.650000 6.020000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n -0.150000 6.270000 m 0.650000 6.020000 l -0.150000 5.770000 l s /Courier-latin1 ff 0.800000 scf sf showpage === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclic.jpg === === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclicref.dia === ‹íZMÛ6½ï¯´@O6MRßÙØ’è¡AIÏ-qm5´èR´½{éoÏHÔ~Ø–X²Ü •]¬ÈÙyiæñ å·ï–ÂÚp•§2ÛaûÝäæm’²7ð3WliA–Wc{¡õêÍh´Ýn‘xÌ™– ‰tr>ú‡ ÁF`4²'7–õÚAÂ4+ƪQ¦µJgkÍ­Œ-ùØž±øë\Éu–Øƪ²‹¥ÊÚ01¶oïË=ªÜŒvü”x£ÀÒ`\UPï_ ¬Mš§3ƒZ­¹ýj}röµ¥W0ùçÇ?¬¡õ †´ýr—°m¥ÉØþ„wW¼xš®dþlT™­dši˜‡ìGt0ŒP¸~øamŒ'qf³}Q°l.øõ*¨ˆÔ!ˆ†N0ú‡±¹àËi,UÆUçq–XÛ4Ñ‹ÃX™xBŠh+ÿ žÎú8€ƒ·™{ÍüÆr ’‚É·=›#žr¸Ìæ;v•¥™™Üþ–¤šAz ¿5‹¬¦^û®_üQØ{™é:Ðb¼2ù‹ ×iÌ^nQ¤ƒ‡Pó 0 Ûì–f]Ú†ˆØ´ Qàì¤m¼’Ðê_3.?퀘HçÙ’×?,ž­—‹ü Š™xÎÔ&©Ÿk®¸,R|¿LV6+ׇ\3}IæúZ5K ξ<›—§‡B³«ø(úï•'¾^y¦ù”Å:ÝÔÒLJÁYftÏDΛm}ùBn§f0?‰QŠ±F˵ÐéJ´Á ØL’¶²0B´Ú`è!Ò±*$l¨….r¼p0$ÈéZ^$È“„Ä#„þï5a¡?—÷[NÓ-š¦À¡Þ`è"Ü+Â^^Zör°ymFÈ/7Šh¯{5xm5ø+_ñ,áYüX# i[I ' žSô:¾Gº”„>òh‰ „y¡ÙòÚ\*½˜–ñ4Šò„©‡¼ï˜>oÚg™¶‘ÞE°R¥»U}j³=UíÇÿïœ5%ŠAÑ)%·•\ñû‚;ïEB,³ ²J1?ØŸf¬Ë’âE±--ËöÍz™­¹ßN/ÄN[Ž ùPE÷áN9"@.-F"¯ ‰…ÀŒ°RL»$‰£až0ùI6öQt¾1ÜòU<#ŸcÛîЕ¨'®Ÿ‰¸pÄõê>a*öúR´9‡¼å¶æ-äû4  > ¢>:$.hü ÂNY‹~Dü;aìVàÅÀÏŽóËßk©ïŠ^U¯ÌÈ5;Çr 좺ïIç':G“¯?Ñé´%òÚÓF`xra·=(ÓlkeSB›Ã×ë¸):ç [9xïäØüé¿¥4zUp…vÆ9[˜ëò{T“›/ZMn¾SžÇ?& === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclicref.eps === %!PS-Adobe-2.0 EPSF-2.0 %%Title: cyclicref.dia %%Creator: Dia v0.41 %%CreationDate: Sat May 29 14:23:49 1999 %%For: a user %%Magnification: 1.0000 %%Orientation: Portrait %%BoundingBox: 0 0 582 369 %%Pages: 1 %%BeginSetup %%EndSetup %%EndComments [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def /Times-Roman-latin1 /Times-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Italic-latin1 /Times-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Bold-latin1 /Times-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-BoldItalic-latin1 /Times-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Book-latin1 /AvantGarde-Book findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-BookOblique-latin1 /AvantGarde-BookOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Demi-latin1 /AvantGarde-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-DemiOblique-latin1 /AvantGarde-DemiOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Light-latin1 /Bookman-Light findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-LightItalic-latin1 /Bookman-LightItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Demi-latin1 /Bookman-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-DemiItalic-latin1 /Bookman-DemiItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-latin1 /Courier findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Oblique-latin1 /Courier-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Bold-latin1 /Courier-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-BoldOblique-latin1 /Courier-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-latin1 /Helvetica findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Oblique-latin1 /Helvetica-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Bold-latin1 /Helvetica-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-BoldOblique-latin1 /Helvetica-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-latin1 /Helvetica-Narrow findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Oblique-latin1 /Helvetica-Narrow-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Bold-latin1 /Helvetica-Narrow-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-BoldOblique-latin1 /Helvetica-Narrow-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Roman-latin1 /NewCenturySchoolbook-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Italic-latin1 /NewCenturySchoolbook-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Bold-latin1 /NewCenturySchoolbook-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-BoldItalic-latin1 /NewCenturySchoolbook-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Roman-latin1 /Palatino-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Italic-latin1 /Palatino-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Bold-latin1 /Palatino-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-BoldItalic-latin1 /Palatino-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Symbol-latin1 /Symbol findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfChancery-MediumItalic-latin1 /ZapfChancery-MediumItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfDingbats-latin1 /ZapfDingbats findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /cp {closepath} bind def /c {curveto} bind def /f {fill} bind def /a {arc} bind def /ef {eofill} bind def /ex {exch} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth pop} bind def /tr {translate} bind def /ellipsedict 8 dict def ellipsedict /mtrx matrix put /ellipse { ellipsedict begin /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc savematrix setmatrix end } def /colortogray { /rgbdata exch store rgbdata length 3 idiv /npixls exch store /rgbindx 0 store 0 1 npixls 1 sub { grays exch rgbdata rgbindx get 20 mul rgbdata rgbindx 1 add get 32 mul rgbdata rgbindx 2 add get 12 mul add add 64 idiv put /rgbindx rgbindx 3 add store } for grays 0 npixls getinterval } bind def /mergeprocs { dup length 3 -1 roll dup length dup 5 1 roll 3 -1 roll add array cvx dup 3 -1 roll 0 exch putinterval dup 4 2 roll putinterval } bind def /colorimage { pop pop {colortogray} mergeprocs image } bind def 28.346000 -28.346000 scale 2.679030 -0.048202 translate %%EndProlog 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 5.306920 -9.874680 m 5.306920 -6.134680 l 11.233720 -6.134680 l 11.233720 -9.874680 l f 0.000000 0.000000 0.000000 srgb n 5.306920 -9.874680 m 5.306920 -6.134680 l 11.233720 -6.134680 l 11.233720 -9.874680 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (EditableCode) dup sw 2 div 8.270320 ex sub -8.734680 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 5.806920 -8.574680 m 10.733720 -8.574680 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n 5.306920 -8.074680 m 11.233720 -8.074680 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (co_code) 5.806920 -6.934680 m gs 1 -1 sc sh gr 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 9.156900 -5.174680 m 9.156900 -1.434680 l 14.308020 -1.434680 l 14.308020 -5.174680 l f 0.000000 0.000000 0.000000 srgb n 9.156900 -5.174680 m 9.156900 -1.434680 l 14.308020 -1.434680 l 14.308020 -5.174680 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (CodeString) dup sw 2 div 11.732460 ex sub -4.034680 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 9.656900 -3.874680 m 13.808020 -3.874680 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n 9.156900 -3.374680 m 14.308020 -3.374680 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (code) 9.656900 -2.234680 m gs 1 -1 sc sh gr 0.100000 slw [1.000000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 7.371530 -6.651800 m 7.371530 -5.551800 l 11.732500 -5.551800 l 11.732500 -5.174680 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 11.482500 -5.974680 m 11.732500 -5.174680 l 11.982500 -5.974680 l s /Courier-latin1 ff 0.800000 scf sf 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 10.671500 -1.901800 m 10.671500 -0.801798 l 16.971500 -0.801798 l 16.971500 -12.101800 l 8.270320 -12.101800 l 8.270320 -9.874680 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 8.020320 -10.674680 m 8.270320 -9.874680 l 8.520320 -10.674680 l s /Courier-latin1 ff 0.800000 scf sf /Courier-latin1 ff 1.000000 scf sf 0.000000 0.000000 0.000000 srgb ("code.co_code") dup sw 2 div 1.662970 ex sub -11.948200 m gs 1 -1 sc sh gr 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 1.721530 -11.851800 m 1.721530 -3.304680 l 9.156900 -3.304680 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 8.356900 -3.054680 m 9.156900 -3.304680 l 8.356900 -3.554680 l s /Courier-latin1 ff 0.800000 scf sf showpage === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/cyclicref.jpg === ÿØÿàJFIFÿþ6 Image generated by GNU Ghostscript (device=ppmraw) ÿÛC    $.' ",#(7),01444'9=82<.342ÿÀ µÿÄÿÄP !1Q"ARVaÒ2B”•67CSUWbu‘’²³á#$35Tcqtv“Ñr%4¡±FÁðÿÚ?ß興ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‹¬îd±ú3/w@¿^³¥ˆ£rv<»Qš'?¬¯k*t³6«ÍB\WÞ"Ùï ¾Àö‡r•åíCŽ¡y´d’In9¼}x_3Ãyó-`$G™_Lns•¥5º³ž†JéèËC€#`BòA«pÖxË2$xŽ;/…ì†G° Ž¹ìØó^Ì–f–%Ð2Ôél8²bÒI!s³Z ÓæX¬6y™]Kz ×d–¼p5ί,B7ד‰Í- ´8n>W~ã’ôØÕ˜Š²L%’ÇEú9l6´Ž…ŽåÛ o-Æç~K1±Ï %‰í|ohsÓ¸p=„Ýb®j,u+ýAÒK5°Þ7AZÌö7Ì\>Õô¡Çd±²d+Øþkp’IcàáÀ#o>ëÍ[Uâ-:. älS?£†y`|qJíö¯p q>m?2Í"Àˬ0Ñ:}¦žh뻆i ­$±FwØ‚ö´ŽG·Ÿ%ÆÔÄÅ”±i‘Ó•­top;¿ˆnÐi'»m×Z9ÚìŠÑ¾X¬¹†FÃbÂ÷0m»ƒ^#˜æÆö§ÆPµb¬’X’jñ‰'ëI7BÒ Å­!¼;2øéÌ»m`¦½c"ËPG<Ím³ÂãkÈiò@Á}+j¼M› 2Oíæýf´‰}/hû;V^åu&?5¥k`¦Š(/Þ5í:F5Àƒ€æ K_Ì.þ 2Úƒ3¦lZÔRÇ-¦ÞšßZÐXÂØùÁý¼Õª""""""""""""""".ik€ ò ù× wXÐváÜ7r˜¯eøöPÞ¡mñ^œMÚñ¾pZcšÐ\Â8Nܶ;öî»^ãÔZ{/?<^@Ùi¯ÖˆØ8z@ÞȈó.¹ §Âx7ãkáîõÉãò×,lòâ2ÀC{|’wÛ’íw¦ÃêZ¹l\¨êb§X…¯‘ð<8¸¸Æ;?ÉÝÃr Fü—Ž„½{Yä­A·M·qì‚+r×{L®c¤æA7mÆÜ[o¿bðbj| „‡‘›PUž¬}Š¤nš9yq0²26wnÇcÏŸz®Óõ!Çiêu«EmÅÌŽÓ·” ÎÀóýÍ—ÇLçlgéObÎö-ÑNø„VÙÂç´NÂ?þ+JÛðlœWñöË-ÙuˆîÁì6FkƒAs @m¶Ør+œ€“?¦rQÐÅO­pŽÀ5ÍÀ×4¼z@84·wÛܹÊdNgüm\]Þ·`ÜÙkº6Õ'î…äp’ÃÌp“¹nñNÍö«çf7ËVhâcš×ú$ŽEKá³á°Qcoâ25ç§ÑEVK —a¶ì{AâÛ~{|×Öû,8àrqâ&êÔÜî’ IsxZðÀx]Â7å¾û8íÌl¾ÒY9¬Î5ÔêYd5^餷4.‡o$·£à8ñqvy+ÉFùÓÖrÕïã¯9òY’Üv+A%e¯$´nÐx\Ð8NÃÛ’ÃÈ·wDÜÇÖÇMRx2´hŸ#¤gNd kÜÞHØî7! ò+×n 7↬óê©ÞéXLÛÀöàKøFÄv‡†êåÌk‹Kš iÜn; 5`Ù ï°.Qö»T†Mkz ¶.¿TuyY4 ¸Í¹àx#—Ûn¶¥}Z×âºÝìcÚÈÞ28œ çÂcî›îºÓ­¬ðg\¿‹Ï7º8œ:Hþ`gq}×ÖÖB½q&CfK¦"'lkyš?/Ûظ’¶²5¦ä1Bc{Š"bv¯¢/ÛØ»[­¬2]Rþ-…ó°Ñé"qà‹ç‡÷¸ù¶]­×Õ®~[ª^Æ1¯c;¤‰Ç£w.#'xíÛeÚzú¬¾ßA{Öº“[\:7nÛ?9ÎïgpíF×Õ}b2ë¸Ó Xð#væ×™ãò=«ŠõõcfÇ›±®µ\Û¡‘8ÏÏ…Ìîofà®)×Õ­n+®^Æ<°Ëð‡G‡Hô}vÞ}×Jõµ‹a ,_źFÚs®DàÍk;í+—VÖ ¿‹é:ùy&'mÕ7äÏüý½‹™ëjóáü[^ëmuBè³+ïå5ýîÛ°ŽIn¶¯pËuKøƹŸt‘8ômùÝ'yîÙv·_U¹Ù©{ƾ¼b—I¼¸ËûÚyí²åÕõ_O)mÜhˆÐàŒݸ··Ë?‘¿›µu‚¾­Õ3ÞÆ:1H¶ÀlNÖväæ÷3³—jâµm\ÓŠë7ñŽ ŽAà‰Ã¤yɘû€;oºâ¥m^ÖbúÝü[ÜÉžrN$4GÜGŸuÖ*ÚÈG_¥Èb‹Åç:bسªüÖËíçع–¶±5¬²¡1¼ tNØUó´þ_·±sf¶°tY!Zþ-¯}†š%ñ8ˆáùÁýîîÙ{°—2–ÍæäêA_¡°c€Å/Iìqî>Å–DDDDDDSZ¸Â&ÁtÒdØNJ.¢7Þa/÷}ê•b¬i¼5«ž|t2K!ÝÏ#™+µ];ˆ¥e–+cáŠfskÚ92É¢""""".aSº™¡¥á®q2b¶’CÕd›¥-ÝÇŸ·µQ¢""""""""""šÒtºœù³ðD˜þšûäâ|ý'XßîƒÑ¹R¢""""")ÍWaµæÂemÐé2106¼EâÆÿs¢Óç*°©½ Uô¬ÃFý& $= ÷ñJ<£Ìžãæö*TDDDDDDDDDDS:F¡Ÿ8b£«Ç{œn?ˆJ}(û™Ü©‘Õ&†[ér1ÇÂaé:ÎÿrŽýꉰ©½a:V€äÌ}$›|&–ùG·ÙÝìT¨ˆˆˆˆˆˆˆˆˆˆ¦´œ‘¾|ßFü«¸o¼;áHû¯ÈîT¨ˆˆˆˆˆŠSÙuy°Á·èTé2°‹qq™Aù‘÷<ùŠ DDDDD! DDE ŸÏd°ž´ýyl‘„ÊC%cÙ³Žm;öîyÕ6ÍO‘tzC …ÌÞ³g#~GÏjä!²õxÉ㧰y‡ø-ºˆˆˆˆˆˆˆˆˆˆŠoJXdóæƒ2—op_{Hµ`€ú ßµ£½R"""""")ýOÓô¸n„b¶ëññü!ÛÃç迼îTˆˆˆˆˆˆˆ |/ãeµ¡ß’¨?žâ'Žô$vŽåðOèR^ ¤·ªõ¥ýGw"ü”xúŒ©^ËãàÝÏòÜ6ös u¢""""""""""›Ò—:ÜÙ¡ðÑÉtWÞÎVÛî~Ý»Õ"""""""ŸÔõåž\1Ž… }øÞãmü& >|}ï`¨¥ÄÁ¬5nwSÚÎ|mzIjÅi²@.d…˜ø“­¿~­ÞO‰:Ûñ‘gêØýäø“­¿~­ÞO‰:Ûñ‘gêØýäø“­¿~­ÞO‰:Ûñ‘gêØýåó³ uºÒÖŸÂ-‰!•…aÆdzšFÄ|¥„Ò õVžÂujzÎL`|¯{àŽ‹$ï°(ä ãœD»wìßšáø9b¦R¥»º®Ô) ³9–Œ½!–?œˈlómËeï£WO×’Ä÷¬jœ¥©*:œV.ёί Ú0;ó$W{0àžÜcèÚÕXÛxúm¢ÛU(È,-f¼:2ÓÌoÙÚJí~¾–ÉéøñWbÔ“IÝe·9Å>ßÒò>À6ä9.1qá)ejär5Vfjm-¨2$s`'‘sCcVÜ·;•ä¹ŠÓ–² £µ«*ÒÉJ%¹¯JVÁ1óî:=ÇÜö#uõÈPÓVîÏ='ê\\6k²µªÔqÏdsÆÐZŒ‘ä’7r]OO3‡¯J}SFÎ&Z µ¨È%tGµ®Þ2ÒÀöv…S¤®ã¡â¡]Ù›¦qškY²5Ò;`7.- € »¿[}‚jͶ?våðð}ö¼Óÿäbý•HˆˆˆˆˆˆŠwKSê“fOÁãú[Ïv:^±¿Ý¢Or¢DDDDDDSZ¶h¢›%½’«Ç’‰­A"SèIùΩQºðk,q嵸|iøz~Ó²Øf¿GúÁ:Ì~õ‚u˜>ýëë0}ú?Ö Ö`ûô¬¬Á÷èÿX'YƒïÑþ°N³ߣý`f¿GúÁ:Ì~õ‚u˜>ýëë0}ú?Ö Ö`ûô¬¬Á÷èÿX,µ± к€ £$ã¬l‡Þܺx>û^iÿò1~ʤDDDDDDE7¤ê6¬ù¢ÜEœK}ï.š^>°OÝÜr¤DDDDDDSz²äu&Á‰31Ý.F(ÚØb/ë$ýÉÝÀ÷ªDDDDE¦t¦ƒÓº¯Pë+YŠrO4Y¹£c›bHönûö5À*ŸZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßOZð\ßM›ßXSà—Fãô–fíllÌž½)¥! ÆäÇg5„ƒ±vǘUþ¾×šüŒ_²©Lé™ùÂÚù8x²$ÞyÁS"""""")ÝSuôæ†eáÇôÙã-–>°ÜÛËÉ'½Q""""-{àËú×[þl$DDEŠÀg"ÏÓ±f(_`·5RA$ÆòÂÀ첨ˆˆ°ZÛìP~m±û·/‡ƒïµæŸÿ#ìªDDDDDDDS:FXdŸ8"µ“œ· ðñy»F.öw*dDDDDDE?©æš)°ÝÜm`ûñµâëw2F>çŸ2 DDDDZ÷Á—õ®·üÿ:ËxJ»j†„¿=KVwL’Ä;ñäh{ÁÁ $ïæÙEêŠ8m#C#>—ÎZ«v|p/§ΔúF‡Øç¹kš×;c¸ìöë­K§5F–ø§’šwäœYv!aÓ‹ø ºwƒ¿ áò†ß(­ª´û1ølÝMG˜Ôy«42tr’±–ºw±ôccÇF#a;l[±ì;ñ•ò†¦:íW“ÔyË1äqö^Êò:Ë¡u8ZŠF3ò¹;°î|ÉFŽ™¼%}ebÌ@`j8xÝ]²Ì÷Èó¶ÞSGÛò–•ÉáÐœ^>wÝ¥‘Îܯ+ä·ÕÝj0^[Å1‡ˆ¿-ÏgXx<©–ÇjÌ­N‚µ1¬ÉF><\0ÌNÜAÄnÐàËضj""Áko°MAù¶Çîܾ¾×šüŒ_²©Mi+L³>l3-nÿG}ì-±€ýí½íê•Oj˜ä|Ø^˜·pä#.ëîß÷Ê…kß_ÖºßóüêöÅxmÖ’µ˜™,´±ñ¼n×ÚX¼n’ÓØx¬ÇŽÃRªË,à±B‘½Ç¼s+åOKc0Í&šÅc([”¹ýÁÍ°ðìWׇS}÷ÿžòóätÞ”vV®S‹øAò02Äìhs¤${O.Kï{HiÜ–Ld®áhغ HžHCŸ»{9ûÛ1¦ðº€Eð¾.¥Þ‡~§ˆ;‡~Ý·\?LàäÄ?ìM3{ÌŽ¬bq;“·~ü×Û„Åચ¸šé@çq˜à`h'¿’÷¢",¶ûÔ›l~íËáàûíy§ÿÈÅû*‘Þ”ºû“æƒóäzïŒ5•ú.®ÜϤGz¤DDDDDDSº¦»§› [‹©{£ÈFòlÊ`þñœü§0THˆˆˆ‹^ø2þµÖÿŸç[ 欮ë˧‚ün=faCùmçÍÃÌ""""Áko°MAù¶Çîܾ¾×šüŒ_²©OiyäšlÀ“!Ž·Áyíh¦ÀÓô$ÛµãÎU """"""œÕU ©°‡àS“è²1IÄ'èú¶ßuü­»¼êkÙ¼…r7¨êÌö?¯Ù}™a«+ZÎ7ÏÍO7½Õ?Ioºž,ozÿª~’ßuÇ2Og†»ÎÍx¼<¼£Ï°.­0ì’ËûU¨‹ò7ôDn6åÌíó{QºÓù+ÆcŠz' Ïæïþ„ ÷<¹¾oj殳ÃÛ›O±Å’ö+ñWxÝŒž.^IåØWJZß |âIJ~|Œ­Å]íܳåqn<Ÿ÷í\A®°–+Óž7Ùà·pÒ‹zÏÊ;wåÈ{O%á[;‰Ëø;¿,Xhdêïݶcò¹rìØ+±au·£á§tÎ5Ò›+puæº75¡O‘³†ãÍÜ·tq¶(™ ÐÖævDDDDDE9¥a|3fK±´iqÞ{«(y˜zoØòqîThˆˆˆˆˆŠkVô=6 ¦øW„¢àø<ì8¼Ý/÷}ê•q°î °î °î °î ORøCÀél¬xÜ€¸ûRCÓW¬é|öß—´,OŽ=/ý›1õtŸôž8ô¿ölÇÕÒÒxãÒÿÙ³WIÿIãKÿfÌ}]'ý'Ž=/ý›1õtŸôºËáJM â’¦]Ìx-p8é9ƒÈù–¡ðsÇéýmfÞPäæ¡ŽŽXq¬mG¼±¯~üÆÞO/þÖáñ˦?³æ~®“þ“Ç.˜þÏ™úºOúOºcû>gêé?é¡Ã2L\Õ*2WB8@sÌÏžþ~í†|µ-4°a²Œ¡z­º8Ç“-ˆkFæqy$·-q ß–áR×£vÓõí¦Ò°Öe+DêìØ˽P6¼_â¹Äb2ç´TÒÓ•±ÓÀɇòŠBØviî>K¿ASöñYLuZ÷Ž-Óº®­³tS; '…Åà:&Ÿ”@wŚҗݓ𣟶ìU¬o2®ÑZcY+ö|ƒ‰À·w3¾À-ˆµïÏ°û¿­þÚØHˆˆ¦ôˆçŸ4s#c‚ûÚáuœ"3èÇÞÎâ©þ§{™.†|\\YÁëàÿd[ýÓ¹P"""""""".7í¸ß¹rµëþßñ§Ýûà®î×uºrÀËWsÆÂXHg´nXŠvýkÎÿɸŸíú×ÿ’?q>)Ûõ¯;ÿ$~â|S·ë^wþHýÄø§oÖ¼ïü‘û‰ñNß­yßù#÷â¿Zó¿òGî'Å;~µçäÜOŠvýkÎÿɸ¼9OPæ¡Š,Ž¡ÍNØdDLÌk£xìs\?àWl/ƒº¸”—êfóžg4Îéçl†`ÞƹÎi${7VK^øû»ùÚßí­„ˆˆŠsJÚë3f‡ÃRäº;ïg t}[û±éÞ¨Ñæ¯e–Ö£r ULƒ)Úm‰›;xŸ¹/ˆyäeÍ}aVÌ´ãn;$Ój›®4¾±oÍwsùv.*ë¶þ áÇdÙð“ds8ëÑpo¿Ièï·.õÖ®³«n<[ÛÊ0d'| ªAŒ·ÎÿE§ÌWëZ²2 nPt·Í Rpù繟”’ëZ‘Wµ1Æå¯u´ÜÖÕ$¹Çç´yÙí\ÚÖujÇ”{±¹GŒ|Ì…á•I2vz@yÊísXÕ¤ü›_ŽÉ¼ãâŽW˜ë öØ3Ò#~cÌ»K««EbÔ'’&µ&ÜqmbCšFü >wûšº³ß ?":Zø&¹Ø4|ÃÜþ_%*jê×&ÅÆÜ~I‡#æa’±0Ýù?Ñ'nAu§¬jÜø'‡“gÂn{cé+ÑpöôžŽûr\VÖUmCJFã²lî:›CëXáóÜÏjëñÖ§V3ü”Ø_xz©ß‹ÓÛÐü¥ÚÖ²«R+ïv;&ñNÛj82±%îwÎg{}«µ½aV¡Ëqc²Oø3£é::Äô¼dÑú[oϹsgWÖ­6F7còO4+2ËË+$ÛÉg¤î|Âáú«'1~H‘øCqXíÃèçù*KPãèj¬Ö>ýk:—“ŸlEb³\Ö1Üð=½Ý¼¼û©7øCÖzFl¶îVËRºÇ¾1€Ô„‚æíË}÷Xêò:Âu\ΟÓsX¶ìa¨ú²IÈ(_ÄÉì»VÉøÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X„øÉá+Ôz_X…ÓÀ«¤~‡°é˜#•Ù;%ìp×qs­ŒˆˆŠwK[u©³!ÙŠùŠóØ =W{w¤Gz¢DDDDDDDDDDDDDDDQú§Mj\þMŒ£ªdÄâz0$Š´#¦s¹ïåù†Û/.+Á”ÇÎ-Z«6Vçi±‘”ÌâÀòÿáxâ¯_0C^ቺyÁ¬¡ ,<ÁldDDDDDE¯|}‡ÝüíoöÖÂDDE=¥åt³f¬ã&á¼ðp–é;ßÞU """"""""""""""""ׯûÅþŸwï‚¿šVA “Jîãispr¡±úë5{àìÅy¾ÈIØ¥/š6ö‘ñðù,å¾ûöWž? 'Pn “M½šXËÂnôûÌ#ìéº.‘¿·}¹ìš‹[eä›=K §]‘¡‡‚Ý¡?Fà÷7rØÚ[åµÀžcÿ¥âÁk+Tt®œÄb)V½}˜šÓY6î6´q5Ñù>Q¹Î ö^rž‘Õ5uv ¹Ѻ'²GAbÌR·å7qÈŽ|ˆíÝg‘½ð9öwóµ¿Û[ ö˜ŽhæÌtÕ±p‡^ya w/òþ_z¡DDDDDDDDDDDDDDDDZõÿoø¿ÓîýðWÖ ešÒÁ&ü°±ÛvìFÅBatÖ³ÇSÇ`¤ËccÂÒO lÍIጇî6Ž{õàƒBj³FÎWñhHYÒÆÇu£[}Ä\Ç=ƒ‹·e¦õ=[ùÖiûøè±ù !¶e¯!gœÀÎÜö÷,;üä+;Ãîþv·ûka"""žÒõ%«6`ÉŠ©C¥¼÷µÕäã3¾?¹Ç¹P¢"""""""""""""""-zÿ·ü_é÷~ø-„ˆ±®½xj&Pך&¿Jnñƒø¶àáíìçºÉ""""-{àsì>ïçk¶¶"")Í)E”¦ÍaŸé¯¾BçÏÒu’~è9ù ÷*4DDDDDDDDDDDDDDDE«u=ûºwÂì¶àòy‡kJýždâçþÁ{üjIêV¦úñO’z•©¾‡üSƤž¥jo¡ÿŠvºÚ¡™³¢5_Xm^¬О-þG>Õ•ñ©'©Z›èÅi- \kXlyšM™×Ä‘8ÖäÚÞxÈó»Ú»Z¡«HVÌRòXc©VÜCùMw¤Ozö`±y dÙ{)-æX²e€I÷<ì}–aÿÙ === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/inert.dia === ‹íZ[â6~Ÿ_e¤>±sgYX©ÛJ}hµÛ}F&ñ€[cSÇÀÌKûžØÌ I&³ÛŠH ||8ŸOr.Ÿ“¼ÿp»Þ†é’+9ö Âþ‡ÉÕû‚Ówð™kºô@A–Õhì/ŒY½ ¶Û-w%5J#Áרdƒ©tJråyû jh%ÛI©1šÏÖ†y’.ÙØŸÑüï¹VkYøNk§—+¡´·¡bì_ßØÃìÌ ìX¼A  5#èÓ;¨Ÿ¡¼ /ùL€Ðè5ó÷Ö§f±Üxæn“_þøÝë{Ÿ@düdz„}cÿ>\ñSÏÀÒt¥Ê¥ÚJqiœc1öú Êî=«õí¬ýÙì©y «§r.Ø=D[ŒxDÊÒ$ëõC„I3H&Ørš+-™îÌ-‹±å…Y»FÅB´±¿`|¾0§B”FÍÌv{d7WK:.¬žèœ°TÂPÎôvšnfrýkÁ …(þ¨ ví¹›Ú·]¿ø“°7Jš:ÐJ¾Sù‰ 3<§§¨ ÒÑE¨¹x?Œš€f`]¸f(K¨×Q’´Ã²5«m¿˜a{´¢‚Ïå’Õ_(&×K‡Ež‰â&¢´IØ—†i¦ªð~ü."›¥êmi¨yM‹nüVù™+(–—Ôlžš Šªv•ýÏò¿]^òrJsÃ7GI4SJ0*Ý‚n¨(Y³~W.Ôvê„åY K´A,×Âð•hï‚:†×Œò‘¶”/±|Œ  îôH…ŽÐ?œ…=Œ’. _[§žCù24O‚9iÊXß’ò}‘7‚• Vxéûl¥—þÒ´¿À–(ÄQÐëcDÈ…û]¸ßë%ê%)[$eÜ#]XßžõµÀø´ï¶b²`2¿«á~A[î—…ÁôÚÑÄi4ì¦Ç)BQ G$@$v}®ám-¥Íbj}iäáUXÚ7Tºô T[0ìÊS¥ùa>Ÿë®çòüôÿ^²¦BSH7­Õ¶£-VõýŠ­öUA®¤„°†,zöýŒ· ²¨nãß3ÊnмÇÙšó}dô9Åá3äVAuâÏŠ׆°mm€¸ ¢(ìõS¤;,PâaCêe“8ŽB@™°àVðãoƒ~úg­Ì¨º¹æ~½%Ûú¨ÖPt÷\‹tδNÝeÔ)•ˆÚ—‹ cwå’ éã¼g•   ¡…Ê` P£¥qÅ,pÖ%•8íáÝ ÃsŠöÉä¡Ò÷¢—ößEûLJí?|qûwcûÖÀäêൂÉÕWxÙ;å-! === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/inert.eps === %!PS-Adobe-2.0 EPSF-2.0 %%Title: /home/mwh21/src/python/bytecodehacks/doc/diagrams/inert.dia %%Creator: Dia v0.41 %%CreationDate: Sat May 29 14:43:39 1999 %%For: a user %%Magnification: 1.0000 %%Orientation: Portrait %%BoundingBox: 0 0 465 247 %%Pages: 1 %%BeginSetup %%EndSetup %%EndComments [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def /Times-Roman-latin1 /Times-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Italic-latin1 /Times-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-Bold-latin1 /Times-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Times-BoldItalic-latin1 /Times-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Book-latin1 /AvantGarde-Book findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-BookOblique-latin1 /AvantGarde-BookOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-Demi-latin1 /AvantGarde-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /AvantGarde-DemiOblique-latin1 /AvantGarde-DemiOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Light-latin1 /Bookman-Light findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-LightItalic-latin1 /Bookman-LightItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-Demi-latin1 /Bookman-Demi findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Bookman-DemiItalic-latin1 /Bookman-DemiItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-latin1 /Courier findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Oblique-latin1 /Courier-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-Bold-latin1 /Courier-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Courier-BoldOblique-latin1 /Courier-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-latin1 /Helvetica findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Oblique-latin1 /Helvetica-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Bold-latin1 /Helvetica-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-BoldOblique-latin1 /Helvetica-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-latin1 /Helvetica-Narrow findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Oblique-latin1 /Helvetica-Narrow-Oblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-Bold-latin1 /Helvetica-Narrow-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Helvetica-Narrow-BoldOblique-latin1 /Helvetica-Narrow-BoldOblique findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Roman-latin1 /NewCenturySchoolbook-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Italic-latin1 /NewCenturySchoolbook-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-Bold-latin1 /NewCenturySchoolbook-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /NewCenturySchoolbook-BoldItalic-latin1 /NewCenturySchoolbook-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Roman-latin1 /Palatino-Roman findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Italic-latin1 /Palatino-Italic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-Bold-latin1 /Palatino-Bold findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Palatino-BoldItalic-latin1 /Palatino-BoldItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /Symbol-latin1 /Symbol findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfChancery-MediumItalic-latin1 /ZapfChancery-MediumItalic findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /ZapfDingbats-latin1 /ZapfDingbats findfont dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding isolatin1encoding def currentdict end definefont pop /cp {closepath} bind def /c {curveto} bind def /f {fill} bind def /a {arc} bind def /ef {eofill} bind def /ex {exch} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth pop} bind def /tr {translate} bind def /ellipsedict 8 dict def ellipsedict /mtrx matrix put /ellipse { ellipsedict begin /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc savematrix setmatrix end } def /colortogray { /rgbdata exch store rgbdata length 3 idiv /npixls exch store /rgbindx 0 store 0 1 npixls 1 sub { grays exch rgbdata rgbindx get 20 mul rgbdata rgbindx 1 add get 32 mul rgbdata rgbindx 2 add get 12 mul add add 64 idiv put /rgbindx rgbindx 3 add store } for grays 0 npixls getinterval } bind def /mergeprocs { dup length 3 -1 roll dup length dup 5 1 roll 3 -1 roll add array cvx dup 3 -1 roll 0 exch putinterval dup 4 2 roll putinterval } bind def /colorimage { pop pop {colortogray} mergeprocs image } bind def 28.346000 -28.346000 scale 0.593570 -0.600000 translate %%EndProlog 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 5.900000 -6.800000 m 5.900000 -3.060000 l 11.826800 -3.060000 l 11.826800 -6.800000 l f 0.000000 0.000000 0.000000 srgb n 5.900000 -6.800000 m 5.900000 -3.060000 l 11.826800 -3.060000 l 11.826800 -6.800000 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (EditableCode) dup sw 2 div 8.863400 ex sub -5.660000 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 6.400000 -5.500000 m 11.326800 -5.500000 l s 0.100000 slw 0.000000 0.000000 0.000000 srgb n 5.900000 -5.000000 m 11.826800 -5.000000 l s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (co_code) 6.400000 -3.860000 m gs 1 -1 sc sh gr 0.100000 slw [] 0 sd 1.000000 1.000000 1.000000 srgb n 6.850000 -1.250000 m 6.850000 0.550000 l 15.758320 0.550000 l 15.758320 -1.250000 l f 0.000000 0.000000 0.000000 srgb n 6.850000 -1.250000 m 6.850000 0.550000 l 15.758320 0.550000 l 15.758320 -1.250000 l cp s /Helvetica-latin1 ff 0.800000 scf sf 0.000000 0.000000 0.000000 srgb (Unfleshed CodeString) dup sw 2 div 11.304160 ex sub -0.110000 m gs 1 -1 sc sh gr 0.050000 slw 0.000000 0.000000 0.000000 srgb n 7.350000 0.050000 m 15.258320 0.050000 l s 0.100000 slw [1.000000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 7.900968 -3.574900 m 7.900968 -2.174900 l 11.304160 -2.174900 l 11.304160 -1.250000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 11.054160 -2.050000 m 11.304160 -1.250000 l 11.554160 -2.050000 l s /Courier-latin1 ff 0.800000 scf sf /Courier-latin1 ff 1.000000 scf sf 0.000000 0.000000 0.000000 srgb ("code") dup sw 2 div 1.324430 ex sub -7.272030 m gs 1 -1 sc sh gr 0.100000 slw [0.400000] 0 sd [0.400000] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 1.283530 -7.262010 m 1.283530 -4.930000 l 5.900000 -4.930000 l s 0.100000 slw [] 0 sd 0 slj 0 slc 0.000000 0.000000 0.000000 srgb n 5.100000 -4.680000 m 5.900000 -4.930000 l 5.100000 -5.180000 l s /Courier-latin1 ff 0.800000 scf sf showpage === Added File Products/PythonMethod/zbytecodehacks/doc/diagrams/inert.jpg === ÿØÿàJFIFÿþ6 Image generated by GNU Ghostscript (device=ppmraw) ÿÛC    $.' ",#(7),01444'9=82<.342ÿÀ º]ÿÄÿÄF !1AVÑ"2QUat“”•#67Wqu‘²ÂRb±¡3BCGS†£ÄÒÿÚ?Þ5jÅ>…O\ú¤¶âÄA‘)×qž þDz]ÏD­M~6¢Ì™ !+u¶Ìò”«Ÿã‘l4j„YÉa‡u;zN“#IÿŸö$ŠúÅn™oÀ9ÕiÄŠJ$r®ìŸt»Ž[•*-6 Ì—âèlÏ-™çý Zǯ‹a7…£6Šn%µ¾I6Ö¬á*JˆÈÏx¶í‘Þº«5ˆÉmœÓ 4Óy.M(Nž­æDcÚ*«5ç¥Én¤ªlÞqˆèe†Ö·4“ZÍz‹’¬$ˆ·q1ÞDÊÍ"ÜIH[jÎHðvVHÐÚn!J,î"N ȨÇY\óCŠÜ÷ê¥=¤8^Û‘ÒÙ ðfÖäe’Ü£VH¸—èûÕ:¥Âüs&ÓË:†Ð¥¼êË$’ÔFD”§gŒ™«Ôbž›QŸCrì™Z4>¸mIu²$øBÙšLȼ•t™pÉg'jõÔ@9ŒÌ©98ˆÝð%Ñ\ä¸Ìš% ~bÕ««8êwm¸›òËn ¨TW6d%dm™¥D]x5<ã›jÌn\7Q‚m%Tuµ!´d¹4¥ÁõdÔj?ò2]Ti¯É¥TäÀL…©Ç˜JRãJYã+$¨Iž7ãqäψôèãÑ]¦ÔeJʯ”Sï/%eŒ)œhÁ‘cˆ³¨’Î1¼ýMÙ§é£0ù¥¦ÍÄ‘éå 85~ì–Gœ*Dʃpëj–šm]è䉞iu—¼Äd¬‘ã©\w™p)–³tùÜzkÓSPl“-“'TE§Qà‹.ììnK0¡W¦Ç†‚ÒÚ4¡Å¡>bZˆÏÔYÎ^´ŽI”6kRô¤‹RÏ&¯YúÇp®ß-Gšßƒ­l-<«O)¸ü\õg€‰k±à¶Å9ƒ§•;C /%ë&·WX·áÍ¢Ükµj}Ïr¢Ý6AÇqäËJ2xÏ!ߦ—×ÝÛߎàé¥õ÷v÷Ç£¸:i}}ݽñèîš__wo|z;ƒ¦—×ÝÛߎàé¥õ÷v÷Ç£¸:i}}ݽñèîš__wo|z;ƒ¦—×ÝÛߎàé¥õ÷v÷Ç£¸:i}}ݽñèîš__wo|z;ƒ¦—×ÝÛߎàé¥õ÷v÷Ç£¸yK¿oH0Þ•#gÏ! !†Pn8£œÉ"ÉŸšÛu‚¸-º}\™äJ[)w“Õ9êÈ´ °Ú^¢ÎmQ×%+ai6VæHüR>£>%ªÂ"Ú´Ö€õ=a)(¯ZÚþÓ>³^lãëEùù¿ð!°ÀRÞS+~Â÷ì1fßfÖ÷±7þ†Rd‰TIÄh}dl,1ÿêŠ{“ýÞaÓJQjS–¦´’a$MÏÿ®ŸRÿ¸\€ y³­çæÿÀ†y1F˜2“2Q6£#.­ÃOZÇjϵ©rªÛA¨5Qz:!³¸TƒJÌ·–[¿šÕ¯ˆÖíE48´Ê¥aèÒü•ÆÆËe¸ffFj2,ã‰ñö5x¥Òí–õFL鑧:Ú¹sвC›ùB3ñ’Nxo¶æÑ*R­f&Ï TdÏ~c±˜j3hú]+^üêÒ’I'j2É‘ã"-Ï~®e™\uêtyô™q!§pNTêÅ4‘‘§%¸÷ÿ‘é^Ú'-nÕ"=KªÐçH¥È~žì’J9]-©^*’£Ò¢Üx<½vïæèT¸Q©Óë57b6ó¬D"56ƒO–µ(È‹&GŒžOx­©^Ž\4Ú$KfB¢Ë«ÌTW^qÊBäÒkt'ÁÂ"Áä¿à{ôFµB®S§Ð«u Œ©n|JœÅ:…2gã-à²ÝŒ`röÓ 6ü—[¤ÔŸ¤DÁäÕ[m&Ãj#ÂŽ¥$‰‘zÖÑ"S*« —>¬¦¢¦\‡`%+K +žòÉ™o"-æB²Õ¼NÎ-ù:­Tœ…ò1™úGÞ"pÈÔfg¹)#,¨Ìˆ· ¢Ûº¢\e-”°ü:„'99Pd‘¬™ïIž ÈÈËy w¼>¦Vý…ïØb;ͭïboý ¤*Â’Š,å-ÇšI0³5°Yq%¤÷§×æ-GvÔ¦-©ä6¦izaaå—eç^lãëEùù¿ð!žËI®Í–5-µ$²xÞd5…»½D·)ôÇöwSÑXKK|çÇ#pȸï#1jû=&èŸW¥RcÌn±ŽY¥ÌB#í¤Ó¼ÏËN«ŽÔ#Z–µb˜»9s›e*¦ÆœÜÃC©2JÝYq¿yð‰·î¾a…GvŽã¡T$;";4°sPâ–¶ÔN’I3Þœä÷´.S¦Ü°âÑ‚¹ê‚ü$®y>”›.')ZÌòg‚Éùú²-®*-Ý{ÁäêTØtƒói´JK§*JÚ[eƒà„xÆ{÷ï!ç\²§*»§ÌÜðÒéŒE[ Õ l8Þwê%,Qþ`MnÓ$PŸ[ƒP]A1ŽBÖÒõ–•6¥¨ÌÌÍDg¸Œóç Ƚ+³éͧ³@‰ÔÈ–ësRò¤iÇÑ$“Á&yÎs¸R3G¼ ÐªV|Z|Ó¤¼ólUW%?Fê5(Ô×”j-J"Æ7ãñ‘I¸­JäÅÐ`±T‰:fyGd¥“aÖQÉ’”Gå$Ȉð[øŠ',*²m»HäÓ›Ÿ"–̆eAj q”®QY%%Ô™pÁnëÈÌ,+aªÏœªStÙ3”‚6 jå8IA·£#<™žîsx}L­û ß°Ä ›}›[ÞÄßúHUw ª4×JãXY›èN¥7¸üb.³."%ªúdÚÔדPv •°“)o7¡oq§¨ÅÀ¯]¤Ëœôõ(®Kaza.–´«ÌeÄX y³­çæÿÀ†mR¤À¬GK¨ÒU¨’¾~qUÐK_б¿Cï‚Zþ…úxt×ô,oÐûà–¿¡c~‡Þµý ô>ðè%¯èXß¡÷‡A-BÆý¼: kú7è}áÐK_б¿Cï‚Zþ…úxt×ô,oÐûà–¿¡c~‡Þ%SíZ*ZeÁ¦²Ãé#"Z3’#â:ÞS+~Â÷ì1fßfÖ÷±7þ†RÂkO½CQœKO­µ%·D•n3.½ã‡6ñ§Ò&Ç~|ÈdÒ#<‡‰´ÍÏ–¬cÄÇ›¬O—T¸Ú:—ƒÐZ{‘ŽÚâfI.éùH=Þ.<ýc•U."âBlÚLy ð’ñ¤uµŒpþáÕŠ­È·â¥êM¶¸*yå’>NAg pÞG»Æõ„J­Êê©E"€Ó%!µªi”’?QgIï;‡Xuk™æ©*•o4Êä:´ÎIJ%x2üUï>aÃ5{¡hˆnÛ­!NN6_"”GÉÇêw†óþÐr¯t&3ëEºÒLâe´xQ¸ÿú¹ÆãþÑÌšµÎÛU51o4êØ’†á¤åxCGå,÷x¸ógU®fN«à–ûO”t¶p³(“á&fZˆ÷x¸,þ8eãiS'ɪOlÄŠãqIöj Î(Ëyóò’£àXþ£È×h½n[~« «pJ®¶qÒµÄu/“w;Ú%‘dÈ‹¬æÀwhÕŠíÆý5TúJ˜Kš‰LëÐîŸ$‹9à64íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø4íS´ÔPsNÕ;MAø ËŽ—´Ä[5EL¸¨ŽF(®¨D%”'’#ê< ³fßfÖ÷±#ý ¤aöWoU+’*µƒ›R[®‰bL…-g©).¡•Ó©4êCÅ: xcK-’Kþ³­çæÿÀ†ÃlÈbF¾AæÝäÖm¯B‰ZT\Rxàeæ€)o©•¿a{ö³o³k{Ø›ÿC)ógZ/ÏÍÿ šî¯»nPü.4R•-çÚ“V’SŽ(’œŸQoo\WUµ±.ä L(ŽK2àe´©dxä Q«<WÒ5ÇvÒ§ÒsB§x UäÆJa¹HŽ¯z³Qád{ÈÍ8ÁÏ&ã»ê’ëÛP)îD¥J8¼Œ¬ò²Ö’-d“%QŒ™ž|þ¡Ôî[Ê·>¦›~›MaŠb‰—Q=JRßBT¦Òh<'±¨òG’]9­ÜoQbÚâ2üÈK›)u5%„%fÙ$‰F£5‘–|Ø1ѯY¶í srʳR¯L%.c¦Qc©: fj-çÇq9 ¾Ã¿æ©Té^ƒ*\ .ÊrŒã¼Ú¸c&fJ.Y1 [ÃêeoØ^ý† lÛìÚÞö&ÿÐÊ@¼ÙÇÖ‹óóàC*ºmô\ÔiʸÎëC¬HG”˨2RT[Ë82ɳ*U&jMÜ× •$LˆqË ø;M¤÷šô+Î0f{±Ž±-¡Q„ºt»žå‘W‡I2r3 CRTn–ä¸æƒRœ2êÝë1“tž›ý3þ]#ÿÀǤÙUsTz‡s9L§Õœ'ä0Qu¸…™-M¬ÔZ XÏ Æ:?aUâÔg»@ºŸ§D¨!%§å×ÊI*q+5•¨ˆ²x=ûdzöà9I~ت*M>2âku£—šQêÂÈÔY=YV}gêÙŒ˜°XSŽªÅAù­Ì~18•rÄD´­~7“Ç$2«v‰.’‡Ý¨T6cæZ–ÛÃiIp$ ŒñÄÌÏ'“ÿìRÞS+~Â÷ì1fßfÖ÷±7þ†R5æÎ>´_Ÿ›ÿ 7V˜–¯Jc¬»ÝC¦PRÖS'ÄÕÕŽ#$·‡ÔÊß°½û @ٷٵ½ìMÿ¡”€ S 5õkÜ×#ôËb5F%Jw„6ë“’Ñ‘c7‹N’m+°¾jžàé&Ò» æ©î’m+°¾jžàé&Ò» æ©îuÃh]4˜Ë¶©±Üu.!ªr©-æKÆSWyÒM¥vÍSÜ$ÚWa!|Õ=ÁÒM¥vÍSÜ$ÚWa!|Õ=ÁÒM¥vÍSÜ$ÚWa!|Õ=ÁÒM¥vÍSÜ$ÚWa!|Õ=ÁÒM¥vÍSÜ!Õª»HªÑæSÕdCl¤²¶MeTIéÔFYÆ=c0²©’¨ÖU›5‰1£%·FG…¬…ð z¨·J2)hlÒî¦äxJ÷áuãÎ2Š\rvÛÒå3LK ZØL™9å’â‹ÅK_X±rî 2Ó®¹TŽ”5,¡-Fgâ¾|øŽ_»(1Šq½Taĵ+&Dµy$~³ȺèQUPKõ6U9(\²3?¡%ù&¯ÄºhlªJ\©°“2Þ#3ñ> ?QŽJé¡©Ô4U6 k‰á©NO{Ï)ø`pÍÓCì6š©°µÌaRc‘ý#Iâ¢õ uvÐ%•<ãÕ#¹Î&¤ÄÒgôÆŸ+Oà8bï·äµ Öj±Ö‰¯œxÊ#?¥p¸¤½cÒ5ÓB˜òTŽã«¨©A+yº’Ê“ø‘ pOFbI¶o°Û¦Úµ£Z ZUç,ð1äªl%IT(Æ•9ʨ¤ï_õî>±Êé°\åuÂŽ®YD§rÒOY—Víçø‚éÐ\7pã¨ß"'u4“å¸jÝ¿°U>f¨qÌÜA6¼´ŸÁ'»yz€©ð‰D¢‡Q7ÉòIÉ#úxpõpÓá!M©ã¥M Ûlɤ‘¡'Å%»qz‡¦Áo‘Ñ :y ›ZZIryã§vïð!UihMB)‘¢±-¦ÖäE 2mÜEŒg#µ*I¯QíZÛ´ˆ.?r ¡)KKKŽêH‰K$–5±¿Ì2™Öê·-¿*³RwS2fºp‘ ‹Cx.w‘ñ ˜¯UôZê®ÛÍÓÜuÙœŠ[ÈwI0r’²Óÿvxz°>‰¶é Ðmºu)²ÂbÇCgë2-çúäZ¶Ÿ[ªÐ­˜ïÑä¦4·ç3Sd²I,ð{ŒBèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïµwe·bê£Õ¦\°¤ÉŒg¦I@$“:|då9ñ·þƒ)èÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïí+·p¾TžðèÞÒ»w åIïE~ñ¾m;ŽEe}‰ÊC-º— —«v7ù†ù÷l?U韜Dýãaâó‡€xC~ÉrÜŽ¯Fq«lî5À9 ”µ4o%^1 ŒˆÕ6L‹ü‰¬®Z!Éz1UbÌ>ˆî ,¡Õžƒó™ZŽäè­Mf’L§Ò¥´Ñ«ÆZSFE׌—ê$Žäè­Nf’L§Ò¥´Ñ«ÆZSFE׌—ê=}¨Ì­çÝCM ²¥­DD’õ™ŠÊEÕ@¯¾ãšÄ)®¶KCŒ‹Ï‚ã…(’“RE“3ê0æF¨Cjd7Û~3É%¶ëjÊVGÖFfŦÃvdÙ ÇŒÊu8ëª$¥%ç31tP®n‘V‡9m)Ä°é,ÒGÀÏØGjtWæHˆÔ†×"6žY¤«*oQe9.¬‘ ç}­}¥Jö(ÿÌ}5îØ~«Ó?8‰ûÆÂ.ÿÎOý¿ÿØ%™§kÐÔ\J‚ùÿó61º=Ïy®jWgTiÏA«Ìn+±Ò¤’õ(—ž>.q‚/ÄSSâÎbˆ§%Ìiô®öm$H`›2Rdž¥äòFfX.¯X²¸v™5ºµ]0+iåKul" ðœyÉ‹G••¤°‚>ŒŸŸŠ†ÒjÒy -ËbÝaØmHŠ‰ðÔò%©^RMÄîl’~.òëȹ¹“W›}Z%M—ç`K5>¤í °Ñž’Éjõg·Š¹[EªÓ©I§ÎŸ š’ê’ óšã(! ÚJ4™¯’NLÔd¬pó˜é jf¸J™©Ì‚l¦A¸êa§Íå’© ÞF•+~3¸„Ø,\ñ¶«@nã› fiÒ”ËÑ™6ð£äµ Ë;ÈŒ‹בm{¶ÅJì´hsÜO7J}÷ÞaG„¾¶F„+ÎYQž:ðBγmP×\£UÜuéÑdYq“Kj‘’?¡Wõï<~#né¼_¶ž½Ðå<¨í)o&—È™8¸È3#Q»“ÂðFxÆ7 3«wuÃV¬¢Ü~ XÆ#j[:•%Õ¶NrGâ–•gÏúŒb“|;Kµ­Šz¬j9¦”̧¦Hˆ¹:‰Z’HBëNLÌË«Ì«6b°ÛÉ€U8•T¥ JÊ©©¯ J·’V“Î gÆ•wQX¶ç[u„%Ö") BãÈÔ“Ëf´qÁ'Qã¬S[µ+¢•eÒ‘©Ù*û°Ð§ãI­íf~6O*N¢áŽ±}"ã®Òa^È~Ti3(°u© ŒM’Ö¦”£3NOvH·d{@­]4Û¦“·> ÈU8/ÉäãÆ6ÔÂÛJU‚33ÔXV2 ¥UÑ|s&è)”îm©Ìe ãaqÙuÒJ —¨õ¤ÈÍž¼ ¶>wÚ×ÚT¯büÇÑ^í‡ê½3󈟼l"à5íË.‰&ºS¢×êšÄfÕOLj§¦õdÒ¤©“ßÀÇ•¥oÓfH¨Ôkõ µMär%*D%§“kwˆ„¥”‘™ž8˜ðŽõ«Þ R ¯0Û£JjKn'2á£Vü]ÙÔ8'-R€˜œï3IVyßW9|§)£ÉáÙ/;Hn¥9úUáV¦Ãžñ¿&#PT²5«rÔ•)¤ú¸ëR:,©rŽÝU… [ ±"€)ä­(NÆâ Ë)ãëÞ,ãÔ-8• –*3 hk†ËjˆéëB‰•ž$H/ÔUÈjÙR•&ÅQ…QMEùìËjÌÛ7°KF“A’’dEÄJrE·:ݨÒëJ¢ôò"rS‘• Óä”iN“߸·žó—hÐîhµêÙR©ËqNÓÔ„’ƒà”ü‘ïëϨY]UFì‚Ë2j3£HŒï/Thî¥Æ\"ÁŸøÔ÷h‰ªÃŸ\ºªuµA,ÄnD6†—ÃY’Z•ŽyÆL@E2ÚA=¥5n=$ä.PÖM™ç“ÔHÔHÏý¤xj…oKªÍ—M¹j4¦ª ¡‰±ã@Q¥ä¤$djAšOIã%¿qy„v#P)¬ÓŽuÔéÒâBLE=Ní$ÌÓ© A‘žòó‰Õ#µ*”°_®UlYÕGÁœ7’þó×½"Éù%‚Á°äÒŽµ £[»êuRœŒË”ãepËN³Ð‚ÔdFdYóˆôæ蓇n9ŇTç8­=i6Ô|¡©däfážxîê2­j‡IµÕ¥£Ÿ£¶Ã¸„çÑhÊ|]üs¼J•X¶$U)UŸ)K¦Æy„5àŽ‘:N%$y=;¼ŸùÍ3™**]ÆÜfj,ºšKð~Š*Rñ-Zž$ei"#Æþ´îÜ>ˆ%©‘›ÂM8’RLÒe’üyŸ6µö•+Ø£ÿ1ô@×»aú¯Lüâ'ï¸öµö•+Ø£ÿ1ô@Õ›Q§fÚ’fJ)­q.#æ>yªúJg¿WxsÍWÒS=ú»Ãžj¾’™ïÕÞóUô”Ï~®ð皯¤¦{õw‡<Õ}%3ß«¼9æ«é)žý]áÏ5_IL÷êïyªúJg¿WxsÍWÒS=ú»Ãžj¾’™ïÕÞóUô”Ï~®ð皯¤¦{õw‡<Õ}%3ß«¼9æ«é)žý]áÏ5_IL÷êïyªúJg¿WxsÍWÒS=ú»Ãžj¾’™ïÕÞóUô”Ï~®ð皯¤¦{õw‡<Õ}%3ß«¼9æ«é)žý]âÞÞü§e¹!ç^ZœQ¨ñãu˜ÿÙ From sidnei at x3ng.com.br Fri May 30 11:17:58 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/XMLDocument - Builder.py:1.1 CHANGES.txt:1.1 Example.zexp:1.1 Node.py:1.1 README.txt:1.1 XMLDocument.py:1.1 __init__.py:1.1 documentAdd.dtml:1.1 documentEdit.dtml:1.1 documentUpload.dtml:1.1 elementEdit.dtml:1.1 version.txt:1.1 xml_doc.gif:1.1 xml_element.gif:1.1 Message-ID: <200305301517.h4UFHwp20802@cvs.baymountain.com> Update of /cvs-zopeorg/Products/XMLDocument In directory cvs.zope.org:/tmp/cvs-serv19195/XMLDocument Added Files: Builder.py CHANGES.txt Example.zexp Node.py README.txt XMLDocument.py __init__.py documentAdd.dtml documentEdit.dtml documentUpload.dtml elementEdit.dtml version.txt xml_doc.gif xml_element.gif Log Message: Adding products needed for migration of NZO === Added File Products/XMLDocument/Builder.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ XML DOM Builder """ from Shared.DC.xml import pyexpat from OFS import ZDOM import Globals class ParseError(Exception): pass class Builder: """ DOM Builder base class 'nodes' maps Node type codes to classes override this class attribute in subclasses """ nodes={} buffer_size=1028 * 32 def __init__(self): self.reset() # Public methods # -------------- def reset(self, doc=None): """ Reset the builder. 'doc' is the Document element to root the tree in. """ if doc is None: doc=self.nodes[ZDOM.DOCUMENT_NODE]("#document") self.cur_elem = self.root = doc self.error = None self.in_cdata=0 def parse(self, input): """ Build a DOM tree give a string or a fileobject. """ p = pyexpat.ParserCreate() p.StartElementHandler = self.start p.EndElementHandler = self.end p.CharacterDataHandler = self.cdata p.StartCdataSectionHandler = self.start_cdata p.EndCdataSectionHandler = self.end_cdata p.ProcessingInstructionHandler = self.pi p.CommentHandler = self.comment p.StartNamespaceDeclHandler = self.start_ns p.EndNamespaceDeclHandler = self.end_ns if type(input)==type(''): rv = p.Parse(input, 1) else: while 1: # hmm, this is causing persistence problems, why? if Globals.DatabaseVersion == '3': get_transaction().commit(1) v=input.read(self.buffer_size) if v == "": rv = 1 break rv = p.Parse(v, 0) if not rv: break if not rv: raise ParseError('%s at line %s' % (pyexpat.ErrorString(p.ErrorCode), p.ErrorLineNumber)) else: self.root.normalize() return self.root # Handler methods # --------------- def start(self, name, attrs): e=self.nodes[ZDOM.ELEMENT_NODE](name) if self.cur_elem is not None: self.cur_elem.appendChild(e) self.cur_elem = e.__of__(self.cur_elem) else: self.cur_elem = self.root = e for i in range(0, len(attrs) ,2): self.cur_elem.setAttribute(attrs[i], attrs[i+1]) def end(self, name): try: self.cur_elem=self.cur_elem.aq_parent except: pass def cdata(self, data): if self.in_cdata: e=self.nodes[ZDOM.CDATA_SECTION_NODE](data) else: e=self.nodes[ZDOM.TEXT_NODE](data) self.cur_elem.appendChild(e) def pi(self, target, data): e=self.nodes[ZDOM.PROCESSING_INSTRUCTION_NODE](target, data) self.cur_elem.appendChild(e) def comment(self, data): e=self.nodes[ZDOM.COMMENT_NODE](data) self.cur_elem.appendChild(e) def start_cdata(self): self.in_cdata=1 def end_cdata(self): self.in_cdata=0 def start_ns(self, prefix, uri): pass def end_ns(self, prefix): pass === Added File Products/XMLDocument/CHANGES.txt === XML Document Changes Version 1.0a2 This version changes quite a bit internally over the last alpha. Now XML Document uses ZDOM as much as it can. This will keep us all happier and saner. Also this version starts to rely on stuff in the latest pyexpat. Finally, the DOM support is much improved. TODO * DOM support is still somewhat incomplete and needs massive testing. I need to document which DOM methods and nodes are supported, and which ones aren't. Features added * Added FTP and PUT support. * Attributes are now available as Attr Nodes thanks to converting to ZDOM. * Comment and CDATA Section Nodes are now parsed. * Support for DocumentFragment Nodes added. * Many more DOM methods implemented. Bugs Fixed * Fixed some DOM modification methods that failed for Nodes that don't support children. Thanks to Andrew Kuchling. * Fixed getElementsByTagName. Thanks again to Andrew. * Fixed the return values of some DOM methods. Thanks to Martijn Faassen. * The clone should work now. Version 1.0a1 Initial alpha version === Added File Products/XMLDocument/Example.zexp === ZEXPZW((U OFS.FolderqUFolderqtqNt.}q(U viewSlideq(U^q(UOFS.DTMLMethodqU DTMLMethodqttQUidq UExampleq U__ac_local_roles__q }q Uamosq ]qUOwnerqasUtreeq(U_q(UOFS.DTMLDocumentqU DTMLDocumentqttQUSlidesq(U’q(U Products.XMLDocument.XMLDocumentqUDocumentqttQU_objectsq(}q(U meta_typeqU DTML Methodqh hu}q(U meta_typeqU DTML DocumentqUidqUtreeq u}q!(hhhUslideq"u}q#(U meta_typeq$U XML Documentq%Uidq&USlidesq'u}q((h$h%h&UTreeq)utUTreeq*(U›q+(hUDocumentq,ttQUtitleq-UXML Document Examplesq.h"(U\q/(hU DTMLDocumentq0ttQu.^¹((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUU__name__qU viewSlideqU__ac_local_roles__q}q Uamosq ]q UOwnerq asUglobalsq }qUrawqT

/viewSlide"><-- previous /viewSlide">next --> qU_varsq}qu._€((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqU Tree tag demoqUrawqUÌ

This tree is created from xml.

qU__ac_local_roles__q }q Uamosq ]q UOwnerq asUglobalsq}qU__name__qUtreeqU_varsq}qu.’Ý((U Products.XMLDocument.XMLDocumentqUDocumentqtqNt.}q(UidqUSlidesqU__ac_local_roles__q}qUamosq ]q UOwnerq asU _child_idsq ]q KêaUtitleqUU _child_mapq}qKê(Uïq(hUElementqttQsU_next_idqM5u.›Ú((U Products.XMLDocument.XMLDocumentqUDocumentqtqNt.}q(UidqUTreeqU__ac_local_roles__q}qUamosq ]q UOwnerq asU _child_idsq ]q KUaUtitleqUU _child_mapq}qKU(Uïfq(hUElementqttQsU_next_idqK€u.\¦((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqU Slide demoqU__name__qUslideqU__ac_local_roles__q }q Uamosq ]q UOwnerq asUglobalsq}qUrawqUô

qU_varsq}qu.ï÷((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUslidesqUidqUe234qU_idq KêU _child_idsq ]q (KëKíMMMM"M2eUcolorq Ugrayq U _propertiesq(}q(UmodeqUwhUtitleqUtypeqUstringqu}q(hUcolorqhhutU _child_mapq}q(M(Uï‚q(UProducts.XMLDocument.NodeqUTextqttQM"(Uïƒq(hUElementqttQM2(Uï„q(hUTextqttQKí(Uï…q(hUElementq ttQKë(Uï†q!(hUTextq"ttQM(Uï‡q#(hUElementq$ttQM(Uïˆq%(hUTextq&ttQuu.ïfH((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUthingsqUidqUe85qU_idq KUU _child_idsq ]q (KVKXKnKqK~eU _child_mapq }q (Kn(Uïgq(UProducts.XMLDocument.NodeqUTextqttQK~(Uïhq(hUTextqttQKX(Uïiq(hUElementqttQKV(Uïjq(hUTextqttQKq(Uïkq(hUElementqttQuu.ï‚^((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe286qU_idqMU_dataqU q u.((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUslideqU _propertiesq(}q(Umodeq UwUidq Utitleq Utypeq Ustringq u}q(h Ucolorqh h uth Ue290qU_idqM"U _child_idsq]q(M#M%M0eUcolorqUredqh U the red slideqU _child_mapq}q(M%(Uï‘q(hUElementqttQM#(Uï’q(UProducts.XMLDocument.NodeqUTextqttQM0(Uï“q(hUTextqttQuu.ï„]((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe306qU_idqM2U_dataqU q u.ï…!((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUslideqUidqUe237qU_idq KíU _child_idsq ]q (KîKðMeUtitleq U first slideq U _child_mapq}q(Kî(Uïq(UProducts.XMLDocument.NodeqUTextqttQM(UïŽq(hUTextqttQKð(Uïq(hUElementqttQuu.ï†Z((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe235qU_idqKëU_dataqU q u.ï‡'((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUslideqUidqUe262qU_idq MU _child_idsq ]q (MM MeUtitleq U second slideq U _child_mapq}q(M(Uï‰q(UProducts.XMLDocument.NodeqUTextqttQM(UïŠq(hUTextqttQM (Uï‹q(hUElementqttQuu.ïˆ^((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe258qU_idqMU_dataqU q u.ïgZ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe110qU_idqKnU_dataqU q u.ïhY((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe126qU_idqK~U_dataqU q u.ïiˆ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUthingqUidqUe88qU_idq KXU _child_idsq ]q (KYK[KbKdKeKgKmeU _child_mapq }q (Km(Uïtq(UProducts.XMLDocument.NodeqUTextqttQK[(Uïuq(hUElementqttQKY(Uïvq(hUTextqttQKg(Uïwq(hUElementqttQKe(Uïxq(hUTextqttQKd(Uïyq(hUElementqttQKb(Uïzq(hUTextqttQuu.ïjX((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe86qU_idqKVU_dataqU q u.ïkH((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUthingqUidqUe113qU_idq KqU _child_idsq ]q (KrKtKuKwK}eU _child_mapq }q (K}(Uïlq(UProducts.XMLDocument.NodeqUTextqttQKw(Uïmq(hUElementqttQKu(Uïnq(hUTextqttQKt(Uïoq(hUElementqttQKr(Uïpq(hUTextqttQuu.ï‘Æ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUbodyqUidqUe293qU_idq M%U _child_idsq ]q M&aU _child_mapq }q M&(Uï”q(UProducts.XMLDocument.NodeqUTextqttQsu.ï’]((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe291qU_idqM#U_dataqU q u.ï“[((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe304qU_idqM0U_dataqU q u.ï\((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe238qU_idqKîU_dataqU q u.ïŽ[((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe256qU_idqMU_dataqU q u.ïÃ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUbodyqUidqUe240qU_idq KðU _child_idsq ]q KñaU _child_mapq }q Kñ(Uïq(UProducts.XMLDocument.NodeqUTextqttQsu.ï‰]((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe263qU_idqMU_dataqU q u.ïŠ[((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe284qU_idqMU_dataqU q u.ï‹Æ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUbodyqUidqUe265qU_idq M U _child_idsq ]q M aU _child_mapq }q M (UïŒq(UProducts.XMLDocument.NodeqUTextqttQsu.ïtV((UProducts.XMLDocument.NodeqUTextqtqNt.}q(U_idqKmU_dataqU UidqUe109qu.ïu((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUheadqUidqUe91qU_idq K[U _child_idsq ]q (K\K^K_eU _child_mapq }q (K_(Uï~q(UProducts.XMLDocument.NodeqUTextqttQK^(Uïq(hUElementqttQK\(Uï€q(hUTextqttQuu.ïvY((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe89qU_idqKYU_dataqU q u.ïw((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUfeetqUidqUe103qU_idq KgU _child_idsq ]q (KhKjKkeU _child_mapq }q (Kk(Uï{q(UProducts.XMLDocument.NodeqUTextqttQKj(Uï|q(hUElementqttQKh(Uï}q(hUTextqttQuu.ïxZ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe101qU_idqKeU_dataqU q u.ïy‡((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUbodyqUidqUe100qU_idq KdU _child_idsq ]q U _child_mapq }q u.ïzY((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe98qU_idqKbU_dataqU q u.ïlV((UProducts.XMLDocument.NodeqUTextqtqNt.}q(U_idqK}U_dataqU UidqUe125qu.ïm((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUsecondqUidqUe119qU_idq KwU _child_idsq ]q (KxKzK{eU _child_mapq }q (K{(Uïqq(UProducts.XMLDocument.NodeqUTextqttQKz(Uïrq(hUElementqttQKx(Uïsq(hUTextqttQuu.ïnZ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe117qU_idqKuU_dataqU q u.ïoˆ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUfirstqUidqUe116qU_idq KtU _child_idsq ]q U _child_mapq }q u.ïpZ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe114qU_idqKrU_dataqU q u.ï”±((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe294qU_idqM&U_dataqUY This slide is red. All the others are grey. The magic is acquisition. q u.ïÖ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe241qU_idqKñU_dataqU This is the first slide Here are some points, that I want to make: * one thing * another thing q u.ïŒð((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe266qU_idqM U_dataqU˜ This is the second slide Here are some points, that I want to make: 1. one thing 2. another thing 3. final point q u.ï~[((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe95qU_idqK_U_dataqU q u.ï†((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUhairqUidqUe94qU_idq K^U _child_idsq ]q U _child_mapq }q u.ï€[((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe92qU_idqK\U_dataqU q u.ï{Z((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe107qU_idqKkU_dataqU q u.ï|‡((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUtoesqUidqUe106qU_idq KjU _child_idsq ]q U _child_mapq }q u.ï}\((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe104qU_idqKhU_dataqU q u.ïqZ((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe123qU_idqK{U_dataqU q u.ïrˆ((U Products.XMLDocument.XMLDocumentqUElementqtqNt.}q(U_nameqUthirdqUidqUe122qU_idq KzU _child_idsq ]q U _child_mapq }q u.ïs\((UProducts.XMLDocument.NodeqUTextqtqNt.}q(UidqUe120qU_idqKxU_dataqU q u.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ === Added File Products/XMLDocument/Node.py === (865/965 lines abridged) ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment [-=- -=- -=- 865 lines omitted -=- -=- -=-] class Comment(Acquisition.Explicit, CharacterData, Node, ZDOM.Node, Persistent): """ Comment Node """ nodeType=COMMENT_NODE _name="#comment" _child_ids=() def __init__(self, data): self._data=data def toXML(self, deep=1, RESPONSE=None): """ DOM tree as XML from this Node. If 'deep' is false, just return the XML of this node and its attributes. """ if RESPONSE is not None: RESPONSE.setHeader('content-type','text/xml') return "" % self._data def cloneNode(self, deep=0): """ Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. The duplicate node has no parent. Cloning an Element copies all attributes and their values, including those generated by the XML processor to represent defaulted attributes, but this method does not copy any text it contains unless it is a deep clone, since the text is contained in a child Text node. Cloning any other type of node simply returns a copy of this node. """ return self.getOwnerDocument().createComment(self._data) class DocumentFragment(Acquisition.Implicit, Node, ZDOM.Node, Persistent): """ Document Fragment """ nodeType=DOCUMENT_FRAGMENT_NODE _name="#document-fragment" def __init__(self): self._child_ids=[] self._child_map={} === Added File Products/XMLDocument/README.txt === Welcome to XML Document, a Zope Product for XML support What is it? XML Document allows you to use xml objects in the Zope environment. You can create xml documents in Zope and leverage Zope to format, query, and manipulate xml. What is the status of this product? This release is *alpha* quality. This means that it is not feature complete, nor is it bug free. This release is also not supported. This means we will answer questions and fix problems as time permits. How can I get involved? DC doesn't currently have a lot of time to spend on this project. This means motivated and opinionated Zope developers are more than welcome to contribute ideas and code to this project. Examples The included Example.zexp file can be imported into Zope to give you a working example of how to use XML Document. Requirements This release requires Zope 2.0.0 beta 2 or later. Features The XML Document product parses xml into a Zopish DOM tree. The individual elements of the tree are true Zope object with id's, properties, acquisition support, persistence, etc. The document and individual sub-elements can be edited trough the management interface. By turning xml into Zope objects you can leverage all the Zopish things you know and love to xml. For example you can format xml with DTML Methods. You can use URL traversal to locate specific elements in the DOM. You can acquire methods and call them on specific elements. You can catalog xml elements. URL traversal When xml is parsed into a DOM tree, sub-elements are created and given ids. You can then use URLs to navigate to specific elements. URL traversal works in two ways, by *id* and by sequence *index*. id traversal This works normally, in the same way can traverse all objects in the Zope object hierarchy by id. For example, 'myDoc/e5/e7/myMethod' This URL traverses from an XML Document object with id 'myDoc', to a sub-element with id, 'e5', to a sub-element with id 'e7' and then to an acquired method with id 'myMethod'. Since node ids are generated automatically and can change when the xml content of a document is reparsed, this method of URL traversal has some short-comings. For example, URLs of this type probably shouldn't be bookmarked since they could change when the xml document is changed. sequence index traversal This form of traversal uses an element's index within its parent rather than its id as URL key. For example, 'myDoc/0/2/myMethod' This URL traverses from an XML Document object with id 'myDoc' to it's first sub-element, to that element's second sub-element to an acquired method with id 'myMethod' Sequence and mapping interface XML Documents and elements support the Python sequence interface for access to sub-elements. At present this support is limited. For example in DTML you access sub-elements like so:: This calls 'myMethod' on a sub-element which is several levels deep in the DOM tree. You can also use the sequence interface to manipulate the DOM tree. For example:: This replaces one sub-node with an other. In addition, you can access sub-elements by id via the mapping interface:: This example shows sub-element access via a combination of id and index style access. Note, you can not currently access sub-elements via 'getattr' style access. In other words this won't work:: # wrong DOM API support The DOM tree created by Zope aims to comply with the DOM level one standard. This allows you to access your xml in DTML or External Methods using a standard and powerful API. Currently the DOM support is a little incomplete, and has not be completely tested. The DOM tree is not built with the xml-sig's DOM package, because it requires significantly different node classes. Another divergence from the DOM API is that DOM attributes are made available as methods not attributes. These attributes are named by prepending 'get' to the attribute name. For example, the 'firstChild' attribute is available via the 'getFirstChild' method. Note, the XML Document DOM is based on the general purpose Zope DOM (ZDOM). The XML Document Product provides a superset of the ZDOM. ObjectManager API support XML Documents and elements support the read methods of the ObjectManger API. These methods include 'objectIds', 'objectValues', and 'objectItems'. For example::
This would iterate through all sub-elements with a tag name of 'book' and would print the 'author' attribute of each sub-element. Attributes and properties XML attributes are mapped to Zope properties. You can edit these values via the standard Zope property management interface and the changes are reflected in the xml of an element. You can also edit attributes by editing the xml and these changes are reflected in the Zope property interface. You can also use standard Zope property management methods from DTML and External Methods to change properties. Meta types The meta type of an XML Document is 'XML Document'. The meta type of sub-Elements of XML Documents is given by their tag name. Editing xml with the management interface XML Documents are elements are editable via the management interface. Documents can be created by uploading xml files. FTP and PUT You can edit XML Documents through the ZServer FTP server. You can also use WebDAV and HTTP PUT to update existing XML Document objects. You cannot create new XML Document objects with FTP, WebDAV or PUT. Limitations This release is *alpha* quality. DOM limitations The currently DOM implementation is incomplete, and most probably contains bugs. Futures The XML Document Product has a long way to go. This is a summary of planned improvements. If you don't see what you want here, you're in luck, this is open source software! You can extend this product yourself or pay someone (including Digital Creations) to extend it for you. In the short term as time permits, we plan to, * Verify that the DOM implementation is fairly complete and correct. * Improve management interface. * Improve performance, especially for very large xml documents. In the longer run plans include, * Provide an ability to bind ZClasses to specific Element types. This is similar to ZSQL Method's notion of brains. * More completely support Zope management and object protocols. * Provide XML validation services. === Added File Products/XMLDocument/XMLDocument.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ Python Product for XML Documents """ import Node from Node import Text, Comment, ProcessingInstruction, CDATASection, \ DocumentFragment from Globals import HTMLFile, MessageDialog from DateTime import DateTime import string from urllib import quote import Builder from OFS import ZDOM class Manageable: """ Mix-in for Zope management """ isPrincipiaFolderish=1 manage_options=({'label':'Edit', 'action':'manage_editForm'}, {'label':'Upload', 'action':'manage_uploadForm'}, {'label':'Properties', 'action':'manage_propertiesForm'}, {'label':'Security', 'action':'manage_access'}, ) __ac_permissions__=( ('Access contents information', ('objectIds', 'objectValues', 'objectItems', 'getfirstChild', 'getlastChild', 'getNextSibling', 'getPreviousSibling', 'getChildNodes', 'getParentNode', 'getOwnerDocument', 'getElementsByTagName', 'nextObject', 'previousObject'), ('Anonymous', 'Manager')), ('View management screens', ('manage', 'manage_main', 'manage_editForm', 'manage_uploadForm')), ('Change XML Documents', ('manage_edit', 'manage_upload', 'insertBefore', 'appendChild', 'removeChild', 'cloneNode', 'normalize', 'setAttribute', 'setAttributeNode', 'removeAttribute', 'removeAttributeNode', 'parse', 'PUT', 'createElement', 'createTextNode', 'createCDATASection', 'createComment', 'createProcessingInstruction', 'createDocumentFragment' )), ('View', ('', 'text_content', 'getnodeType', 'getnodeValue', 'toXML', 'document_src', 'getAttribute', 'getAttributes')), ('Manage properties', ('manage_addProperty', 'manage_editProperties', 'manage_delProperties', 'manage_changeProperties',)), ('FTP access', ('manage_FTPstat','manage_FTPget','manage_FTPlist')), ) # Content Editing Methods # ----------------------- manage_uploadForm=HTMLFile('documentUpload', globals()) def get_size(self): return len(self.toXML()) _size_changes={ 'Bigger': (5,5), 'Smaller': (-5,-5), 'Narrower': (0,-5), 'Wider': (0,5), 'Taller': (5,0), 'Shorter': (-5,0), } def _er(self,data,title,SUBMIT,dtpref_cols,dtpref_rows,REQUEST): dr,dc = self._size_changes[SUBMIT] rows=max(1,string.atoi(dtpref_rows)+dr) cols=max(40,string.atoi(dtpref_cols)+dc) e=(DateTime('GMT') + 365).rfc822() resp=REQUEST['RESPONSE'] resp.setCookie('dtpref_rows',str(rows),path='/',expires=e) resp.setCookie('dtpref_cols',str(cols),path='/',expires=e) return self.manage_editForm( self,REQUEST,title=title,toXML=data, dtpref_cols=cols,dtpref_rows=rows) def manage_edit(self,data,title=None,SUBMIT='Change',dtpref_cols='50', dtpref_rows='20',REQUEST=None): """ Replaces a Documents contents with Data, Title with Title. The SUBMIT parameter is also used to change the size of the editing area on the default Document edit screen. If the value is "Smaller", the rows and columns decrease by 5. If the value is "Bigger", the rows and columns increase by 5. If any other or no value is supplied, the data gets checked for DTML errors and is saved. """ if self._size_changes.has_key(SUBMIT): return self._er(data,title,SUBMIT,dtpref_cols,dtpref_rows,REQUEST) if title is not None: self.title=title try: self.parse(data) except Builder.ParseError, message: if REQUEST: return self.manage_editForm(self, REQUEST, toXML=data, manage_tabs_message='XML Parsing Error: %s' % message) if REQUEST: message="Content changed." return self.manage_editForm(self, REQUEST, manage_tabs_message=message) def manage_upload(self, file='', REQUEST=None): """Replace the contents of the document with the text in file.""" try: self.parse(file) except Builder.ParseError, message: if REQUEST: return MessageDialog( title ='XML Parsing Error', message=message, action ='manage_workspace') if REQUEST: return MessageDialog( title ='Success!', message='Your changes have been saved', action ='manage_workspace') def manage_afterAdd(self, item, container): pass def manage_beforeDelete(self, item, container): pass def manage_afterClone(self, item): pass # Node classes # ------------ class Document(Manageable, Node.Document): """ XML Document Zope object """ meta_type='XML Document' manage=manage_main=manage_editForm=HTMLFile('documentEdit', globals()) def _get_builder(self): # returns a DOM builder return DOMBuilder() def _build_tree(self, data): # Return a DOM tree given XML data. # This tree has no ownerDocument p=self._get_builder() p.reset() p.parse(data) return p.root.getDocumentElement().aq_base def parse(self, data): """ Build a DOM tree rooted in this node given XML text or file object. """ self._clear() p=self._get_builder() p.reset(self) p.parse(data) # DOM write methods # ----------------- def createElement(self, tagName): """ Creates an element of the type specified. Note that the instance returned implements the Element interface, so attributes can be specified directly on the returned object. """ return self._get_builder().nodes[ZDOM.ELEMENT_NODE](tagName) def createTextNode(self, data): """ Creates a Text node given the specified string. """ return self._get_builder().nodes[ZDOM.TEXT_NODE](data) def createCDATASection(self, data): """ Creates a CDATASection node whose value is the specified string. """ return self._get_builder().nodes[ZDOM.CDATA_SECTION_NODE](data) def createComment(self, data): """ Creates a Comment node given the specified string. """ return self._get_builder().nodes[ZDOM.COMMENT_NODE](data) def createProcessingInstruction(self, target, data): """ Creates a ProcessingInstruction node given the specified name and data strings. """ return self._get_builder().nodes[ZDOM.PROCESSING_INSTRUCTION_NODE](data) def createAttribute(self, name): """ Creates an Attr of the given name. Note that the Attr instance can then be set on an Element using the setAttribute method. """ return self._get_builder().nodes[ZDOM.ATTRIBUTE_NODE](name,'') def createDocumentFragment(self): """ Creates an empty DocumentFragment object. """ return self._get_builder().nodes[ZDOM.DOCUMENT_FRAGMENT_NODE]() # Protocol handlers # ----------------- def PUT(self, REQUEST, RESPONSE): """Handle HTTP PUT requests""" self.dav__init(REQUEST, RESPONSE) body=REQUEST.get('BODY', '') self.parse(body) RESPONSE.setStatus(204) return RESPONSE def manage_FTPget(self): "Get source for FTP download" return self.toXML() class Element(Manageable, Node.Element): """ XML Element Zope object """ icon="misc_/XMLDocument/xml_element.gif" def parse(self, data): """ Build a DOM tree rooted in this node given XML text or file object. """ e=self.aq_acquire('_build_tree')(data) self._child_map=e._child_map self._child_ids=e._child_ids self._properties=e._properties for k,v in e.propertyItems(): setattr(self, k, v) manage_editForm=HTMLFile('elementEdit', globals()) # DOM Builder class # ----------------- class DOMBuilder(Builder.Builder): nodes={ ZDOM.DOCUMENT_NODE : Document, ZDOM.DOCUMENT_FRAGMENT_NODE : DocumentFragment, ZDOM.ELEMENT_NODE : Element, ZDOM.TEXT_NODE : Text, ZDOM.CDATA_SECTION_NODE : CDATASection, ZDOM.COMMENT_NODE : Comment, ZDOM.PROCESSING_INSTRUCTION_NODE : ProcessingInstruction, ZDOM.ATTRIBUTE_NODE : ZDOM.Attr, } # Add form and method # ------------------- addForm=HTMLFile('documentAdd', globals()) def add(self, id, title='', file='', REQUEST=None, submit=None): """ Add a XML Document object with the contents of file. """ ob=Document() ob.title=title ob.id=id if file: ob.parse(file) id=self._setObject(id, ob) if REQUEST is not None: try: u=self.DestinationURL() except: u=REQUEST['URL1'] if submit==" Add and Edit ": u="%s/%s" % (u,quote(id)) REQUEST.RESPONSE.redirect(u+'/manage_main') return '' === Added File Products/XMLDocument/__init__.py === ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # 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. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``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 DIGITAL CREATIONS 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 Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """ XML Document Product """ import XMLDocument from Globals import ImageFile import OFS.misc_ def initialize(context): context.registerClass( XMLDocument.Document, permission='Add XML Documents', constructors=(XMLDocument.addForm, XMLDocument.add), icon='xml_doc.gif' ) context.registerBaseClass(XMLDocument.Document) # manual icon registration for XMLElement icon=ImageFile('xml_element.gif', globals()) icon.__roles__=None OFS.misc_.misc_.XMLDocument['xml_element.gif']=icon === Added File Products/XMLDocument/documentAdd.dtml === Add XML Document

Add XML Document

You may create a new XML Document using the form below. You may also choose to upload an existing XML file from your local computer by clicking the Browse button.

Id
Title
File
=== Added File Products/XMLDocument/documentEdit.dtml === Edit
Id
Title
Size bytes
Last modified
=== Added File Products/XMLDocument/documentUpload.dtml === Upload

You may upload the source for using the form below. Choose an existing html file from your local computer by clicking the Browse button.

File

=== Added File Products/XMLDocument/elementEdit.dtml === Edit
Id
Size bytes
Last modified
=== Added File Products/XMLDocument/version.txt === XML Document 1.0a2 === Added File Products/XMLDocument/xml_doc.gif === === Added File Products/XMLDocument/xml_element.gif === From sidnei at x3ng.com.br Fri May 30 11:17:50 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/PythonMethod/zbytecodehacks - ChangeLog:1.1 Makefile:1.1 README:1.1 TODO:1.1 VSExec.py:1.1 __init__.py:1.1 attr_freeze.py:1.1 closure.py:1.1 code_editor.py:1.1 common.py:1.1 cyclehandle.py:1.1 dbc.py:1.1 find_function_call.py:1.1 iif.py:1.1 inline.py:1.1 label.py:1.1 macro.py:1.1 macros.py:1.1 opbases.py:1.1 ops.py:1.1 rationalize.py:1.1 tailr.py:1.1 version:1.1 xapply.py:1.1 Message-ID: <200305301517.h4UFHoC20492@cvs.baymountain.com> Update of /cvs-zopeorg/Products/PythonMethod/zbytecodehacks In directory cvs.zope.org:/tmp/cvs-serv19195/PythonMethod/zbytecodehacks Added Files: ChangeLog Makefile README TODO VSExec.py __init__.py attr_freeze.py closure.py code_editor.py common.py cyclehandle.py dbc.py find_function_call.py iif.py inline.py label.py macro.py macros.py opbases.py ops.py rationalize.py tailr.py version xapply.py Log Message: Adding products needed for migration of NZO === Added File Products/PythonMethod/zbytecodehacks/ChangeLog === 1999-12-11 Evan Simpson * Tupleizing and UntupleFunction now handle nested function definitions * Subdirectories reverted to v0.5 bytecodehacks, since the only change I've ever made was to accidentally change line endings in them to CRLF 1999-09-09 Evan Simpson * Tupleizing a function now omits globals * New UntupleFunction re-applies globals, with automatic initialization of variables to None, since there's no way to check if they exist. It also includes $functions, and checks __builtins__ handling. * Moved all bytecode manipulation into Munge_window class, which uses op.execute to maintain information about who did what to the stack. * Added Munger which re-enables creation of dictionary literals. * Made all Mungers load frequently used functions from the global dict into the local instead of storing them in co_consts. * Simplified GuardedOps and turned off test Guard. * Wrote lots of docstring. 1999-08-28 Evan Simpson * Ripped out Fleshy acquisition-style class and added CycleHandle in an attempt to improve speed. * code_editor.py: Added "as_tuple" to Function and EditableCode to provide (hopefully) pickleable representations. Their __init__s now accept these tuples. * Added VSExec.py (the point of all this), which provides facilities for compiling arbitrary blocks of code with heavy restrictions. 1999-06-11 Michael Hudson * a monumental amount has changed. I haven't been keeping the ChangeLog up to date, sorry. 1999-05-16 Michael Hudson * doc/bch.tex: documented macro and macros. * macros.py: added basic library of macros. * setq2.py: does same job as setq.py, but uses the new macro package. * macro.py It's a macro packages of sorts. Needs documentation. 1999-05-15 Michael Hudson * inline.py: Substantially rewritten to use find_function_call, and to support keyword arguments. No varags yet. * setq.py Added changes written by Christian Tismer (now converts globals to locals) 1999-05-13 Michael Hudson * Release 0.11 - cleaned up production of documentation following advice from the documentation master, Fred L. Drake. 1999-05-12 Michael Hudson * Release 0.10. * doc/ There's documentation (gasp) 1999-05-10 Michael Hudson * inline.py: Python now has inline functions! Bet you never expected that. * It's all changing again! Much polish, some docstrings, everything rewritten to use code_editor that wasn't already, many style fixes. 1999-05-06 Michael Hudson * attr_freeze.py: implement an attribute freezer that works. * xapply2.py: implement xapply for functions (again!) using the new code editing framework from code_editor.py. * code_editor.py: That's more like it! 1999-05-04 Michael Hudson * attr_freeze.py: implements a (buggy) attempt at freezing attribute references. * read_code.py,opbases.py,ops.py,write_ops.py, common.py,__init__.py: Much stuff added/changed. It not pretty or internally consistent yet. I might bash on it some more some time. I'm afraid I don't feel like explaining myself properly yet either. 1999-05-02 Michael Hudson * README,ChangeLog: Added. * xapply.py: Added, following prompting by Christian Tismer. * closure.py: Made improvements suggested by Tim Peters. === Added File Products/PythonMethod/zbytecodehacks/Makefile === SUBDIRS=tests code_gen doc clean: clean-local clean-recursive release: version src-release doc-release clean-local: $(RM) *.pyc *~ *.pyo clean-recursive: for i in $(SUBDIRS); do \ (cd $$i && make clean); \ done src-release: clean cd .. && ./mkdist.sh doc-release: clean cd doc && make release === Added File Products/PythonMethod/zbytecodehacks/README === Welcome to the bytecodehacks! There's docmentation in doc/; To build it you need an unpacked python source distribution somewhere, and for html output you also need latex2html. Build docs like this: $(path to Python source)/Doc/tools/mkhowto --$(format) (--a4) bch.tex You can get built html docs at ftp://starship.python.net/pub/crew/mwh/bytecodehacks-doc-$(VERSION).tar.gz. The bytecodehacks rewrite the bytecode of functions to do unlikely things in Python. The package (and that's how it's distributed) splits into two parts - the byte code editing routines and the "bytecodehacks" that are usuable without a degree in python arcanery, although one might help understand some of the consequences. Some highlights: bytecodehacks.closure - bind global references to constants bytecodehacks.xapply - a sort-of lazy apply bytecodehacks.setq - this one should interest people! bytecodehacks.inline - Python gets inline functions bytecodehacks.macro - Python gets semantic (hygenic) macros! Please note that these modules are not really bullet-proof, more a proof-of-concept than anything else. The are also public domain; do what you like with them. If you find bugs, or more imaginative uses for these techniques, I'd surely like to know! Thanks for taking an interest. === Added File Products/PythonMethod/zbytecodehacks/TODO === polish attr_freeze. === Added File Products/PythonMethod/zbytecodehacks/VSExec.py === '''Safe execution of arbitrary code through bytecode munging CodeBlock is a base class for bytecode munging of code strings. Derived classes should override 'forbid' and 'Mungers'. The class constructor takes a function name, a parameter string, and a function body string. It combines the name, parameters, and body into a function (indented one space), compiles it, and then examines its bytecode. Any bytecode whose opcode is a key in 'forbid' with a true value may not appear in the compiled code. Each object in 'Mungers' is called with the code window object (at start) and the variable name information for the function. Mungers can use this opportunity to examine the code and variables, and perform setup operations. The value returned from the call is discarded if false, otherwise it is assumed to be a collection of bytecode-specific functions. The code window object is passed over the bytecodes, maintaining a stack of "responsible" opcodes. At any given position, the size of the stack should be the same as the size of the run-time stack would be when that part of the code is executing, and the top of the stack would have been put there by the "responsible" opcode. At each position, the mungers are examined to see if they have a function corresponding to the current opcode. If so, the function is called with the code window object. The function can then use the code window object to examine or change the bytecode. Once all processing is done, and if there have not been any errors, the compiled, edited function is converted into a pickleable tuple, which is stored as attribute 't' of the resulting instance. In order for this to work, mungers must not place unpickleable objects into the list of constants. In order for unpickling to be robust, they should not place any function objects there either. If a function must be provided for use in the bytecode, it should be loaded from the global dictionary, preferably with an 'illegal' name. ''' from string import replace, join import ops, code_editor from closure import bind class Warning(Exception): pass class ForbiddenOp(Exception): pass general_special_globals = {} class Munge_window: def __init__(self, code, use_stack): self.code = code self.opn = -1 self.use_stack = use_stack if use_stack: self.stack = [] self.last_empty_stack = None def insert_code(self, rcode, at = None): opn = self.opn # rcode is passed as a (callables, args) pair rcode = map(apply, rcode[0], rcode[1]) if at is None: at = opn self.code[at:at]=rcode self.opn = opn + len(rcode) return rcode def set_code(self, rct = 1, rcode = ()): 'Replace "rct" bytecodes at current position with "rcode"' opn = self.opn # rcode is passed as a (callables, args) pair if rcode: rcode = map(apply, rcode[0], rcode[1]) self.code[opn:opn+rct] = rcode if self.use_stack: stack = self.stack for op in rcode: try: op.execute(stack) except: del stack[:] if not stack: self.last_empty_stack = op self.opn = opn + len(rcode) - 1 def advance(self): self.opn = opn = self.opn + 1 code = self.code if opn < len(code): self.op = code.opcodes[opn] self.opname = self.op.__class__.__name__ return 1 elif opn == len(code): # Hack! self.op = None self.opname = 'finalize' return 1 def do_op(self): if self.use_stack and self.op: op = self.op stack = self.stack try: op.execute(stack) except: del stack[:] if not stack: self.last_empty_stack = op def after_code_for(self, stack_idx): stack = self.stack if stack_idx < 0 and len(stack) + stack_idx < 0: whichop = self.last_empty_stack if whichop is None: return 0 else: whichop = stack[stack_idx] return self.code.index(whichop)+1 def assert_stack_size(self, size, ctxt): if self.use_stack and len(self.stack) != size: raise Warning, ('PythonMethod Bug: %s objects were on the stack ' '%s when only %s should be.' % (len(self.stack), ctxt, size)) class CodeBlock: '''Compile a string containing Python code, with restrictions''' forbid = {} Mungers = () globals = {'__builtins__': None} forbidden = "Forbidden operation %s at line %d" def __init__(self, name, paramstr, src): self.name = name self.src = src self.paramstr = paramstr self.f = None # Exec 'src' as a function body, indented one space, with empty globals # Waaa: triple-quoted strings will get indented too defns = {'__builtins__': None} defblk = 'def %s(%s):\n %s\n' % (name, self.paramstr , replace(self.src, '\n', '\n ')) exec defblk in defns block = defns[name] # Crack open the resulting function and munge it. f = code_editor.Function(block) f.func_globals = self.globals self.warnings, self.errors = [], [] self.munge_data = {} self.munge(f.func_code) if not self.errors: self.t = f.as_tuple() def munge(self, fc, depth=0): # Recurse into nested functions first for subcode in fc.subcodes: self.munge(subcode, depth+1) # Make the current recursion depth accessible self.depth = depth code = fc.co_code warnings, errors = self.warnings, self.errors # Initialize the Munge objects mungers = [] window = Munge_window(code, 1) margs = (self, window, fc) for M in self.Mungers: try: mungers.append(apply(M, margs)) except Exception, e: errors.append(e.__class__.__name__ + ', ' + str(e)) # Try to collect all initialization errors before failing if errors: return # Mungers which only perform an initial pass should return false mungers = filter(None, mungers) line = 0 ; forbid = self.forbid while window.advance(): op, opname = window.op, window.opname if isinstance(op, ops.SET_LINENO): line = op.arg window.do_op() elif op and forbid.get(op.op, 0): errors.append(self.forbidden % (opname, line)) window.do_op() #??? else: for m in mungers: handler = getattr(m, opname, None) if handler: try: # Return true to prevent further munging handled = handler(window) except ForbiddenOp: errors.append(self.forbidden % (opname, line)) except Exception, e: raise errors.append(e.__class__.__name__ + ', ' + str(e)) else: if not handled: continue break else: window.do_op() def __call__(self, *args, **kargs): F = code_editor.Function(self.t) F.func_globals = self.globals self.__call__ = f = F.make_function() return apply(f, args, kargs) def _print_handler(printlist, *txt): add = printlist.append if len(txt): if printlist and printlist[-1:] != ['\n']: add(' ') add(str(txt[0])) else: add('\n') def _join_printed(printlist): return join(printlist, '') _join_printed = bind(_join_printed, join=join, map=map, str=str) general_special_globals['$print_handler'] = _print_handler general_special_globals['$join_printed'] = _join_printed general_special_globals['$printed'] = None class Printing: '''Intercept print statements Print statements are either converted to no-ops, or replaced with calls to a handler. The default handler _print_handler appends the intended output to a list. 'printed' is made into a reserved name which can only be used to read the result of _join_printed. _print_handler and _join_printed should be provided in the global dictionary as $print_handler and $join_printed''' lfnames = (('$printed',), ('$print_handler',), ('$join_printed',)) print_prep = ( (ops.LOAD_FAST, ops.LOAD_FAST), (lfnames[1], lfnames[0]) ) get_printed = ( (ops.LOAD_FAST, ops.LOAD_FAST, ops.CALL_FUNCTION), (lfnames[2], lfnames[0], (1,)) ) init_printed = ( (ops.BUILD_LIST, ops.STORE_GLOBAL), ((0,), lfnames[0]) ) make_local = (ops.LOAD_GLOBAL, ops.STORE_FAST) call_print1 = ( (ops.CALL_FUNCTION, ops.POP_TOP), ((1,), ()) ) call_print2 = ( (ops.CALL_FUNCTION, ops.POP_TOP), ((2,), ()) ) def __init__(self, cb, w, fc): if 'printed' in fc.co_varnames: raise SyntaxError, '"printed" is a reserved word.' self.warnings, self.depth = cb.warnings, cb.depth self.md = cb.munge_data['Printing'] = cb.munge_data.get('Printing', {}) self.names_used = names_used = {} names = fc.co_names if 'printed' in names: names_used[0] = names.index('printed') names_used[2] = 1 else: self.LOAD_GLOBAL = None def finalize(self, w): names_used = self.names_used if names_used: # Load special names used by the function (and $printed always) ln = self.lfnames names_used[0] = 1 for i in names_used.keys(): w.insert_code( (self.make_local, (ln[i], ln[i])), 0) # Inform higher-level mungers of name usage self.md.update(names_used) if self.md and self.depth == 0: # Initialize the $printed variable in the base function w.insert_code(self.init_printed, 0) if not self.md.has_key(2): self.warnings.append( "Prints, but never reads 'printed' variable.") def PRINT_ITEM(self, w): # Load the printing function before the code for the operand. w.insert_code(self.print_prep, w.after_code_for(-2)) w.assert_stack_size(1, "at a 'print' statement") # Instead of printing, call our function and discard the result. w.set_code(1, self.call_print2) self.names_used[1] = 1 return 1 def PRINT_NEWLINE(self, w): w.assert_stack_size(0, "at a 'print' statement") w.insert_code(self.print_prep) w.set_code(1, self.call_print1) self.names_used[1] = 1 return 1 def LOAD_GLOBAL(self, w): if w.op.arg==self.names_used[0]: # Construct the print result instead of getting non-existent var. w.set_code(1, self.get_printed) return 1 def PublicNames(cb, w, fc): '''Restrict access to all but public names Forbid use of any multi-character name starting with _ ''' protected = [] for name in fc.co_names: if name[:1]=='_' and len(name)>1: protected.append(name) if protected: raise SyntaxError, ('Names starting with "_" are not allowed (%s).' % join(protected, ', ')) class AllowMapBuild: '''Allow literal mappings Construction of literal dictionaries requires STORE_SUBSCR, which is usually forbidden. Allow it by checking the stack.''' def __init__(self, cb, w, fc): pass def STORE_SUBSCR(self, w): if isinstance(w.stack[-2], ops.BUILD_MAP): return raise ForbiddenOp def _get_call(w): load_guard = ((ops.LOAD_FAST, ops.LOAD_ATTR), (('$guard',), (guard,))) # Load the binary guard function before its parameters are computed. iops = w.insert_code(load_guard, w.after_code_for(-3)) # Fix the execution stack to refer to the loaded function. if w.use_stack: w.stack[-2:-2] = iops[1:] # Call guard function instead of performing binary op w.set_code(1, cf2) return 1 def _SLICE(w): load_guard = ((ops.LOAD_FAST, ops.LOAD_ATTR, ops.ROT_TWO), (('$guard',), ('getslice',), ())) # Load the Slice guard and switch it with the argument. w.insert_code(load_guard, w.opn+1) # Call the slice guard after performing the slice. w.insert_code(cf1, w.opn+4) return 1 class _GuardedOps: def __call__(self, cb, w, fc): localize_guard = ( (ops.LOAD_GLOBAL, ops.STORE_FAST), (('$guard',),('$guard',)) ) # Insert setup code; no need to fix stack w.insert_code(localize_guard, 0) return self def GuardedOps(guards): '''Allow operations to be Guarded, by replacing them with guard calls. Construct a munging object which will replace specific opcodes with calls to methods of a guard object. The guard object must appear in the global dictionary as $guard.''' gops = _GuardedOps() opmap = (('mul', 'BINARY_MULTIPLY') ,('div', 'BINARY_DIVIDE') ,('power', 'BINARY_POWER') ,('getattr', 'LOAD_ATTR') ,('getitem', 'BINARY_SUBSCR')) cf1 = ((ops.CALL_FUNCTION,), ((1,),)) cf2 = ((ops.CALL_FUNCTION,), ((2,),)) for guard, defname in opmap: if hasattr(guards, guard): setattr(gops, defname, bind(_get_call, guard=guard, cf2=cf2)) if hasattr(guards, 'getslice'): gops.SLICE_3 = gops.SLICE_2 = gops.SLICE_1 = gops.SLICE_0 = bind(_SLICE, cf1=cf1) return gops class SafeBlock(CodeBlock): forbid = {ops.STORE_FAST.op: 0, ops.STORE_GLOBAL.op: 0, ops.STORE_SUBSCR.op: 0} for opclass in ops._bytecodes.values(): if forbid.get(opclass.op, 1): opname = opclass.__name__ if (opname[:6]=='STORE_' or opname[:7]=='DELETE_' or opname[:5]=='EXEC_'): forbid[opclass.op] = 1 Mungers = [Printing, PublicNames, AllowMapBuild] def UntupleFunction(t, special_globals, **globals): import new globals.update(general_special_globals) globals.update(special_globals) globals['global_exists'] = defined = globals.has_key if not defined('__builtins__'): globals['__builtins__'] = {} t = list(t) # Handle nested functions and lambdas t_code = t[2] if len(t_code) == 13: sub_codes = [t_code] funstack = [sub_codes] while funstack: if len(t_code) == 13: # This has nested code objects, so make it mutable sub_codes[0] = t_parent = t_code = list(t_code) # Put the list of nested codes on the stack for processing sub_codes = list(t_code.pop()) funstack.append(sub_codes) else: # This code tuple is fully processed, so untuple it func_code = apply(new.code, tuple(t_code)) # Find the first placeholder () in the parent's constants t_consts = list(t_parent[5]) # Replace the placeholder with the code object t_consts[t_consts.index(())] = func_code t_parent[5] = tuple(t_consts) # Clear it from the stack del sub_codes[0] # Get the next code tuple to process if not sub_codes: # Back up one level funstack.pop() sub_codes = funstack[-1] if len(funstack) > 1: t_parent = funstack[-2][0] else: funstack = None t_code = sub_codes[0] f = new.function(apply(new.code, tuple(t_code)), globals, t[0]) f.func_defaults = t[3] and tuple(t[3]) f.func_doc = t[1] return f if 0: #demonstrator Guard class Guard: def mul(self, a, b): if a*b>10: return 'ha!' else: return a*b def getslice(self, s): if len(s)>2: raise "Too long a slice!" return s def test(p, c): sb = SafeBlock('f', p, c) print sb.errors, sb.warnings f = code_editor.Function(sb.t) for c in f.func_code.co_code: print c for subcode in f.func_code.subcodes: for c in subcode.co_code: print ' ', c return sb if __name__ == '__main__': sb = test('x', '''\ print x def plus1(x): print x+1 plus1(x) return printed''') f = UntupleFunction(sb.t, {}) #from dis import dis #dis(f) print f(2), print f(3), === Added File Products/PythonMethod/zbytecodehacks/__init__.py === __all__=[ 'closure', 'xapply', 'common', 'inline', 'code_editor', 'opbases', 'ops', 'attr_freeze', 'code_gen'] === Added File Products/PythonMethod/zbytecodehacks/attr_freeze.py === from code_editor import Function from ops import LOAD_GLOBAL, LOAD_ATTR, LOAD_CONST def freeze_one_attr(cs,code,attr,value): looking_for=0 is_global=1 inserted=0 i = 0 while i < len(cs): op=cs[i] if is_global: if op.__class__ is LOAD_GLOBAL: if code.co_names[op.arg]==attr[looking_for]: looking_for=looking_for+1 is_global=0 else: if op.__class__ is LOAD_ATTR \ and code.co_names[op.arg]==attr[looking_for]: looking_for=looking_for+1 if looking_for == len(attr): inserted=1 newop=LOAD_CONST(len(code.co_consts)) cs[i-len(attr)+1:i+1]=[newop] i=i-len(attr) looking_for=0 is_global=1 else: looking_for=0 is_global=1 i=i+1 if inserted: code.co_consts.append(value) return cs class Ref: def __init__(self,name=()): self.name=name def __getattr__(self,attr): return Ref(self.name+(attr,)) def __call__(self): return self.name def __repr__(self): return `self.name` def freeze_attrs(func,*vars): func=Function(func) code=func.func_code cs=code.co_code if len(vars)%2 <> 0: raise TypeError, "wrong number of arguments" for i in range(0,len(vars),2): freeze_one_attr(cs,code,vars[i](),vars[i+1]) return func.make_function() === Added File Products/PythonMethod/zbytecodehacks/closure.py === """\ closure implements a form of closures by abusing the co_consts field of a code object. exports: bind, bind_locals, bind_now and contains two examples: make_adder, make_balance """ from code_editor import Function from ops import * def scan_for_STORE(func,name): for i in func.func_code.co_code: if i.__class__ in [STORE_FAST,STORE_NAME,STORE_GLOBAL] \ and i.name == name: return 1 return 0 def bind(function,newname=None,**vars): """\ bind(function[,newname],var1=value1,var2=value2,...) -> function returns a new function (optionally renamed) where every reference to one of var1, var2, etc is replaced by a reference to the respective valueN.""" func = Function(function) code = func.func_code cs = func.func_code.co_code name2index = {} mutated = {} for name in vars.keys(): mutated[name] = scan_for_STORE(func,name) if 0 in code.co_consts: zeroIndex = code.co_consts.index(0) else: zeroIndex = len(code.co_consts) code.co_consts.append(0) i = 0 while i < len(cs): op = cs[i] i = i + 1 # should LOAD_NAME be here??? tricky, I'd say if op.__class__ in [LOAD_GLOBAL,LOAD_NAME,LOAD_FAST]: if not vars.has_key(op.name): continue if mutated[name]: if not name2index.has_key(op.name): name2index[op.name]=len(code.co_consts) code.co_consts.append([vars[op.name]]) cs[i-1:i] = [LOAD_CONST(name2index[op.name]), LOAD_CONST(zeroIndex), BINARY_SUBSCR()] i = i + 2 else: if not name2index.has_key(op.name): name2index[op.name]=len(code.co_consts) code.co_consts.append(vars[op.name]) cs[i-1] = LOAD_CONST(name2index[op.name]) elif op.__class__ in [STORE_FAST,STORE_NAME,STORE_GLOBAL]: if not vars.has_key(op.name): continue if not mutated[name]: continue # shouldn't be reached cs[i-1:i] = [LOAD_CONST(name2index[op.name]), LOAD_CONST(zeroIndex), STORE_SUBSCR()] i = i + 2 if newname is not None: func.func_name = newname return func.make_function() bind=Function(bind) bind.func_code.co_varnames[0]='$function' bind.func_code.co_varnames[1]='$newname' bind=bind.make_function() def bind_locals(func): """bind_locals(func) -> function returns a new function where every global variable reference in func is replaced, if possible, by a reference to a local variable in the callers context.""" try: raise "" except: import sys frame = sys.exc_traceback.tb_frame.f_back name = func.func_name+'+' l = apply(bind,(func,name),frame.f_locals) frame = None return l def bind_now(func): """bind_now(func) -> function returns a new function where every global variable reference in func is replaced, if possible, by a reference to a variable in the callers context.""" try: raise "" except: import sys frame = sys.exc_traceback.tb_frame.f_back l = apply(bind,(func,),frame.f_locals) g = apply(bind,(l,),frame.f_globals) frame = None return g ## examples def make_adder(n): """make_adder(n) -> function return a monadic function that adds n to its argument.""" def adder(x): return x+n return bind_locals(adder) def make_balance(initial_amount): """make_balance(initial_amount) -> function demonstrates an object with state, sicp style.""" def withdraw(amount): if current[0]) # behaves like list of opcodes, eg # len(mc) => number of bytecodes in code # mc[i] returns some representation of the ith opcode # mc.assemble() => codestring, or maybe code object. import types,StringIO,struct,new import ops from cyclehandle import CycleHandle class CodeString(CycleHandle): def __init__(self,cs=None,bytecodes=None): self._set_workers(CodeStringWorker(cs, bytecodes)) class CodeStringWorker: def __init__(self,cs,bytecodes): self.labels=[] self.byte2op={} self.opcodes=[] if bytecodes is None: bytecodes = ops._bytecodes if type(cs) is type(""): self.disassemble_no_code(cs,bytecodes) else: self.disassemble(cs,bytecodes) def disassemble(self,code,bytecodes): self.labels = [] self.byte2op = {} self.opcodes = [] self.code = code cs=StringIO.StringIO(code.co_code) i, op, n = 0, 0, len(code.co_code) while i < n: self.byte2op[i]=op byte=cs.read(1) self.opcodes.append(bytecodes[byte](cs,self)) i = cs.tell() op = op + 1 del self.code for label in self.labels: label.resolve(self) def disassemble_no_code(self,codestring,bytecodes): self.labels = [] self.byte2op = {} self.opcodes = [] cs=StringIO.StringIO(codestring) i, op, n = 0, 0, len(codestring) while i < n: self.byte2op[i]=op byte=cs.read(1) self.opcodes.append(bytecodes[byte](cs,self)) i = cs.tell() op = op + 1 for label in self.labels: label.resolve(self) def add_label(self,label): self.labels.append(label) def find_labels(self,index): labelled=self.opcodes[index] pointees=[] for l in self.labels: if l.op == labelled: pointees.append(l) return pointees def __getitem__(self,index): return self.opcodes[index] def __setitem__(self,index,value): # find labels that point to the removed opcode pointees=self.find_labels(index) if self.opcodes[index].is_jump(): self.labels.remove(self.opcodes[index].label) self.opcodes[index]=value for l in pointees: l.op=value if value.is_jump(): self.labels.append(value.label) def __delitem__(self,index): # labels that pointed to the deleted item get attached to the # following insn (unless it's the last insn - in which case I # don't know what you're playing at, but I'll just point the # label at what becomes the last insn) pointees=self.find_labels(index) if index + 1 == len(self.opcodes): replacement = self.opcodes[index] else: replacement = self.opcodes[index + 1] for l in pointees: l.op=replacement going=self.opcodes[index] if going.is_jump(): self.labels.remove(going.label) del self.opcodes[index] def __getslice__(self,lo,hi): return self.opcodes[lo:hi] def __setslice__(self,lo,hi,values): # things that point into the block being stomped on get # attached to the start of the new block (if there are labels # pointing into the block, rather than at its start, a warning # is printed, 'cause that's a bit dodgy) pointees=[] opcodes = self.opcodes indices=range(len(opcodes))[lo:hi] for i in indices: if opcodes[i].is_jump(): self.labels.remove(opcodes[i].label) p=self.find_labels(i) if p and i <> lo: print "What're you playing at?" pointees.extend(p) codes = [] for value in values: if value.is_jump(): self.labels.append(value.label) codes.append(value) opcodes[lo:hi]=codes replacement = opcodes[min(lo, len(opcodes)-1)] for l in pointees: l.op = replacement def __delslice__(self,lo,hi): self.__setslice__(lo, hi, []) def __len__(self): return len(self.opcodes) def append(self,value): self.opcodes.append(value) if value.is_jump(): self.labels.append(value.label) def insert(self,index,value): self.opcodes.insert(index,value) if value.is_jump(): self.labels.append(value.label) def remove(self,x): del self[self.opcodes.index(x)] def index(self,x): return self.opcodes.index(x) def assemble(self): out=StringIO.StringIO() for i in self: i.byte=out.tell() out.write(i.assemble(self)) for l in self.labels: l.write_refs(out) out.seek(0) return out.read() def set_code(self, code): self.code = code class EditableCode(CycleHandle): def __init__(self,code=None): self._set_workers(EditableCodeWorker(code)) class EditableCodeWorker: # bits for co_flags CO_OPTIMIZED = 0x0001 CO_NEWLOCALS = 0x0002 CO_VARARGS = 0x0004 CO_VARKEYWORDS = 0x0008 AUTO_RATIONALIZE = 0 def __init__(self,code=None): if code is None: self.init_defaults() elif type(code) in (type(()), type([])): self.init_tuple(code) else: self.init_code(code) self.co_code.set_code(self) def name_index(self,name): if name not in self.co_names: self.co_names.append(name) return self.co_names.index(name) def local_index(self,name): if name not in self.co_varnames: self.co_varnames.append(name) return self.co_varnames.index(name) def rationalize(self): from rationalize import rationalize rationalize(self) def init_defaults(self): self.co_argcount = 0 self.co_stacksize = 0 # ??? self.co_flags = 0 # ??? self.co_consts = [] self.co_names = [] self.co_varnames = [] self.co_filename = '' self.co_name = 'no name' self.co_firstlineno = 0 self.co_lnotab = '' # ??? self.co_code = CodeString() self.subcodes = [] def init_code(self,code): self.co_argcount = code.co_argcount self.co_stacksize = code.co_stacksize self.co_flags = code.co_flags self.co_consts = consts = list(code.co_consts) self.co_names = list(code.co_names) self.co_varnames = list(code.co_varnames) self.co_filename = code.co_filename self.co_name = code.co_name self.co_firstlineno = code.co_firstlineno self.co_lnotab = code.co_lnotab self.co_code = CodeString(code) self.subcodes = subcodes = [] from types import CodeType for i in range(len(consts)): if type(consts[i]) == CodeType: subcodes.append(EditableCode(consts[i])) consts[i] = () def init_tuple(self,tup): self.subcodes = [] if len(tup)==13: self.subcodes = map(EditableCode, tup[-1]) tup = tup[:-1] ( self.co_argcount, ignored, self.co_stacksize, self.co_flags , self.co_code, co_consts, co_names, co_varnames, self.co_filename , self.co_name, self.co_firstlineno, self.co_lnotab ) = tup self.co_consts = list(co_consts) self.co_names = list(co_names) self.co_varnames = list(co_varnames) self.co_code = CodeString(self) def make_code(self): if self.AUTO_RATIONALIZE: self.rationalize() else: # hack to deal with un-arg-ed names for op in self.co_code: if (op.has_name() or op.has_local()) and not hasattr(op, "arg"): if op.has_name(): op.arg = self.name_index(op.name) else: op.arg = self.local_index(op.name) return apply(new.code, self.as_tuple()[:12]) def set_function(self, function): self.function = function def as_tuple(self): # the assembling might change co_names or co_varnames - so # make sure it's done *before* we start gathering them. bytecode = self.co_code.assemble() subcodes = [] for subcode in self.subcodes: subcodes.append(subcode.as_tuple()) return ( self.co_argcount, len(self.co_varnames), self.co_stacksize, self.co_flags, bytecode, tuple(self.co_consts), tuple(self.co_names), tuple(self.co_varnames), self.co_filename, self.co_name, self.co_firstlineno, self.co_lnotab, tuple(subcodes)) class Function(CycleHandle): def __init__(self,func=None): self._set_workers(FunctionWorker(func)) class FunctionWorker: def __init__(self,func): if func is None: self.init_defaults() elif type(func) in (type(()), type([])): self.init_tuple(func) else: self.init_func(func) self.func_code.set_function(self) def init_defaults(self): self.__name = "no name" self.__doc = None self.func_code = EditableCode() self.func_defaults = [] self.func_globals = {} # ??? def init_func(self,func): self.__name = func.func_name self.__doc = func.func_doc self.func_code = EditableCode(func.func_code) self.func_defaults = func.func_defaults self.func_globals = func.func_globals def init_tuple(self,tup): ( self.__name, self.__doc, func_code, self.func_defaults , self.func_globals ) = tup self.func_code = EditableCode(func_code) def __getattr__(self,attr): # for a function 'f.__name__ is f.func_name' # so lets hack around to support that... if attr in ['__name__','func_name']: return self.__name if attr in ['__doc__','func_doc']: return self.__doc raise AttributeError, attr def __setattr__(self,attr,value): if attr in ['__name__','func_name']: self.__name = value elif attr in ['__doc__','func_doc']: self.__doc = value else: self.__dict__[attr]=value def make_function(self): newfunc = new.function( self.func_code.make_code(), self.func_globals, self.__name) if not self.func_defaults: defs=None else: defs=tuple(self.func_defaults) newfunc.func_defaults = defs newfunc.func_doc = self.__doc return newfunc def __call__(self,*args,**kw): return apply(self.make_function(),args,kw) def set_method(self, method): self.method = method def as_tuple(self): if not self.func_defaults: defs=None else: defs=tuple(self.func_defaults) return (self.__name, self.__doc, self.func_code.as_tuple(), defs, {}) class InstanceMethod(CycleHandle): def __init__(self,meth=None): self._set_workers(InstanceMethodWorker(meth)) class InstanceMethodWorker: def __init__(self,meth): if meth is None: self.init_defaults() else: self.init_meth(meth) self.im_func.set_method(self) def init_defaults(self): self.im_class = None self.im_func = Function() self.im_self = None def init_meth(self,meth): self.im_class = meth.im_class self.im_func = Function(meth.im_func) self.im_self = meth.im_self def make_instance_method(self): return new.instancemethod( self.im_func.make_function(), self.im_self,self.im_class) class FunctionOrMethod: def __init__(self,functionormethod): if type(functionormethod) is types.FunctionType: self.is_method = 0 self.function = Function(functionormethod) elif type(functionormethod) is types.UnboundMethodType: self.is_method = 1 self.method = InstanceMethod(functionormethod) self.function = self.method.im_func def make_function_or_method(self): if self.is_method: return self.method.make_instance_method() else: return self.function.make_function() === Added File Products/PythonMethod/zbytecodehacks/common.py === import new def copy_code_with_changes(codeobject, argcount=None, nlocals=None, stacksize=None, flags=None, code=None, consts=None, names=None, varnames=None, filename=None, name=None, firstlineno=None, lnotab=None): if argcount is None: argcount = codeobject.co_argcount if nlocals is None: nlocals = codeobject.co_nlocals if stacksize is None: stacksize = codeobject.co_stacksize if flags is None: flags = codeobject.co_flags if code is None: code = codeobject.co_code if consts is None: consts = codeobject.co_consts if names is None: names = codeobject.co_names if varnames is None: varnames = codeobject.co_varnames if filename is None: filename = codeobject.co_filename if name is None: name = codeobject.co_name if firstlineno is None: firstlineno = codeobject.co_firstlineno if lnotab is None: lnotab = codeobject.co_lnotab return new.code(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab) code_attrs=['argcount', 'nlocals', 'stacksize', 'flags', 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'firstlineno', 'lnotab'] === Added File Products/PythonMethod/zbytecodehacks/cyclehandle.py === class CycleHandle: '''CycleHandles are proxies for cycle roots A CycleHandle subclass should create one or more workers, and pass them to _set_workers. These workers can then participate in cycles, as long as deleting all of the worker's attributes will break the cycle. When a CycleHandle instance goes away, it deletes all attributes of all of its workers. You could also explicitly call drop_workers. For example, >>> class Ham: ... def __del__(self): ... print 'A ham has died!' ... >>> ct = CycleHandle() >>> ct._set_workers(Ham(), Ham()) >>> ct._workers[0].ham2 = ct._workers[1] >>> ct._workers[1].ham1 = ct._workers[0] >>> del ct A ham has died! A ham has died! ''' _workers = () def _set_workers(self, *workers): self.__dict__['_workers'] = workers def _not_mutable(self, *x): raise TypeError, 'CycleHandle is not mutable' _not_mutable_defs = ('__delslice__', '__setslice__', '__delitem__' , '__setitem__', '__delattr__', '__setattr__') def __getattr__(self, attr): for worker in self._workers: if hasattr(worker, attr): return getattr(worker, attr) if attr in self._not_mutable_defs: return self._not_mutable raise AttributeError, attr def _drop_workers(self): for worker in self._workers: worker.__dict__.clear() self.__dict__['_workers'] = () def __del__(self, drop_workers=_drop_workers): drop_workers(self) def _test(): import doctest, cyclehandle return doctest.testmod(cyclehandle) if __name__ == "__main__": _test() === Added File Products/PythonMethod/zbytecodehacks/dbc.py === from code_editor import Function from ops import * import dis,new,string PRECONDITIONS = 1 POSTCONDITIONS = 2 INVARIANTS = 4 EVERYTHING = PRECONDITIONS|POSTCONDITIONS|INVARIANTS if __debug__: __strength__ = PRECONDITIONS|POSTCONDITIONS else: __strength__ = 0 # TODO: docs, sort out inheritance. if __debug__: def add_contracts(target_class,contract_class,strength=None): if strength is None: strength = __strength__ newmethods = {} contractmethods = contract_class.__dict__ if strength & INVARIANTS: inv = contractmethods.get("class_invariants",None) for name, meth in target_class.__dict__.items(): if strength & PRECONDITIONS: pre = contractmethods.get("pre_"+name,None) if pre is not None: meth = add_precondition(meth,pre) if strength & POSTCONDITIONS: post = contractmethods.get("post_"+name,None) if post is not None: meth = add_postcondition(meth,post) if (strength & INVARIANTS) and inv \ and type(meth) is type(add_contracts): if name <> '__init__': meth = add_precondition(meth,inv) meth = add_postcondition(meth,inv) newmethods[name] = meth return new.classobj(target_class.__name__, target_class.__bases__, newmethods) def add_precondition(meth,cond): meth = Function(meth) cond = Function(cond) mcs = meth.func_code.co_code ccs = cond.func_code.co_code nlocals = len(meth.func_code.co_varnames) nconsts = len(meth.func_code.co_consts) nnames = len(meth.func_code.co_names) nargs = meth.func_code.co_argcount retops = [] for op in ccs: if op.__class__ is RETURN_VALUE: # RETURN_VALUEs have to be replaced by JUMP_FORWARDs newop = JUMP_FORWARD() ccs[ccs.index(op)] = newop retops.append(newop) elif op.op in dis.hasname: op.arg = op.arg + nnames elif op.op in dis.haslocal: if op.arg >= nargs: op.arg = op.arg + nlocals elif op.op in dis.hasconst: op.arg = op.arg + nconsts new = POP_TOP() mcs.insert(0,new) mcs[0:0] = ccs.opcodes for op in retops: op.label.op = new meth.func_code.co_consts.extend(cond.func_code.co_consts) meth.func_code.co_varnames.extend(cond.func_code.co_varnames) meth.func_code.co_names.extend(cond.func_code.co_names) return meth.make_function() def add_postcondition(meth,cond): """ a bit of a monster! """ meth = Function(meth) cond = Function(cond) mcode = meth.func_code ccode = cond.func_code mcs = mcode.co_code ccs = ccode.co_code nlocals = len(mcode.co_varnames) nconsts = len(mcode.co_consts) nnames = len(mcode.co_names) nargs = ccode.co_argcount cretops = [] Result_index = len(meth.func_code.co_varnames) mcode.co_varnames.append('Result') old_refs = find_old_refs(cond) for op in ccs: if op.__class__ is RETURN_VALUE: newop = JUMP_FORWARD() ccs[ccs.index(op)] = newop cretops.append(newop) elif op.op in dis.hasname: if cond.func_code.co_names[op.arg] == 'Result' \ and op.__class__ is LOAD_GLOBAL: ccs[ccs.index(op)] = LOAD_FAST(Result_index) else: op.arg = op.arg + nnames elif op.op in dis.haslocal: if op.arg >= nargs: op.arg = op.arg + nlocals + 1 # + 1 for Result elif op.op in dis.hasconst: op.arg = op.arg + nconsts # lets generate the prologue code to save values for `Old' # references and point the LOAD_FASTs inserted by # find_old_refs to the right locations. prologue = [] for ref, load_op in old_refs: if ref[0] in mcode.co_varnames: prologue.append(LOAD_FAST(mcode.co_varnames.index(ref[0]))) else: prologue.append(LOAD_GLOBAL(mcode.name_index(ref[0]))) for name in ref[1:]: prologue.append(LOAD_ATTR(mcode.name_index(name))) lname = string.join(ref,'.') lindex = len(mcode.co_varnames) mcode.co_varnames.append(lname) prologue.append(STORE_FAST(lindex)) load_op.arg = lindex mcs[0:0] = prologue mretops = [] for op in mcs: if op.__class__ is RETURN_VALUE: newop = JUMP_FORWARD() mcs[mcs.index(op)] = newop mretops.append(newop) n = len(mcs) # insert the condition code mcs[n:n] = ccs.opcodes # store the returned value in Result store_result = STORE_FAST(Result_index) mcs.insert(n, store_result) # target the returns in the method to this store for op in mretops: op.label.op = store_result # the post condition will leave a value on the stack; lose it. # could just strip off the LOAD_CONST & RETURN_VALLUE at the # end of the function and scan for RETURN_VALUES in the # postcondition as a postcondition shouldn't be returning # things (certainly not other than None). new = POP_TOP() mcs.append(new) # redirect returns in the condition to the POP_TOP just # inserted... for op in cretops: op.label.op = new # actually return Result... mcs.append(LOAD_FAST(Result_index)) mcs.append(RETURN_VALUE()) # and add the new constants and names (to avoid core dumps!) mcode.co_consts .extend(ccode.co_consts ) mcode.co_varnames.extend(ccode.co_varnames) mcode.co_names .extend(ccode.co_names ) return meth.make_function() def find_old_refs(func): chaining = 0 refs = [] ref = [] code = func.func_code cs = code.co_code i = 0 while i < len(cs): op=cs[i] if not chaining: if op.__class__ is LOAD_GLOBAL: if code.co_names[op.arg]=='Old': chaining=1 else: if op.__class__ is LOAD_ATTR: ref.append(code.co_names[op.arg]) else: newop = LOAD_FAST(0) cs[i-len(ref)-1:i] = [newop] i = i - len(ref) refs.append((ref,newop)) ref = [] chaining = 0 i=i+1 return refs else: # if not __debug__ def add_contracts(target_class,contracts_class): return target_class # example class Uncontracted: def __init__(self,x,y): self.x=x self.y=y def do(self): # self.x = self.x + 1 # sneaky! return self.x/self.y class Contracts: def pre___init__(self,x,y): assert y <> 0 def post_do(self): assert Old.self.x == self.x assert Old.self.y == self.y assert Result > 0, "Result was %s"%`Result` def class_invariants(self): assert self.x > 0 Contracted = add_contracts(Uncontracted,Contracts) === Added File Products/PythonMethod/zbytecodehacks/find_function_call.py === from code_editor import Function from ops import * def find_function_call(infunc,calledfuncname, allowkeywords=0, startindex=0): i = startindex code = infunc.func_code cs = code.co_code def match(op,name = calledfuncname): return getattr(op,'name',None) == name while i < len(cs): op = code.co_code[i] if match(op): try: if allowkeywords: return simulate_stack_with_keywords(code,i) else: return simulate_stack(code,i) except: i = i + 1 i = i + 1 if allowkeywords: return None,0 else: return None def call_stack_length_usage(arg): num_keyword_args=arg>>8 num_regular_args=arg&0xFF return 2*num_keyword_args + num_regular_args def simulate_stack(code,index_start): stack = [] cs = code.co_code i, n = index_start, len(cs) while i < n: op = cs[i] if op.__class__ is CALL_FUNCTION and op.arg+1==len(stack): stack.append(op) return stack elif op.is_jump(): i = cs.index(op.label.op)+1 else: op.execute(stack) i = i + 1 raise "no call found!" def simulate_stack_with_keywords(code,index_start): stack = [] cs = code.co_code i, n = index_start, len(cs) while i < n: op = cs[i] if op.__class__ is CALL_FUNCTION \ and call_stack_length_usage(op.arg)+1==len(stack): stack.append(op) return stack, op.arg>>8 elif op.is_jump(): i = cs.index(op.label.op)+1 else: op.execute(stack) i = i + 1 raise "no call found!" === Added File Products/PythonMethod/zbytecodehacks/iif.py === from code_editor import Function from ops import * from find_function_call import find_function_call def iifize(func): func = Function(func) cs = func.func_code.co_code while 1: stack = find_function_call(func,"iif") if stack is None: break load, test, consequent, alternative, call = stack cs.remove(load) jump1 = JUMP_IF_FALSE(alternative) cs.insert(cs.index(test)+1,jump1) jump2 = JUMP_FORWARD(call) cs.insert(cs.index(consequent)+1,jump2) cs.remove(call) cs = None return func.make_function() === Added File Products/PythonMethod/zbytecodehacks/inline.py === import dis from code_editor import Function from find_function_call import find_function_call from ops import \ LOAD_GLOBAL, RETURN_VALUE, SET_LINENO, CALL_FUNCTION, \ JUMP_FORWARD, STORE_FAST INLINE_MAX_DEPTH = 100 def inline(func, **funcs): func = Function(func) code = func.func_code for name, function in funcs.items(): count = inline1(func, name, function) if count <> 0: fcode=function.func_code code.co_consts=code.co_consts+list(fcode.co_consts) code.co_varnames=code.co_varnames+list(fcode.co_varnames) code.co_names=code.co_names+list(fcode.co_names) code.co_stacksize=code.co_stacksize+fcode.co_stacksize return func.make_function() def munge_code(function,code): f = Function(function) fcs = f.func_code.co_code i, n = 0, len(fcs) retops = [] while i < n: op = fcs[i] if op.__class__ is RETURN_VALUE: # RETURN_VALUEs have to be replaced by JUMP_FORWARDs newop = JUMP_FORWARD() fcs[i] = newop retops.append(newop) elif op.op in dis.hasname: op.arg = op.arg + len(code.co_names) elif op.op in dis.haslocal: op.arg = op.arg + len(code.co_varnames) elif op.op in dis.hasconst: op.arg = op.arg + len(code.co_consts) # should we hack out SET_LINENOs? doesn't seem worth it. i = i + 1 return fcs.opcodes, retops def inline1(func,funcname,function): code = func.func_code cs = code.co_code count = 0 defaults_added = 0 while count < INLINE_MAX_DEPTH: stack, numkeywords = find_function_call(func,funcname,allowkeywords=1) if stack is None: return count count = count + 1 load_func, posargs, kwargs, function_call = \ stack[0], stack[1:-2*numkeywords-1], stack[-2*numkeywords-1:-1], stack[-1] kw={} for i in range(0,len(kwargs),2): name = code.co_consts[kwargs[i].arg] valuesrc = kwargs[i+1] kw[name] = valuesrc varnames = list(function.func_code.co_varnames) for i in kw.keys(): if i in varnames: if varnames.index(i) < len(posargs): raise TypeError, "keyword parameter redefined" else: raise TypeError, "unexpected keyword argument: %s"%i # no varargs yet! # flags = function.func_code.co_flags # varargs = flags & (1<<2) # varkeys = flags & (1<<3) args_got = len(kw) + len(posargs) args_expected = function.func_code.co_argcount if args_got > args_expected: raise TypeError,"too many arguments; expected %d, got %d"%(ac,len(lf) + len(posargs)) elif args_got < args_expected: # default args? raise TypeError,"not enough arguments; expected %d, got %d"%(ac,len(lf) + len(posargs)) cs.remove(load_func) local_index = len(code.co_varnames) for insn in posargs: new = STORE_FAST(local_index) cs.insert(cs.index(insn)+1,new) labels = cs.find_labels(cs.index(new)+1) for label in labels: label.op = new local_index = local_index + 1 for name, insn in kw.items(): new = STORE_FAST(varnames.index(name) + len(code.co_varnames)) cs.insert(cs.index(insn)+1,new) labels = cs.find_labels(cs.index(new)+1) for label in labels: label.op = new newops, retops = munge_code(function,code) call_index = cs.index(function_call) nextop = cs[call_index + 1] cs[call_index:call_index + 1] = newops for op in retops: op.label.op = nextop raise RuntimeError, "are we trying to inline a recursive function here?" === Added File Products/PythonMethod/zbytecodehacks/label.py === import struct class Label: def __init__(self,byte=None): self.byte=byte self.__op=None self.absrefs=[] self.relrefs=[] def resolve(self,code): self.__op=code.opcodes[code.byte2op[self.byte]] def add_absref(self,byte): # request that the absolute address of self.op be written to # the argument of the opcode starting at byte in the # codestring self.absrefs.append(byte) def add_relref(self,byte): # request that the relative address of self.op be written to # the argument of the opcode starting at byte in the # codestring self.relrefs.append(byte) def __setattr__(self,attr,value): if attr == 'op': self.__op = value else: self.__dict__[attr] = value def __getattr__(self,attr): if attr == 'op': return self.__op else: raise AttributeError, attr def write_refs(self,cs): address=self.__op.byte for byte in self.absrefs: cs.seek(byte+1) cs.write(struct.pack(' 0 and not insertions.has_key(macro): fcode=macro.func_code code.co_consts=code.co_consts+list(fcode.co_consts) code.co_varnames=code.co_varnames+list(fcode.co_varnames) code.co_names=code.co_names+list(fcode.co_names) code.co_stacksize=code.co_stacksize+fcode.co_stacksize insertions[macro] = 0 if not outercount: return func.make_function() trips = trips + 1 raise RuntimeError, "unbounded recursion?!" def expand_these(func,**macros): return expand(func,macros) def remove_epilogue(cs): try: last,butone,buttwo = cs[-3:] except: return if last.__class__ is buttwo.__class__ is RETURN_VALUE: if butone.__class__ is LOAD_CONST: if cs.code.co_consts[butone.arg] is None: if not (cs.find_labels(-1) or cs.find_labels(-2)): del cs[-2:] def munge_code(function,code,imported_locals): f = Function(function) fcs = f.func_code.co_code if fcs[0].__class__ is SET_LINENO: del fcs[1:1 + 2*len(imported_locals)] else: del fcs[0:2*len(imported_locals)] # a nicety: let's see if the last couple of opcodes are necessary # (Python _always_ adds a LOAD_CONST None, RETURN_VALUE to the end # of a function, and I'd like to get rid of that if we can). remove_epilogue(fcs) i, n = 0, len(fcs) retops = [] while i < n: op = fcs[i] if op.__class__ is RETURN_VALUE: # RETURN_VALUEs have to be replaced by JUMP_FORWARDs newop = JUMP_FORWARD() fcs[i] = newop retops.append(newop) elif op.op in dis.hasname: op.arg = op.arg + len(code.co_names) elif op.op in dis.haslocal: localname = f.func_code.co_varnames[op.arg] op.arg = imported_locals.get(localname,op.arg + len(code.co_varnames)) elif op.op in dis.hasconst: op.arg = op.arg + len(code.co_consts) # should we hack out SET_LINENOs? doesn't seem worth it. i = i + 1 return fcs.opcodes, retops def expand1(func,name,macro): code = func.func_code cs = code.co_code count = 0 macrocode = macro.func_code while count < MAX_MACRO_DEPTH: stack = find_function_call(func,name) if stack is None: return count count = count + 1 load_func, args, function_call = \ stack[0], stack[1:-1], stack[-1] args_got = len(args) args_expected = macrocode.co_argcount if args_got > args_expected: raise TypeError,"too many arguments; expected %d, got %d"%(args_expected,args_got) elif args_got < args_expected: # default args? raise TypeError,"not enough arguments; expected %d, got %d"%(args_expected,args_got) cs.remove(load_func) arg_names = macrocode.co_varnames[:macrocode.co_argcount] import_args = [] normal_args = [] for i in range(len(arg_names)): if arg_names[i][0] == '.': import_args.append(args[i]) else: normal_args.append(args[i]) imported_locals = {} for insn in import_args: cs.remove(insn) if insn.__class__ is LOAD_GLOBAL: name = code.co_names[insn.arg] var = global_to_local(code, name) elif insn.__class__ is not LOAD_FAST: raise TypeError, "imported arg must be local" else: var = insn.arg argindex = macrocode.co_argcount + import_args.index(insn) argname = macrocode.co_varnames[argindex] imported_locals[argname] = var local_index = len(code.co_varnames) for insn in normal_args: new = STORE_FAST(local_index + args.index(insn)) cs.insert(cs.index(insn)+1,new) labels = cs.find_labels(cs.index(new)+1) for label in labels: label.op = new newops, retops = munge_code(macro,code,imported_locals) call_index = cs.index(function_call) nextop = cs[call_index + 1] cs[call_index:call_index + 1] = newops for op in retops: if cs.index(nextop) - cs.index(op) == 1: cs.remove(op) else: op.label.op = nextop raise RuntimeError, "are we trying to expand a recursive macro here?" def global_to_local(code, name): """\ internal function to make a global variable into a local one, for the case that setq is the first reference to a variable. Modifies a code object in-place. Return value is index into variable table """ cs = code.co_code index = len(code.co_varnames) code.co_varnames.append(name) for i in range(len(cs)): op = cs[i] if op.__class__ not in [LOAD_GLOBAL,STORE_GLOBAL]: continue thisname = code.co_names[op.arg] if thisname <> name: continue if op.__class__ is LOAD_GLOBAL: cs[i] = LOAD_FAST(index) else: cs[i] = STORE_FAST(index) return index === Added File Products/PythonMethod/zbytecodehacks/macros.py === from macro import add_macro def main(): def setq((x),v): x = v return v add_macro(setq) def pre_incr((x)): x = x + 1 return x add_macro(pre_incr) def post_incr((x)): t = x x = x + 1 return t add_macro(post_incr) def pre_decr((x)): x = x - 1 return x add_macro(pre_decr) def post_decr((x)): t = x x = x + 1 return t add_macro(post_decr) def add_set((x),v): x = x + v return x add_macro(add_set) def sub_set((x),v): x = x - v return x add_macro(sub_set) def mul_set((x),v): x = x * v return x add_macro(mul_set) def div_set((x),v): x = x / v return x add_macro(div_set) def mod_set((x),v): x = x % v return x add_macro(mod_set) main() def test(): from macro import expand def f(x): i = 0 while pre_incr(i) < len(x): if setq(c, x[i]) == 3: print c, 42 x = expand(f) return x x(range(10)) === Added File Products/PythonMethod/zbytecodehacks/opbases.py === import struct,dis,new from label import Label class ByteCode: pass class GenericOneByteCode(ByteCode): def __init__(self,cs,code): pass def __repr__(self): return self.__class__.__name__ def assemble(self,code): return self.opc def is_jump(self): return 0 def has_name(self): return 0 def has_name_or_local(self): return self.has_name() or self.has_local() def has_local(self): return 0 class GenericThreeByteCode(GenericOneByteCode): def __init__(self,cs,code): GenericOneByteCode.__init__(self,cs,code) arg=cs.read(2) self.arg=struct.unpack('>8 num_regular_args=self.arg&0xFF stack[-2*num_keyword_args-num_regular_args-1:]=[self] _bytecodes[CALL_FUNCTION.opc]=CALL_FUNCTION class MAKE_FUNCTION(_opbases.GenericThreeByteCode): op = 132 opc = '\204' def __init__(self,csorarg,code=None): if code is not None: _opbases.GenericThreeByteCode.__init__(self,csorarg,code) else: self.user_init(csorarg) def execute(self,stack): stack[-self.arg-1:]=[self] _bytecodes[MAKE_FUNCTION.opc]=MAKE_FUNCTION class BUILD_SLICE(_opbases.GenericThreeByteCode): op = 133 opc = '\205' def __init__(self,csorarg,code=None): if code is not None: _opbases.GenericThreeByteCode.__init__(self,csorarg,code) else: self.user_init(csorarg) def execute(self,stack): stack[-self.arg:]=[self] _bytecodes[BUILD_SLICE.opc]=BUILD_SLICE === Added File Products/PythonMethod/zbytecodehacks/rationalize.py === import code_editor from ops import * import operator CONDJUMP = [ JUMP_IF_TRUE, JUMP_IF_FALSE ] UNCONDJUMP = [ JUMP_FORWARD, JUMP_ABSOLUTE ] UNCOND = UNCONDJUMP + [ BREAK_LOOP, STOP_CODE, RETURN_VALUE, \ RAISE_VARARGS ] PYBLOCK = [ SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY ] PYENDBLOCK = [ POP_BLOCK ] binaryops = { 'BINARY_ADD': operator.add, 'BINARY_SUBTRACT': operator.sub, 'BINARY_MULTIPLY': operator.mul, 'BINARY_DIVIDE': operator.div, 'BINARY_MODULO': operator.mod, 'BINARY_POWER': pow, 'BINARY_LSHIFT': operator.lshift, 'BINARY_RSHIFT': operator.rshift, 'BINARY_AND': operator.and_, 'BINARY_OR': operator.or_, 'BINARY_XOR': operator.xor } unaryops = { 'UNARY_POS': operator.pos, 'UNARY_NEG': operator.neg, 'UNARY_NOT': operator.not_ } def rationalize(code): calculateConstants(code) strip_setlineno(code) simplifyjumps(code) removeconstjump(code) simplifyjumps(code) eliminateUnusedNames(code) eliminateUnusedLocals(code) def calculateConstants(co): """Precalculate results of operations involving constants.""" cs = co.co_code cc = co.co_consts stack = [] i = 0 while i < len(cs): op = cs[i] if binaryops.has_key(op.__class__.__name__): if stack[-1].__class__ is stack[-2].__class__ is LOAD_CONST: arg1 = cc[stack[-2].arg] arg2 = cc[stack[-1].arg] result = binaryops[op.__class__.__name__](arg1,arg2) if result in cc: arg = cc.index(result) else: arg = len(cc) cc.append(result) cs.remove(stack[-2]) cs.remove(stack[-1]) i = i - 2 cs[i] = LOAD_CONST(arg) stack.pop() stack.pop() stack.append(cs[i]) else: op.execute(stack) elif unaryops.has_key(op.__class__.__name__): if stack[-1].__class__ is LOAD_CONST: arg1 = cc[stack[-1].arg] result = unaryops[op.__class__.__name__](arg1) if result in cc: arg = cc.index(result) else: arg = len(cc) cc.append(result) cs.remove(stack[-1]) i = i - 1 cs[i] = LOAD_CONST(arg) stack.pop() stack.append(cs[i]) else: op.execute(stack) else: # this is almost certainly wrong try: op.execute(stack) except: pass i = i + 1 def strip_setlineno(co): """Take in an EditableCode object and strip the SET_LINENO bytecodes""" i = 0 while i < len(co.co_code): op = co.co_code[i] if op.__class__ is SET_LINENO: co.co_code.remove(op) else: i = i + 1 def simplifyjumps(co): cs = co.co_code i = 0 pyblockstack = [None] loopstack = [None] trystack = [None] firstlook = 1 while i < len(cs): op = cs[i] # new pyblock? if firstlook: if op.__class__ in PYBLOCK: pyblockstack.append(op) if op.__class__ is SETUP_LOOP: loopstack.append(op.label.op) else: trystack.append(op.label.op) # end of pyblock? elif op.__class__ == POP_BLOCK: op2 = pyblockstack.pop() if op2.__class__ == SETUP_LOOP: loopstack.pop() else: trystack.pop() # Is the code inaccessible if i >= 1: if cs[i-1].__class__ in UNCOND and not (cs.find_labels(i) or \ op.__class__ in PYENDBLOCK): cs.remove(op) firstlook = 1 continue # are we jumping from the statement before? if cs[i-1].__class__ in UNCONDJUMP: if cs[i-1].label.op == op: cs.remove(cs[i-1]) firstlook = 1 continue # break before end of loop? elif cs[i-1].__class__ == BREAK_LOOP: if op.__class__ == POP_BLOCK: cs.remove(cs[i-1]) firstlook = 1 continue # Do we have an unconditional jump to an unconditional jump? if op.__class__ in UNCONDJUMP: if op.label.op.__class__ in UNCONDJUMP: refop = op.label.op if op.__class__ == JUMP_FORWARD: newop = JUMP_ABSOLUTE() newop.label.op = refop.label.op cs[i] = newop else: op.label.op = refop.label.op firstlook = 0 continue # Do we have a conditional jump to a break? if op.__class__ in CONDJUMP and loopstack[-1]: destindex = cs.index(op.label.op) preendindex = cs.index(loopstack[-1])-2 if cs[i+2].__class__ == BREAK_LOOP and cs[preendindex].__class__ \ == POP_TOP: if op.__class__ == JUMP_IF_FALSE: newop = JUMP_IF_TRUE() else: newop = JUMP_IF_FALSE() newop.label.op = cs[preendindex] cs[i] = newop cs.remove(cs[i+1]) cs.remove(cs[i+1]) cs.remove(cs[i+1]) firstlook = 0 continue elif cs[destindex+1].__class__ == BREAK_LOOP and \ cs[preendindex].__class__ == POP_TOP: op.label.op = cs[preendindex] cs.remove(cs[destindex]) cs.remove(cs[destindex]) cs.remove(cs[destindex]) firstlook = 0 continue firstlook = 1 i = i+1 def removeconstjump(co): cs = co.co_code cc = co.co_consts i = 0 while i < len(cs): op = cs[i] if op.__class__ in CONDJUMP and cs[i-1].__class__ == LOAD_CONST: if (op.__class__ == JUMP_IF_FALSE and cc[cs[i-1].arg]) or \ (op.__class__ == JUMP_IF_TRUE and not cc[cs[i-1].arg]): cs.remove(cs[i-1]) cs.remove(cs[i-1]) cs.remove(cs[i-1]) i = i-2 else: cs.remove(cs[i-1]) cs.remove(cs[i]) newop = JUMP_FORWARD() newop.label.op = cs[cs.index(op.label.op)+1] cs[i-1] = newop i = i-1 i = i+1 def eliminateUnusedNames(code): used_names = {} for op in code.co_code: if op.has_name(): if hasattr(op,"arg"): arg = op.arg else: arg = op.arg = code.name_index(op.name) used_names[arg] = 1 used_names = used_names.keys() used_names.sort() name_mapping = {} for i in range(len(used_names)): name_mapping[used_names[i]]=i newnames = [] for i in range(len(code.co_names)): if i in used_names: newnames.append(code.co_names[i]) code.co_names = newnames for op in code.co_code: if op.has_name(): op.arg = name_mapping[op.arg] def eliminateUnusedLocals(code): used_names = {} for op in code.co_code: if op.has_local(): if hasattr(op,"arg"): arg = op.arg else: arg = op.arg = code.local_index(op.name) used_names[arg] = 1 used_names = used_names.keys() used_names.sort() name_mapping = {} for i in range(len(used_names)): name_mapping[used_names[i]]=i newnames = [] for i in range(len(code.co_varnames)): if i in used_names: newnames.append(code.co_varnames[i]) code.co_varnames = newnames for op in code.co_code: if op.has_local(): op.arg = name_mapping[op.arg] === Added File Products/PythonMethod/zbytecodehacks/tailr.py === from code_editor import Function from find_function_call import find_function_call from ops import * def make_tail_recursive(func): func = Function(func) code = func.func_code cs = code.co_code index = 0 while 1: stack = find_function_call(func,func.func_name,startindex=index) if stack is None: break index = cs.index(stack[-1]) if cs[index + 1].__class__ is RETURN_VALUE: cs.remove(stack[0]) newop = JUMP_ABSOLUTE() cs[index - 1:index] = [newop] newop.label.op = cs[0] del stack[0],stack[-1] nlocals = len(code.co_varnames) code.co_varnames = code.co_varnames + code.co_varnames for op in stack: cs.insert(cs.index(op)+1,STORE_FAST(stack.index(op)+nlocals)) iindex = cs.index(newop) for i in range(len(stack)): cs.insert(iindex,STORE_FAST(i)) cs.insert(iindex,LOAD_FAST(i+nlocals)) index = iindex return func.make_function() def _facr(n,c,p): if c <= n: return _facr(n,c+1,c*p) return p def facr(n,_facr=_facr): return _facr(n,1,1l) _factr = make_tail_recursive(_facr) def factr(n,_factr=_factr): return _factr(n,1,1l) def faci(n): p = 1l; c = 1; while c <= n: p = c*p c = c+1 return p import time def suite(n,c=10,T=time.time): r = [0,0,0] for i in range(c): t=T(); facr(n); r[0] = T()-t + r[0] t=T(); factr(n); r[1] = T()-t + r[1] t=T(); faci(n); r[2] = T()-t + r[2] print " recursive: 1.000000000000 (arbitrarily)" print "tail recursive:",r[1]/r[0] print " iterative:",r[2]/r[0] === Added File Products/PythonMethod/zbytecodehacks/version === 0.52z === Added File Products/PythonMethod/zbytecodehacks/xapply.py === """\ xapply Inspired by Don Beaudry's functor module. xapply exports one public function, the eponymous xapply. xapply can be thought of as `lazy apply' or `partial argument resolution'. It takes a function and part of it's argument list, and returns a function with the first parameters filled in. An example: def f(x,y): return x+y add1 = xapply(f,1) add1(2) => 3 This xapply is not yet as general as that from the functor module, but the functions return are as fast as normal function, i.e. twice as fast as functors. This may be generalised at some point in the future. """ import new,string,re,types from ops import LOAD_FAST, LOAD_CONST from code_editor import Function, InstanceMethod def xapply_munge(code, args, except0=0): nconsts = len(code.co_consts) nvars = len(args) code.co_consts.extend(list(args)) if except0: var2constlim = nvars+1 var2constoff = nconsts-1 else: var2constlim = nvars var2constoff = nconsts cs = code.co_code for i in range(len(cs)): op = cs[i] if op.__class__ is LOAD_FAST: if op.arg == 0 and except0: continue if op.arg < var2constlim: cs[i] = LOAD_CONST(op.arg + var2constoff) else: op.arg = op.arg - nvars code.co_varnames = code.co_varnames[nvars:] code.co_argcount = code.co_argcount - nvars def xapply_func(func,args): f = Function(func) xapply_munge(f.func_code,args,0) return f.make_function() def xapply_meth(meth,args): im = InstanceMethod(meth) xapply_munge(im.im_func.func_code,args,1) return im.make_instance_method() def xapply(callable,*args): """ xapply(callable,arg1,arg2,...) -> callable if f=xapply(callable,arg1,arg2,...,argn) then f(arg,....argm) is equivalent to callable(arg1,...,argn,arg,..argm) callable currently must be a function or instance method, and keyword arguments are currently not allowed. """ callable_type=type(callable) if callable_type is types.FunctionType: return xapply_func(callable,args) elif callable_type is types.UnboundMethodType: return xapply_meth(callable,args) else: raise "nope" From sidnei at x3ng.com.br Fri May 30 12:08:24 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.6 Message-ID: <200305301608.h4UG8O728141@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv28127 Modified Files: buildout_zope_sandbox Log Message: Added Old Products for Migration === NZO_SiteLayout/buildout_zope_sandbox 1.5 => 1.6 === ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor Products/ExternalEditor " CMFPackage="$COLLECTIVE_CVS_REPOSITORY co -dCMFPackage CMFPackage " +# Old Products are: +# BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase +BTreeFolder="$ZOPEORG_CVS_REPOSITORY co -dBTreeFolder Products/BTreeFolder " +ExternalMount="$ZOPEORG_CVS_REPOSITORY co -dExternalMount Products/ExternalMount " +ParsedXML="$ZOPEORG_CVS_REPOSITORY co -dParsedXML Products/ParsedXML " +PortalBase="$ZOPEORG_CVS_REPOSITORY co -dPortalBase Products/PortalBase " +PythonMethod="$ZOPEORG_CVS_REPOSITORY co -dPythonMethod Products/PythonMethod " +Redirector="$ZOPEORG_CVS_REPOSITORY co -dRedirector Products/Redirector " +TrackerBase="$ZOPEORG_CVS_REPOSITORY co -dTrackerBase Products/TrackerBase " +XMLDocument="$ZOPEORG_CVS_REPOSITORY co -dXMLDocument Products/XMLDocument " +ZDBase="$ZOPEORG_CVS_REPOSITORY co -dZDBase Products/ZDBase " + #------------------------------------------------------------------------------ # Build top-level sandbox dirs #------------------------------------------------------------------------------ @@ -387,6 +399,62 @@ echo "Retrying in 30s"; sleep 30; done +# Old Products are: +# BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase +echo "Checking out BTreeFolder"; +echo "cvs -Q -z7 -d $BTreeFolder"; +while ! `cvs -Q -z7 -d $BTreeFolder`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out ExternalMount"; +echo "cvs -Q -z7 -d $ExternalMount"; +while ! `cvs -Q -z7 -d $ExternalMount`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out ParsedXML"; +echo "cvs -Q -z7 -d $ParsedXML"; +while ! `cvs -Q -z7 -d $ParsedXML`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out PortalBase"; +echo "cvs -Q -z7 -d $PortalBase"; +while ! `cvs -Q -z7 -d $PortalBase`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out PythonMethod"; +echo "cvs -Q -z7 -d $PythonMethod"; +while ! `cvs -Q -z7 -d $PythonMethod`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out Redirector"; +echo "cvs -Q -z7 -d $Redirector"; +while ! `cvs -Q -z7 -d $Redirector`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out TrackerBase"; +echo "cvs -Q -z7 -d $TrackerBase"; +while ! `cvs -Q -z7 -d $TrackerBase`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out XMLDocument"; +echo "cvs -Q -z7 -d $XMLDocument"; +while ! `cvs -Q -z7 -d $XMLDocument`; do + echo "Retrying in 30s"; sleep 30; +done + +echo "Checking out ZDBase"; +echo "cvs -Q -z7 -d $ZDBase"; +while ! `cvs -Q -z7 -d $ZDBase`; do + echo "Retrying in 30s"; sleep 30; +done + cd $optdir cp -rs $srcdir/CMF-$CMF_VERSION . ln -s CMF-$CMF_VERSION CMF @@ -403,6 +471,19 @@ ln -s $srcdir/ExternalEditor . ln -s $srcdir/CMFPackage . +# Old Products are: +# BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase +ln -s $srcdir/BTreeFolder . +ln -s $srcdir/ExternalMount . +ln -s $srcdir/ParsedXML . +ln -s $srcdir/PortalBase . +ln -s $srcdir/PythonMethod . +ln -s $srcdir/Redirector . +ln -s $srcdir/TrackerBase . +ln -s $srcdir/XMLDocument . +ln -s $srcdir/ZDBase . + + if [ "$CMF_VERSION" == "1.3.1" -o "$CMF_VERSION" == "1.3-branch" ]; then cd $srcdir cvs -Q -z7 -d $ZOPE_CVSROOT co -d DCWorkflow-$DCWORKFLOW_VERSION \ @@ -441,6 +522,19 @@ ln -s $optdir/Formulator . ln -s $optdir/ExternalEditor . ln -s $optdir/CMFPackage . + +# Old Products are: +# BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase +ln -s $optdir/BTreeFolder . +ln -s $optdir/ExternalMount . +ln -s $optdir/ParsedXML . +ln -s $optdir/PortalBase . +ln -s $optdir/PythonMethod . +ln -s $optdir/Redirector . +ln -s $optdir/TrackerBase . +ln -s $optdir/XMLDocument . +ln -s $optdir/ZDBase . + if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then ln -s $optdir/DBTab . From sidnei at x3ng.com.br Fri May 30 12:19:05 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/Extensions Products/Extensions - New directory Message-ID: <200305301619.h4UGJ5N29687@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Extensions In directory cvs.zope.org:/tmp/cvs-serv29675/Extensions Log Message: Directory /cvs-zopeorg/Products/Extensions added to the repository === Added directory Products/Extensions === From sidnei at x3ng.com.br Fri May 30 12:19:37 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/Extensions - Catalog.py:1.1 DocSurvey.py:1.1 Expander.py:1.1 Expander.sh:1.1 ExportToLDAP.py:1.1 Hacks.py:1.1 MemberCleanout.py:1.1 MemberInfo.py:1.1 Membership.py:1.1 MyCatalog.py:1.1 Project.py:1.1 ProjectLib.py:1.1 TrackerMethods.py:1.1 ZopeSite.py:1.1 commit_version.py:1.1 countDoubles.py:1.1 fixfiles.py:1.1 fixids.py:1.1 getcwd.py:1.1 move_news.py:1.1 ownerous.py:1.1 plaintext.py:1.1 rconsole.py:1.1 rfc1123.py:1.1 rungc.py:1.1 set_title.py:1.1 sort_link.py:1.1 sort_link.py.old:1.1 test.py:1.1 which_node.py:1.1 wikimnt.py:1.1 Message-ID: <200305301619.h4UGJbs29791@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Extensions In directory cvs.zope.org:/tmp/cvs-serv29717/Extensions Added Files: Catalog.py DocSurvey.py Expander.py Expander.sh ExportToLDAP.py Hacks.py MemberCleanout.py MemberInfo.py Membership.py MyCatalog.py Project.py ProjectLib.py TrackerMethods.py ZopeSite.py commit_version.py countDoubles.py fixfiles.py fixids.py getcwd.py move_news.py ownerous.py plaintext.py rconsole.py rfc1123.py rungc.py set_title.py sort_link.py sort_link.py.old test.py which_node.py wikimnt.py Log Message: Add external methods from old zope.org === Added File Products/Extensions/Catalog.py === """ Catalog management """ import string, pdb def catalogedIn(self, catalog): """ Am I cataloged in a given catalog? """ return catalog._catalog.uids.has_key(self.url()) manageCatalog_request_letter = """ %(username)s requests that an object be cataloged. View it: %(url)s Catalog it %(url)s/manageCatalogForm Make sure to be logged in as superuser to perform catalog entry adding. ------------------------------------------------------------------------------- Manage the items in the reviewing queue at http://www.zope.org/UnreviewedIndex/ %(queue)s """ def manageCatalog(self, submit, REQUEST): """ Change catalog entry for an object. """ path=self.url() catalog=self.SiteIndex user=REQUEST.AUTHENTICATED_USER if not (user.has_role('Owner', self) or user.has_role('Manager', self) or user.has_role('Reviewer', self)): return self.manageCatalogForm(self, REQUEST, manage_tabs_message='Cannot change catalog entry. You must be the Owner of this object.') if submit==' Add Entry ': if user.has_role('Contributor', self) or \ user.has_role('Reviewer', self) or \ user.has_role('Manager', self): self.unindex_object(self, 'UnreviewedIndex') self.index_object(self, 'SiteIndex') if not user.has_role('Owner', self): try: notify_cataloged(self, REQUEST) except: pass elif submit==' Update Entry ': if user.has_role('Contributor', self) or catalog._catalog.uids.has_key(path): self.index_object(self) elif submit==' Remove Entry ': if user.has_role('Contributor', self) or catalog._catalog.uids.has_key(path): self.unindex_object(self) elif submit==' Request Entry ': unreviewedQueue = self.UnreviewedIndex.reportUnreviewedQueue() self.index_object(self, 'UnreviewedIndex') self.Utilities.mail_reviewers(self, REQUEST, subject="Catalog Request", body=manageCatalog_request_letter % { 'fullname': user.full_name, 'email': user.email, 'username': user.getUserName(), 'url': self.absolute_url(), 'queue': unreviewedQueue } ) return self.manageCatalogForm(self, REQUEST, manage_tabs_message='Your request has been submitted.') return self.manageCatalogForm(self, REQUEST, manage_tabs_message='Catalog entry changed.') def notify_cataloged(self, REQUEST): message = """\ From: "%(manager)s" <%(manageremail)s> To: "%(user)s" <%(useremail)s> Subject: [Zope Site] Object cataloged %(manager)s has cataloged your object at: %(url)s """ dict = { 'manager':REQUEST.AUTHENTICATED_USER.full_name, 'manageremail':REQUEST.AUTHENTICATED_USER.email, 'user': self.acl_users.getUser(self.creator()).full_name, 'useremail': self.acl_users.getUser(self.creator()).email, 'url': self.absolute_url() } self.MailHost.send(message % dict) def reportUnreviewedQueue(self, REQUEST=None): if not REQUEST: REQUEST = self.REQUEST queue = self.searchResults() if not queue: return 'There are currently no other items awaiting review.' report = 'Total items awaiting review: %s' % (len(queue) + 1) report = '%s\n\nOther items still waiting:\n' % report count = 0 for entry in queue: count = count + 1 rec_url = '%s/%s' % (REQUEST.BASE0, self.getpath(entry.data_record_id_)) report = '%s%s: %s\n' % (report, count, rec_url) return report === Added File Products/Extensions/DocSurvey.py === file="/usr/local/dc/www.zope.org/var/docsurvey.data" import marshal import os.path import string import fcntl import FCNTL def process(REQUEST): """ process survey results """ d={} for i in range(1,13) + ['comments']: k=str(i) if REQUEST.has_key(k): d[k]=REQUEST[k] try: d[k]=string.atoi(d[k]) except: pass if not os.path.exists(file): results={} for i in range(1,13) + ['comments']: results[str(i)]=[] else: f=open(file,'rb') fcntl.flock(f.fileno(), FCNTL.LOCK_SH) results=marshal.load(f) fcntl.flock(f.fileno(), FCNTL.LOCK_UN) f.close() for k,v in d.items(): results[k].append(v) f=open(file,'wb') fcntl.flock(f.fileno(), FCNTL.LOCK_EX) marshal.dump(results,f) fcntl.flock(f.fileno(), FCNTL.LOCK_UN) f.close() def results(): """ survey results """ f=open(file,'rb') fcntl.flock(f.fileno(), FCNTL.LOCK_SH) return marshal.load(f) fcntl.flock(f.fileno(), FCNTL.LOCK_UN) f.close() def averages(): """ average scores for survey results """ d=results() del d['comments'] averages={} for k,v in d.items(): if len(v)==0: averages[k]='n/a' else: total=0 for i in v: total=total+i averages[k]=total/float(len(v)) return averages def table(): """ A table showing responses to question 1 """ out="""""" r=results()['1'] d={1:0,2:0,3:0,4:0,5:0} for v in r: d[v]=d[v]+1 scale =200.0/max(d.values()) for i in range(1,6): out=out+"""""" % d[i] out=out+"""
""" out=out+""" """ % (200 - int(round(scale*d[i])),) out=out+""" """ % int(round(scale * d[i])) out=out+"""
 
 
(%s)
Very useful
and effective
Very unhelpful
and ineffective
""" return out === Added File Products/Extensions/Expander.py === import os def Expander(): os.system('/usr/local/dc/org/Extensions/Expander.sh') === Added File Products/Extensions/Expander.sh === #!/bin/sh cd /usr/local/dc/apache/htdocs/Browsable for i in $(ncftpls -u mindlace -p 6vSuG -1 \ ftp://www.zope.org:1321/Documentation/Developer/ZopeSrcDocs/ \ | grep '.tar.gz'); do ncftpget -u mindlace -p 6vSuG -P 1321 www.zope.org ./ /Documentation/Developer/ZopeSrcDocs/$i tar xzf $i done === Added File Products/Extensions/ExportToLDAP.py === # Export the user folder data to an LDAP importfile, to be downloaded through # the TTW interface. # # We map the user properties as follows: # # Property LDAP field # # name cn # email mail # full_name gn and sn (split on first occuring space) # company o # public_email public # # last_visit and prev_visit are not exported. # # We first write to a temp file, then write the contents of that file to the # broswer using RESPONSE.write import string import tempfile, thread, sha, base64, binascii import re import time LDAP_MEMBER_ENTRY = ( ('objectClass', 'top'), ('objectClass', 'zopeOrgPerson'), ('cn', 'id'), ('sn', 'last_name'), ('gn', 'first_name'), ('o', 'company'), ('mail', 'email'), ('public', 'public'), ('lastLogin', 'last_visit'), ('prevLogin', 'prev_visit'), ('userPassword', 'password'), ) LDAP_STRUCTURAL_ENTRIES = """dn: dc=zope,dc=org objectClass: top objectClass: dcObject dc: zope dn: ou=people,dc=zope,dc=org objectClass: top objectClass: organizationalUnit ou: people description: All user records are stored here dn: ou=groups,dc=zope,dc=org objectClass: top objectClass: organizationalUnit ou: groups description: All groupings are stored underneath this unit dn: ou=websites,ou=groups,dc=zope,dc=org objectClass: top objectClass: organizationalUnit ou: websites description: All website membership groups are underneath this unit dn: ou=maillists,ou=groups,dc=zope,dc=org objectClass: top objectClass: organizationalUnit ou: maillists description: All mailing list membership groups go here dn: ou=www.zope.org,ou=websites,ou=groups,dc=zope,dc=org objectClass: top objectClass: organizationalUnit ou: www.zope.org description: membership groups for www.zope.org """ LDAP_ROLE_ENTRY = ( ('objectClass', 'top'), ('objectClass', 'groupOfUniqueNames'), ('cn', 'role'), ) # LDAP safe-string, any attribute value matching this RE will not have to be # base64 encoded. safeString = re.compile( # Start with any ascii < 127 except NUL, LF, CR, SPACE, ':' or '<'. '[\x01-\x09\x0B-\x0C\x0E-\x1F\x21-\x39\x3B\x3D-\x7F]' # Followed by any ascii < 127 except NUL, LF or CR. '[\x01-\x09\x0B-\x0C\x0E-\x7F]*' # This must match the whole value '$' ) def encryptPassword(password): return '{SHA}%s' % binascii.b2a_base64(sha.new(password).digest())[:-1] def formatGeneralizedTime(dt): try: return dt.strftime('%Y%m%d%H%M%SZ') except: return time.strftime('%Y%m%d%H%M%SZ', time.localtime(time.time())) def createAttrVal(attr, val, commaAllowed=0): if not val: return '' # Empty values should not be included. # Escape commas; unless it is explicetly allowed (dn). if not commaAllowed and ',' in str(val): val = string.join(string.split(val, ','), '\,') if safeString.match(val): # The value doesn't need to be base64 encoded return '%s: %s\n' % (attr, val) else: val = base64.encodestring(val) # Multiline base64 values are okay, just make sure there is an extra # space at the start of all the lines. if '\n' in val[:-1]: val = string.join(string.split(val[:-1], '\n'), '\n ') + '\n' return '%s:: %s' % (attr, val) def createCnValue(Cn, template): if ',' in Cn: Cn = string.join(string.split(Cn, ','), '\,') return template % Cn def createMemberDistinguishedName(id): value = createCnValue(id, 'cn=%s,ou=people,dc=zope,dc=org') return createAttrVal('dn', value, commaAllowed=1) def createRoleDistinguishedName(role): value = createCnValue(role, 'cn=%s,ou=www.zope.org,ou=websites,ou=groups,dc=zope,dc=org') return createAttrVal('dn', value, commaAllowed=1) def createUniqueMember(id): value = createCnValue(id, 'cn=%s,ou=people,dc=zope,dc=org') return createAttrVal('uniqueMember', value, commaAllowed=1) def exportToLDAP(self, max=0): temp = tempfile.TemporaryFile(suffix='LDAPExport%s' % thread.get_ident()) # Write the LDIF version number #temp.write('version: 1\n') # Write the structural entries for the directory at the top temp.write(string.strip(LDAP_STRUCTURAL_ENTRIES)) users = self.acl_users.getUsers() count = 0 roles = {} for user in users: parts = string.split(user.full_name, ' ', 1) first_name = parts[0] if len(parts) > 1: last_name = parts[1] else: last_name = '' # Force public to be 1 or 0 (strings) public = user.public_email and '1' or '0' # Build record. data = { 'top': 'top', 'zopeOrgPerson': 'zopeOrgPerson', 'id': user.name, 'last_name': last_name, 'first_name': first_name, 'company': user.company, 'email': user.email, 'public': public, 'last_visit': formatGeneralizedTime(user.last_visit), 'prev_visit': formatGeneralizedTime(user.prev_visit), 'password': encryptPassword(user._pw_) } entry = createMemberDistinguishedName(user.name) for attr, key in LDAP_MEMBER_ENTRY: entry = '%s%s' % (entry, createAttrVal(attr, data[key])) # Add extra newline to delimit records. if entry: entry = '\n%s' % entry temp.write(entry) # Collect roles information. for role in user.roles: if not roles.has_key(role): roles[role] = [] roles[role].append(user.name) # For testing purposes we can limit the number of records returned by # adding ?max:int= to the URL. if max: count = count + 1 if count >= max: break # Process the collected roles info for role, members in roles.items(): data = { 'top': 'top', 'groupOfUniqueNames': 'groupOfUniqueNames', 'role': role, } entry = createRoleDistinguishedName(role) for attr, key in LDAP_ROLE_ENTRY: entry = '%s%s' % (entry, createAttrVal(attr, data[key])) for member in members: entry = '%s%s' % (entry, createUniqueMember(member)) # Add extra newline to delimit records. if entry: entry = '\n%s' % entry temp.write(entry) # Write collected data to browser length = temp.tell() temp.seek(0) resp = self.REQUEST.RESPONSE resp.setHeader('content-type', 'text/directory') resp.setHeader('content-length', length) while 1: buffer = temp.read(1024) if not buffer: break resp.write(buffer) temp.close() === Added File Products/Extensions/Hacks.py === def convert(self, REQUEST): '''dock string''' for x in self.SiteIndex._catalog.paths.values(): obj = REQUEST.resolve_url('http://www.zope.org:18200/' + x) if obj is None: raise 'DumnAssError' self.Foo._catalog.catalogObject(obj, x) === Added File Products/Extensions/MemberCleanout.py === # External methods used to clean out old Members (no login for ore that 60 days) import tempfile, thread from DateTime import DateTime from cPickle import Pickler # Determine if a member is stale; hasn't logged in for a number of days. def memberIsStale(context, member, staleDate=(DateTime()-90)): if member.last_visit.lessThan(staleDate): hasContent = context.SiteIndex(creator=member.getUserName()) hasContent = len(filter(lambda o: o.url[:7] == 'Members', hasContent)) return not hasContent return 0 # Export a pickle file with member data of stale members to generate warning # emails. def exportStaleMembers(self, max=0): stale = [] add = stale.append users = self.acl_users.getUsers() for user in users: if memberIsStale(self, user): add((user.name, user.full_name, user.email, user.last_visit)) # Write collected data to browser temp = tempfile.TemporaryFile(suffix='StaleMembers%s' % thread.get_ident()) pout = Pickler(temp, 1) # Binary pickles please (saves a *lot* of bandwidth) pout.dump(stale) length = temp.tell() temp.seek(0) resp = self.REQUEST.RESPONSE resp.setHeader('content-type', 'text/directory') resp.setHeader('content-length', length) while 1: buffer = temp.read(256) if not buffer: break resp.write(buffer) temp.close() # Remove still existing domains fields def cleanDomainsCruft(self): users = self.acl_users.getUsers() count = 0 for user in users: if user.domains: self.acl_users.changeUser(user.name, user._pw_, user.roles, ()) count = count + 1 return '%s domains fields cleared out.' % count # Remove all accounts on "the date", which is 7 days after the warning mails # have gone out. now = DateTime() today = DateTime(now.Date()) theDate = DateTime('2001/04/12') daysTillTheDate = theDate - today staleDate = now - (90 + (7 - daysTillTheDate)) def deleteStaleMembers(self): # Only on or before the set date. if daysTillTheDate < 0: return ( 'The date (%s) has passed. Please reconfigure the External ' 'Method.' % theDate.Date()) stale = [] add = stale.append users = self.acl_users.getUsers() total = len(users) # Store before removal of users.. for user in users: if memberIsStale(self, user, staleDate=staleDate): add(user.name) totalRemove = len(stale) # Store before removal of users.. # If not yet the date, only return a count. if daysTillTheDate: return ( "Today, we'd be removing %s users out of %s total Members, " "leaving %s active Members." % ( totalRemove, total, total - totalRemove)) else: self.acl_users.delUser(stale) return ( "Removed %s users out of %s total Members, " "leaving %s active Members." % ( totalRemove, total, total - totalRemove)) === Added File Products/Extensions/MemberInfo.py === ### # Methods for collecting and caching info on the # Member Folders # # MJ ### from time import time from string import find, upper # Return info hash on Member Folders # Create cash if needed. def memberInfo(self, max_cache_time=60*60, max_active_age=2*7*24*60*60): try: if hasattr(self, '_v_meminfo_cache'): info=self._v_meminfo_cache if time()-info['timestamp']<=max_cache_time: return info except: pass # cache empty or expired info=self._v_meminfo_cache={} info['timestamp']=time() # Member folder statistics and listed members list allFolders=self.objectValues(['Folder']) listedMembers=[] for folder in allFolders: if hasattr(folder, 'listed') and folder.listed: listedMembers.append((folder.id, folder.title)) info['number_of_members']=len(allFolders) listedMembers.sort(lambda a,b: cmp(a[0], b[0])) info['listed_members']=tuple(listedMembers) # Active members allMembers=self.acl_users.data.values() activeMembers=0 for member in allMembers: if time()-member.last_visit.timeTime()<=max_active_age: activeMembers=activeMembers+1 info['active_members']=activeMembers return info def filterMembers(self, member_filter): info=self.memberInfo() listed=info['listed_members'] member_filter=upper(member_filter) return filter(lambda m, f=member_filter: find(upper(m[0]), f)!=-1, listed) === Added File Products/Extensions/Membership.py === # This module implements various external methods used # by our Membership and registration objects. import sys, os, string, time, random, re from DateTime import DateTime from DocumentTemplate import HTML from App.Dialogs import MessageDialog # Registration methods # -------------------- def added_props(self): """ """ stdprops=('name','email','last_visit','prev_visit','full_name','company') c=self.Control_Panel.Products.ZopeSite.MemberFolder c=c.propertysheets.methods._getOb('Member') ps=c.propertysheets.common.CommonProperties ids=ps.propertyIds() set=[] for id in ids: if not (id in stdprops): set.append(id) return set chars=string.letters+string.digits # remove characters that cause confusion in certain fonts # this will cut down on support for 'wrong' passwords. MJ chars=string.translate(chars,string.maketrans('',''),'iIloO01') def gen_password(choose=random.choice, chars=chars, join=string.join): result=[] for n in range(5): result.append(choose(chars)) return join(result, '') def nameUsed(name, names, lower=string.lower): return lower(name) in map(lower, names) def register(self, username='', full_name='', company='', email='', REQUEST=None): """ """ register_html=getattr(self, 'register.html') if not username or not email: return register_html(self, REQUEST, error=('You must enter a value for Name and a valid Email ' 'Address.')) disapproval = username_policy(username) if disapproval: return register_html(self, REQUEST, error=(disapproval)) if nameUsed(username, self.acl_users.data.keys()): return register_html(self, REQUEST, error=('The login name you selected is already in use. Please ' 'choose another.')) password = REQUEST.get('password', gen_password()) disapproval = password_policy(password) if disapproval: return register_html(self, REQUEST, error=(disapproval)) confirm = REQUEST.get('confirm', password) if confirm != password: return register_html(self, REQUEST, error=('Your password and confirmation did not match. ' 'Please try again.')) # Add the member self.acl_users.addUser(username, password, ['Member'], []) user=self.acl_users.getUser(username) for ps in user.propertysheets: ps.manage_changeProperties(REQUEST) # Here we add a new Folder for this user in Members, # giving the user the local role 'Owner' in his Folder. try: members=self.Members except AttributeError: members = None if members is not None: members.manage_addFolder(username) folder=members[username] if REQUEST: name=REQUEST['AUTHENTICATED_USER'].getUserName() folder.manage_delLocalRoles([name]) folder.manage_setLocalRoles(username, ['Owner']) # Generate email notification self.notify(self, REQUEST, password=password) return getattr(self, 'success.html')(self, REQUEST) def password_policy(candidate): """Implement here the password characteristics policy for your site. Returns an error message on failure, or None if all is ok.""" if len(candidate) < 5: return 'Your password must contain at least 5 characters.' def username_policy(candidate, username_match=re.compile('^[-_a-zA-Z0-9]+$').match): """Check for illegal characters in usernames""" if not username_match(candidate): return "You can only use letters, digits, dashes and underscores" +\ " in your username. Please choose another name." def updateMember(self, REQUEST): """ """ user=REQUEST['AUTHENTICATED_USER'] name=user.getUserName() if hasattr(user, 'propertysheets'): for ps in user.propertysheets: ps.manage_changeProperties(REQUEST) return self.update_html(self, REQUEST, message='Your changes have been saved.') else: return self.update_html(self, REQUEST, message='Cannot set non-member %s' % user) # MemberFolder methods # -------------------- def fixup_user(user): if hasattr(user, 'last_visit'): try: if not user.last_visit.isCurrentDay(): user.prev_visit=user.last_visit user.last_visit=DateTime().earliestTime() get_transaction().commit() except: pass # don't screw login if in read-only mode return user def addMemberFolder(self, REQUEST=None): if hasattr(self.aq_base, 'acl_users'): return MessageDialog( title ='Item Exists', message='This object already contains a User Folder', action ='%s/manage_main' % REQUEST['URL1']) dest=self.Destination() ob=self.MemberFolder() #'acl_users', REQUEST) dest._setObject('acl_users', ob) dest.__allow_groups__=dest.acl_users if REQUEST: return dest.manage_main(dest, REQUEST, update_menu=1) def addUser(self, name, password, roles, domains, REQUEST=None): """ """ # zclass=self.Control_Panel.Products.ZopeSite.MemberFolder.Member._zclass_ user=self.Member(name, password, roles, domains) user.id=name self.data[name]=user if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def getUser(self, name): """ """ if self.data.has_key(name): user=self.data[name].__of__(self) # user=fixup_user(user) Only on login!! # Placing this here wil cause *all* access to the user (like checking # for when the last visit was) to update the last_visit property. return user return None def changeUser_Form(self, names, REQUEST=None): """ """ name = names[0] user=self.data[name].__of__(self) return self.changeUserForm(self, REQUEST=REQUEST, user=user, password=user._getPassword()) def changeUser(self, name, password, roles, domains, REQUEST=None): """ """ user=self.data[name] user._pw_=password user.roles=roles user.domains=domains if REQUEST is not None: return self.changeUser_Form(self, names=(user,), REQUEST=REQUEST) def changeUserPassword(self, name, password, domains, REQUEST=None): """ """ user=self.data[name] user._pw_=password user.domains=domains if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def delUser(self, names, REQUEST=None): """ """ # Delete and clean up after a user try: members=self.Members except AttributeError: members = None for name in names: if self.data.has_key(name): del self.data[name] if (members is not None) and hasattr(members.aq_base, name): members._delObject(name) if REQUEST is not None: return self.manage_main(self, REQUEST=REQUEST) def getUserNames(self): """Return a list of usernames""" # convert to a list (data is a BTree) names=list(self.data.keys()) names.sort() return names def getUsers(self): """Return a list of user objects""" names=self.getUserNames() data=self.data users=[] f=users.append for n in names: f(data[n]) return users def renameUsers(self, names=[], new_names=[], REQUEST=None): """Rename users""" if len(names) != len(new_names): raise 'Bad Request','Please rename each listed user.' try: members = self.Members except AttributeError: members = None data = self.data si = self.SiteIndex ur = self.UnreviewedIndex for i in range(len(names)): name, new_name = names[i], new_names[i] if name != new_name: if nameUsed(new_name, data.keys()): raise 'Rename Error', MessageDialog( title='Invalid User Id', message=sys.exc_info()[1], action ='manage_main') user = data[name] user.name = new_name data[new_name] = user del data[name] # Store objects that have been catalogued indexed = si(creator=name) indexed = map(lambda o, go=si.getobject: go(o.data_record_id_), indexed) unreviewed = ur(creator=name) unreviewed = map(lambda o, go=ur.getobject: go(o.data_record_id_), unreviewed) # Rename the Member Folder if members is not None and hasattr(members.aq_base, name): memberFolder = getattr(members, name) fixupLocalRolesAndOwnership(memberFolder, name, new_name, user.__of__(self)) members.manage_renameObject(name, new_name) # Fix catalogued stuff for ob in indexed: try: ob.unindex_object(ob, 'SiteIndex') except: ob.unindex_object('SiteIndex') fixupLocalRolesAndOwnership(ob, name, new_name, user.__of__(self)) try: ob.index_object(ob, 'SiteIndex') except: ob.index_object('SiteIndex') for ob in unreviewed: try: ob.unindex_object(ob, 'UnreviewedIndex') except: ob.unindex_object('UnreviewedIndex') fixupLocalRolesAndOwnership(ob, name, new_name, user.__of__(self)) try: ob.index_object(ob, 'UnreviewedIndex') except: ob.index_object('UnreviewedIndex') if REQUEST is not None: return self.manage_main(self, REQUEST) return None # Utility methods # --------------- def fixupLocalRolesAndOwnership(base, oldUser, newUser, user): if hasattr(base.aq_base, 'owner_info'): info = base.owner_info() if info and info['explicit'] and info['id'] == oldUser: base.changeOwnership(user, recursive=1) if hasattr(base.aq_base, 'get_local_roles_for_userid'): roles = base.get_local_roles_for_userid(oldUser) if roles: base.manage_delLocalRoles([oldUser]) base.manage_setLocalRoles(newUser, list(roles)) if hasattr(base.aq_base, 'objectValues'): for ob in base.objectValues(): fixupLocalRolesAndOwnership(ob, oldUser, newUser, user) def mail_password(self, forgotten_username, REQUEST): """Email a forgotten password to a member""" user = self.acl_users.getUser(forgotten_username) if user is None: return MessageDialog( title ='Username not found', message='The username you entered could not be found.', action ='mail_password_form') if not user.email: return MessageDialog( title ='User has no email address', message='This user has no email address and cannot be mailed a ' 'password. Please file an isssue in the ' 'Zope.org Tracker for assistance.', action ='mail_password_form') return self.mail_password_template(self, REQUEST, full_name=user.full_name, email=user.email, password=user._getPassword()) === Added File Products/Extensions/MyCatalog.py === def myUpdate(self, submit, REQUEST, urls=None): """ Update my Catalog entries """ user=REQUEST.AUTHENTICATED_USER n=0 if urls is None: urls=[] if submit == " Update Selected ": for url in urls: ob=self.resolve_url(url, REQUEST) if ob and user.has_role('Owner', ob): self.catalog_object(ob, url) n=n+1 message='Updated %d objects.' % n elif submit == " Remove Selected ": for url in urls: ob=self.resolve_url(url, REQUEST) if ob and user.has_role('Owner', ob): self.uncatalog_object(url) n=n+1 message='Removed %d objects.' % n elif submit == " Update All ": for record in self.searchResults(creator=user.getUserName()): url=self.getpath(record.data_record_id_) ob=self.resolve_url(url, REQUEST) if ob and user.has_role('Owner', ob): self.catalog_object(ob, url) n=n+1 message='Updated %d objects.' % n elif submit == " Remove All ": for record in self.searchResults(creator=user.getUserName()): url=self.getpath(record.data_record_id_) ob=self.resolve_url(url, REQUEST) if ob and user.has_role('Owner', ob): self.uncatalog_object(url) n=n+1 message='Removed %d objects.' % n return self.myObjects(self, REQUEST, message=message) === Added File Products/Extensions/Project.py === import sys, os, string, time, random, urllib from DateTime import DateTime def sort_key(self): if hasattr(self.aq_parent.aq_base, 'sort_key_'): return str(self.sort_key_) return self.id def addProject(self, id, title='', REQUEST=None): """ """ dest=self.Destination() ob=self.Project(id) ob.id=id ob.title=title dest._setObject(id, ob) ob=getattr(dest, id) k=0 for n in ('Inception','Elaboration','Construction','Transition'): p=ob.Phase(n) p.id=n p.sort_key_=k k=k+1 ob._setObject(n, p) p=getattr(ob, n) addIteration(p, 'Iteration_1') ob.Inception.status='Active' ob.Inception.Iteration_1.status='Active' # date=DateTime() # ds=REQUEST.get('date_override','') # if ds: date=DateTime(ds) # else: date=DateTime() # REQUEST['date']=date # ob.propertysheets.Findables.manage_changeProperties(REQUEST) # ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def addIteration(self, id, title='', REQUEST=None): """ """ ob=self.Iteration(id) ob.id=id ob.title=title self._setObject(id, ob) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def addTask(self, id, title='', REQUEST=None): """ """ ob=self.Task(id) ob.id=id ob.title=title self._setObject(id, ob) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') # Findable object methods. These are methods common to objects # which subclass Findable, which provide implementations for # obtaining certain metadata (such as creator), as well as # common methods that handle the details of indexing and # unindexing Findable objects. def onDeleteObject(self): """Object delete handler.""" self.unindex_object() def creator(self): """Return a sequence of user names who have the local Owner role on an object. The name creator is used for this method to conform to Dublin Core.""" parent=self.aq_parent roles=parent.aq_acquire('__ac_local_roles__') dict=roles or {} #parent.__ac_local_roles__ or {} items=[] for key, val in dict.items(): if 'Owner' in val: items.append(key) return string.join(items, ', ') def url(self, ftype=urllib.splittype, fhost=urllib.splithost): """Return a SCRIPT_NAME-based url for an object.""" if hasattr(self, 'DestinationURL') and \ callable(self.DestinationURL): url='%s/%s' % (self.DestinationURL(), self.id) else: url=self.absolute_url() type, uri=ftype(url) host, uri=fhost(uri) script_name=self.REQUEST['SCRIPT_NAME'] __traceback_info__=(`uri`, `script_name`) if script_name: uri=filter(None, string.split(uri, script_name))[0] uri=uri or '/' if uri[0]=='/': uri=uri[1:] return uri def summary(self, num=200): """Return a summary of the text content of the object.""" if not hasattr(self, 'text_content'): return '' attr=getattr(self, 'text_content') if callable(attr): text=attr() else: text=attr n=min(num, len(text)) return text[:n] def index_object(self): """A common method to allow Findables to index themselves.""" self.SiteIndex.indexObject(self) def unindex_object(self): """A common method to allow Findables to unindex themselves.""" self.SiteIndex.unindexObject(self) # STX Document methods # --------------------- default_format=""" """ def addSTXDocument(self, id, title='', submit='', REQUEST={}): """ """ dest=self.Destination() ob=self.STXDocument(default_format, __name__=id) ob.title=title dest._setObject(id, ob) ob=getattr(dest, id) date=DateTime() ds=REQUEST.get('date_override','') if ds: date=DateTime(ds) else: date=DateTime() REQUEST['date']=date ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.propertysheets.Basic.manage_changeProperties(REQUEST) ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] if submit==" Add and Edit ": url="%s/%s" % (url, urllib.quote(id)) REQUEST.RESPONSE.redirect(url+'/manage_workspace') def STXDocument_text_content(self): """Return the text content of the object.""" # return the actual stx content... return self.content def STXDocument_onEditBegin(self): """ """ self.SiteIndex.unindexObject(self) def STXDocument_onEditComplete(self): """ """ self.SiteIndex.indexObject(self) # HTML Document methods # --------------------- def addHTMLDocument(self, id, title='', file='', submit='', REQUEST={}): """ """ dest=self.Destination() ob=self.HTMLDocument(file, __name__=id) ob.title=title dest._setObject(id, ob) ob=getattr(dest, id) date=DateTime() ds=REQUEST.get('date_override','') if ds: date=DateTime(ds) else: date=DateTime() REQUEST['date']=date ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] if submit==" Add and Edit ": url="%s/%s" % (url, urllib.quote(id)) REQUEST.RESPONSE.redirect(url+'/manage_workspace') def HTMLDocument_text_content(self): """Return the text content of the object.""" # could try to __call__ ourselves here, but its probably # better not to, since the text of the object should be # the most relevant and stuff common to site pages should # be include using var tags... return self.read() def HTMLDocument_onEditBegin(self): """ """ self.SiteIndex.unindexObject(self) def HTMLDocument_onEditComplete(self): """ """ self.SiteIndex.indexObject(self) # NewsItem methods # ---------------- def NewsItem_text_content(self): """Return the text content of the object.""" return self.text def approveNewsItem(self, approve=0, REQUEST=None): """ """ for ps in self.propertysheets.values(): ps.manage_changeProperties(REQUEST=REQUEST) if approve: self.index_object() # Add to catalog here... self.title=title def findAllMemberNames(self): """ """ # XXX This should go up the folder tree... allusers=self.acl_users.getUsers() names=[] for user in allusers: if user.has_role('Member'): names.append(user.getUserName()) return names def foo(self): t = [] obj = self count = 0 while 1: if hasattr(obj, 'aq_parent'): t.append(`obj`) obj = obj.aq_parent else: break count = count + 1 if count > 10: t.append("!!") break return "

Self gots .%s.

" % string.join(t, ', ') def getOwners(self, join=string.join): parent = self.aq_parent # XXX Workaround parent.aq_acquire('__ac_local_roles__') dict = parent.__ac_local_roles__ or {} # XXX Workaround list=[] for key, val in dict.items(): if 'Owner' in val: list.append(key) return join(list, ', ') def aq_base(ob): if hasattr(ob, 'aq_base'): return ob.aq_base return ob def reindex_all(self, obj=None): """ """ if obj is None: obj=self if hasattr(aq_base(obj), 'index_object'): obj.index_object() if hasattr(aq_base(obj), 'objectValues'): sub=obj.objectValues() for item in obj.objectValues(): reindex_all(self, item) return 'done!' === Added File Products/Extensions/ProjectLib.py === import sys, os, string, time, random, urllib from DateTime.DateTime import DateTime def gen_class_id(self): import md5, base64, time id=md5.new() id.update(self.absolute_url()) id.update(str(time.time())) id=id.digest() id=string.strip(base64.encodestring(id)) return '*'+id def sort_key(self): if hasattr(self.aq_parent.aq_base, 'sort_key_'): return str(self.sort_key_) return self.id def getValidUserNames(self): """ """ # XXX This should go up the folder tree... allusers=self.acl_users.getUsers() names=[] for user in allusers: if user.has_role('Member'): names.append(user.getUserName()) return names def assignedTo(self): return ['brian'] def index_object(self): """ """ try: if self.project_type=='Community': self.SiteIndex.catalog_object(self, self.url()) except: pass def unindex_object(self): """ """ try: if self.project_type=='Community': self.SiteIndex.uncatlog_object(self.url()) except: pass def nid(self): """ """ return self._p_oid def getArtifacts(self, subs=0, obs=None): if obs is None: obs=[] for ob in self.objectValues(['Generic Artifact','File']): obs.append(ob) if subs: for ob in self.objectValues(['Project','Phase','Iteration']): obs=ob.getArtifacts(subs=1, obs=obs) return obs def status_change(self, status, req={}, zero=DateTime('1/1/1970')): sd, fd=self.act_start_date, self.act_finish_date date=DateTime() if status==self.status: return elif status=='Pending': req['act_start_date']=zero req['act_finish_date']=zero elif status=='Active': if sd == zero: req['act_start_date']=date if fd != zero: req['act_finish_date']=zero elif status=='Completed': if sd == zero: req['act_start_date']=date if fd == zero: req['act_finish_date']=date def addProject(self, id, title, project_type, est_start_date, est_finish_date, est_effort, est_value, status, abstract, customer='', REQUEST={}): """ """ # Projects are created in Project Libraries, so self in # this case is the Project factory, which is contained # in the ProjectLibrary ZClass -self.aq_parent.aq_parent # is the Project Library instance where we are creating # the new Project. dest=self.aq_parent.aq_parent ob=self.Project(id) ob.id=id ob.title=title dest._setObject(id, ob) ob=getattr(dest, id) k=0 for n in ('Inception','Elaboration','Construction','Transition'): p=ob.Phase(n) p.id=n p.sort_key_=k k=k+1 ob._setObject(n, p) p=getattr(ob, n) addIteration(p, 'Iteration_1') REQUEST['date']=DateTime() status_change(ob, status, REQUEST) ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.propertysheets.ProjectProperties.manage_changeProperties(REQUEST) ob.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL2'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def editProject(self, title, project_type, est_start_date, est_finish_date, est_effort, est_value, status, abstract, customer='', REQUEST={}): """ """ self.unindex_object() status_change(self, status, REQUEST) self.propertysheets.ProjectProperties.manage_changeProperties(REQUEST) self.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) self.propertysheets.Findables.manage_changeProperties(REQUEST) self.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def addIteration(self, id, title='', REQUEST=None): """ """ ob=self.Iteration(id) ob.id=id ob.title=title self._setObject(id, ob) ob=getattr(self, id) ob.date=DateTime() ob.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL2'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def editIteration(self, title, est_start_date, est_finish_date, est_effort, act_effort, status, REQUEST={}): """ """ self.title=title status_change(self, status, REQUEST) self.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def addTask(self, id, title, priority, assigned_to, est_start_date, est_finish_date, est_effort, status, desc, REQUEST={}): """ """ ob=self.Task(id) ob.id=id self._setObject(id, ob) ob=getattr(self, id) REQUEST['date']=DateTime() status_change(self, status, REQUEST) ob.propertysheets.TaskProperties.manage_changeProperties(REQUEST) ob.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL2'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') def editTask(self, title, priority, assigned_to, est_start_date, est_finish_date, est_effort, status, desc, REQUEST={}): """ """ self.unindex_object() status_change(self, status, REQUEST) self.propertysheets.TaskProperties.manage_changeProperties(REQUEST) self.propertysheets.TrackableProperties.manage_changeProperties(REQUEST) self.propertysheets.Findables.manage_changeProperties(REQUEST) self.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] REQUEST.RESPONSE.redirect(url+'/manage_workspace') default_format="""
""" def addGenericArtifact(self, id, title, format, content='', submit='', REQUEST={}): """ """ ob=self.GenericArtifact(default_format, __name__=id) ob.id=id ob.title=title self._setObject(id, ob) ob=getattr(self, id) REQUEST['date']=DateTime() ob.propertysheets.Basic.manage_changeProperties(REQUEST) ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.index_object() if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL2'] if submit==" Add and Edit ": url="%s/%s" % (url, urllib.quote(id)) REQUEST.RESPONSE.redirect(url+'/manage_workspace') def onDeleteObject(self): """Object delete handler.""" self.unindex_object() def findAllMemberNames(self): """ """ # XXX This should go up the folder tree... allusers=self.acl_users.getUsers() names=[] for user in allusers: if user.has_role('Member'): names.append(user.getUserName()) return names def getOwners(self, join=string.join): parent = self.aq_parent # XXX Workaround parent.aq_acquire('__ac_local_roles__') dict = parent.__ac_local_roles__ or {} # XXX Workaround list=[] for key, val in dict.items(): if 'Owner' in val: list.append(key) return join(list, ', ') def aq_base(ob): if hasattr(ob, 'aq_base'): return ob.aq_base return ob === Added File Products/Extensions/TrackerMethods.py === (2194/2294 lines abridged) """External methods for Tracker-related ZClasses and Products.""" #import Products.TrackerBase.TrackerMisc # DEBUG #reload(Products.TrackerBase.TrackerMisc) # DEBUG from Products.TrackerBase.TrackerMisc import * import OFS.Image import sys, time TRACKER_DATA_VERSION = 1 ISSUE_DATA_VERSION = 1 ITEM_DATA_VERSION = 1 def addTracker(self, id, REQUEST=None): """ """ # self = Factory - actually, FactoryDispatcher # Destination() = the folder in which the obj is being created. if not id: raise ValueError, "You must specify an id." inst = self.Tracker(id) dest = self.Destination() dest._setObject(id, inst) tracker = getattr(dest, id) tracker.DATA_VERSION = TRACKER_DATA_VERSION user = (REQUEST and `REQUEST.AUTHENTICATED_USER`) or '' tracker.manage_addLocalRoles(user, ['TrackerOwner']) for role in unique(ROLE_CATEGORIES['open'] + ROLE_CATEGORIES['dedicated']): if not tracker._has_user_defined_role(role): tracker._addRole(role) setTrackerRules(tracker) # Use the default, not the local host name # tracker.smtphost = socket.gethostname() tracker.smtpport = 25 for ps in tracker.propertysheets: ps.manage_changeProperties(REQUEST) tracker.supporters = [] tracker.clients = [] tracker.peers = [] tracker.open_subscribe = tracker.default_open_subscribe [-=- -=- -=- 2194 lines omitted -=- -=- -=-] ## (INCLUDE, 'overdue', 'ownership')))), ( # Clear up ownership pending state when suitable. (CONDITION, (NOT, (STATE, 'stage', 'pending'))), ( (CONDITION, (CONTAINS, 'due', 'ownership')), (ACTIONS, (REMOVE, 'due', 'ownership'))), ( (CONDITION, (CONTAINS, 'overdue', 'ownership')), (ACTIONS, (REMOVE, 'overdue', 'ownership')))), ( # Clear up rsvp pending state when suitable. (CONDITION, (AND, (OR, (CONTAINS, 'due', 'rsvp'), (CONTAINS, 'overdue', 'rsvp')), (NOT, (STATE, 'msgfromrole', 'Requester', 0)))), ( (CONDITION, (CONTAINS, 'due', 'rsvp')), (ACTIONS, (REMOVE, 'due', 'rsvp'))), ( (CONDITION, (CONTAINS, 'overdue', 'rsvp')), (ACTIONS, (REMOVE, 'overdue', 'rsvp')))), ( # Alert to languishing reply. (CONDITION, # The last correspondence is from the requester: (AND, (OR, ('<', (STATE, 'msgfromrole', ['Requester', 'TrackerOwner'], 0), (STATE, 'msgfromrole', 'Supporter', 0)), ('>', (STATE, 'msgfromrole', 'Requester', 0), 3*ADAY)))), # Send daily alerts to issue owner, after initial grace period: ( (CONDITION, (OR, (NOT, (STATE, 'alert', 'rsvp due', 0)), ('>', (STATE, 'alert', 'rsvp due', 0), 1*ADAY))), (ACTIONS, (SET, 'alert', 'rsvp due'), (NOTIFY, 'IssueOwner', "Issue %[var title]s %[var id]s correspondence pending", "Issue %[var issueIdentity]s requester is owed" " correspondence.") )), # This has been going on too long - alert the tracker owner once: ( (CONDITION, (AND, ('>', (STATE, 'alert', 'rsvp due', 0), 7*ADAY), (NOT, (STATE, 'alert', 'rsvp overdue', 0)))), (ACTIONS, (SET, 'alert', 'rsvp overdue'), (NOTIFY, 'TrackerOwner', "Issue %[var title]s %[var id]s correspondence WAY pending", "Issue %[var issueIdentity]s requester has been owed" " correspondence for more than 7 days.")))) ] return standard === Added File Products/Extensions/ZopeSite.py === import sys, os, string, time, random, urllib from DateTime import DateTime import pdb # Findable object methods. These are methods common to objects # which subclass Findable, which provide implementations for # obtaining certain metadata (such as creator), as well as # common methods that handle the details of indexing and # unindexing Findable objects. def manage_afterAdd(self, item, container): self.index_object(self) for object in self.objectValues(): try: s=object._p_changed except: s=0 object.manage_afterAdd(item, container) if s is None: object._p_deactivate() def manage_afterClone(self, item): # self.index_object(self) # Don't automaticall catalog clones. You can't, anyway. They're not # acquiring yet. for object in self.objectValues(): try: s=object._p_changed except: s=0 object.manage_afterClone(item) if s is None: object._p_deactivate() def manage_beforeDelete(self, item, container): self.unindex_object(self) for object in self.objectValues(): try: s=object._p_changed except: s=0 object.manage_beforeDelete(item, container) if s is None: object._p_deactivate() def creator(self, first_only=0): """Return a sequence of user names who have the local Owner role on an object. The name creator is used for this method to conform to Dublin Core. If first_only is true, return only the first name.""" #parent=self.aq_parent #roles=parent.aq_acquire('__ac_local_roles__') #dict=roles or {} #parent.__ac_local_roles__ or {} #items=[] #for key, val in dict.items(): # if 'Owner' in val: # items.append(key) #return string.join(items, ', ') users=[] for user, roles in self.get_local_roles(): if 'Owner' in roles: users.append(user) if users and first_only: return users[0] return string.join(users, ', ') def url(self, ftype=urllib.splittype, fhost=urllib.splithost): """Return a SCRIPT_NAME-based url for an object.""" if hasattr(self, 'DestinationURL') and \ callable(self.DestinationURL): url='%s/%s' % (self.DestinationURL(), self.id) else: url=self.absolute_url() type, uri=ftype(url) host, uri=fhost(uri) script_name=self.REQUEST['SCRIPT_NAME'] if script_name: uri=filter(None, string.split(uri, script_name))[0] uri=uri or '/' if uri[0]=='/': uri=uri[1:] return uri def summary(self, num=200): """Return a summary of the text content of the object.""" if not hasattr(self, 'text_content'): return '' attr=getattr(self, 'text_content') if callable(attr): text=attr() else: text=attr n=min(num, len(text)) return text[:n] def getIndex(self, REQUEST=None): # return the index to index an object in. # this is used to index Members's objects in a different # index than Contributors's objects. if REQUEST is None: REQUEST=self.REQUEST if REQUEST.AUTHENTICATED_USER.has_role('Contributor'): return self.SiteIndex return self.UnreviewedIndex def in_catalogs(self): """What catalogs am I REALLY in?""" catalogs = getattr(self, 'SiteCatalogs', ['SiteIndex', 'UnreviewedIndex']) catalogs = map(lambda x, self=self: getattr(self, x), catalogs) catalogs = filter(lambda x, self=self: x._catalog.uids.has_key(self.url()), catalogs) return map(lambda x: x.id, catalogs) def index_object(self, catalog=None): """ Update all catalogs I belong to. If passed a path in Catalog, also add self to that catalog. """ # Get the list of catalogs I already belong to catalogs = self.in_catalogs() # Refresh my entry in each of these catalogs for path in catalogs: try: catobj = resolve_path(self, path) try: catobj.uncatalog_object(self.absolute_url(1)) except: pass catobj.catalog_object(self, self.absolute_url(1)) except: pass # Did I get passed a new path? if catalog is not None and catalog not in catalogs: catobj = resolve_path(self, catalog) try: catobj.uncatalog_object(self.absolute_url(1)) except: pass catobj.catalog_object(self, self.absolute_url(1)) def unindex_object(self, catalog=None): """ Remove self from the path passed in catalog. If catalog is not given, remove self from all catalogs. """ if catalog is not None: catobj = resolve_path(self, catalog) try: catobj.uncatalog_object(self.absolute_url(1)) except: pass return catalogs = self.in_catalogs() for catalog in catalogs: catobj = resolve_path(self, catalog) try: catobj.uncatalog_object(self.absolute_url(1)) except: pass def date(self): """ Modification date. """ return self.bobobase_modification_time() # Utility functions # ----------------- def resolve_path(obj, path): while hasattr(obj, 'aq_parent'): obj = obj.aq_parent if hasattr(obj, 'aq_base'): b = obj.aq_base else: b = obj if hasattr(b, 'isTopLevelPrincipiaApplicationObject') and \ b.isTopLevelPrincipiaApplicationObject: break try: for id in string.split(path, '/'): try: obj=getattr(obj, id) except: obj=obj[id] return obj except: raise 'Catalog error', 'Can\'t resolve path: ' + `path` def fix_catalog_items(self, REQUEST): """self should be a catalog""" url = self.absolute_url(1) write = REQUEST.RESPONSE.write buf = '' for item in self.searchResults(): try: obj = self.getobject(item.data_record_id_, REQUEST) catalogs = getattr(obj, 'aq_base', obj).catalogs try: if url not in catalogs: catalogs.append(url) buf = buf + 'fixed %s\n' % obj.absolute_url(1) except: catalogs = [url] obj.catalogs = catalogs except: buf = buf + 'can\'t fix %s\n' % self.getpath(item.data_record_id_) return buf # STX Document methods # --------------------- default_format=""" """ def addSTXDocument(self, id, title='', submit='', REQUEST={}): """ """ dest=self.Destination() ob=self.STXDocument(default_format, __name__=id) REQUEST['date']=DateTime() ob.propertysheets.Findables.manage_changeProperties(REQUEST) ob.propertysheets.Basic.manage_changeProperties(REQUEST) dest._setObject(id, ob) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] if submit==" Add and Edit ": url="%s/%s" % (url, urllib.quote(id)) REQUEST.RESPONSE.redirect(url+'/manage_workspace') def manage_edit_ex(self, data, title, SUBMIT='Change', dtpref_cols='50', dtpref_rows='20', REQUEST=None): """Override manage_edit""" self.unindex_object(REQUEST=REQUEST) method=self.__class__.inheritedAttribute('manage_edit') method(self, data, title, SUBMIT, dtpref_cols, dtpref_rows) self.index_object() if REQUEST: message="Content changed." return self.manage_main(self,REQUEST,manage_tabs_message=message) def manage_upload_ex(self, file='', REQUEST=None): """Override manage_upload""" self.unindex_object(REQUEST=REQUEST) method=self.__class__.inheritedAttribute('manage_upload') method(self, file) self.index_object() if REQUEST: message="Content changed." return self.manage_main(self,REQUEST,manage_tabs_message=message) def STXDocument_text_content(self): """Return the text content of the object.""" # return the actual stx content... return self.content + ' ' + self.title # HTML Document methods # --------------------- def addHTMLDocument(self, id, title='', file='', submit='', REQUEST={}): """ """ dest=self.Destination() ob=self.HTMLDocument(file, __name__=id) REQUEST['date']=DateTime() ob.propertysheets.Findables.manage_changeProperties(REQUEST) dest._setObject(id, ob) if REQUEST: try: url=self.DestinationURL() except: url=REQUEST['URL1'] if submit==" Add and Edit ": url="%s/%s" % (url, urllib.quote(id)) REQUEST.RESPONSE.redirect(url+'/manage_workspace') def HTMLDocument_text_content(self): """Return the text content of the object.""" try: return self.read() except AttributeError: return "" # NewsItem methods # ---------------- def NewsItem_text_content(self): """Return the text content of the object.""" return self.text + ' ' + self.title # Link methods # ------------ def Link_text_content(self): """Return text description of a link.""" return self.description + ' ' + self.title # How-To methods # -------------- def HowTo_text_content(self): """Return text content of a How-To.""" return self.content + ' ' + self.title # Tip methods # ----------- def Tip_text_content(self): """Return text content of a tip""" return self.tip + self.details # Case Study methods # ------------------ def CaseStudy_text_content(self): """Return composite of major sections for indexing.""" return self.case_study_summary + '\n' + \ self.facts + '\n' + \ self.problem + '\n' + \ self.solution + '\n' + \ self.external_url # Software methods # ---------------- def Software_text_content(self): """Return text content of a Software object.""" return self.description + ' ' + self.title def findAllMemberNames(self): """ """ # XXX This should go up the folder tree... allusers=self.acl_users.getUsers() names=[] for user in allusers: if user.has_role('Member'): names.append(user.getUserName()) return names def foo(self): t = [] obj = self count = 0 while 1: if hasattr(obj, 'aq_parent'): t.append(`obj`) obj = obj.aq_parent else: break count = count + 1 if count > 10: t.append("!!") break return "

Self gots .%s.

" % string.join(t, ', ') def getOwners(self, join=string.join): parent = self.aq_parent # XXX Workaround parent.aq_acquire('__ac_local_roles__') dict = parent.__ac_local_roles__ or {} # XXX Workaround list=[] for key, val in dict.items(): if 'Owner' in val: list.append(key) return join(list, ', ') def reindex_all(self, obj=None): """ """ if obj is None: obj=self if hasattr(aq_base(obj), 'index_object'): obj.index_object() if hasattr(aq_base(obj), 'objectValues'): sub=obj.objectValues() for item in obj.objectValues(): reindex_all(self, item) return 'done!' === Added File Products/Extensions/commit_version.py === """Put this in the Extensions directory and create an external method in the Zope root named "commit_version" with a function name of "commit_version". Then fire up the debugger and do import Zope; app=Zope.app() Then grab a hold of the object that's locked in the database and assign it to a local variable, e.g.: a = app.Wikis.locked Then do: app.commit_version('version_name', a) This should commit the version.""" def commit_version(self, version=None, ob=None): """ version should be string which contains the version name that is to be committed. ob should be any object out of the database which houses the version to be committed. A good choice of objects is the one on which a "versionlock" icon is showing. """ if version is None: raise "You must provide a version name" if ob is None: raise ("You must pass in an object that resides in the same" " database as the one in which the version resides.") db = ob._p_jar._db db.commitVersion(version) get_transaction().commit() === Added File Products/Extensions/countDoubles.py === # # countDoubles: count the number of user names that are the same and only differ in capitalization # import string def countDoubles(self): double_names = {} uf = self.acl_users user_list = uf.getUserNames() total = len(user_list) header = '' lower_list = map(string.lower, user_list) for name in lower_list: occurrences = lower_list.count(name) if occurrences > 1: double_names[name] = occurrences doubles_list = double_names.keys() doubles_list.sort() double_count = len(doubles_list) header = 'Total users: %d\nNumber of doubles: %d\n\n' % (total, double_count) doubles_str = '' for name in doubles_list: user_str = name + ' (%d):\n' % double_names.get(name) lc_user = uf.getUser(name) fc_user = uf.getUser(string.capitalize(name)) auc_user = uf.getUser(string.upper(name)) for user in (lc_user, fc_user, auc_user): if user is not None: str = '%s is: %s (%s), last visit %s\n' % ( getattr(user, 'name', 'n/a') , getattr(user, 'full_name', 'n/a') , getattr(user, 'email', 'n/a') , user.last_visit.Date() ) user_str = user_str + str doubles_str = doubles_str + user_str + '\n\n' return header + doubles_str === Added File Products/Extensions/fixfiles.py === from types import StringType def fixfiles(self): nzo = self.getPhysicalRoot().nzo recs = nzo.portal_catalog(Type='Software Release File') for rec in recs: ob = rec.getObject() if isinstance(ob.data, StringType) and len(ob.data) >= 65536: ob.manage_upload(ob.data) get_transaction().commit(1) ob._p_deactivate() === Added File Products/Extensions/fixids.py === from string import join def _fix(obj, fixed): if hasattr(obj, 'objectIds'): for id in obj.objectIds(): subobj = getattr(obj, id) if hasattr(subobj, '__name__') and subobj.__name__ == '': # Correct this one. subobj.__name__ = id fixed.append(subobj.absolute_url()) _fix(subobj, fixed) return fixed def fixids(self): corrections = _fix(self, []) return 'Corrections:\n%s\n\nDone.' % join(corrections, '\n') === Added File Products/Extensions/getcwd.py === import os def getcwd(): return os.getcwd() === Added File Products/Extensions/move_news.py === import sys, os, string, md5 from webdav.client import Resource from base64 import encodestring from urllib import quote dest_url='http://tarzan.digicool.com/dev/zope/News' username='Brian Lloyd' password='123' def auth_gen(name, pw): # hack - create a MemberFolder auth cookie. enc=md5.new() enc.update('%s:%s' % (name, pw)) token=enc.digest() token=string.join(map(lambda c: '%02x' % ord(c), token), '') token='%s:%s' % (name, token) token=encodestring(token) token=quote(token) return token def send_item(item): """ """ url='%s/manage_addProduct/ZopeSite/fNewsItem/addNewsItem' % dest_url obj=Resource(url) headers={'Cookie': '__ac="%s"' % auth_gen(username, password)} id='%04s' % item.data_record_id_ subject=filter(None, map(string.strip, string.split(item.Keywords, ', '))) result=obj.post(id=id, title=item.Title, text=item.Text, subject__list=subject, date_override=str(item.Date), headers=headers, ) return result def test(): class foo: data_record_id_=99 Text='item text' Keywords='foo, bar' Title='item title' Date='1999/12/05' result=send_item(foo()) print result if __name__=='__main__': test() === Added File Products/Extensions/ownerous.py === # External method to fixup membership on zope.org. import string def fixup_members(self): users=self.acl_users Members=self.Members r=[] for i in Members.objectIds(): try: u=users.getUserById(i) m=getattr(Members, i) except: pass else: if u is not None: u=u.__of__(users) m.changeOwnership(u) r.append(i) return string.join(r,'\n') === Added File Products/Extensions/plaintext.py === import string import re pat=re.compile(r"(http://|https://|ftp://|mailto:)(.+?)(\s|\")") def linkf(m): url=m.group(1) + m.group(2) return """%s%s""" % (url, url, m.group(3)) def replace(text): "simple minded url linking" return re.sub(pat, linkf, text) def plaintext(text): "simple text formatting" text=string.replace(text, '>', '>') text=string.replace(text, '<', '<') text=string.replace(text, '&', '&') text=string.replace(text, '"', '"') text=replace(text) text=string.replace(text, '\n', '
\n') return text def strip_html(text): "strip html brutally" html_smell = re.compile('<.*?>') text=html_smell.sub('',text) broken_link= re.compile('<.*') finished_text=broken_link.sub('',text) return finished_text === Added File Products/Extensions/rconsole.py === import socket from code import InteractiveConsole from types import IntType, StringType from thread import start_new_thread, get_ident import sys import time class ThreadedObjectProxy: """Proxy to different objects based which thread invoked it. """ def __init__(self, default): self._default = default self._alts = {} def setAlternative(self, o): self._alts[get_ident()] = o def delAlternative(self): try: del self._alts[get_ident()] except KeyError: pass def __getattr__(self, name): ob = self._alts.get(get_ident(), self._default) return getattr(ob, name) class RemoteConsole(InteractiveConsole): def __init__(self, sock, file, filename=None, locals=None): if filename is None: filename = str(file) self.sock = sock self.file = file InteractiveConsole.__init__(self, locals=locals, filename=filename) def raw_input(self, prompt=''): if prompt: self.file.write(prompt) s = self.file.readline().rstrip() if s == '\x04': # Ctrl-D raise EOFError return s def interactAndClose(self): sys.stdout.setAlternative(self.file) sys.stderr.setAlternative(self.file) sys.stdin.setAlternative(self.file) try: try: self.interact() except EOFError: pass finally: sys.stdout.delAlternative() sys.stderr.delAlternative() sys.stdin.delAlternative() self.file.close() self.sock.close() def setupStreams(): if not hasattr(sys.stdout, 'setAlternative'): sys.stdout = ThreadedObjectProxy(sys.stdout) if not hasattr(sys.stderr, 'setAlternative'): sys.stderr = ThreadedObjectProxy(sys.stderr) if not hasattr(sys.stdin, 'setAlternative'): sys.stdin = ThreadedObjectProxy(sys.stdin) def accept_connections(s): while 1: cs, addr = s.accept() f = cs.makefile('w+', 0) i = RemoteConsole(cs, f) start_new_thread(i.interactAndClose, ()) def listen(addr, locals=None): setupStreams() if isinstance(addr, StringType): t = socket.AF_UNIX elif isinstance(addr, IntType): t = socket.AF_INET addr = ('', addr) else: t = socket.AF_INET s = socket.socket(t, socket.SOCK_STREAM) s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, s.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1 ) s.bind(addr) s.listen(1) start_new_thread(accept_connections, (s,)) def listenlocal(port=8765): listen(('localhost', port)) if __name__ == '__main__': listen(8765) while 1: time.sleep(1) === Added File Products/Extensions/rfc1123.py === from webdav.common import rfc1123_date def rfc1123(self, date): """ Returns a RFC1123 date string give a DateTime object. This is useful for HTTP headers. """ return rfc1123_date(date.timeTime()) === Added File Products/Extensions/rungc.py === def rungc(): """Invokes garbage collection.""" import gc res = gc.collect() return 'gc results: %s' % repr(res) === Added File Products/Extensions/set_title.py === import re pat=re.compile(r"(.*?)", re.IGNORECASE) def set_title(self): """ set the title on a title-less DTML Document or Method by consulting the document source and looking for a title tag. """ m=pat.search(self.read()) if m is not None: title=m.group(1) setattr(self, 'title', title) === Added File Products/Extensions/sort_link.py === import re, urllib sort_pat=re.compile(r'(\&)?sort(-|_)on=([^\&]+)') order_pat=re.compile(r'(\&)?sort(-|_)order=([^&]+)') start_pat=re.compile(r'(\&)?query_start=([^&]+)') def sort_link(self, name, index, REQUEST): """ Returns Anchor tag with appropriate link to do a sorted search. name is the name of the link index is the index to sort on """ sort=None order=None klass='listheader' image='spc.gif' qs=REQUEST['QUERY_STRING'] m=sort_pat.search(qs) if m is not None: sort=m.group(3) qs=qs[:m.start()] + qs[m.end():] m=order_pat.search(qs) if m is not None: order=m.group(3) qs=qs[:m.start()] + qs[m.end():] m=start_pat.search(qs) if m is not None: start=m.group(2) qs=qs[:m.start()] + qs[m.end():] qs=qs + '&sort_on=' + urllib.quote_plus(index) if sort==index: if order != 'reverse': qs=qs + '&sort_order=reverse' klass='listheader_selected' image='dwn_arrow.gif' else: klass='listheader_reverse' image='up_arrow.gif' # return '

%s

' % (klass, REQUEST['URL'], qs, name) return '

%s

' % (image, REQUEST['URL'], urllib.quote(qs, '/%&='), name) === Added File Products/Extensions/sort_link.py.old === import re, urllib sort_pat=re.compile(r'(\&)?sort(-|_)on=([^\&]+)') order_pat=re.compile(r'(\&)?sort(-|_)order=([^&]+)') start_pat=re.compile(r'(\&)?query_start=([^&]+)') def sort_link(self, name, index, REQUEST): """ Returns Anchor tag with appropriate link to do a sorted search. name is the name of the link index is the index to sort on """ sort=None order=None klass='listheader' qs=REQUEST['QUERY_STRING'] m=sort_pat.search(qs) if m is not None: sort=m.group(3) qs=qs[:m.start()] + qs[m.end():] m=order_pat.search(qs) if m is not None: order=m.group(3) qs=qs[:m.start()] + qs[m.end():] m=start_pat.search(qs) if m is not None: start=m.group(2) qs=qs[:m.start()] + qs[m.end():] qs=qs + '&sort_on=' + urllib.quote_plus(index) if sort==index: if order != 'reverse': qs=qs + '&sort_order=reverse' klass='listheader_selected' else: klass='listheader_reverse' return '

%s

' % (klass, REQUEST['URL'], qs, name) === Added File Products/Extensions/test.py === import sys, string, os import pdb def testfunc(self, arg1, arg2=None): """A test method""" return 'ok' def callmeth(self, REQUEST): pdb.set_trace() self.standard_html_header(REQUEST) === Added File Products/Extensions/which_node.py === def which_node(): return 'node 1' === Added File Products/Extensions/wikimnt.py === # Define the Wiki database mounted database import ZServer, ZODB, ZEO.ClientStorage def wikidb(): if 0: import ZODB.FileStorage, os Storage=ZODB.FileStorage.FileStorage( os.path.join(INSTANCE_HOME,'var','Wikis.fs'), #read_only=1 ) else: Storage=ZEO.ClientStorage.ClientStorage( ('127.0.0.1',2222), cache_size=50*1000*1000, max_disconnect_poll=40, min_disconnect_poll=1, storage='Wikis', ) return ZODB.DB(Storage) From sidnei at x3ng.com.br Fri May 30 12:20:31 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/Extensions - sort_link.py.old:NONE Message-ID: <200305301620.h4UGKVe29947@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Extensions In directory cvs.zope.org:/tmp/cvs-serv29934 Removed Files: sort_link.py.old Log Message: old === Removed File Products/Extensions/sort_link.py.old === From sidnei at x3ng.com.br Fri May 30 12:30:20 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.7 Message-ID: <200305301630.h4UGUK931319@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv31305 Modified Files: buildout_zope_sandbox Log Message: Added Extensions, removed PythonMethod === NZO_SiteLayout/buildout_zope_sandbox 1.6 => 1.7 === ExternalMount="$ZOPEORG_CVS_REPOSITORY co -dExternalMount Products/ExternalMount " ParsedXML="$ZOPEORG_CVS_REPOSITORY co -dParsedXML Products/ParsedXML " PortalBase="$ZOPEORG_CVS_REPOSITORY co -dPortalBase Products/PortalBase " -PythonMethod="$ZOPEORG_CVS_REPOSITORY co -dPythonMethod Products/PythonMethod " +#PythonMethod="$ZOPEORG_CVS_REPOSITORY co -dPythonMethod Products/PythonMethod " Redirector="$ZOPEORG_CVS_REPOSITORY co -dRedirector Products/Redirector " TrackerBase="$ZOPEORG_CVS_REPOSITORY co -dTrackerBase Products/TrackerBase " XMLDocument="$ZOPEORG_CVS_REPOSITORY co -dXMLDocument Products/XMLDocument " ZDBase="$ZOPEORG_CVS_REPOSITORY co -dZDBase Products/ZDBase " +Extensions="$ZOPEORG_CVS_REPOSITORY co -dExtensions Products/Extensions " #------------------------------------------------------------------------------ # Build top-level sandbox dirs @@ -425,11 +426,11 @@ echo "Retrying in 30s"; sleep 30; done -echo "Checking out PythonMethod"; -echo "cvs -Q -z7 -d $PythonMethod"; -while ! `cvs -Q -z7 -d $PythonMethod`; do - echo "Retrying in 30s"; sleep 30; -done +# echo "Checking out PythonMethod"; +# echo "cvs -Q -z7 -d $PythonMethod"; +# while ! `cvs -Q -z7 -d $PythonMethod`; do +# echo "Retrying in 30s"; sleep 30; +# done echo "Checking out Redirector"; echo "cvs -Q -z7 -d $Redirector"; @@ -455,6 +456,12 @@ echo "Retrying in 30s"; sleep 30; done +echo "Checking out Extensions"; +echo "cvs -Q -z7 -d $Extensions"; +while ! `cvs -Q -z7 -d $Extensions`; do + echo "Retrying in 30s"; sleep 30; +done + cd $optdir cp -rs $srcdir/CMF-$CMF_VERSION . ln -s CMF-$CMF_VERSION CMF @@ -477,11 +484,12 @@ ln -s $srcdir/ExternalMount . ln -s $srcdir/ParsedXML . ln -s $srcdir/PortalBase . -ln -s $srcdir/PythonMethod . +# ln -s $srcdir/PythonMethod . ln -s $srcdir/Redirector . ln -s $srcdir/TrackerBase . ln -s $srcdir/XMLDocument . ln -s $srcdir/ZDBase . +ln -s $srcdir/Extensions . if [ "$CMF_VERSION" == "1.3.1" -o "$CMF_VERSION" == "1.3-branch" ]; then @@ -529,12 +537,14 @@ ln -s $optdir/ExternalMount . ln -s $optdir/ParsedXML . ln -s $optdir/PortalBase . -ln -s $optdir/PythonMethod . +# ln -s $optdir/PythonMethod . ln -s $optdir/Redirector . ln -s $optdir/TrackerBase . ln -s $optdir/XMLDocument . ln -s $optdir/ZDBase . +cd $vardir/zope +ln -s $optdir/Extensions . if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then ln -s $optdir/DBTab . @@ -577,7 +587,7 @@ zeo_start=$optdir/Zope/lib/python/ZEO/start.py INSTANCE_HOME=$vardir/storage -EVENT_LOG_FILE=$INSTANCE_HOME/var/debug.log +EVENT_LOG_FILE=\$INSTANCE_HOME/var/debug.log export INSTANCE_HOME EVENT_LOG_FILE pidfile=\$INSTANCE_HOME/var/ZEO_SERVER.pid From sidnei at x3ng.com.br Fri May 30 13:07:00 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.8 Message-ID: <200305301707.h4UH70704027@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv4013 Modified Files: buildout_zope_sandbox Log Message: add ZopeProfiler === NZO_SiteLayout/buildout_zope_sandbox 1.7 => 1.8 === PYXML_SF_DOWNLOAD=http://aleron.dl.sourceforge.net/sourceforge/pyxml PYXML_URL=$PYXML_SF_DOWNLOAD/PyXML-$PYXML_VERSION.tar.gz +ZOPEPROFILER_URL=http://www.dieter.handshake.de/pyprojects/zope/ZopeProfiler.tgz + ZOPE_CVSROOT=:pserver:anonymous@cvs.zope.org:/cvs-repository PYTHON_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/python ZOPEORG_CVS_REPOSITORY=:pserver:anonymous@cvs.zope.org:/cvs-zopeorg @@ -252,6 +254,11 @@ cd PyXML $bindir/python setup.py install +cd $tmpdir +wget --continue $ZOPEPROFILER_URL +cd $srcdir +tar xzf $tmpdir/ZopeProfiler.tgz + #------------------------------------------------------------------------------ # Build Zope SOFTWARE_HOME #------------------------------------------------------------------------------ @@ -477,6 +484,7 @@ ln -s $srcdir/Formulator . ln -s $srcdir/ExternalEditor . ln -s $srcdir/CMFPackage . +ln -s $srcdir/ZopeProfiler . # Old Products are: # BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase @@ -530,6 +538,7 @@ ln -s $optdir/Formulator . ln -s $optdir/ExternalEditor . ln -s $optdir/CMFPackage . +ln -s $optdir/ZopeProfiler . # Old Products are: # BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase From sidnei at x3ng.com.br Fri May 30 17:10:19 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.9 Message-ID: <200305302110.h4ULAJS08749@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv8735 Modified Files: buildout_zope_sandbox Log Message: Enabling ContentList and fixing a misconfiguration. === NZO_SiteLayout/buildout_zope_sandbox 1.8 => 1.9 === ZWiki="$ZWIKI_CVS_REPOSITORY co -dZWiki zwiki " BackTalk="$BACKTALK_CVS_REPOSITORY co -dBackTalk BackTalk " CMFBackTalk="$COLLECTIVE_CVS_REPOSITORY co -dCMFBackTalk CMFBackTalk " +CMFContentList="$COLLECTIVE_CVS_REPOSITORY co -dCMFContentList CMFContentList " CMFPlone="$PLONE_CVS_REPOSITORY co -dCMFPlone -r$PLONE_TAG CMFPlone " Formulator="$FORMULATOR_CVS_REPOSITORY co -dFormulator -r$FORMULATOR_TAG Formulator " ExternalEditor="$ZOPE_CVSROOT co -dExternalEditor Products/ExternalEditor " @@ -383,6 +384,12 @@ echo "Retrying in 30s"; sleep 30; done +echo "Checking out CMFContentList"; +echo "cvs -Q -z7 -d $CMFContentList"; +while ! `cvs -Q -z7 -d $CMFContentList`; do + echo "Retrying in 30s"; sleep 30; +done + echo "Checking out CMFPlone"; echo "cvs -Q -z7 -d $CMFPlone"; while ! `cvs -Q -z7 -d $CMFPlone`; do @@ -478,6 +485,7 @@ ln -s $srcdir/ZWiki . ln -s $srcdir/BackTalk . ln -s $srcdir/CMFBackTalk . +ln -s $srcdir/CMFContentList . ln -s $srcdir/CMFCollector . ln -s $srcdir/QueueCatalog . ln -s $srcdir/CMFPlone . @@ -518,6 +526,12 @@ fi #------------------------------------------------------------------------------ +# Install Extansions +#------------------------------------------------------------------------------ +cd $vardir/zope +ln -s $optdir/Extensions . + +#------------------------------------------------------------------------------ # Install products #------------------------------------------------------------------------------ cd $vardir/zope/Products @@ -526,6 +540,7 @@ ln -s $optdir/CMF/CMFTopic . ln -s $optdir/CMF/CMFCalendar . ln -s $optdir/CMFBackTalk . +ln -s $optdir/CMFContentList . ln -s $optdir/CMFCollector . ln -s $optdir/QueueCatalog . ln -s $optdir/DCWorkflow . @@ -551,9 +566,6 @@ ln -s $optdir/TrackerBase . ln -s $optdir/XMLDocument . ln -s $optdir/ZDBase . - -cd $vardir/zope -ln -s $optdir/Extensions . if [ "$ZOPE_VERSION" == "2.6.1" -o "$ZOPE_VERSION" == "2.6-branch" ]; then ln -s $optdir/DBTab . From sidnei at x3ng.com.br Fri May 30 17:13:36 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/ZopeOrg-NV/Extensions - NZOMigrate.py:1.24 Message-ID: <200305302113.h4ULDab09175@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZopeOrg-NV/Extensions In directory cvs.zope.org:/tmp/cvs-serv9145/Extensions Modified Files: NZOMigrate.py Log Message: Fixing some bits on the installer. Enabling CMFContentList, disabling CMFDateIndexes, hotfixing DublinCore (Overflow!), added QueueCatalog. Fixing some bits on the migration. Try to deactivate objects as much as possible, and lower the subtransaction interval (weve got some BIG objects here eh) === Products/ZopeOrg-NV/Extensions/NZOMigrate.py 1.23 => 1.24 === from StringIO import StringIO from ZODB.POSException import POSKeyError from Acquisition import aq_base, aq_parent, aq_inner +from Products.CMFCore.WorkflowCore import WorkflowException from Products.CMFCore.utils import getToolByName from Products.CMFCollector.CollectorIssue import CollectorIssue from DateTime import DateTime @@ -141,11 +142,19 @@ if action != 'request' and action not in issue._valid_actions(): raise 'Unauthorized', "Invalid action '%s'" % action - issue.portal_workflow.doActionFor(issue, - action, - comment=comment, - username=username, - assignees=assignees) + try: + issue.portal_workflow.doActionFor(issue, + action, + comment=comment, + username=username, + assignees=assignees) + except WorkflowException: + action = 'new_issue' + issue.portal_workflow.doActionFor(issue, + action, + comment=comment, + username=username, + assignees=assignees) new_status = issue.status().split('_')[0] @@ -208,7 +217,7 @@ comment = '(Supporters added by migration tool)' action = 'assign' date = DateTime() - + issue.portal_workflow.doActionFor(issue, action, comment=comment, @@ -812,6 +821,7 @@ 'application/octet-stream') r.update_data(data, content_type, size) + r.manage_upload(data) r._calculateMD5() r.setPlatform(platform) f.setMaturity(maturity) @@ -852,7 +862,7 @@ transcript = new_issue.get_transcript() transcript.edit(new_issue.TRANSCRIPT_FORMAT, text) - doIssueAssign(new_issue, + doIssueAssign(new_issue, assignees=kw['assignees']) doIssueAction(new_issue, action=kw['resolution'], comment=getattr(last_issue, 'description'), @@ -865,9 +875,13 @@ att['title'], att['data']) result.append(new_issue) get_transaction().commit() + issue._p_deactivate() + new_issue._p_deactivate() self.log('Migrated Issue %s.\n' % kw['id']) CollectorIssue._send_update_notice = CollectorIssue._old_send_update_notice + collector._setPropValue('last_issue_id', int(kw['id'])) + collector._p_deactivate() return tuple(result) @@ -1199,9 +1213,11 @@ if self._count % 100: get_transaction().commit() - elif self._count % 50: + elif self._count % 20: get_transaction().commit(1) + new_obj._p_deactivate() + obj._p_deactivate() self.log('%s: Success.\n' % obj_url) return 'Ok.\n' From sidnei at x3ng.com.br Fri May 30 17:14:06 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/ZopeOrg-NV - Installer.py:1.3 __init__.py:1.23 Message-ID: <200305302114.h4ULE6W09317@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZopeOrg-NV In directory cvs.zope.org:/tmp/cvs-serv9145 Modified Files: Installer.py __init__.py Log Message: Fixing some bits on the installer. Enabling CMFContentList, disabling CMFDateIndexes, hotfixing DublinCore (Overflow!), added QueueCatalog. Fixing some bits on the migration. Try to deactivate objects as much as possible, and lower the subtransaction interval (weve got some BIG objects here eh) === Products/ZopeOrg-NV/Installer.py 1.2 => 1.3 === import os, string from StringIO import StringIO +from Acquisition import aq_base from Products.CMFPlone.Portal import addPolicy from Products.CMFPlone.CustomizationPolicy import DefaultCustomizationPolicy @@ -15,10 +16,12 @@ from Products.ZCTextIndex import ZCTextIndex from Products.PluginIndexes.DateIndex.DateIndex import DateIndex from Products.PluginIndexes.DateRangeIndex.DateRangeIndex import DateRangeIndex -from Products.CMFDateIndexes.RSCatalogTool import RSCatalogTool from Products.ExternalMethod.ExternalMethod import ExternalMethod +from Products.QueueCatalog import QueueCatalog + + def register(context, app_state): addPolicy('Zope.org Policy', ZopeOrgPolicy()) @@ -30,8 +33,8 @@ NEEDED_PRODUCTS = ( 'CMFDefault' , 'CMFCore' , 'CMFCalendar' - , 'CMFDateIndexes' , 'CMFCollector' + , 'CMFContentList' , 'ZWiki' , 'CMFPackage' , 'BackTalk' @@ -44,10 +47,12 @@ , 'CMFPlone' , 'Formulator' , 'ExternalEditor' + , 'QueueCatalog' + , 'ZopeProfiler' ) SKINPATHS = ( 'Basic', - 'NZO', + 'NZO', 'Plone Core', 'Plone Default', 'Plone Autumn', @@ -78,7 +83,7 @@ ZCTEXTINDEXES = ( 'Description', 'SearchableText', 'Title' ) WORKFLOWS = (('default', 'zopeorg_default_workflow', - 'Default Zope.org Workflow'), + 'Default Zope.org Workflow'), ) EXT_METHODS = ( { 'id' : 'ZO_NZOMigrate' @@ -90,7 +95,7 @@ , 'title' : 'Synchronize ZODB and filesystem skeleton' , 'module' : 'ZopeOrg.synchronizeSkeleton' , 'function' : 'synchronize' - } + } ) PRODUCTS_SETUP = ({'id' : 'ZWiki' @@ -109,6 +114,10 @@ , 'module': 'CMFCollector.Extensions.Install' , 'function' : 'install' } + , { 'id' : 'CMFContentList' + , 'module': 'CMFContentList.Extensions.Install' + , 'function' : 'install' + } ) SEPARATOR = '\n' + '='*65 + '\n' @@ -120,7 +129,7 @@ class ZopeOrgPolicy(DefaultCustomizationPolicy): """ Zope.org Initialization """ - + __implements__ = ICustomizationPolicy def __init__(self): @@ -128,7 +137,7 @@ def log(self, msg): self.out.write(msg + SEPARATOR) - + def customize(self, portal): DefaultCustomizationPolicy().customize(portal) self.log('Checking dependencies....') @@ -146,6 +155,9 @@ self.log('Configuring Actions....') self.setupActions(portal) + self.log('Fixing Collector Actions....') + self.setupCollectorActions(portal) + self.log('Configuring Slots....') self.setupDefaultSlots(portal) @@ -158,7 +170,7 @@ self.log('Setting up new skins....') self.registerSkins(portal) - self.log('Replacing Portal Catalog Tool with Date Range version....') + self.log('Replacing Portal Catalog Tool with QueueCatalog....') self.replaceCatalogTool(portal) self.log('Modifying Catalog Indexes and Metadata....') @@ -167,13 +179,13 @@ self.catalogReplaceIndexes(portal) self.catalogAddColumns(portal) self.catalogAddZCTextIndexes(portal) - + self.log('Instantiating type objects in the Types tool...') self.setupTypes( portal ) self.log('Enabling Discussions....') self.setupDiscussions(portal) - + self.log('Instantiating MetaData Policies in the MetaData tool....') self.setupMetaData(portal) @@ -185,7 +197,7 @@ self.log('Finished conversion process!') return self.out.getvalue() - + def setupProducts(self, portal): for p in PRODUCTS_SETUP: d = {} @@ -220,7 +232,7 @@ import Products not_installed = [] installed_products = dir( Products ) - + for prod_name in NEEDED_PRODUCTS: if prod_name not in installed_products: not_installed.append(prod_name) @@ -230,7 +242,7 @@ def registerWorkflows(self, portal): """ Insert new zope.org workflows into the workflow tool """ - + for wf_tuple in WORKFLOWS: wf_portaltype = wf_tuple[0] wf_id = wf_tuple[1] @@ -247,7 +259,7 @@ wf_tool.setChainForPortalTypes( (wf_portaltype,) , wf_id ) - self.log(' - Inserted workflow "%s" for type "%s"' % (wf_id, + self.log(' - Inserted workflow "%s" for type "%s"' % (wf_id, wf_portaltype)) wf_tool.updateRoleMappings() @@ -379,31 +391,49 @@ ) self.log('Set allowed types for BTree Folder to: %s' % all_types) + def setupCollectorActions(self, portal): + types_tool = getattr( portal, 'portal_types' ) + all_types = types_tool.objectIds() + fixed = [] + + for type in all_types: + if type.find('Collector') >= 0: + fixed.append(type) + t = getattr(types_tool, type) + ptype_actions=t._cloneActions() + for action in ptype_actions: + if action['action'].find('string:${object_url}/') == 0: + action['action'] = action['action'][21:] + t._actions=tuple(ptype_actions) + + self.log('Fixed actions for : %s' % fixed) + def replaceCatalogTool(self, portal): """Replace the catalog tool if necessary""" p_cat = getattr(portal, 'portal_catalog') - if isinstance(p_cat, RSCatalogTool): - self.log(' - Portal Catalog tool already an RSCatalogTool') + if isinstance(p_cat, QueueCatalog): + self.log(' - Portal Catalog tool already a QueueCatalog') return - new_cat = RSCatalogTool() + new_cat = QueueCatalog() new_cat.__dict__.update(p_cat.__dict__) + new_cat.manage_edit('', location='portal_catalog_real', immediate_removal=1) new_cat._p_changed = 1 setattr(portal, 'portal_catalog', new_cat) + portal._setObject('portal_catalog_real', aq_base(p_cat)) objmap = portal._objects for info in objmap: if info['id'] == 'portal_catalog': info['meta_type'] = new_cat.meta_type portal._objects = objmap - self.log(' - Replaced Portal Catalog tool with RSCatalogTool') - + self.log(' - Replaced Portal Catalog tool with QueueCatalog') def catalogAddIndexes(self, portal): """ Add Indexes to the portal catalog """ - p_cat = getattr(portal, 'portal_catalog') + p_cat = getattr(portal, 'portal_catalog_real') cat_core = p_cat._catalog retained = [] added = [] @@ -429,7 +459,7 @@ def catalogAddZCTextIndexes(self, portal): """ Add ZCTextIndexes to the portal catalog """ - p_cat = getattr(portal, 'portal_catalog') + p_cat = getattr(portal, 'portal_catalog_real') cat_core = p_cat._catalog replaced = [] added = [] @@ -479,7 +509,7 @@ def catalogReplaceIndexes(self, portal): """ Replace indexes in the portal catalog """ - p_cat = getattr(portal, 'portal_catalog') + p_cat = getattr(portal, 'portal_catalog_real') cat_core = p_cat._catalog retained = [] replaced = [] @@ -506,7 +536,7 @@ def catalogAddColumns(self, portal): """ Add metadata colums to the portal catalog """ - p_cat = getattr(portal, 'portal_catalog') + p_cat = getattr(portal, 'portal_catalog_real') cat_core = p_cat._catalog added = [] retained = [] @@ -527,7 +557,7 @@ def catalogAddEffectiveRange(self, portal): """ Add the effectiveRange DateRangeIndex index """ - p_cat = getattr(portal, 'portal_catalog') + p_cat = getattr(portal, 'portal_catalog_real') cat_core = p_cat._catalog if cat_core.indexes.has_key('effectiveRange'): @@ -546,7 +576,7 @@ contentTypes = ['Document', 'File', 'HowTo', 'Link', 'News Item', 'Tip'] for i in contentTypes: if i in tt.objectIds(): - ob = tt._getOb(i) + ob = tt._getOb(i) ob.allow_discussion = 1 self.log(' - Enabling Discussion on "%s"' % i) @@ -560,7 +590,7 @@ if type in prePolicies: mt.removeElementPolicy(element='Subject', content_type='%s' % type) self.log(' - Existing %s MetaData Policy removed' % type) - + mt.addElementPolicy(element='Subject' , content_type='Link' , is_required=0 === Products/ZopeOrg-NV/__init__.py 1.22 => 1.23 === +from string import rfind +from DateTime.DateTime import DateTime + from Products.CMFCore.DirectoryView import registerDirectory from Products.CMFCore.utils import registerIcon, ToolInit, ContentInit from Products.CMFCore.CMFCorePermissions import AddPortalContent @@ -9,11 +12,14 @@ import ZopeServiceProvider import ZopeOrgTypes import ZPublisher.Publish -from string import rfind #Hackish workaround to allow accesing the broken ZODB on ZopeOrg class ImplicitAcquirerWrapper: pass + +from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl +DefaultDublinCoreImpl._DefaultDublinCoreImpl__FLOOR_DATE = DateTime(1979, 0) +DefaultDublinCoreImpl._DefaultDublinCoreImpl__CEILING_DATE = DateTime(2979, 0) Acquisition.ImplicitAcquirerWrapper = ImplicitAcquirerWrapper ZPublisher.Publish.rfind = rfind From sidnei at x3ng.com.br Fri May 30 17:15:19 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/Extensions - TrackerMethods.py:1.2 Message-ID: <200305302115.h4ULFJr09469@cvs.baymountain.com> Update of /cvs-zopeorg/Products/Extensions In directory cvs.zope.org:/tmp/cvs-serv9455 Modified Files: TrackerMethods.py Log Message: Overflow with Python2.2.3 === Products/Extensions/TrackerMethods.py 1.1 => 1.2 === def setTrackerConfig(self, REQUEST): """Process fundamental configuration activities. - If request has a 'nextpage' setting, we redirect there, otherwise we go + If request has a 'nextpage' setting, we redirect there, otherwise we go to the tracker proper.""" # XXX Will this be needed for site search stuff? @@ -102,7 +102,7 @@ for role in roles: if not tracker._has_user_defined_role(role): tracker._addRole(role) - + if do_catalog: trackerInitCatalog(tracker) @@ -179,7 +179,7 @@ REQUEST.set('tickets_%s_date' % i, dstr) # tracker.assignments: {supporter: {trait: [vals, ...]}} - sa = {} + sa = {} if hasattr(self, 'assignments'): sa.update(self.assignments) # tracker.supporters: [supporter, ...] @@ -288,7 +288,7 @@ sa[t] = curr self.assignments = assignments - + def addTrackerIssue(self, REQUEST=None): """Do permission setting and item allocations for new issue. @@ -448,13 +448,13 @@ Populate the issue with a freshly minted item, setting the item's action from the msgrole setting and the description, from, date, etc from the - REQUEST, and doing a lot of incidental business: + REQUEST, and doing a lot of incidental business: - Create a new item - Add the item to the issue - Register the item's action according to the msgrole. - Set some other item metadata according to the REQUEST and incidental - data (time, etc.) + data (time, etc.) - Do divert, if any - Set the issue and item stage using setIssueStage(), IF valid. - Stash user's new signature and/or alternate email addr if specified @@ -579,7 +579,7 @@ for ps in item.propertysheets: ps.manage_changeProperties(REQUEST) - + origin = REQUEST.get("in_reply_to", '') if origin: try: @@ -638,7 +638,7 @@ if msgrole in ['resolve', 'defer', 'reject']: respred = REQUEST['RESPONSE'].redirect msg = urllib.quote('manage_tabs_message=' - 'Issue %s %s done.' % (issue.id, + 'Issue %s %s done.' % (issue.id, msgrole)) return respred(tracker.absolute_url() + '?' + msg) else: @@ -660,7 +660,7 @@ stuff (full names, emails) are ported from the old to the new issue.""" ## XXX Currently we fail to port anonymous or superuser requesters and - ## subscribers to the target issue of the divert. This is a bug, but + ## subscribers to the target issue of the divert. This is a bug, but ## it's a hassle to fix and i'm a bit undermotivated to cater to ## anonymous/superuser submitters. @@ -692,7 +692,7 @@ # Ensure parties to diverted issue can view target. # XXX Eventually offer choices, simple override or: # - endow those who can't view with privilege, - # - abandon those who can't view, + # - abandon those who can't view, requester = issue.requester unpriv = "" numunpriv = 0 @@ -704,7 +704,7 @@ return ('Divert failed - ' '

Diverted issue participant%s %s ' ' not privileged to view the target issue' - ' %s.' + ' %s.' '

Hit back to return to the form and change your' '
target, or, if suitable, visit the target and change its' '
privacy or security settings to enable access.\n' @@ -718,7 +718,7 @@ d = DateTime() text = 'Subject: [%s] Subsuming issue %s\n' % (target_emblem, diverted_emblem) - text = text + ('From: Tracker System for <%s>\n' % + text = text + ('From: Tracker System for <%s>\n' % tgt_tracker.adminaddr) text = text + 'To: "Issue Participants":;\n' text = text + 'Date: %s\n' % d.rfc822() @@ -771,7 +771,7 @@ if not tgt_issue.alt_full_names: tgt_issue.alt_full_names = {} tgt_issue.alt_full_names.update(issue.alt_full_names) - + tgt_issue.audited_state.set('subsume_issue', diverted_emblem, `REQUEST.AUTHENTICATED_USER`) @@ -1131,14 +1131,14 @@ "\nowner to take %s action." % which) if stage in ['accepted', 'resolved', 'completed', 'diverted', 'deferred', - 'rejected']: + 'rejected']: if userid in tracker.supporters: issue.manage_addLocalRoles(userid, ['IssueOwner']) if item: item.msgrole = stage elif stage == 'pending': # Enable moving an issue to pending while still keeping - # supporter assignment. People can 'Edit State' to remove the + # supporter assignment. People can 'Edit State' to remove the # supporter, as well. # XXX Eventually this should be an optional behavior. #clear_local_role('IssueOwner', issue) @@ -1311,12 +1311,12 @@ if self.id in self.promotes(): raise 'Bad Request', "Promoted items must be public." self.manage_permission('View', roles=minimal, acquire=0) - + ## def index_object(self): ## """Site catalog indexing -## The tracker has an explicit one for the reindexing process, so that the +## The tracker has an explicit one for the reindexing process, so that the ## subcomponents are traversed then.""" ## return None # XXX !!! Temporary until cataloging @@ -1333,7 +1333,7 @@ def trackerOnDeleteObject(self): """Object delete handler. - Tracker has an explicit one both to do its own unindexing and also cause + Tracker has an explicit one both to do its own unindexing and also cause traversal of the subcomponents.""" for i in self.values(): for j in i.values(): @@ -1377,7 +1377,7 @@ # Problem is that the collection of traits is dynamic, and the names # may well collide with catalogued attributes, like title, priority, # stage, etc. So we would need a handle in each element for each - # trait - yuck. For now they're grouped together - which means people + # trait - yuck. For now they're grouped together - which means people # only get an 'or' style search within traits. If we had some easy # 'and'ing mechanism for search results, we would have a way to do # multiple passes, refiningthe search to the desired results. @@ -1414,7 +1414,7 @@ path = make_catalogPath(element) tracker._catalog.uncatalogObject(path) tracker._catalog.catalogObject(element, path) - + def make_catalogPath(element): """Construct element's catalog path, wrt encompassing tracker and issue.""" if element.type == 'tracker_issue': @@ -1603,7 +1603,7 @@ boundary = max(0, len(pool) - 1) if boundary > lenpool: boundary == lenpool - + if direction in [0, 1]: # Going forwards from boundary. start = boundary @@ -1620,7 +1620,7 @@ ## % (len(pool), size, direction, last_start, last_end, ## boundary, start, end)) return(pool[start:end], start, len(pool) - end) - + def fieldValuesRange(self, field, precedence=None, include=None): """Return the sorted range of values for a particular catalog field. @@ -1676,7 +1676,7 @@ # XXX Would probably be better to use an explicit .get/.set # interface, if this were actually *on* a user object. - # XXX Generalizing this would means something like 'MemberPref', where the + # XXX Generalizing this would means something like 'MemberPref', where the # application name would be a parameter - and there should be some # shared space. # XXX There's no security provision! Not sure how i'd organize it. Sigh. @@ -1759,20 +1759,20 @@ if period_only: return (start, end) - + criteria = criteria.copy() criteria.update({'date': [start, end], 'date_usage': 'range:min:max'}) results = tracker._catalog.searchResults(criteria) return (results, start, end) -INFINITY = 1e200**2 +INFINITY = 1e32**2 + 0L def quota_stats(self, stat, expired=0): """Return triple: (tracker activity stat, start-date, end-date). An activity stat is the number of tracker issues having the indicated - status - for + status - for The figures are computed with respect to the tracker's quota, if it's a dedicated one. @@ -1815,7 +1815,7 @@ return (tracker.tickets_max - (resolved - quota_stats(tracker, 'accepted'))) - # This needs to be after the + # This needs to be after the elif stat == 'period': return quota_stat_search(tracker, period_only=1) @@ -1844,7 +1844,7 @@ (, ) := : ((supporter, ), ...) - := {'platinum': , 'gold': , + := {'platinum': , 'gold': , 'silver': , 'bronze': , 'open': , 'total': ] := [#active, #resolved, #other].""" @@ -1969,7 +1969,7 @@ The objects are returned as single-element tuples, to make them easy to distinguish from the error-message returns (ie, result[1][1:] == ()) and - to insulate them from the zope auto-call mechanism applied in dtml-var and + to insulate them from the zope auto-call mechanism applied in dtml-var and dtml-in operations. For those URLs which do not resolve into trackers (or resolve into @@ -2021,7 +2021,7 @@ if branchpoint: ps = ps[branchpoint:] - # Ascend to the branch point, then go back down to the object, bailing + # Ascend to the branch point, then go back down to the object, bailing # if we hit an access error. *NOTE* that by ascending and descending # we ensure that the acqusition hierarchy - hence the permissions # context - is for the object we're visiting. @@ -2072,7 +2072,7 @@ For now, every acl_user account is a member account. - Optional ceiling specifies a maximum amount of users to fetch - we + Optional ceiling specifies a maximum amount of users to fetch - we return the usernames for the first of that number that we find.""" # Collect users from all acquired acl_users: users = [] @@ -2108,7 +2108,7 @@ AUTHENTICATED_USER must have the 'manager' global role to run this. - Go to the value of the REQUEST nextpage setting, if any, or to fromurl, if + Go to the value of the REQUEST nextpage setting, if any, or to fromurl, if any, or to referer.""" if REQUEST is None: @@ -2116,7 +2116,7 @@ requester = REQUEST.AUTHENTICATED_USER if not tracker_role(self, 'staff', user=requester): - raise 'Bad Request', "Restricted to tracker owner and supporters." + raise 'Bad Request', "Restricted to tracker owner and supporters." for acl_users in get_acl_users_acquired(self): @@ -2174,7 +2174,7 @@ def createRules(): """Create the rules for an issue tracker.""" # XXX This is an external method for convenience. - # XXX Eventually this will be a (perhaps more genericish) default, + # XXX Eventually this will be a (perhaps more genericish) default, # and there will be a ttw interface for changing and refining them. # See TrackerBase.Noodge.eval_contingency(), .eval_condition(), and @@ -2207,7 +2207,7 @@ ## " %[var absolute_url]s."), ## (SET, 'alert', 'receipt ack'), ## (SET, 'msgfromrole', 'requester'))), - + ## ( # Ownership pending alerts. ## (CONDITION, (AND, ## (VALUE, 'rsvps'), From sidnei at x3ng.com.br Sat May 31 08:32:02 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.10 Message-ID: <200305311232.h4VCW2N07605@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv7526 Modified Files: buildout_zope_sandbox Log Message: Adding LDAP thingies === NZO_SiteLayout/buildout_zope_sandbox 1.9 => 1.10 === PYXML_URL=$PYXML_SF_DOWNLOAD/PyXML-$PYXML_VERSION.tar.gz ZOPEPROFILER_URL=http://www.dieter.handshake.de/pyprojects/zope/ZopeProfiler.tgz +CMFLDAP_URL=http://www.dataflake.org/software/cmfldap/cmfldap_2.0beta1/CMFLDAP-2_0beta1.tgz/download +LDAPUF_URL=http://www.dataflake.org/software/ldapuserfolder/ldapuserfolder_2.2beta2/LDAPUserFolder-2_2beta2.tgz/download +PYLDAP_URL=http://heanet.dl.sourceforge.net/sourceforge/python-ldap/python-ldap-2.0.0pre12.tar.gz ZOPE_CVSROOT=:pserver:anonymous@cvs.zope.org:/cvs-repository PYTHON_CVS_REPOSITORY=:pserver:anonymous@cvs.sf.net:/cvsroot/python @@ -259,6 +262,69 @@ wget --continue $ZOPEPROFILER_URL cd $srcdir tar xzf $tmpdir/ZopeProfiler.tgz + +cd $tmpdir +wget --continue $CMFLDAP_URL +mv download CMFLDAP.tar.gz +cd $srcdir +tar xzf $tmpdir/CMFLDAP.tar.gz + +cd $tmpdir +wget --continue $LDAPUF_URL +mv download LDAPUserFolder.tar.gz +cd $srcdir +tar xzf $tmpdir/LDAPUserFolder.tar.gz + +cd $tmpdir +wget --continue $PYLDAP_URL +cd $srcdir +tar xzf $tmpdir/python-ldap-2.0.0pre12.tar.gz +cd python-ldap-2.0.0pre12 +cat > setup.cfg << SETUPCFG_EOF +# Example for setup.cfg +# You have to edit this file to reflect your system configuation +# +# $Id$ + +# Section for compiling the C extension module +# for wrapping OpenLDAP 2 libs +[_ldap] + +#library_dirs = /usr/local/openldap-REL_ENG_2_1/lib /usr/local/cyrus-sasl/lib +#include_dirs = /usr/local/openldap-REL_ENG_2_1/include /usr/local/cyrus-sasl/include + +extra_compile_args = +extra_objects = + +# Example for sparse build: basic functionality +#libs = ldap lber + +# Some Linux systems might need explicitly linking with -lresolv +libs = ldap lber resolv + +# Example for full-featured build: +# Support for StartTLS/LDAPS, SASL bind and reentrant libldap_r. +# This needs recent OpenLDAP 2.0.26+ or 2.1.3+ built with +# ./configure --with-cyrus-sasl --with-tls +#libs = ldap_r lber sasl2 ssl crypto + +# Installation options +[install] +compile = 1 +optimize = 1 + +# Linux distributors/packagers should adjust these settings +[bdist_rpm] +provides = python-ldap +requires = python libldap.so.2 +# distribution_name = +release = 0 +packager = Michael Stroeder +doc_files = CHANGES README TODO Demo/ + +SETUPCFG_EOF +$bindir/python setup.cfg build +$bindir/python setup.cfg install #------------------------------------------------------------------------------ # Build Zope SOFTWARE_HOME From sidnei at x3ng.com.br Sat May 31 08:33:16 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/ZopeOrg-NV/Extensions - NZOMigrate.py:1.25 Message-ID: <200305311233.h4VCXGb07817@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZopeOrg-NV/Extensions In directory cvs.zope.org:/tmp/cvs-serv7803/Extensions Modified Files: NZOMigrate.py Log Message: Adding default values from run script === Products/ZopeOrg-NV/Extensions/NZOMigrate.py 1.24 => 1.25 === def migrate(source, dest, ignore_path=None, type_map=None, exceptions=None): dest_path = dest.getPhysicalPath() - if ignore_path is None: ignore_path = [] + if ignore_path is None: + migrate = ['About','CVS','DevHome','DocProjects','Documentation', 'Download', 'Images',\ + 'PTK', 'Products', 'Register', 'Resources', 'SpotlightOn', 'Support', 'Tour',\ + 'Tracker', 'Utilities', 'WikiCentral', 'projects', 'CatalogHelp', 'Help', \ + 'SiteAnnouncement', 'WhatIsZope', 'ZopeArchitecture', 'ZopeNews', 'privacy.html'] + members_ignore = ['epson', 'ltunes', 'michel', 'superuser', 'myUnreviewed', 'mail_password_form', \ + 'mail_password_template', 'password_html', 'tim.kidder', 'update_html', \ + 'index_html'] + ignore_path = ['/%s' % o for o in source.objectIds() if o not in migrate] + dont_migrate = ['/Members/%s' % o for o in members_ignore] + ignore_path.extend(dont_migrate) + cs = source.Resources.CaseStudies + for ob in cs.objectValues(): + if ob.meta_type == 'Folder': + exceptions['%s/index_html' % ob.absolute_url(relative=1)] = 'CaseStudies2ZopeOrgCaseStudies' + for subob in ob.objectValues(): + if subob.meta_type != 'Image' and subob.getId() != 'index_html': + ignore_path.append('/%s' % subob.absolute_url(relative=1)) + if not dest_path in ignore_path: ignore_path.append(dest_path) ignore_path = [tuple(p.split('/')) for p in ignore_path \ @@ -49,7 +67,7 @@ if exceptions is None: exceptions = {} exceptions['Resources/ZSP/zsp.xml'] = 'ZSP2ZopeOrgZSP' - exceptions['Resources/CaseStudies'] = 'CaseStudies2ZopeOrgCaseStudies' + #exceptions['Resources/CaseStudies'] = 'CaseStudies2ZopeOrgCaseStudies' tmut = Transmutator(source, dest, ignore_path, type_map, exceptions) tmut.log('Migration script started at %s.\n' % DateTime().ISO()) From sidnei at x3ng.com.br Sat May 31 08:45:21 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.11 Message-ID: <200305311245.h4VCjL909439@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv9425 Modified Files: buildout_zope_sandbox Log Message: Dang! I always forget to link the directories === NZO_SiteLayout/buildout_zope_sandbox 1.10 => 1.11 === ln -s $srcdir/ExternalEditor . ln -s $srcdir/CMFPackage . ln -s $srcdir/ZopeProfiler . +ln -s $srcdir/CMFLDAP . +ln -s $srcdir/LDAPUserFolder . # Old Products are: # BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase @@ -620,6 +622,8 @@ ln -s $optdir/ExternalEditor . ln -s $optdir/CMFPackage . ln -s $optdir/ZopeProfiler . +ln -s $optdir/CMFLDAP . +ln -s $optdir/LDAPUserFolder . # Old Products are: # BTreeFolder ExternalMount ParsedXML PortalBase PythonMethod Redirector TrackerBase XMLDocument ZDBase From sidnei at x3ng.com.br Sat May 31 08:49:18 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: NZO_SiteLayout - buildout_zope_sandbox:1.12 Message-ID: <200305311249.h4VCnIo09973@cvs.baymountain.com> Update of /cvs-zopeorg/NZO_SiteLayout In directory cvs.zope.org:/tmp/cvs-serv9959 Modified Files: buildout_zope_sandbox Log Message: Dang again! Its setup.py, not cfg. === NZO_SiteLayout/buildout_zope_sandbox 1.11 => 1.12 === doc_files = CHANGES README TODO Demo/ SETUPCFG_EOF -$bindir/python setup.cfg build -$bindir/python setup.cfg install +$bindir/python setup.py build +$bindir/python setup.py install #------------------------------------------------------------------------------ # Build Zope SOFTWARE_HOME From sidnei at x3ng.com.br Sat May 31 09:48:46 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/ZopeOrg-NV/Extensions - NZOMigrate.py:1.26 Message-ID: <200305311348.h4VDmke17985@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZopeOrg-NV/Extensions In directory cvs.zope.org:/tmp/cvs-serv17971/Extensions Modified Files: NZOMigrate.py Log Message: A few improvements over the previous version === Products/ZopeOrg-NV/Extensions/NZOMigrate.py 1.25 => 1.26 === ignore_path = ['/%s' % o for o in source.objectIds() if o not in migrate] dont_migrate = ['/Members/%s' % o for o in members_ignore] ignore_path.extend(dont_migrate) + if exceptions is None: + exceptions = {} cs = source.Resources.CaseStudies for ob in cs.objectValues(): if ob.meta_type == 'Folder': @@ -64,10 +66,8 @@ "External Method": "Unsafe" } - if exceptions is None: - exceptions = {} + if not 'Resources/ZSP/zsp.xml' in exceptions.keys(): exceptions['Resources/ZSP/zsp.xml'] = 'ZSP2ZopeOrgZSP' - #exceptions['Resources/CaseStudies'] = 'CaseStudies2ZopeOrgCaseStudies' tmut = Transmutator(source, dest, ignore_path, type_map, exceptions) tmut.log('Migration script started at %s.\n' % DateTime().ISO()) @@ -848,7 +848,7 @@ f.setChangesURL(changes_url) f.setInstallationURL(installation_url) f.setLicense(license) - + del data return (f, r) def Tracker2CMFCollector(self, obj, source, dest): @@ -863,6 +863,7 @@ return None collector = getattr(dest, obj.getId()) result.append(collector) + kw = {'id': 1 } for issue in obj.values(): kw, atts, text = dumpTrackerIssue(issue) kw['container'] = collector @@ -966,8 +967,10 @@ data = str(obj.data) size = len(data) f.update_data(data, content_type, size) + f.manage_upload(data) f.setTitle(title) f.setFormat(content_type) + del data return f def Image2CMFDefaultImage(self, obj, source, dest): @@ -983,8 +986,10 @@ data = str(obj.data) size = len(data) f.update_data(data, content_type, size) + f.manage_upload(data) f.setTitle(title) f.setFormat(content_type) + del data return f def NewsItem2CMFDefaultNewsItem(self, obj, source, dest): From sidnei at x3ng.com.br Sat May 31 18:21:22 2003 From: sidnei at x3ng.com.br (Sidnei da Silva) Date: Sun Aug 10 17:02:13 2008 Subject: [zopeorg-checkins] CVS: Products/ZopeOrg-NV/Extensions - NZOMigrate.py:1.27 Message-ID: <200305312221.h4VMLMd23043@cvs.baymountain.com> Update of /cvs-zopeorg/Products/ZopeOrg-NV/Extensions In directory cvs.zope.org:/tmp/cvs-serv23029/Extensions Modified Files: NZOMigrate.py Log Message: More migration fixes === Products/ZopeOrg-NV/Extensions/NZOMigrate.py 1.26 => 1.27 === def _send_update_notice(self, *args, **kw): pass -def migrate(source, dest, ignore_path=None, type_map=None, exceptions=None): +def migrate(source, dest, ignore_path=None, type_map=None, exceptions=None, debug=0): dest_path = dest.getPhysicalPath() if ignore_path is None: migrate = ['About','CVS','DevHome','DocProjects','Documentation', 'Download', 'Images',\ 'PTK', 'Products', 'Register', 'Resources', 'SpotlightOn', 'Support', 'Tour',\ 'Tracker', 'Utilities', 'WikiCentral', 'projects', 'CatalogHelp', 'Help', \ - 'SiteAnnouncement', 'WhatIsZope', 'ZopeArchitecture', 'ZopeNews', 'privacy.html'] - members_ignore = ['epson', 'ltunes', 'michel', 'superuser', 'myUnreviewed', 'mail_password_form', \ - 'mail_password_template', 'password_html', 'tim.kidder', 'update_html', \ - 'index_html'] + 'SiteAnnouncement', 'WhatIsZope', 'ZopeArchitecture', 'ZopeNews', 'privacy.html', + 'Members'] ignore_path = ['/%s' % o for o in source.objectIds() if o not in migrate] - dont_migrate = ['/Members/%s' % o for o in members_ignore] - ignore_path.extend(dont_migrate) - if exceptions is None: - exceptions = {} - cs = source.Resources.CaseStudies - for ob in cs.objectValues(): - if ob.meta_type == 'Folder': - exceptions['%s/index_html' % ob.absolute_url(relative=1)] = 'CaseStudies2ZopeOrgCaseStudies' - for subob in ob.objectValues(): - if subob.meta_type != 'Image' and subob.getId() != 'index_html': - ignore_path.append('/%s' % subob.absolute_url(relative=1)) - + members_ignore = ['billqian', 'edward', 'epson', 'ltunes', 'michel', 'superuser', \ + 'myUnreviewed', 'mail_password_form', \ + 'mail_password_template', 'password_html', 'tim.kidder', 'update_html', \ + 'index_html'] + dont_migrate = ['/Members/%s' % o for o in members_ignore] + ignore_path.extend(dont_migrate) + if exceptions is None: + exceptions = {} + cs = source.Resources.CaseStudies + for ob in cs.objectValues(): + if ob.meta_type == 'Folder': + exceptions['%s/index_html' % ob.absolute_url(relative=1)] = 'CaseStudies2ZopeOrgCaseStudies' + for subob in ob.objectValues(): + if subob.meta_type != 'Image' and subob.getId() != 'index_html': + ignore_path.append('/%s' % subob.absolute_url(relative=1)) if not dest_path in ignore_path: ignore_path.append(dest_path) ignore_path = [tuple(p.split('/')) for p in ignore_path \ @@ -69,7 +70,7 @@ if not 'Resources/ZSP/zsp.xml' in exceptions.keys(): exceptions['Resources/ZSP/zsp.xml'] = 'ZSP2ZopeOrgZSP' - tmut = Transmutator(source, dest, ignore_path, type_map, exceptions) + tmut = Transmutator(source, dest, ignore_path, type_map, exceptions, debug=debug) tmut.log('Migration script started at %s.\n' % DateTime().ISO()) result = tmut.run() tmut.log('Migration script finished at %s.\n' % DateTime().ISO()) @@ -629,7 +630,7 @@ class Transmutator: - def __init__(self, source, dest, ignore_path, type_map, exceptions, count=0): + def __init__(self, source, dest, ignore_path, type_map, exceptions, count=0, debug=0): self._source = source self._dest = dest self._ignore_path = ignore_path @@ -637,6 +638,7 @@ self._count = count self._exceptions = exceptions self._out = StringIO() + self._debug = debug def log(self, message, summary='', severity=0, dup=1): self._out.write(message) @@ -1133,6 +1135,11 @@ dest = self._dest ignore = self._ignore_path source_id = source.getId() + if not hasattr(aq_base(dest), 'meta_type') or \ + not hasattr(aq_base(dest), 'objectIds'): + # maybe-not-object. eg: we acquired the 'view' method + self.log('Destination is invalid. %r \n' % dest) + return 'Ok.\n' if hasattr(source, 'objectIds') and \ hasattr(source, 'getPhysicalPath'): path = source.getPhysicalPath() @@ -1164,6 +1171,10 @@ mm = self.getMigrationMethod(obj, obj_url) + if self._debug: + import pdb + pdb.set_trace() + try: __traceback_info__ = (obj_url, obj.__class__.__name__, obj, source, dest) new_objs = mm(obj, source, dest) @@ -1218,11 +1229,11 @@ self.log(Transmutator(obj, new_obj, \ ignore, self._type_map, \ self._exceptions, \ - self._count).run(), dup=0) + self._count, debug=self._debug).run(), dup=0) - if source_id == 'Members': - res = recursiveOwnerFix(new_obj, oid, 1) - setLocalRoles(new_obj, (oid, ), 'Owner', obj_url) + #if source_id == 'Members': + # res = recursiveOwnerFix(new_obj, oid, 1) + # setLocalRoles(new_obj, (oid, ), 'Owner', obj_url) try: new_obj = fixModificationDate(obj, new_obj)