[ZPT] CVS: Packages/Products/PageTemplates (Products/DC/PageTemplates) - PythonExpr.py:1.1 ZPythonExpr.py:1.1 ZRPythonExpr.py:1.1 Expressions.py:1.14 PageTemplateFile.py:1.2 ZopePageTemplate.py:1.10

evan@serenade.digicool.com evan@serenade.digicool.com
Tue, 22 May 2001 14:47:33 -0400


Update of /cvs-repository/Packages/Products/PageTemplates
In directory serenade:/home/evan/Zope/trunk/lib/python/Products/PageTemplates

Modified Files:
	Expressions.py PageTemplateFile.py ZopePageTemplate.py 
Added Files:
	PythonExpr.py ZPythonExpr.py ZRPythonExpr.py 
Log Message:
Factor out Python Expressions into three modules:

One for non-Zope use, one for pre-2.4 Zope use, and one for Zope 2.4+ use.



--- Added File PythonExpr.py in package Packages/Products/PageTemplates ---
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################

"""Generic Python Expression Handler
"""

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

from string import strip, split, join, replace, lstrip

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') % sys.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 = {}
        var = econtext.contexts['var']
        getType = econtext._engine.getTypes().get
        for vname in self._f_varnames:
            has, val = var.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):
        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)


--- Added File ZPythonExpr.py in package Packages/Products/PageTemplates ---
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################

"""Old Zope-specific Python Expression Handler

Handler for Python expressions, using the pre-Python 2.1 restriction
machinery from PythonScripts.
"""

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

from AccessControl import getSecurityManager
from Products.PythonScripts.Guarded import _marker, \
     GuardedBlock, theGuard, safebin, WriteGuard, ReadGuard, UntupleFunction
from string import strip, split, join, replace, lstrip

from PythonExpr import PythonExpr

class PythonExpr(PythonExpr):
    def __init__(self, name, expr, engine):
        self.expr = expr = replace(strip(expr), '\n', ' ')
        blk = GuardedBlock('def f():\n return \\\n %s\n' % expr)
        if blk.errors:
            raise CompilerError, ('Python expression error:\n%s' %
                                  join(blk.errors, '\n') )
        guards = {'$guard': theGuard, '$write_guard': WriteGuard,
                  '$read_guard': ReadGuard, '__debug__': __debug__}
        self._f = UntupleFunction(blk.t, guards, __builtins__=safebin)
        self._get_used_names()

    def __call__(self, econtext):
        f = self._f
        f.func_globals.update(self._bind_used_names(econtext))
        
        # Execute the function in a new security context.
        template = econtext.contexts['template']
        security = getSecurityManager()
        security.addContext(template)
        try:
            __traceback_info__ = self.expr
            return f()
        finally:
            security.removeContext(template)

class _SecureModuleImporter:
    __allow_access_to_unprotected_subobjects__ = 1
    def __getitem__(self, module):
        mod = safebin['__import__'](module)
        path = split(module, '.')
        for name in path[1:]:
            mod = getattr(mod, name)
        return mod

from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
def validate(accessed, container, name, value, dummy):
    return getSecurityManager().validate(accessed, container, name, value)
def call_with_ns(f, ns, arg=1):
    td = TemplateDict()
    td.validate = validate
    td.this = None
    td._push(ns['request'])
    td._push(InstanceDict(ns['here'], td))
    td._push(ns['var'])
    try:
        if arg==2:
            return f(None, td)
        else:
            return f(td)
    finally:
        td._pop(3)

--- Added File ZRPythonExpr.py in package Packages/Products/PageTemplates ---
##############################################################################
# 
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# 
# Copyright (c) Digital Creations.  All rights reserved.
# 
# This license has been certified as Open Source(tm).
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions in source code must retain the above copyright
#    notice, this list of conditions, and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions, and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 
# 3. Digital Creations requests that attribution be given to Zope
#    in any manner possible. Zope includes a "Powered by Zope"
#    button that is installed by default. While it is not a license
#    violation to remove this button, it is requested that the
#    attribution remain. A significant investment has been put
#    into Zope, and this effort will continue if the Zope community
#    continues to grow. This is one way to assure that growth.
# 
# 4. All advertising materials and documentation mentioning
#    features derived from or use of this software must display
#    the following acknowledgement:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    In the event that the product being advertised includes an
#    intact Zope distribution (with copyright and license included)
#    then this clause is waived.
# 
# 5. Names associated with Zope or Digital Creations must not be used to
#    endorse or promote products derived from this software without
#    prior written permission from Digital Creations.
# 
# 6. Modified redistributions of any form whatsoever must retain
#    the following acknowledgment:
# 
#      "This product includes software developed by Digital Creations
#      for use in the Z Object Publishing Environment
#      (http://www.zope.org/)."
# 
#    Intact (re-)distributions of any official Zope release do not
#    require an external acknowledgement.
# 
# 7. Modifications are encouraged but must be packaged separately as
#    patches to official Zope releases.  Distributions that do not
#    clearly separate the patches from the original work must be clearly
#    labeled as unofficial distributions.  Modifications which do not
#    carry the name Zope may be packaged in any form, as long as they
#    conform to all of the clauses above.
# 
# 
# Disclaimer
# 
#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.
# 
# 
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations.  Specific
# attributions are listed in the accompanying credits file.
# 
##############################################################################

