view roundup/cgi/PageTemplates/PythonExpr.py @ 5632:a29a8dae2095

Initial implementation of function to return data for / and /data endpoints under /rest/. /rest/ returns: 1) default_version of the interface and supported_version array 2) list of links with rel and uri properties that indicate what assets are available under /rest. E.g. /rest/data /data returns: a list of possible assets (e.g. issue, user, keyword, status) and links for accessing those assets. E.G. { "data": { "keyword": { "link": "https://example.net/demo/rest/data/keyword" }, "user": { "link": "https://example.net/demo/rest/data/user" }, ... } } Both of these are currently hand coded. Others will be doing more development on the rest interface. These two examples are meant to spark discussion on what the payloads returned by the rest interface should look like and give some ideas around HATEOAS.
author John Rouillard <rouilj@ieee.org>
date Fri, 01 Mar 2019 23:24:40 -0500
parents f8673e720f30
children e70885fe72a4
line wrap: on
line source

##############################################################################
#
# 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
#
##############################################################################
# Modified for Roundup:
# 
# 1. more informative traceback info

"""Generic Python Expression Handler
"""

from .TALES import CompilerError
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 = expr.strip().replace('\n', ' ')
        try:
            d = {}
            exec('def f():\n return %s\n' % expr.strip(), 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.__code__.co_names:
            if vname[0] not in '$_':
                vnames.append(vname)

    def _bind_used_names(self, econtext, _marker=[]):
        # Bind template variables
        names = {'CONTEXTS': econtext.contexts}
        vars = econtext.vars
        getType = econtext.getCompiler().getTypes().get
        for vname in self._f_varnames:
            val = vars.get(vname, _marker)
            if val is _marker:
                has = val = getType(vname)
                if has:
                    val = ExprTypeProxy(vname, val, econtext)
                    names[vname] = val
            else:
                names[vname] = val
        return names

    def __call__(self, econtext):
        __traceback_info__ = 'python expression "%s"'%self.expr
        f = self._f
        f.__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.getCompiler())(self._econtext)


Roundup Issue Tracker: http://roundup-tracker.org/