Bindings.py :  » Web-Frameworks » Zope » Zope-2.6.0 » lib » python » Shared » DC » Scripts » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Zope 
Zope » Zope 2.6.0 » lib » python » Shared » DC » Scripts » Bindings.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
#
##############################################################################

__version__='$Revision$'[11:-2]

import Globals
from Persistence import Persistent
from string import join,strip
import re

defaultBindings = {'name_context': 'context',
                   'name_container': 'container',
                   'name_m_self': 'script',
                   'name_ns': '',
                   'name_subpath': 'traverse_subpath'}

_marker = []  # Create a new marker

class NameAssignments:
    # Note that instances of this class are intended to be immutable
    # and persistent but not inherit from ExtensionClass.

    _exprs = (('name_context',   'self._getContext()'),
              ('name_container', 'self._getContainer()'),
              ('name_m_self',    'self'),
              ('name_ns',        'self._getNamespace(caller_namespace, kw)'),
              ('name_subpath',   'self._getTraverseSubpath()'),
              )

    _isLegalName = re.compile(r'_$|[a-zA-Z][a-zA-Z0-9_]*$').match
    _asgns = {}

    __allow_access_to_unprotected_subobjects__ = 1

    def __init__(self, mapping):
        # mapping is presumably the REQUEST or compatible equivalent.
        # Note that we take care not to store expression texts in the ZODB.
        asgns = {}
        _isLegalName = self._isLegalName
        for name, expr in self._exprs:
            if mapping.has_key(name):
                assigned_name = strip(mapping[name])
                if not assigned_name:
                    continue
                if not _isLegalName(assigned_name):
                    raise ValueError, ('"%s" is not a valid variable name.'
                                       % assigned_name)
                asgns[name] = assigned_name
        self._asgns = asgns

    def isAnyNameAssigned(self):
        if len(self._asgns) > 0:
            return 1
        return 0

    def isNameAssigned(self, name):
        return self._asgns.has_key(name)

    def getAssignedName(self, name, default=_marker):
        val = self._asgns.get(name, default)
        if val is _marker:
            raise KeyError, name
        return val

    def getAssignedNames(self):
        # Returns a copy of the assigned names mapping
        return self._asgns.copy()

    def getAssignedNamesInOrder(self):
        # Returns the assigned names in the same order as that of
        # self._exprs.
        rval = []
        asgns = self._asgns
        for name, expr in self._exprs:
            if asgns.has_key(name):
                assigned_name = asgns[name]
                rval.append(assigned_name)
        return rval

    def _generateCodeBlock(self, bindtext, assigned_names):
        # Returns a tuple: exec-able code that can compute the value of
        # the bindings and eliminate clashing keyword arguments,
        # and the number of names bound.
        text = ['bound_data.append(%s)\n' % bindtext]
        for assigned_name in assigned_names:
            text.append('if kw.has_key("%s"):\n' % assigned_name)
            text.append('    del kw["%s"]\n'     % assigned_name)
        codetext = join(text, '')
        return (compile(codetext, '<string>', 'exec'), len(assigned_names))

    def _createCodeBlockForMapping(self):
        # Generates a code block which generates the "bound_data"
        # variable and removes excessive arguments from the "kw"
        # variable.  bound_data will be a mapping, for use as a
        # global namespace.
        exprtext = []
        assigned_names = []
        asgns = self._asgns
        for name, expr in self._exprs:
            if asgns.has_key(name):
                assigned_name = asgns[name]
                assigned_names.append(assigned_name)
                exprtext.append('"%s":%s,' % (assigned_name, expr))
        text = '{%s}' % join(exprtext, '')
        return self._generateCodeBlock(text, assigned_names)

    def _createCodeBlockForTuple(self, argNames):
        # Generates a code block which generates the "bound_data"
        # variable and removes excessive arguments from the "kw"
        # variable.  bound_data will be a tuple, for use as
        # positional arguments.
        assigned_names = []
        exprtext = []
        asgns = self._asgns
        for argName in argNames:
            passedLastBoundArg = 1
            for name, expr in self._exprs:
                # Provide a value for the available exprs.
                if asgns.has_key(name):
                    assigned_name = asgns[name]
                    if assigned_name == argName:
                        # The value for this argument will be filled in.
                        exprtext.append('%s,' % expr)
                        assigned_names.append(assigned_name)
                        passedLastBoundArg = 0
                        break
            if passedLastBoundArg:
                # Found last of bound args.
                break
        text = '(%s)' % join(exprtext, '')
        return self._generateCodeBlock(text, assigned_names)