"""Zope-specific Python Expression Handler

Handler for Python expressions that uses the RestrictedPython package.
"""

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

from AccessControl import full_read_guard, full_write_guard, \
     safe_builtins, getSecurityManager
from RestrictedPython import compile_restricted_eval
from string import strip, split, join, replace, lstrip

from PythonExpr import PythonExpr

class PythonExpr(PythonExpr):
    _globals = {'__debug__': __debug__,
                '__builtins__': safe_builtins,
                '_read_': full_read_guard,
                '_write_': full_write_guard,}
    def __init__(self, name, expr, engine):
        self.expr = expr = replace(strip(expr), '\n', ' ')
        code, err, warn, use = compile_restricted_eval(expr, str(self))
        if err:
            raise CompilerError, ('Python expression error:\n%s' %
                                  join(err, '\n') )
        self._f_varnames = use.keys()
        self._code = code
        
    def __call__(self, econtext):
        code = self._code
        g = self._bind_used_names(econtext)
        g.update(self._globals)
        
        # Execute the function in a new security context.
        template = econtext.contexts['template']
        security = getSecurityManager()
        security.addContext(template)
        try:
            __traceback_info__ = self.expr
            return eval(code, g, {})
        finally:
            security.removeContext(template)

class _SecureModuleImporter:
    __allow_access_to_unprotected_subobjects__ = 1
    def __getitem__(self, module):
        mod = safe_builtins['__import__'](module)
        path = split(module, '.')
        for name in path[1:]:
            mod = getattr(mod, name)
        return mod

from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
def call_with_ns(f, ns, arg=1):
    td = TemplateDict()
    td.this = None
    td._push(ns['request'])
    td._push(InstanceDict(ns['here'], td, full_read_guard))
    td._push(ns['var'])
    try:
        if arg==2:
            return f(None, td)
        else:
            return f(td)
    finally:
        td._pop(3)

--- Updated File Expressions.py in package Packages/Products/PageTemplates --
--- Expressions.py	2001/05/21 16:54:14	1.13
+++ Expressions.py	2001/05/22 18:47:33	1.14
@@ -86,7 +86,7 @@
 """Page Template Expression Engine
 
 Page Template-specific implementation of TALES, with handlers
-for Python expressions, Python string literals, and paths.
+for Python expressions, string literals, and paths.
 """
 
 __version__='$Revision$'[11:-2]
@@ -113,28 +113,18 @@
     reg('string', StringExpr)
     reg('python', PythonExpr)
     reg('not', NotExpr)
-    reg('import', ImportExpr)
 
 if sys.modules.has_key('Zope'):
+    import AccessControl
     from AccessControl import getSecurityManager
-    from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
-    def validate(accessed, container, name, value, dummy):
-        return getSecurityManager().validate(accessed, container, name, value)
-    def call_with_ns(f, ns, arg=1):
-        td = TemplateDict()
-        td.validate = validate
-        td.this = None
-        td._push(ns['request'])
-        td._push(InstanceDict(ns['here'], td))
-        td._push(ns['var'])
-        try:
-            if arg==2:
-                return f(None, td)
-            else:
-                return f(td)
-        finally:
-            td._pop(3)
+    if hasattr(AccessControl, 'full_read_guard'):
+        from ZRPythonExpr import PythonExpr, _SecureModuleImporter, \
+             call_with_ns
+    else:
+        from ZPythonExpr import PythonExpr, _SecureModuleImporter, \
+             call_with_ns
 else:
+    from PythonExpr import getSecurityManager, PythonExpr
     def call_with_ns(f, ns, arg=1):
         if arg==2:
             return f(None, ns)
@@ -279,114 +269,6 @@
     def __repr__(self):
         return '<NotExpr %s>' % `self._s`
 
