view roundup/cgi/PageTemplates/PythonExpr.py @ 5108:67fad01d2009

issue2550653: xapian search, stemming is not working This is a partial fix for the issue. It does make stemming work (so searching for silent will also return docs with silently in them). However to do this we need to lowercase the text so the porter stemmer will work. This means capitalization is not preserved. Tests in test/test_indexer for xapian backend all pass. David Wolever (wolever) did the work.
author John Rouillard <rouilj@ieee.org>
date Mon, 27 Jun 2016 22:10:45 -0400
parents 6e3e4f24c753
children 35ea9b1efc14
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() 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, _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.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.getCompiler())(self._econtext)


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