class Bindings:

    __ac_permissions__ = (
        ('View management screens', ('getBindingAssignments',)),
        ('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

    def _setupBindings(self, names={}):
        self._bind_names = names = NameAssignments(names)
        return names

    def getBindingAssignments(self):
        if not hasattr(self, '_bind_names'):
            self._setupBindings()
        return self._bind_names

    def __before_publishing_traverse__(self, self2, request):
        path = request['TraversalRequestNameStack']
        names = self.getBindingAssignments()
        if (not names.isNameAssigned('name_subpath') or
            (path and hasattr(self.aq_base, path[-1])) ):
            return
        subpath = path[:]
        path[:] = []
        subpath.reverse()
        request.set('traverse_subpath', subpath)

    def _createBindCode(self, names):
        return names._createCodeBlockForMapping()

    def _prepareBindCode(self):
        # Creates:
        # - a code block that quickly generates "bound_data" and
        #   modifies the "kw" variable.
        # - a count of the bound arguments.
        # Saves them in _v_bindcode and _v_bindcount.
        # Returns .
        names = self.getBindingAssignments()
        if names.isAnyNameAssigned():
            bindcode, bindcount = self._createBindCode(names)
        else:
            bindcode, bindcount = None, 0
        self._v_bindcode = bindcode
        self._v_bindcount = bindcount
        return bindcode

    def _getBindCount(self):
        bindcount = getattr(self, '_v_bindcount', _marker)
        if bindcount is _marker:
            self._prepareBindCode()
            bindcount = self._v_bindcount
        return bindcount

    def _getContext(self):
        # Utility for bindcode.
        while 1:
            self = self.aq_parent
            if not getattr(self, '_is_wrapperish', None):
                return self

    def _getContainer(self):
        # Utility for bindcode.
        while 1:
            self = self.aq_inner.aq_parent
            if not getattr(self, '_is_wrapperish', None):
                return self

    def _getTraverseSubpath(self):
        # Utility for bindcode.
        if hasattr(self, 'REQUEST'):
            return self.REQUEST.other.get('traverse_subpath', [])
        else:
            return []

    def _getNamespace(self, caller_namespace, kw):
        # Utility for bindcode.
        if caller_namespace is None:
            # Try to get the caller's namespace by scanning
            # the keyword arguments for an argument with the
            # same name as the assigned name for name_ns.
            names = self.getBindingAssignments()
            assigned_name = names.getAssignedName('name_ns')
            caller_namespace = kw.get(assigned_name, None)
        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.'''
        return self._bindAndExec(args, kw, None)

    def __render_with_namespace__(self, namespace):
        '''Calls the script with the specified namespace.'''
        namevals = {}
        # Try to find unbound parameters in the namespace, if the
        # namespace is bound.
        if self.getBindingAssignments().isNameAssigned('name_ns'):
            code = self.func_code
            for name in code.co_varnames[:code.co_argcount]:
                try:
                    namevals[name] = namespace[name]
                except KeyError:
                    pass
        return self._bindAndExec((), namevals, namespace)

    render = __call__

    def _bindAndExec(self, args, kw, caller_namespace):
        '''Prepares the bound information and calls _exec(), possibly
        with a namespace.
        '''
        bindcode = getattr(self, '_v_bindcode', _marker)
        if bindcode is _marker:
            bindcode = self._prepareBindCode()
        if bindcode is None:
            bound_data = {}
        else:
            bound_data = []
            exec bindcode
            bound_data = bound_data[0]
        return self._exec(bound_data, args, kw)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.