Commit b8895543 authored by Aurel's avatar Aurel

update patches

parent 8829837b
diff -Naur Acquisition-4.7.orig/src/Acquisition/_Acquisition.c Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/_Acquisition.c
--- Acquisition-4.7.orig/src/Acquisition/_Acquisition.c 2021-03-17 16:22:28.266539592 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/_Acquisition.c 2021-03-17 16:28:59.609842948 +0100
@@ -543,6 +543,64 @@
}
static PyObject *
+Wrapper_GetAttr(PyObject *self, PyObject *attr_name, PyObject *orig)
+{
+ /* This function retrieves an attribute from an object by PyObject_GetAttr.
+
+ The main difference between Wrapper_GetAttr and PyObject_GetAttr is that
+ Wrapper_GetAttr calls _aq_dynamic to generate an attribute dynamically, if
+ the attribute is not found.
+ */
+ PyObject *r, *v, *tb;
+ PyObject *d, *m;
+ PyObject *o;
+
+ if (isWrapper (self))
+ o = WRAPPER(self)->obj;
+ else
+ o = self;
+
+ /* Try to get an attribute in the normal way first. */
+ r = PyObject_GetAttr(o, attr_name);
+ if (r)
+ return r;
+
+ /* If an unexpected error happens, return immediately. */
+ PyErr_Fetch(&r,&v,&tb);
+ if (r != PyExc_AttributeError)
+ {
+ PyErr_Restore(r,v,tb);
+ return NULL;
+ }
+
+ /* Try to get _aq_dynamic. */
+ m = PyObject_GetAttrString(o, "_aq_dynamic");
+ if (! m) {
+ PyErr_Restore(r,v,tb);
+ return NULL;
+ }
+
+ /* Call _aq_dynamic in the context of the original acquisition wrapper. */
+ if (PyECMethod_Check(m) && PyECMethod_Self(m)==o)
+ ASSIGN(m,PyECMethod_New(m,OBJECT(self)));
+ else if (has__of__(m)) ASSIGN(m,__of__(m,OBJECT(self)));
+ d = PyObject_CallFunction(m, "O", attr_name);
+ Py_DECREF(m);
+
+ /* In the case of None, assume that the attribute is not found. */
+ if (d == Py_None) {
+ Py_DECREF(d);
+ PyErr_Restore(r,v,tb);
+ return NULL;
+ }
+
+ Py_XDECREF(r);
+ Py_XDECREF(v);
+ Py_XDECREF(tb);
+ return d;
+}
+
+static PyObject *
Wrapper_acquire(Wrapper *self, PyObject *oname,
PyObject *filter, PyObject *extra, PyObject *orig,
int explicit, int containment);
@@ -677,8 +735,8 @@
return NULL;
}
- /* normal attribute lookup */
- else if ((r = PyObject_GetAttr(self->obj, oname))) {
+ /* Give _aq_dynamic a chance, then normal attribute lookup */
+ else if ((r = Wrapper_GetAttr(OBJECT(self), oname, orig))) {
if (r == Acquired) {
Py_DECREF(r);
return Wrapper_acquire(
@@ -806,7 +864,7 @@
return NULL;
}
- if ((r = PyObject_GetAttr(self->container, oname)) == NULL) {
+ if ((r = Wrapper_GetAttr(self->container, oname, orig)) == NULL) {
/* May be AttributeError or some other kind of error */
return NULL;
}
@@ -830,7 +888,7 @@
static PyObject *
Wrapper_getattro(Wrapper *self, PyObject *oname)
{
- return Wrapper_findattr(self, oname, NULL, NULL, NULL, 1, 1, 0, 0);
+ return Wrapper_findattr(self, oname, NULL, NULL, OBJECT(self), 1, 1, 0, 0);
}
static PyObject *
@@ -846,7 +904,7 @@
if (STR_EQ(PyBytes_AS_STRING(tmp), "acquire")) {
result = Py_FindAttr(OBJECT(self), oname);
} else {
- result = Wrapper_findattr(self, oname, NULL, NULL, NULL, 1, 0, 0, 0);
+ result = Wrapper_findattr(self, oname, NULL, NULL, OBJECT(self), 1, 0, 0, 0);
}
Py_DECREF(tmp);
diff -Naur Acquisition-4.7.orig/src/Acquisition/test_dynamic_acquisition.py Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/test_dynamic_acquisition.py
--- Acquisition-4.7.orig/src/Acquisition/test_dynamic_acquisition.py 1970-01-01 01:00:00.000000000 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/test_dynamic_acquisition.py 2021-03-17 16:30:07.082413986 +0100
@@ -0,0 +1,160 @@
+##############################################################################
+#
+# Copyright (c) 1996-2002 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
+#
+##############################################################################
+import Acquisition
+
+def checkContext(self, o):
+ # Python equivalent to aq_inContextOf
+ from Acquisition import aq_base, aq_parent, aq_inner
+ subob = self
+ o = aq_base(o)
+ while 1:
+ if aq_base(subob) is o:
+ return True
+ self = aq_inner(subob)
+ if self is None: break
+ subob = aq_parent(self)
+ if subob is None: break
+ return False
+
+class B(Acquisition.Implicit):
+ color='red'
+
+ def __init__(self, name='b'):
+ self.name = name
+
+ def _aq_dynamic(self, attr):
+ if attr == 'bonjour': return None
+
+ def dynmethod():
+ chain = ' <- '.join(repr(obj) for obj in Acquisition.aq_chain(self))
+ print repr(self) + '.' + attr
+ print 'chain:', chain
+
+ return dynmethod
+
+ def __repr__(self):
+ return "%s(%r)" % (self.__class__.__name__, self.name)
+
+class A(Acquisition.Implicit):
+
+ def __init__(self, name='a'):
+ self.name = name
+
+ def hi(self):
+ print self, self.color
+
+ def _aq_dynamic(self, attr):
+ return None
+
+ def __repr__(self):
+ return "%s(%r)" % (self.__class__.__name__, self.name)
+
+def test_dynamic():
+ r'''
+ The _aq_dynamic functionality allows an object to dynamically provide an
+ attribute.
+
+ If an object doesn't have an attribute, Acquisition checks to see if the
+ object has a _aq_dynamic method, which is then called. It is functionally
+ equivalent to __getattr__, but _aq_dynamic is called with 'self' as the
+ acquisition wrapped object where as __getattr__ is called with self as the
+ unwrapped object.
+
+ Let's see how this works. In the examples below, the A class defines
+ '_aq_dynamic', but returns 'None' for all attempts, which means that no new
+ attributes should be generated dynamically. It also doesn't define 'color'
+ attribute, even though it uses it in the 'hi' method.
+
+ >>> A().hi()
+ Traceback (most recent call last):
+ ...
+ AttributeError: color
+
+ The class B, on the other hand, generates all attributes dynamically,
+ except if it is called 'bonjour'.
+
+ First we need to check that, even if an object provides '_aq_dynamic',
+ "regular" Aquisition attribute access should still work:
+
+ >>> b=B()
+ >>> b.a=A()
+ >>> b.a.hi()
+ A('a') red
+ >>> b.a.color='green'
+ >>> b.a.hi()
+ A('a') green
+
+ Now, let's see some dynamically generated action. B does not define a
+ 'salut' method, but remember that it dynamically generates a method for
+ every attribute access:
+
+ >>> b.a.salut()
+ B('b').salut
+ chain: B('b')
+
+ >>> a=A('a1')
+ >>> a.b=B('b1')
+ >>> a.b.salut()
+ B('b1').salut
+ chain: B('b1') <- A('a1')
+
+ >>> b.a.bonjour()
+ Traceback (most recent call last):
+ ...
+ AttributeError: bonjour
+
+ >>> a.b.bonjour()
+ Traceback (most recent call last):
+ ...
+ AttributeError: bonjour
+
+ '''
+
+def test_wrapper_comparissons():
+ r'''
+
+ Test wrapper comparisons in presence of _aq_dynamic
+
+ >>> b=B()
+ >>> b.a=A()
+ >>> foo = b.a
+ >>> bar = b.a
+ >>> assert( foo == bar )
+ >>> c = A('c')
+ >>> b.c = c
+ >>> b.c.d = c
+ >>> b.c.d == c
+ True
+ >>> b.c.d == b.c
+ True
+ >>> b.c == c
+ True
+
+ Test contextuality in presence of _aq_dynamic
+
+ >>> checkContext(b.c, b)
+ True
+ >>> checkContext(b.c, b.a)
+ False
+
+ >>> assert b.a.aq_inContextOf(b)
+ >>> assert b.c.aq_inContextOf(b)
+ >>> assert b.c.d.aq_inContextOf(b)
+ >>> assert b.c.d.aq_inContextOf(c)
+ >>> assert b.c.d.aq_inContextOf(b.c)
+ >>> assert not b.c.aq_inContextOf(foo)
+ >>> assert not b.c.aq_inContextOf(b.a)
+ >>> assert not b.a.aq_inContextOf('somestring')
+'''
+
diff -Naur Acquisition-4.7.orig/src/Acquisition/tests.py Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/tests.py
--- Acquisition-4.7.orig/src/Acquisition/tests.py 2021-03-17 16:22:28.266539592 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/tests.py 2021-03-17 16:31:31.971132854 +0100
@@ -3366,6 +3366,7 @@
suites = [
DocTestSuite(),
+ DocTestSuite('Acquisition.test_dynamic_acquisition'),
unittest.defaultTestLoader.loadTestsFromName(__name__),
]
diff -Naur Acquisition-4.7.orig/src/Acquisition.egg-info/SOURCES.txt Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition.egg-info/SOURCES.txt
--- Acquisition-4.7.orig/src/Acquisition.egg-info/SOURCES.txt 2021-03-17 16:22:28.262539558 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition.egg-info/SOURCES.txt 2021-03-17 16:32:31.619638229 +0100
@@ -15,9 +15,10 @@
src/Acquisition/__init__.py
src/Acquisition/interfaces.py
src/Acquisition/tests.py
+src/Acquisition/test_dynamic_acquisition.py
src/Acquisition.egg-info/PKG-INFO
src/Acquisition.egg-info/SOURCES.txt
src/Acquisition.egg-info/dependency_links.txt
src/Acquisition.egg-info/not-zip-safe
src/Acquisition.egg-info/requires.txt
-src/Acquisition.egg-info/top_level.txt
\ Pas de fin de ligne à la fin du fichier
+src/Acquisition.egg-info/top_level.txt
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/DCWorkflow.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/DCWorkflow.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/DCWorkflow.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/DCWorkflow.py 2021-03-18 15:43:47.791236880 +0100
@@ -38,6 +38,7 @@
from Products.DCWorkflow.interfaces import IDCWorkflowDefinition
from Products.DCWorkflow.Transitions import TRIGGER_AUTOMATIC
from Products.DCWorkflow.Transitions import TRIGGER_USER_ACTION
+from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.DCWorkflow.utils import Message as _
from Products.DCWorkflow.utils import modifyRolesForGroup
from Products.DCWorkflow.utils import modifyRolesForPermission
@@ -279,6 +280,52 @@
self._changeStateOf(ob, tdef, kw)
@security.private
+ def isWorkflowMethodSupported(self, ob, method_id):
+ '''
+ Returns a true value if the given workflow method
+ is supported in the current state.
+ '''
+ sdef = self._getWorkflowStateOf(ob)
+ if sdef is None:
+ return 0
+ if method_id in sdef.transitions:
+ tdef = self.transitions.get(method_id, None)
+ if (tdef is not None and
+ tdef.trigger_type == TRIGGER_WORKFLOW_METHOD and
+ self._checkTransitionGuard(tdef, ob)):
+ return 1
+ return 0
+
+ @security.private
+ def wrapWorkflowMethod(self, ob, method_id, func, args, kw):
+ '''
+ Allows the user to request a workflow action. This method
+ must perform its own security checks.
+ '''
+ sdef = self._getWorkflowStateOf(ob)
+ if sdef is None:
+ raise WorkflowException('Object is in an undefined state')
+ if method_id not in sdef.transitions:
+ raise Unauthorized(method_id)
+ tdef = self.transitions.get(method_id, None)
+ if tdef is None or tdef.trigger_type != TRIGGER_WORKFLOW_METHOD:
+ raise WorkflowException(
+ 'Transition %s is not triggered by a workflow method'
+ % method_id)
+ if not self._checkTransitionGuard(tdef, ob):
+ raise Unauthorized(method_id)
+ res = func(*args, **kw)
+ try:
+ self._changeStateOf(ob, tdef)
+ except ObjectDeleted:
+ # Re-raise with a different result.
+ raise ObjectDeleted(res)
+ except ObjectMoved as ex:
+ # Re-raise with a different result.
+ raise ObjectMoved(ex.getNewObject(), res)
+ return res
+
+ @security.private
def isInfoSupported(self, ob, name):
'''
Returns a true value if the given info name is supported.
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transition_properties.dtml Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transition_properties.dtml
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transition_properties.dtml 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transition_properties.dtml 2021-03-18 15:37:55.144028451 +0100
@@ -56,6 +56,16 @@
</tr>
<tr>
+<th></th>
+<td>
+<dtml-let checked="trigger_type==2 and 'checked' or ' '">
+<input type="radio" name="trigger_type" value="2" &dtml-checked; />
+Initiated by WorkflowMethod
+</dtml-let>
+</td>
+</tr>
+
+<tr>
<th align="left">Script (before)</th>
<td>
<select name="script_name">
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transitions.dtml Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transitions.dtml
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transitions.dtml 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transitions.dtml 2021-03-18 15:37:55.144028451 +0100
@@ -17,7 +17,8 @@
<td>
Destination state: <code><dtml-if new_state_id>&dtml-new_state_id;<dtml-else>(Remain in state)</dtml-if></code> <br />
Trigger: <dtml-var expr="(trigger_type == 0 and 'Automatic') or
- (trigger_type == 1 and 'User action')">
+ (trigger_type == 1 and 'User action') or
+ (trigger_type == 2 and 'WorkflowMethod')">
<br />
<dtml-if script_name>
Script (before): &dtml-script_name;
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/exportimport.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/exportimport.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/exportimport.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/exportimport.py 2021-03-18 15:44:34.903667147 +0100
@@ -40,7 +40,7 @@
from Products.DCWorkflow.utils import _xmldir
-TRIGGER_TYPES = ('AUTOMATIC', 'USER')
+TRIGGER_TYPES = ('AUTOMATIC', 'USER', 'METHOD' )
_FILENAME = 'workflows.xml'
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/Transitions.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/Transitions.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/Transitions.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/Transitions.py 2021-03-18 15:37:55.148028486 +0100
@@ -31,6 +31,7 @@
TRIGGER_AUTOMATIC = 0
TRIGGER_USER_ACTION = 1
+TRIGGER_WORKFLOW_METHOD = 2
class TransitionDefinition(SimpleItem):
diff -Naur Zope-4.5.3/OFS/XMLExportImport.py Zope-4.5.3-Nexedi/OFS/XMLExportImport.py
--- Zope-4.5.3/OFS/XMLExportImport.py 1970-01-01 01:00:00.000000000 +0100
+++ Zope-4.5.3-Nexedi/OFS/XMLExportImport.py 2021-03-09 16:11:55.000000000 +0100
@@ -0,0 +1,124 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+from base64 import encodestring
+from cStringIO import StringIO
+from ZODB.serialize import referencesf
+from ZODB.ExportImport import TemporaryFile, export_end_marker
+from ZODB.utils import p64
+from ZODB.utils import u64
+from Shared.DC.xml import ppml
+
+
+magic='<?xm' # importXML(jar, file, clue)}
+
+def XMLrecord(oid, len, p):
+ q=ppml.ToXMLUnpickler
+ f=StringIO(p)
+ u=q(f)
+ id=u64(oid)
+ aka=encodestring(oid)[:-1]
+ u.idprefix=str(id)+'.'
+ p=u.load().__str__(4)
+ if f.tell() < len:
+ p=p+u.load().__str__(4)
+ String=' <record id="%s" aka="%s">\n%s </record>\n' % (id, aka, p)
+ return String
+
+def exportXML(jar, oid, file=None):
+
+ if file is None: file=TemporaryFile()
+ elif type(file) is str: file=open(file,'w+b')
+ write=file.write
+ write('<?xml version="1.0"?>\012<ZopeData>\012')
+ ref=referencesf
+ oids=[oid]
+ done_oids={}
+ done=done_oids.has_key
+ load=jar._storage.load
+ while oids:
+ oid=oids[0]
+ del oids[0]
+ if done(oid): continue
+ done_oids[oid]=1
+ try:
+ try:
+ p, serial = load(oid)
+ except TypeError:
+ # Some places inside the ZODB 3.9 still want a version
+ # argument, for example TmpStore from Connection.py
+ p, serial = load(oid, None)
+ except:
+ pass # Ick, a broken reference
+ else:
+ ref(p, oids)
+ write(XMLrecord(oid,len(p),p))
+ write('</ZopeData>\n')
+ return file
+
+class zopedata:
+ def __init__(self, parser, tag, attrs):
+ self.file=parser.file
+ write=self.file.write
+ write('ZEXP')
+
+ def append(self, data):
+ file=self.file
+ write=file.write
+ pos=file.tell()
+ file.seek(pos)
+ write(data)
+
+def start_zopedata(parser, tag, data):
+ return zopedata(parser, tag, data)
+
+def save_zopedata(parser, tag, data):
+ file=parser.file
+ write=file.write
+ pos=file.tell()
+ file.seek(pos)
+ write(export_end_marker)
+
+def save_record(parser, tag, data):
+ file=parser.file
+ write=file.write
+ pos=file.tell()
+ file.seek(pos)
+ a=data[1]
+ if a.has_key('id'): oid=a['id']
+ oid=p64(int(oid))
+ v=''
+ for x in data[2:]:
+ v=v+x
+ l=p64(len(v))
+ v=oid+l+v
+ return v
+
+def importXML(jar, file, clue=''):
+ import xml.parsers.expat
+ if type(file) is str:
+ file=open(file, 'rb')
+ outfile=TemporaryFile()
+ data=file.read()
+ F=ppml.xmlPickler()
+ F.end_handlers['record'] = save_record
+ F.end_handlers['ZopeData'] = save_zopedata
+ F.start_handlers['ZopeData'] = start_zopedata
+ F.binary=1
+ F.file=outfile
+ p=xml.parsers.expat.ParserCreate()
+ p.CharacterDataHandler=F.handle_data
+ p.StartElementHandler=F.unknown_starttag
+ p.EndElementHandler=F.unknown_endtag
+ r=p.Parse(data)
+ outfile.seek(0)
+ return jar.importFile(outfile,clue)
diff -Naur Zope-4.5.3/Shared/DC/xml/__init__.py Zope-4.5.3-Nexedi/Shared/DC/xml/__init__.py
--- Zope-4.5.3/Shared/DC/xml/__init__.py 1970-01-01 01:00:00.000000000 +0100
+++ Zope-4.5.3-Nexedi/Shared/DC/xml/__init__.py 2021-03-09 16:13:49.000000000 +0100
@@ -0,0 +1,12 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
diff -Naur Zope-4.5.3/Shared/DC/xml/ppml.py Zope-4.5.3-Nexedi/Shared/DC/xml/ppml.py
--- Zope-4.5.3/Shared/DC/xml/ppml.py 1970-01-01 01:00:00.000000000 +0100
+++ Zope-4.5.3-Nexedi/Shared/DC/xml/ppml.py 2021-03-09 16:13:49.000000000 +0100
@@ -0,0 +1,597 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""Provide conversion between Python pickles and XML
+"""
+
+from pickle import *
+import struct
+import base64
+import re
+from marshal import loads as mloads
+from xyap import NoBlanks
+from xyap import xyap
+
+binary = re.compile('[^\x1f-\x7f]').search
+
+
+def escape(s, encoding='repr'):
+ if binary(s) and isinstance(s, str):
+ s = base64.encodestring(s)[:-1]
+ encoding = 'base64'
+ elif '>' in s or '<' in s or '&' in s:
+ if not ']]>' in s:
+ s = '<![CDATA[' + s + ']]>'
+ encoding = 'cdata'
+ else:
+ s = s.replace('&', '&amp;')
+ s = s.replace('>', '&gt;')
+ s = s.replace('<', '&lt;')
+ return encoding, s
+
+def unescape(s, encoding):
+ if encoding == 'base64':
+ return base64.decodestring(s)
+ else:
+ s = s.replace('&lt;', '<')
+ s = s.replace('&gt;', '>')
+ return s.replace('&amp;', '&')
+
+class Global:
+ def __init__(self, module, name):
+ self.module = module
+ self.name = name
+
+ def __str__(self, indent=0):
+ if hasattr(self, 'id'):
+ id = ' id="%s"' % self.id
+ else:
+ id = ''
+ name = self.__class__.__name__.lower()
+ return '%s<%s%s name="%s" module="%s"/>\n' % (
+ ' ' * indent, name, id, self.name, self.module)
+
+class Scalar:
+ def __init__(self, v):
+ self._v = v
+
+ def value(self):
+ return self._v
+
+ def __str__(self, indent=0):
+ if hasattr(self, 'id'):
+ id = ' id="%s"' % self.id
+ else:
+ id = ''
+ name = self.__class__.__name__.lower()
+ return '%s<%s%s>%s</%s>\n' % (
+ ' ' * indent, name, id, self.value(), name)
+
+class Long(Scalar):
+ def value(self):
+ result = str(self._v)
+ if result[-1:] == 'L':
+ return result[:-1]
+ return result
+
+class String(Scalar):
+ def __init__(self, v, encoding=''):
+ encoding, v = escape(v, encoding)
+ self.encoding = encoding
+ self._v = v
+
+ def __str__(self, indent=0):
+ if hasattr(self,'id'):
+ id = ' id="%s"' % self.id
+ else:
+ id = ''
+ if hasattr(self, 'encoding'):
+ encoding = ' encoding="%s"' % self.encoding
+ else:
+ encoding = ''
+ name = self.__class__.__name__.lower()
+ return '%s<%s%s%s>%s</%s>\n' % (
+ ' ' * indent, name, id, encoding, self.value(), name)
+
+class Unicode(String):
+ def __init__(self, v, encoding):
+ v = unicode(v, encoding)
+ String.__init__(self, v)
+
+ def value(self):
+ return self._v.encode('utf-8')
+
+class Wrapper:
+ def __init__(self, v):
+ self._v = v
+
+ def value(self):
+ return self._v
+
+ def __str__(self, indent=0):
+ if hasattr(self, 'id'):
+ id = ' id="%s"' % self.id
+ else:
+ id = ''
+ name = self.__class__.__name__.lower()
+ v = self._v
+ i = ' ' * indent
+ if isinstance(v, Scalar):
+ return '%s<%s%s>%s</%s>\n' % (i, name, id, str(v)[:-1], name)
+ else:
+ try:
+ v = v.__str__(indent + 2)
+ except TypeError:
+ v = v.__str__()
+ return '%s<%s%s>\n%s%s</%s>\n' % (i, name, id, v, i, name)
+
+class Collection:
+ def __str__(self, indent=0):
+ if hasattr(self, 'id'):
+ id = ' id="%s"' % self.id
+ else:
+ id = ''
+ name = self.__class__.__name__.lower()
+ i = ' ' * indent
+ if self:
+ return '%s<%s%s>\n%s%s</%s>\n' % (
+ i, name, id, self.value(indent + 2), i, name)
+ else:
+ return '%s<%s%s/>\n' % (i, name, id)
+
+class Dictionary(Collection):
+ def __init__(self):
+ self._d = []
+
+ def __len__(self):
+ return len(self._d)
+
+ def __setitem__(self, k, v):
+ self._d.append((k, v))
+
+ def value(self, indent):
+ return ''.join(
+ map(lambda i, ind=' ' * indent, indent=indent + 4:
+ '%s<item>\n'
+ '%s'
+ '%s'
+ '%s</item>\n'
+ %
+ (ind,
+ Key(i[0]).__str__(indent),
+ Value(i[1]).__str__(indent),
+ ind),
+ self._d
+ ))
+
+class Sequence(Collection):
+ def __init__(self, v=None):
+ if not v:
+ v = []
+ self._subs = v
+
+ def __len__(self):
+ return len(self._subs)
+
+ def append(self, v):
+ self._subs.append(v)
+
+ def extend(self, v):
+ self._subs.extend(v)
+
+ def _stringify(self, v, indent):
+ try:
+ return v.__str__(indent + 2)
+ except TypeError:
+ return v.__str__()
+
+ def value(self, indent):
+ return ''.join(map(
+ lambda v, indent=indent: self._stringify(v, indent),
+ self._subs))
+
+class none:
+ def __str__(self, indent=0):
+ return ' ' * indent + '<none/>\n'
+none = none()
+
+class Reference(Scalar):
+ def __init__(self, v):
+ self._v = v
+
+ def __str__(self, indent=0):
+ v = self._v
+ name = self.__class__.__name__.lower()
+ return '%s<%s id="%s"/>\n' % (' ' * indent, name, v)
+
+Get = Reference
+
+class Object(Sequence):
+ def __init__(self, klass, args):
+ self._subs = [Klass(klass), args]
+
+ def __setstate__(self, v):
+ self.append(State(v))
+
+class Int(Scalar): pass
+class Float(Scalar): pass
+class List(Sequence): pass
+class Tuple(Sequence): pass
+class Key(Wrapper): pass
+class Value(Wrapper): pass
+class Klass(Wrapper): pass
+class State(Wrapper): pass
+class Pickle(Wrapper): pass
+class Persistent(Wrapper): pass
+
+
+class ToXMLUnpickler(Unpickler):
+ def load(self):
+ return Pickle(Unpickler.load(self))
+
+ dispatch = {}
+ dispatch.update(Unpickler.dispatch)
+
+ def persistent_load(self, v):
+ return Persistent(v)
+
+ def load_persid(self):
+ pid = self.readline()[:-1]
+ self.append(self.persistent_load(String(pid)))
+ dispatch[PERSID] = load_persid
+
+ def load_none(self):
+ self.append(none)
+ dispatch[NONE] = load_none
+
+ def load_int(self):
+ self.append(Int(int(self.readline()[:-1])))
+ dispatch[INT] = load_int
+
+ def load_binint(self):
+ self.append(Int(mloads('i' + self.read(4))))
+ dispatch[BININT] = load_binint
+
+ def load_binint1(self):
+ self.append(Int(ord(self.read(1))))
+ dispatch[BININT1] = load_binint1
+
+ def load_binint2(self):
+ self.append(Int(mloads('i' + self.read(2) + '\000\000')))
+ dispatch[BININT2] = load_binint2
+
+ def load_long(self):
+ self.append(Long(long(self.readline()[:-1], 0)))
+ dispatch[LONG] = load_long
+
+ def load_float(self):
+ self.append(Float(float(self.readline()[:-1])))
+ dispatch[FLOAT] = load_float
+
+ def load_binfloat(self, unpack=struct.unpack):
+ self.append(Float(unpack('>d', self.read(8))[0]))
+ dispatch[BINFLOAT] = load_binfloat
+
+ def load_string(self):
+ rep = self.readline()[:-1]
+ for q in "\"'":
+ if rep.startswith(q):
+ if not rep.endswith(q):
+ raise ValueError, 'insecure string pickle'
+ rep = rep[len(q):-len(q)]
+ break
+ else:
+ raise ValueError, 'insecure string pickle'
+ self.append(String(rep.decode('string-escape')))
+ dispatch[STRING] = load_string
+
+ def load_binstring(self):
+ len = mloads('i' + self.read(4))
+ self.append(String(self.read(len)))
+ dispatch[BINSTRING] = load_binstring
+
+ def load_unicode(self):
+ self.append(Unicode(self.readline()[:-1],'raw-unicode-escape'))
+ dispatch[UNICODE] = load_unicode
+
+ def load_binunicode(self):
+ len = mloads('i' + self.read(4))
+ self.append(Unicode(self.read(len),'utf-8'))
+ dispatch[BINUNICODE] = load_binunicode
+
+ def load_short_binstring(self):
+ len = ord(self.read(1))
+ self.append(String(self.read(len)))
+ dispatch[SHORT_BINSTRING] = load_short_binstring
+
+ def load_tuple(self):
+ k = self.marker()
+ self.stack[k:] = [Tuple(self.stack[k + 1:])]
+ dispatch[TUPLE] = load_tuple
+
+ def load_empty_tuple(self):
+ self.stack.append(Tuple())
+ dispatch[EMPTY_TUPLE] = load_empty_tuple
+
+ def load_empty_list(self):
+ self.stack.append(List())
+ dispatch[EMPTY_LIST] = load_empty_list
+
+ def load_empty_dictionary(self):
+ self.stack.append(Dictionary())
+ dispatch[EMPTY_DICT] = load_empty_dictionary
+
+ def load_list(self):
+ k = self.marker()
+ self.stack[k:] = [List(self.stack[k + 1:])]
+ dispatch[LIST] = load_list
+
+ def load_dict(self):
+ k = self.marker()
+ d = Dictionary()
+ items = self.stack[k + 1:]
+ for i in range(0, len(items), 2):
+ key = items[i]
+ value = items[i + 1]
+ d[key] = value
+ self.stack[k:] = [d]
+ dispatch[DICT] = load_dict
+
+ def load_inst(self):
+ k = self.marker()
+ args = Tuple(self.stack[k + 1:])
+ del self.stack[k:]
+ module = self.readline()[:-1]
+ name = self.readline()[:-1]
+ value = Object(Global(module, name), args)
+ self.append(value)
+ dispatch[INST] = load_inst
+
+ def load_obj(self):
+ stack = self.stack
+ k = self.marker()
+ klass = stack[k + 1]
+ del stack[k + 1]
+ args = Tuple(stack[k + 1:])
+ del stack[k:]
+ value = Object(klass, args)
+ self.append(value)
+ dispatch[OBJ] = load_obj
+
+ def load_global(self):
+ module = self.readline()[:-1]
+ name = self.readline()[:-1]
+ self.append(Global(module, name))
+ dispatch[GLOBAL] = load_global
+
+ def load_reduce(self):
+ stack = self.stack
+
+ callable = stack[-2]
+ arg_tup = stack[-1]
+ del stack[-2:]
+
+ value = Object(callable, arg_tup)
+ self.append(value)
+ dispatch[REDUCE] = load_reduce
+
+ idprefix=''
+
+ def load_get(self):
+ self.append(Get(self.idprefix + self.readline()[:-1]))
+ dispatch[GET] = load_get
+
+ def load_binget(self):
+ i = ord(self.read(1))
+ self.append(Get(self.idprefix + repr(i)))
+ dispatch[BINGET] = load_binget
+
+ def load_long_binget(self):
+ i = mloads('i' + self.read(4))
+ self.append(Get(self.idprefix + repr(i)))
+ dispatch[LONG_BINGET] = load_long_binget
+
+ def load_put(self):
+ self.stack[-1].id = self.idprefix + self.readline()[:-1]
+ dispatch[PUT] = load_put
+
+ def load_binput(self):
+ i = ord(self.read(1))
+ last = self.stack[-1]
+ if getattr(last, 'id', last) is last:
+ last.id = self.idprefix + repr(i)
+ dispatch[BINPUT] = load_binput
+
+ def load_long_binput(self):
+ i = mloads('i' + self.read(4))
+ last = self.stack[-1]
+ if getattr(last, 'id', last) is last:
+ last.id = self.idprefix + repr(i)
+ dispatch[LONG_BINPUT] = load_long_binput
+
+
+def ToXMLload(file):
+ return ToXMLUnpickler(file).load()
+
+def ToXMLloads(str):
+ from StringIO import StringIO
+ file = StringIO(str)
+ return ToXMLUnpickler(file).load()
+
+def name(self, tag, data):
+ return ''.join(data[2:]).strip()
+
+def start_pickle(self, tag, attrs):
+ self._pickleids = {}
+ return [tag, attrs]
+
+def save_int(self, tag, data):
+ if self.binary:
+ v = int(name(self, tag, data))
+ if v >= 0:
+ if v <= 0xff:
+ return BININT1 + chr(v)
+ if v <= 0xffff:
+ return '%c%c%c' % (BININT2, v & 0xff, v >> 8)
+ hb = v >> 31
+ if hb == 0 or hb == -1:
+ return BININT + struct.pack('<i', v)
+ return INT + name(self, tag, data) + '\n'
+
+def save_float(self, tag, data):
+ if self.binary:
+ return BINFLOAT + struct.pack('>d', float(name(self, tag, data)))
+ else:
+ return FLOAT + name(self, tag, data) + '\n'
+
+def save_put(self, v, attrs):
+ id = attrs.get('id', '')
+ if id:
+ prefix = id.rfind('.')
+ if prefix >= 0:
+ id = id[prefix + 1:]
+ elif id[0] == 'i':
+ id = id[1:]
+ if self.binary:
+ id = int(id)
+ if id < 256:
+ id = BINPUT + chr(id)
+ else:
+ id = LONG_BINPUT + struct.pack('<i', id)
+ else:
+ id = PUT + repr(id) + '\n'
+ return v + id
+ return v
+
+def save_string(self, tag, data):
+ a = data[1]
+ v = ''.join(data[2:])
+ encoding = a['encoding']
+ if encoding is not '':
+ v = unescape(v, encoding)
+ if self.binary:
+ l = len(v)
+ if l < 256:
+ v = SHORT_BINSTRING + chr(l) + v
+ else:
+ v = BINSTRING + struct.pack('<i', l) + v
+ else:
+ v = STRING + repr(v) + '\n'
+ return save_put(self, v, a)
+
+def save_unicode(self, tag, data):
+ a = data[1]
+ v = ''.join(data[2:])
+ encoding = a['encoding']
+ if encoding is not '':
+ v = unescape(v, encoding)
+ if self.binary:
+ v = v.encode('utf-8')
+ v = BINUNICODE + struct.pack("<i", len(v)) + v
+ else:
+ v = v.replace("\\", "\\u005c")
+ v = v.replace("\n", "\\u000a")
+ v.encode('raw-unicode-escape')
+ v = UNICODE + v + '\n'
+ return save_put(self, v, a)
+
+def save_tuple(self, tag, data):
+ T = data[2:]
+ if not T:
+ return EMPTY_TUPLE
+ return save_put(self, MARK + ''.join(T) + TUPLE, data[1])
+
+def save_list(self, tag, data):
+ L = data[2:]
+ if self.binary:
+ v = save_put(self, EMPTY_LIST, data[1])
+ if L:
+ v = v + MARK + ''.join(L) + APPENDS
+ else:
+ v = save_put(self, MARK + LIST, data[1])
+ if L:
+ v = APPEND.join(L) + APPEND
+ return v
+
+def save_dict(self, tag, data):
+ D = data[2:]
+ if self.binary:
+ v = save_put(self, EMPTY_DICT, data[1])
+ if D:
+ v = v + MARK + ''.join(D) + SETITEMS
+ else:
+ v = save_put(self, MARK + DICT, data[1])
+ if D:
+ v = v + SETITEM.join(D) + SETITEM
+ return v
+
+def save_reference(self, tag, data):
+ a = data[1]
+ id = a['id']
+ prefix = id.rfind('.')
+ if prefix >= 0:
+ id = id[prefix + 1:]
+ if self.binary:
+ id = int(id)
+ if id < 256:
+ return BINGET + chr(id)
+ else:
+ return LONG_BINGET + struct.pack('<i', i)
+ else:
+ return GET + repr(id) + '\n'
+
+def save_object(self, tag, data):
+ v = MARK + data[2]
+ x = data[3][1:]
+ stop = x.rfind('t') # This seems
+ if stop >= 0: # wrong!
+ x = x[:stop]
+ v = save_put(self, v + x + OBJ, data[1])
+ v = v + data[4] + BUILD # state
+ return v
+
+def save_global(self, tag, data):
+ a = data[1]
+ return save_put(self, GLOBAL + a['module'] + '\n' + a['name'] + '\n', a)
+
+def save_persis(self, tag, data):
+ v = data[2]
+ if self.binary:
+ return v + BINPERSID
+ else:
+ return PERSID + v
+
+class xmlPickler(NoBlanks, xyap):
+ start_handlers = {
+ 'pickle': lambda self, tag, attrs: [tag, attrs],
+ }
+ end_handlers = {
+ 'pickle': lambda self, tag, data: str(data[2]) + STOP,
+ 'none': lambda self, tag, data: NONE,
+ 'int': save_int,
+ 'long': lambda self, tag, data: LONG + str(data[2]) + LONG + '\n',
+ 'float': save_float,
+ 'string': save_string,
+ 'reference': save_reference,
+ 'tuple': save_tuple,
+ 'list': save_list,
+ 'dictionary': save_dict,
+ 'item': lambda self, tag, data: ''.join(map(str, data[2:])),
+ 'value': lambda self, tag, data: data[2],
+ 'key' : lambda self, tag, data: data[2],
+ 'object': save_object,
+ 'klass': lambda self, tag, data: data[2],
+ 'state': lambda self, tag, data: data[2],
+ 'global': save_global,
+ 'persistent': save_persis,
+ 'unicode': save_unicode,
+ }
diff -Naur Zope-4.5.3/Shared/DC/xml/xyap.py Zope-4.5.3-Nexedi/Shared/DC/xml/xyap.py
--- Zope-4.5.3/Shared/DC/xml/xyap.py 1970-01-01 01:00:00.000000000 +0100
+++ Zope-4.5.3-Nexedi/Shared/DC/xml/xyap.py 2021-03-09 16:13:49.000000000 +0100
@@ -0,0 +1,117 @@
+"""Yet another XML parser
+
+This is meant to be very simple:
+
+ - stack based
+
+ - The parser has a table of start handlers and end handlers.
+
+ - start tag handlers are called with the parser instance, tag names
+ and attributes. The result is placed on the stack. The default
+ handler places a special object on the stack (uh, a list, with the
+ tag name and attributes as the first two elements. ;)
+
+ - end tag handlers are called with the object on the parser, the tag
+ name, and top of the stack right after it has been removed. The
+ result is appended to the object on the top of the stack.
+
+Note that namespace attributes should recieve some special handling.
+Oh well.
+"""
+
+import string
+import xml.parsers.expat
+
+
+class xyap:
+ start_handlers = {}
+ end_handlers = {}
+
+ def __init__(self):
+ top = []
+ self._stack = _stack = [top]
+ self.push = _stack.append
+ self.append = top.append
+
+ def handle_data(self, data):
+ self.append(data)
+
+ def unknown_starttag(self, tag, attrs):
+ if isinstance(attrs, list):
+ attrs = dict(attrs)
+ start = self.start_handlers
+ if tag in start:
+ tag = start[tag](self, tag, attrs)
+ else:
+ tag = [tag, attrs]
+ self.push(tag)
+ self.append = tag.append
+
+ def unknown_endtag(self, tag):
+ _stack = self._stack
+ top = _stack.pop()
+ append = self.append = _stack[-1].append
+ end = self.end_handlers
+ if tag in end:
+ top = end[tag](self, tag, top)
+ append(top)
+
+class NoBlanks:
+
+ def handle_data(self, data):
+ if data.strip():
+ self.append(data)
+
+
+def struct(self, tag, data):
+ r = {}
+ for k, v in data[2:]:
+ r[k] = v
+ return r
+
+_nulljoin = "".join
+
+def name(self, tag, data):
+ return _nulljoin(data[2:]).strip()
+
+def tuplef(self, tag, data):
+ return tuple(data[2:])
+
+class XYap(xyap):
+ def __init__(self):
+ self._parser = xml.parsers.expat.ParserCreate()
+ self._parser.StartElementHandler = self.unknown_starttag
+ self._parser.EndElementHandler = self.unknown_endtag
+ self._parser.CharacterDataHandler = self.handle_data
+ xyap.__init__(self)
+
+class xmlrpc(NoBlanks, XYap):
+ end_handlers = {
+ 'methodCall': tuplef,
+ 'methodName': name,
+ 'params': tuplef,
+ 'param': lambda self, tag, data: data[2],
+ 'value': lambda self, tag, data: data[2],
+ 'i4':
+ lambda self, tag, data, atoi=string.atoi, name=name:
+ atoi(name(self, tag, data)),
+ 'int':
+ lambda self, tag, data, atoi=string.atoi, name=name:
+ atoi(name(self, tag, data)),
+ 'boolean':
+ lambda self, tag, data, atoi=string.atoi, name=name:
+ atoi(name(self, tag, data)),
+ 'string': lambda self, tag, data, join=string.join:
+ join(data[2:], ''),
+ 'double':
+ lambda self, tag, data, atof=string.atof, name=name:
+ atof(name(self, tag, data)),
+ 'float':
+ lambda self, tag, data, atof=string.atof, name=name:
+ atof(name(self, tag, data)),
+ 'struct': struct,
+ 'member': tuplef,
+ 'name': name,
+ 'array': lambda self, tag, data: data[2],
+ 'data': lambda self, tag, data: data[2:],
+ }
......@@ -410,7 +410,7 @@ egg = ${:_buildout_section_name_}
<= zope-product-with-eggtestinfo
[Products.DCWorkflow]
<= zope-product-with-eggtestinfo
Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method.patch#975b49e96bae33ac8563454fe5fa9899
Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method-2.4.1.patch#ec7bb56a9f1d37fcbf960cd1e96e6e6d
Products.DCWorkflow-patch-options = -p1
[Products.GenericSetup]
<= zope-product-with-eggtestinfo
......@@ -560,6 +560,8 @@ eggs = ${neoppod:eggs}
Products.ExternalMethod
Products.SiteErrorLog
tempstorage
Products.DCWorkflow
Record
# parameterizing the version of the generated python interpreter name by the
# python section version causes dependency between this egg section and the
......@@ -628,8 +630,8 @@ depends =
# neoppod, mysqlclient, slapos.recipe.template
# patched eggs
#Acquisition = 2.13.12+SlapOSPatched001
Products.DCWorkflow = 2.2.4+SlapOSPatched001
Acquisition = 4.7+SlapOSPatched001
Products.DCWorkflow = 2.4.1+SlapOSPatched001
ocropy = 1.0+SlapOSPatched001
pysvn = 1.7.10+SlapOSPatched002
python-ldap = 2.4.32+SlapOSPatched001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment