Commit 563ad818 authored by Evan Simpson's avatar Evan Simpson

Made namespace handling saner.

parent 9bebe884
......@@ -129,26 +129,29 @@ class HTMLFile(DocumentTemplate.HTMLFile,MethodObject.Method,):
defaultBindings = {'name_context': 'context',
'name_container': 'container',
'name_m_self': 'self',
'name_ns': '_',
'name_ns': 'caller_namespace',
'name_subpath': 'traverse_subpath'}
from Shared.DC.Scripts.Bindings import Bindings
from Acquisition import Explicit
from DocumentTemplate.DT_String import _marker, DTReturn, render_blocks
from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
from AccessControl import getSecurityManager
class DTMLFile(Bindings, Explicit, HTMLFile):
"HTMLFile with bindings and support for __render_with_namespace__"
class func_code: pass
func_code=func_code()
func_code.co_varnames=()
func_code.co_argcount=0
func_code = None
func_defaults = None
_Bindings_ns_class = TemplateDict
# By default, we want to look up names in our container.
_Bindings_client = 'container'
def __init__(self, name, _prefix=None, **kw):
self.ZBindings_edit(defaultBindings)
self._setFuncSignature()
apply(DTMLFile.inheritedAttribute('__init__'),
(self, name, _prefix), kw)
......@@ -156,57 +159,59 @@ class DTMLFile(Bindings, Explicit, HTMLFile):
# Cook if we haven't already
self._cook_check()
# Get our namespace
name_ns = self.getBindingAssignments().getAssignedName('name_ns')
ns = bound_data[name_ns]
# Get our caller's namespace, and set up our own.
cns = bound_data['caller_namespace']
ns = self._Bindings_ns_class()
push = ns._push
ns.validate = None
# Check for excessive recursion
level = ns.level
if level > 200: raise SystemError, (
'infinite recursion in document template')
ns.level = level + 1
req = None
kw_bind = kw
if level == 0:
# If this is the starting namespace, get the REQUEST.
try:
req = self.aq_acquire('REQUEST')
except: pass
else:
# Get last set of bindings. Copy the request reference
if cns:
# Someone called us.
push(cns)
ns.level = cns.level + 1
# Get their bindings. Copy the request reference
# forward, and include older keyword arguments in the
# current 'keyword_args' binding.
try:
last_bound = ns[('current bindings',)]
req = last_bound.get('REQUEST', None)
last_req = last_bound.get('REQUEST', None)
if last_req:
bound_data['REQUEST'] = last_req
old_kw = last_bound['keyword_args']
if old_kw:
kw_bind = old_kw.copy()
kw_bind.update(kw)
except: pass
# Add 'REQUEST' and 'keyword_args' bound names.
if req:
else:
# We're first, so get the REQUEST.
try:
req = self.aq_acquire('REQUEST')
except: pass
bound_data['REQUEST'] = req
# Bind 'keyword_args' to the complete set of keyword arguments.
bound_data['keyword_args'] = kw_bind
# Push globals, initialized variables, REQUEST (if any),
# and keyword arguments onto the namespace stack, followed
# by the the container and the bound names.
# and keyword arguments onto the namespace stack
for nsitem in (self.globals, self._vars, req, kw):
if nsitem:
push(nsitem)
# This causes dtml files to bypass their context unless they
# explicitly use it through the 'context' name binding.
push(InstanceDict(self._getContainer(), ns))
# Push the 'container' (default), 'context', or nothing.
bind_to = self._Bindings_client
if bind_to in ('container', 'client'):
push(InstanceDict(bound_data[bind_to], ns))
# Push the name bindings, and a reference to grab later.
push(bound_data)
push({('current bindings',): bound_data})
security = getSecurityManager()
security.addContext(self)
try:
value = self.ZDocumentTemplate_beforeRender(ns, _marker)
if value is _marker:
......@@ -217,10 +222,10 @@ class DTMLFile(Bindings, Explicit, HTMLFile):
else:
return value
finally:
# Clear the namespace
security.removeContext(self)
# Clear the namespace, breaking circular references.
while len(ns): ns._pop()
from Shared.DC.Scripts.Signature import _setFuncSignature
......@@ -217,14 +217,23 @@ class Bindings:
__ac_permissions__ = (
('View management screens', ('getBindingAssignments',)),
('Change bindings', ('ZBindings_edit')),
('Change bindings', ('ZBindings_edit', 'ZBindings_setClient')),
)
_Bindings_client = None
def ZBindings_edit(self, mapping):
names = self._setupBindings(mapping)
self._prepareBindCode()
self._editedBindings()
def ZBindings_setClient(self, clientname):
'''Name the binding to be used as the "client".
This is used by classes such as DTMLFile that want to
choose an object on which to operate by default.'''
self._Bindings_client = str(clientname)
def _editedBindings(self):
# Override to receive notification when the bindings are edited.
pass
......@@ -305,13 +314,10 @@ class Bindings:
names = self.getBindingAssignments()
assigned_name = names.getAssignedName('name_ns')
caller_namespace = kw.get(assigned_name, None)
# Create a local namespace.
my_namespace = self._Bindings_ns_class()
if caller_namespace is not None:
# Include the caller's namespace.
my_namespace._push(caller_namespace)
my_namespace.level = caller_namespace.level
return my_namespace
if caller_namespace is None:
# Create an empty namespace.
return self._Bindings_ns_class()
return caller_namespace
def __call__(self, *args, **kw):
'''Calls the script.
......
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