-
-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)
-
-if sys.modules.has_key('Zope'):
-    from AccessControl import getSecurityManager
-    from Products.PythonScripts.Guarded import _marker, \
-      GuardedBlock, theGuard, safebin, WriteGuard, ReadGuard, UntupleFunction
-
-    class PythonExpr:
-        def __init__(self, name, expr, engine):
-            self.expr = expr = replace(strip(expr), '\n', ' ')
-            blk = GuardedBlock('def f():\n return %s\n' % expr)
-            if blk.errors:
-                raise CompilerError, ('Python expression error:\n%s' %
-                                      join(blk.errors, '\n') )
-            guards = {'$guard': theGuard, '$write_guard': WriteGuard,
-                      '$read_guard': ReadGuard, '__debug__': __debug__}
-            self._f = UntupleFunction(blk.t, guards, __builtins__=safebin)
-            self._f_varnames = vnames = []
-            for vname in self._f.func_code.co_names:
-                if vname[0] not in '$_':
-                    vnames.append(vname)
-
-        def __call__(self, econtext):
-            f = self._f
-
-            # Bind template variables
-            var = econtext.contexts['var']
-            getType = econtext._engine.getTypes().get
-            for vname in self._f_varnames:
-                has, val = var.has_get(vname)
-                if not has:
-                    has = val = getType(vname)
-                    if has:
-                        val = ExprTypeProxy(vname, val, econtext)
-                if has:
-                    f.func_globals[vname] = val
-
-            # Execute the function in a new security context.
-            template = econtext.contexts['template']
-            security = getSecurityManager()
-            security.addContext(template)
-            try:
-                __traceback_info__ = self.expr
-                return f()
-            finally:
-                security.removeContext(template)
-
-        def __str__(self):
-            return 'Python expression "%s"' % self.expr
-        def __repr__(self):
-            return '<PythonExpr %s>' % self.expr
-
-else:
-    class getSecurityManager:
-        '''Null security manager'''
-        def validate(self, *args, **kwargs):
-            return 1
-        validateValue = validate
-    _marker = []
-
-    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') % sys.exc_info()[:2]
-            self._f_varnames = vnames = []
-            for vname in self._f.func_code.co_names:
-                if vname[0] not in '$_':
-                    vnames.append(vname)
-
-        def __call__(self, econtext):
-            f = self._f
-
-            # Bind template variables
-            var = econtext.contexts['var']
-            for vname in self._f_varnames:
-                has, val = var.has_get(vname)
-                if has:
-                    f.func_globals[vname] = val
-
-            return f()
-
-        def __str__(self):
-            return 'Python expression "%s"' % self.expr
-        def __repr__(self):
-            return '<PythonExpr %s>' % self.expr
-    
-class ImportExpr:
-    def __init__(self, name, expr, engine):
-        self._s = expr
-    def __call__(self, econtext):
-        return safebin['__import__'](self._s)
-    def __repr__(self):
-        return '<ImportExpr %s>' % `self._s`
 
 def restrictedTraverse(self, path):
 

--- Updated File PageTemplateFile.py in package Packages/Products/PageTemplates --
--- PageTemplateFile.py	2001/05/11 23:44:51	1.1
+++ PageTemplateFile.py	2001/05/22 18:47:33	1.2
@@ -92,7 +92,7 @@
 import os, AccessControl, Acquisition, sys
 from Globals import package_home, DevelopmentMode
 from zLOG import LOG, ERROR, INFO
-from string import join, strip, rstrip, split, replace, lower
+from string import join, strip, rstrip, split, lower
 from Shared.DC.Scripts.Script import Script, BindingsUI
 from Shared.DC.Scripts.Signature import FuncCode
 from AccessControl import getSecurityManager
@@ -173,6 +173,10 @@
                 return
         self.pt_edit(open(self.filename), None)
         self._cook()
+        if self._v_errors:
+            LOG('PageTemplateFile', ERROR, 'Error in template',
+                join(self._v_errors, '\n'))
+            return
         self._v_last_read = mtime
 
     def document_src(self, REQUEST=None, RESPONSE=None):

--- Updated File ZopePageTemplate.py in package Packages/Products/PageTemplates --
--- ZopePageTemplate.py	2001/05/18 18:12:09	1.9
+++ ZopePageTemplate.py	2001/05/22 18:47:33	1.10
@@ -302,15 +302,7 @@
 d = ZopePageTemplate.__dict__
 d['source.xml'] = d['source.html'] = Src()
 
-from Products.PythonScripts.Guarded import safebin
-class _SecureModuleImporter:
-    __allow_access_to_unprotected_subobjects__ = 1
-    def __getitem__(self, module):
-        mod = safebin['__import__'](module)
-        path = split(module, '.')
-        for name in path[1:]:
-            mod = getattr(mod, name)
-        return mod
+from Expressions import _SecureModuleImporter
 SecureModuleImporter = _SecureModuleImporter()
 
 # Product registration and Add support