Update of /cvsroot/happydoc/HappyDoc3/happydoclib/docset/docset_TAL
In directory sc8-pr-cvs1:/tmp/cvs-serv31791/happydoclib/docset/docset_TAL
Added Files:
Iterator.py MapStack.py PythonExpr.py
Log Message:
Import a file files from the PageTemplates module of Zope 2. Refer to
TAL/LICENSE.txt for licensing information.
--- NEW FILE: Iterator.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
#
##############################################################################
__doc__='''Iterator class
Unlike the builtin iterators of Python 2.2+, these classes are
designed to maintain information about the state of an iteration.
The Iterator() function accepts either a sequence or a Python
iterator. The next() method fetches the next item, and returns
true if it succeeds.
$Id: Iterator.py,v 1.1 2003/01/26 19:12:11 doughellmann Exp $'''
__version__='$Revision: 1.1 $'[11:-2]
import string
class Iterator:
'''Simple Iterator class'''
__allow_access_to_unprotected_subobjects__ = 1
nextIndex = 0
def __init__(self, seq):
self.seq = seq
for inner in seqInner, iterInner:
if inner._supports(seq):
self._inner = inner
self._prep_next = inner.prep_next
return
raise TypeError, "Iterator does not support %s" % `seq`
def __getattr__(self, name):
try:
inner = getattr(self._inner, 'it_' + name)
except AttributeError:
raise AttributeError, name
return inner(self)
def next(self):
if not (hasattr(self, '_next') or self._prep_next(self)):
return 0
self.index = i = self.nextIndex
self.nextIndex = i+1
self._advance(self)
return 1
def _advance(self, it):
self.item = self._next
del self._next
del self.end
self._advance = self._inner.advance
self.start = 1
def number(self): return self.nextIndex
def even(self): return not self.index % 2
def odd(self): return self.index % 2
def letter(self, base=ord('a'), radix=26):
index = self.index
s = ''
while 1:
index, off = divmod(index, radix)
s = chr(base + off) + s
if not index: return s
def Letter(self):
return self.letter(base=ord('A'))
def Roman(self, rnvalues=(
(1000,'M'),(900,'CM'),(500,'D'),(400,'CD'),
(100,'C'),(90,'XC'),(50,'L'),(40,'XL'),
(10,'X'),(9,'IX'),(5,'V'),(4,'IV'),(1,'I')) ):
n = self.index + 1
s = ''
for v, r in rnvalues:
rct, n = divmod(n, v)
s = s + r * rct
return s
def roman(self, lower=string.lower):
return lower(self.Roman())
def first(self, name=None):
if self.start: return 1
return not self.same_part(name, self._last, self.item)
def last(self, name=None):
if self.end: return 1
return not self.same_part(name, self.item, self._next)
def same_part(self, name, ob1, ob2):
if name is None:
return ob1 == ob2
no = []
return getattr(ob1, name, no) == getattr(ob2, name, no) is not no
def __iter__(self):
return IterIter(self)
class InnerBase:
'''Base Inner class for Iterators'''
# Prep sets up ._next and .end
def prep_next(self, it):
it.next = self.no_next
it.end = 1
return 0
# Advance knocks them down
def advance(self, it):
it._last = it.item
it.item = it._next
del it._next
del it.end
it.start = 0
def no_next(self, it):
return 0
def it_end(self, it):
if hasattr(it, '_next'):
return 0
return not self.prep_next(it)
class SeqInner(InnerBase):
'''Inner class for sequence Iterators'''
def _supports(self, ob):
try: ob[0]
except TypeError: return 0
except: pass
return 1
def prep_next(self, it):
i = it.nextIndex
try:
it._next = it.seq[i]
except IndexError:
it._prep_next = self.no_next
it.end = 1
return 0
it.end = 0
return 1
def it_length(self, it):
it.length = l = len(it.seq)
return l
try:
StopIteration=StopIteration
except NameError:
StopIteration="StopIteration"
class IterInner(InnerBase):
'''Iterator inner class for Python iterators'''
def _supports(self, ob):
try:
if hasattr(ob, 'next') and (ob is iter(ob)):
return 1
except:
return 0
def prep_next(self, it):
try:
it._next = it.seq.next()
except StopIteration:
it._prep_next = self.no_next
it.end = 1
return 0
it.end = 0
return 1
class IterIter:
def __init__(self, it):
self.it = it
self.skip = it.nextIndex > 0 and not it.end
def next(self):
it = self.it
if self.skip:
self.skip = 0
return it.item
if it.next():
return it.item
raise StopIteration
seqInner = SeqInner()
iterInner = IterInner()
--- NEW FILE: MapStack.py ---
#!/usr/bin/env python
#
# $Id: MapStack.py,v 1.1 2003/01/26 19:12:11 doughellmann Exp $
#
# Copyright 2003 Doug Hellmann.
#
#
# 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 Doug
# Hellmann not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL DOUG HELLMANN 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.
#
"""Implements a dictionary-like class to provide namespace and context stacking.
Based on the MultiMapping extension class found in Zope.
"""
__rcs_info__ = {
#
# Creation Information
#
'module_name' : '$RCSfile: MapStack.py,v $',
'rcs_id' : '$Id: MapStack.py,v 1.1 2003/01/26 19:12:11 doughellmann Exp $',
'creator' : 'Doug Hellmann <do...@he...>',
'project' : 'HappyDoc',
'created' : 'Sun, 19-Jan-2003 07:45:43 EST',
#
# Current Information
#
'author' : '$Author: doughellmann $',
'version' : '$Revision: 1.1 $',
'date' : '$Date: 2003/01/26 19:12:11 $',
}
try:
__version__ = __rcs_info__['version'].split(' ')[1]
except:
__version__ = '0.0'
#
# Import system modules
#
import unittest
#
# Import Local modules
#
#
# Module
#
class MapStack:
"""Implements a dictionary-like class to provide namespace and context stacking.
Based on the MultiMapping extension class found in Zope.
"""
def __init__(self, *dicts):
"""Construct a new MapStack.
Pass some existing mappings to be pushed onto the stack.
"""
#print 'MapStack', dicts
self.stack = []
for d in dicts:
self.push(d)
return
def push(self, newDict):
"""Add a new context to the stack.
"""
self.stack.insert(0, newDict)
return
_push = push
def pop(self):
"""Remove and return the top context.
"""
if self.stack:
top = self.stack[0]
else:
top = None
self.stack = self.stack[1:]
return top
_pop = pop
def __getitem__(self, key):
for map in self.stack:
if map.has_key(key):
return map[key]
raise KeyError(key)
def dump(self):
for map in self.stack:
print map.keys()
return
def __setitem__(self, name, value):
#print 'MapStack.setitem(%s, %s)' % (name, value)
if not self.stack:
raise ValueError('Stack empty')
top = self.stack[0]
top[name] = value
return
def has_get(self, key):
try:
val = self[key]
except KeyError:
has = 0
val = None
else:
has = 1
#print 'has_get(%s) -> (%s, %s)' % (key, has, val)
#if not has:
# self.dump()
return (has, val)
class MapStackTest(unittest.TestCase):
def testEmpty(self):
ms = MapStack()
try:
anything = ms['anything']
except KeyError:
pass
else:
self.fail('Should have raised KeyError. Got: %s' % anything)
return
def testOneLevel(self):
ms = MapStack()
ms.push({'one':1, 'two':2})
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
try:
two = ms['two']
except KeyError:
self.fail('Should have found two')
return
def testTwoLevels(self):
ms = MapStack()
ms.push({'one':1})
ms.push({'two':2})
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
try:
two = ms['two']
except KeyError:
self.fail('Should have found two')
return
def testTwoLevelsWithOverride(self):
ms = MapStack()
ms.push({'one':1})
ms.push({'one':3, 'two':2})
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
else:
self.failUnlessEqual(one, 3)
try:
two = ms['two']
except KeyError:
self.fail('Should have found two')
return
def testTwoLevelsWithPop(self):
ms = MapStack()
ms.push({'one':1})
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
else:
self.failUnlessEqual(one, 1)
ms.push({'one':3, 'two':2})
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
else:
self.failUnlessEqual(one, 3)
try:
two = ms['two']
except KeyError:
self.fail('Should have found two')
removed = ms.pop()
try:
one = ms['one']
except KeyError:
self.fail('Should have found one')
else:
self.failUnlessEqual(one, 1)
try:
two = ms['two']
except KeyError:
pass
else:
self.fail('Should have gotten a KeyError')
return
if __name__ == '__main__':
unittest.main()
--- NEW FILE: PythonExpr.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
#
##############################################################################
"""Generic Python Expression Handler
"""
__version__='$Revision: 1.1 $'[11:-2]
from hdTALES import CompilerError
from string import strip, split, join, replace, lstrip
from sys import exc_info
class getSecurityManager:
'''Null security manager'''
def validate(self, *args, **kwargs):
return 1
addContext = removeContext = validateValue = validate
class PythonExpr:
def __init__(self, name, expr, engine):
self.expr = expr = replace(strip(expr), '\n', ' ')
try:
d = {}
exec 'def f():\n return %s\n' % strip(expr) in d
self._f = d['f']
except:
raise CompilerError, ('Python expression error:\n'
'%s: %s') % exc_info()[:2]
self._get_used_names()
def _get_used_names(self):
self._f_varnames = vnames = []
for vname in self._f.func_code.co_names:
if vname[0] not in '$_':
vnames.append(vname)
def _bind_used_names(self, econtext):
# Bind template variables
names = {}
vars = econtext.vars
getType = econtext._engine.getTypes().get
for vname in self._f_varnames:
has, val = vars.has_get(vname)
if not has:
has = val = getType(vname)
if has:
val = ExprTypeProxy(vname, val, econtext)
if has:
names[vname] = val
return names
def __call__(self, econtext):
__traceback_info__ = self.expr
f = self._f
f.func_globals.update(self._bind_used_names(econtext))
return f()
def __str__(self):
return 'Python expression "%s"' % self.expr
def __repr__(self):
return '<PythonExpr %s>' % self.expr
class ExprTypeProxy:
'''Class that proxies access to an expression type handler'''
def __init__(self, name, handler, econtext):
self._name = name
self._handler = handler
self._econtext = econtext
def __call__(self, text):
return self._handler(self._name, text,
self._econtext._engine)(self._econtext)
|