[Zope-CVS] CVS: Packages/cZPT/OFS - Makefile:1.1 cTraversable.c:1.1 pseudocode.py:1.1 speedtest.py:1.1
Shane Hathaway
shane@cvs.zope.org
Mon, 16 Sep 2002 11:44:34 -0400
Update of /cvs-repository/Packages/cZPT/OFS
In directory cvs.zope.org:/tmp/cvs-serv23309/OFS
Added Files:
Makefile cTraversable.c pseudocode.py speedtest.py
Log Message:
Optimized TALInterpreter and restrictedTraverse() in C.
This code is just educational for now. Before doing much more, we should
write performance tests and try out Pyrex.
=== Added File Packages/cZPT/OFS/Makefile ===
all: cTraversable.so
cTraversable.so: cTraversable.c
gcc -g -Wall -I /usr/local/include/python2.1 \
-I /home/shane/cvs/Zope/lib/Components/ExtensionClass/src -shared -o \
cTraversable.so cTraversable.c
=== Added File Packages/cZPT/OFS/cTraversable.c === (554/654 lines abridged)
/*****************************************************************************
Copyright (c) 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
****************************************************************************/
/*
$Id: cTraversable.c,v 1.1 2002/09/16 15:44:33 shane Exp $
Based on revision 1.15 of OFS/Traversable.py and revision 1.36 of
Products/PageTemplates/Expressions.py.
*/
#include <Python.h>
#include <ExtensionClass.h>
#include <Acquisition.h>
#define CHECKPTR(expr) if ((expr) == NULL) goto error
#define CHECKINT(expr) if ((expr) < 0) goto error
#define DECREF_ASSIGN(var, value) Py_DECREF(var); (var) = (value)
#define DECREF2_CHECK(owned, maybe_owned) \
Py_DECREF(owned); CHECKPTR(maybe_owned); Py_DECREF(maybe_owned)
#define RETURN_NONE Py_INCREF(Py_None); return Py_None
PyObject *Unauthorized, *getSecurityManager, *aq_validate, *Containers;
PyObject *py___bobo_traverse__, *py_validate, *py_TraversalRequestNameStack;
PyObject *py_getPhysicalRoot, *py_path;
static int
isSimpleContainer(PyObject *object) {
/*
# Returns 1 for container object types that don't need to be protected.
return Containers(type(object))
*/
PyObject *o1, *o2;
int res;
CHECKPTR(o1 = PyTuple_New(1));
CHECKPTR(o2 = PyObject_Type(object));
PyTuple_SET_ITEM(o1, 0, o2);
[-=- -=- -=- 554 lines omitted -=- -=- -=-]
PURE_MIXIN_CLASS(Traversable, "Traversable mixin (C)",
traversable_methods);
if (!ExtensionClassImported)
return;
/* Create a type */
CHECKPTR(m = Py_InitModule3("cTraversable",
module_functions, module___doc__));
aq_init();
INIT_STRING(py___bobo_traverse__, "__bobo_traverse__");
INIT_STRING(py_validate, "validate");
INIT_STRING(py_TraversalRequestNameStack, "TraversalRequestNameStack");
INIT_STRING(py_getPhysicalRoot, "getPhysicalRoot");
INIT_STRING(py_path, "path");
d = PyModule_GetDict(m);
PyExtensionClass_Export(d, "Traversable", TraversableType);
/*
from AccessControl import getSecurityManager, Unauthorized
from AccessControl.cAccessControl import aq_validate
from AccessControl.SimpleObjectPolicies import Containers
*/
CHECKPTR(other = PyImport_ImportModule("AccessControl"));
CHECKPTR(getSecurityManager =
PyObject_GetAttrString(other, "getSecurityManager"));
CHECKPTR(Unauthorized = PyObject_GetAttrString(other, "Unauthorized"));
Py_DECREF(other);
CHECKPTR(other = PyImport_ImportModule("AccessControl.cAccessControl"));
CHECKPTR(aq_validate = PyObject_GetAttrString(other, "aq_validate"));
Py_DECREF(other);
CHECKPTR(other =
PyImport_ImportModule("AccessControl.SimpleObjectPolicies"));
CHECKPTR(Containers = PyObject_GetAttrString(other, "Containers"));
Py_DECREF(other);
other = NULL;
return;
error:
Py_XDECREF(other);
return;
}
=== Added File Packages/cZPT/OFS/pseudocode.py ===
##############################################################################
#
# Copyright (c) 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
#
##############################################################################
"""pseudocode for cTraversable.c.
This is the pseudocode for the merging of OFS.Traversable.restrictedTraverse()
and Products.PageTemplates.Expressions.restrictedTraverse(). The two are
slightly different. This pseudocode is the basis for most of cTraversable.
Note that this code probably works, but in Python it is probably slower
than either implementation of restrictedTraverse(). However, in C it
is much faster.
"""
from AccessControl import getSecurityManager, Unauthorized
from AccessControl.cAccessControl import aq_validate
from AccessControl.SimpleObjectPolicies import Containers
def isSimpleContainer(object):
# Returns 1 for container object types that don't need to be protected.
return Containers(type(object))
def traverseName(object, name, validate, request_ptr, path, allow_tuple):
o = None
if allow_tuple and isinstance(name, type(())):
# Special case apparently used for ZPT repeat.
return apply(object, name)
if name[0] == '_':
# Never allowed in a URL.
raise Unauthorized, name
if name == '.':
return object
if name == '..':
o = aq_parent(object)
if o is not None:
if validate is not None and not isSimpleContainer(object):
if not validate(object, object, name, o):
raise Unauthorized, name
return o
t = get(object, '__bobo_traverse__', N)
if t is not None:
if not request_ptr:
# create the request on the fly.
if path is None:
path = []
request_ptr.append({"TraversalRequestNameStack": path,
"path": path})
o = t(request_ptr[0], name)
if validate is not None and not isSimpleContainer(object):
# Guess at the container. :-(
container = None
if hasattr(o, 'im_self'):
container = o.im_self
elif (hasattr(getattr(object, 'aq_base', object), name)
and getattr(object, name) == o):
container = object
if not validate(object, container, name, o):
raise Unauthorized, name
return o
# Try an attribute.
o = getattr(object, name, _marker)
if o is not _marker:
if validate is not None and not isSimpleContainer(object):
# Check access to the attribute.
if has(object, 'aq_acquire'):
object.aq_acquire(
name, aq_validate, validate)
else:
if not validate(object, object, name, o):
raise Unauthorized, name
return o
# Try an item.
o=object[name]
if validate is not None and not isSimpleContainer(object):
if not validate(object, object, None, o):
raise Unauthorized, name
return o
def traversePath(start, orig_path, default_, restricted, allow_tuple):
request_ptr = []
securityManager = None
validate = None
path = None
object = None
name = None
if not orig_path:
return self
if restricted:
securityManager = getSecurityManager()
validate = securityManager.validate
if isinstance(orig_path, StringType):
if '/' not in orig_path:
try:
return traverseName(start, orig_path, validate,
request_ptr, None, allow_tuple)
except:
if default_ is not None:
return default_
raise
path = '/'.split(orig_path)
path.reverse()
else:
if len(orig_path) == 1 and orig_path[0]:
try:
return traverseName(start, orig_path[0], validate,
request_ptr, None, allow_tuple)
except:
if default_ is not None:
return default_
raise
path = list(orig_path)
path.reverse()
if len(path) > 1 and not path[0]:
# Remove trailing slash
path.pop(0)
if not path[-1]:
# If the path starts with an empty string, go to the root first.
pop()
object = start.getPhysicalRoot()
if (restricted and not securityManager.validateValue(self)):
raise Unauthorized, name
else:
object = start
while path:
name = path.pop()
try:
object = traverseName(object, name, validate,
request_ptr, path, allow_tuple)
except:
if default_ is not None:
return default_
raise
return object
=== Added File Packages/cZPT/OFS/speedtest.py ===
import ZODB
from OFS.cTraversable import restrictedTraverse as c_rt
from Products.PageTemplates.Expressions import py_restrictedTraverse as py_rt
from AccessControl import User, getSecurityManager
from time import time
ob = {'a': {'b': {'c': 53}}}
path = ['a', 'b', 'c']
iter = range(10000)
assert py_rt(ob, path) == ob['a']['b']['c']
assert c_rt(ob, path) == ob['a']['b']['c']
start = time()
for n in iter:
py_rt(ob, path)
end = time()
py_t = end - start
start = time()
for n in iter:
c_rt(ob, path)
end = time()
c_t = end - start
start = time()
for n in iter:
ob[path[0]][path[1]][path[2]]
end = time()
lookup_t = end - start
print py_t, c_t, lookup_t
# c_t is 2x-3x the speed of py_t, but lookup_t is 20x faster than c_t.