commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

r5518 - in trunk/gnue-common/src/logic: . adapters adapters/ECMAscript


From: johannes
Subject: r5518 - in trunk/gnue-common/src/logic: . adapters adapters/ECMAscript
Date: Fri, 26 Mar 2004 03:47:33 -0600 (CST)

Author: johannes
Date: 2004-03-26 03:47:32 -0600 (Fri, 26 Mar 2004)
New Revision: 5518

Added:
   trunk/gnue-common/src/logic/adapters/
   trunk/gnue-common/src/logic/adapters/python.py
Removed:
   trunk/gnue-common/src/logic/adapters/python/
Modified:
   trunk/gnue-common/src/logic/adapters/Base.py
   trunk/gnue-common/src/logic/adapters/ECMAscript/Adapter.py
Log:
Restructuring of language engine stuff (to be continued ...)


Copied: trunk/gnue-common/src/logic/adapters (from rev 5517, 
trunk/gnue-common/src/logic/language)

Modified: trunk/gnue-common/src/logic/adapters/Base.py
===================================================================
--- trunk/gnue-common/src/logic/language/Base.py        2004-03-26 00:57:14 UTC 
(rev 5517)
+++ trunk/gnue-common/src/logic/adapters/Base.py        2004-03-26 09:47:32 UTC 
(rev 5518)
@@ -16,150 +16,183 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place
 # - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2003-2004 Free Software Foundation
+# Copyright 2001-2004 Free Software Foundation
 #
-#
-# FILE:
-# Base.py
-#
-# DESCRIPTION:
-# Provides a way to execute arbitrary code in a given environment
-#
-# NOTES:
-#
+# $Id: $
 
-from gnue.common.logic.NamespaceCore import NamespaceFunction, NamespaceElement
-from gnue.common.utils.FileUtils import dyn_import
+import sys
+import traceback
+import string
 
-######
-#
-#  We have three types of classes to access:
-#
-#    LanguageEngine: the Language Engine, which has to be loaded just once
-#                    (it can possibly loaded twice if more security is needed)
-#
-#    ExecutionContext:  Environmet where the code is executed.
-#                       if you need to reload/change global values just
-#                       create a new context
-#
-#    VirtualMethod:  A method of an object which provides an pointer to
-#                    the execution context (python: self, ECMAscript: this)
-#
-#    VirtualAttribute:  An attribute of an object
-#
+from gnue.common.logic.language import ImplementationError
+from gnue.common.logic.NamespaceCore import NamespaceElement, NamespaceFunction
 
-class LangIfError(StandardError):
-  pass
 
-class LangIfCompileError(LangIfError):
-  pass
+# =============================================================================
+# Base class for LanguageAdapters
+# =============================================================================
 
-class LangIfRuntimeError(LangIfError):
-  pass
+class BaseLanguageAdapter:
+  """
+  This is the base class for language adapters. A language adapter has to
+  provide a public function for creation of new execution contexts.
+  """
 
-class LanguageEngine:
-  def __init__(self):
-    pass
+  # ---------------------------------------------------------------------------
+  # Create and return a new execution context
+  # ---------------------------------------------------------------------------
 
-  def createNewContext(self):
-    return ExecutionContext(None)
+  def createNewContext (self):
+    """
+    Abstract: Create a new execution context.
+    """
+    raise ImplementationError, (self.__class__, 'createNewContext ()')
 
-class ExecutionContext:
-  
-  def __init__(self, runtime):
-    self._runtime=runtime
-    self._shortname   = "unknown_executioncontext"
-    self._description = "There is no description provided."
 
-  ######
-  #
-  #  Namespace creation
-  #
-  #  add python objects, procedures and attributes to the global namespace
-  #
 
-  # helper function to reuse the GObj Namespace, 
-  # define global namespace ('global' directive in python)
-  def defineNamespace(self, ns, globalns=0):
-    for name in ns.keys():
-      if name!=None:
-        # just add Namespace elements/functions
-        if isinstance(ns[name], NamespaceFunction):
-          self.bindFunction(name, ns[name])
-          
-        if isinstance(ns[name], NamespaceElement):
-          self.bindObject(name, ns[name])
+# =============================================================================
+# Base class for execution contexts
+# =============================================================================
 
-  def bindObject(self, name, object, klass=None):
-    pass
+class BaseExecutionContext:
+  """
+  An execution context provides an environment where code can be transformed
+  and executed.
+  """
 
-  def bindFunction(self, name, object):
-    pass
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
 
-  #####
-  #
-  #  build virtual methods, attributs and functions and add to the namespace
-  #
-  
-  def buildMethod(self, name, code, parameter):
-    # name has to be the name of a global accesible object
-    return VirtualMethod(self, name, code, parameter)
-  
-  def buildAttribute(self, name, value):
-    # name has to be the name of a global accesible object
-    return VirtualAttribute(self, name, value)
+  def __init__ (self, runtime = None):
+    self._runtime    = runtime
+    self.shortname   = "unknown_executioncontext"
+    self.description = "There is no description provided"
 
-  def buildFunction(self, name, code, parameter):
-    return VirtualFunction(self, name, code, parameter)
 
-  #####
-  #
-  # a possibility to set Description o
-  #
+  # ---------------------------------------------------------------------------
+  # Merge a namespace into the execution contexts namespace
+  # ---------------------------------------------------------------------------
 
-  def setDescription(self, shortname, description):
-    self._shortname   = shortname
-    self._description = description
+  def defineNamespace (self, addNS, asGlobal = False):
+    """
+    Merge the given namespace @addNS into the execution context. This function
+    is doing this using bindFunction () and bindObject () depeding on the
+    namespace elements type.
+    """
+    for (name, value) in addNS.items ():
+      if name is not None:
+        if isinstance (value, NamespaceFunction):
+          self.bindFunction (name, value, asGlobal)
 
+        if isinstance (value, NamespaceElement):
+          self.bindObject (name, value, asGlobal)
+
+
+  # ---------------------------------------------------------------------------
+  # Bind an object into the contexts namespace using the given name
+  # ---------------------------------------------------------------------------
+
+  def bindObject (self, name, aObject, asGlobal = False):
+    """
+    Abstract: A descendant overrides this function to bind a given object into
+    the local or global namespace.
+    """
+    raise ImplementationError, (self.__class__, 'bindObject ()')
+
+
+  # ---------------------------------------------------------------------------
+  # Bind a function into the contexts namespace using the given name
+  # ---------------------------------------------------------------------------
+
+  def bindFunction (self, name, aFunction, asGlobal = False):
+    """
+    Abstract: A descendant overrides this function to bind a given function 
+    with into the local or global namespace.
+    """
+    raise ImplementationError, (self.__class__, 'bindFunction ()')
+
+
+  # ---------------------------------------------------------------------------
+  # Create a new function instance 
+  # ---------------------------------------------------------------------------
+
+  def buildFunction (self, name, code, parameters = {}):
+    """
+    Abstract: Create a new instance of a virtual function and prepare it's 
+    code.
+    """
+    raise ImplementationError, (self.__class__, 'buildFunction ()')
+
+
+
+# =============================================================================
+# Base class of a virtual function
+# =============================================================================
+
 class VirtualFunction:
-  def __init__(self, context, name, code, parameter):
-    self._code    = code
-    self._context = context
-    self._name    = name
-    self._parameter= parameter
-    
-  def compile(self):
-    pass
+  """
+  This is the base class of virtual functions. Such an instance must be able to
+  prepare a sourcecode and to execute it.
+  """
 
-  def execute(self, *args, **params):
-    pass
-  
-  def __call__(self, *args, **params):
-    return apply(self.execute,args,params)
-  
-class VirtualMethod(VirtualFunction):
-  def rebind(self, obj, name):
-    pass
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
 
-class VirtualAttribute:
-  def __init__(self, context, name, value):
-    self._context = context
-    self._name    = name
-    self._value    = value
-    
-  def get(self):
-    return self._value
+  def __init__ (self, context, name, code, parameters):
+    self._context    = context
+    self._name       = name
+    self._code       = code
+    self._parameters = parameters
+    self._prepare ()
 
-  def set(self,value):
-    self._value = value
 
+  # ---------------------------------------------------------------------------
+  # Execute the function using the given arguments
+  # ---------------------------------------------------------------------------
 
-def loadLanguageEngine(language):
-  try:
-    adapter = dyn_import('gnue.common.logic.language.%s.Adapter' \
-                         % language)
-  except ImportError:
-    GDebug.printMesg(0, "Language %s not implemented" % self.language)
-    sys.exit()
+  def execute (self, *args, **params):
+    """
+    Execute the function using the given arguments. A descendant must override
+    this function.
+    """
+    raise ImplementationError, (self.__class__, 'execute ()')
 
-  return adapter.LanguageEngine()
+
+
+  # ---------------------------------------------------------------------------
+  # redirect a call of an instance to the execute () function.
+  # ---------------------------------------------------------------------------
+
+  def __call__ (self, *args, **params):
+    """
+    If an instance gets called, redirect this call to the execute () function.
+    """
+    return apply (self.execute, args, params)
+
+
+  # ---------------------------------------------------------------------------
+  # Prepare the given source code
+  # ---------------------------------------------------------------------------
+
+  def _prepare (self):
+    """
+    This function gets called on constructing an instance at could be used by a
+    descendant to prepare the sourcecode, i.e. compile it.
+    """
+    pass
+
+
+  # ---------------------------------------------------------------------------
+  # Put info for current exception into a string
+  # ---------------------------------------------------------------------------
+
+  def _traceback (self, count):
+    """
+    Returns the complete traceback of the current exception as a string, where
+    the first @count lines of the traceback are hidden.
+    """
+    lines = traceback.format_exception (*sys.exc_info ())
+    del lines [1:count + 1]
+    return string.join (lines, '')


Property changes on: trunk/gnue-common/src/logic/adapters/Base.py
___________________________________________________________________
Name: svn:keywords
   + svn:Id

Modified: trunk/gnue-common/src/logic/adapters/ECMAscript/Adapter.py
===================================================================
--- trunk/gnue-common/src/logic/language/ECMAscript/Adapter.py  2004-03-26 
00:57:14 UTC (rev 5517)
+++ trunk/gnue-common/src/logic/adapters/ECMAscript/Adapter.py  2004-03-26 
09:47:32 UTC (rev 5518)
@@ -56,10 +56,10 @@
 
   # namespace creation (global namespace)
   #
-  def bindObject(self, name, object, klass=None):
-    if klass!=None:
-      self._cx.bind_class(klass)
-    self._cx.bind_object(name, object)
+  def bindObject (self, name, aObject, aClass = None):
+    if aClass != None:
+      self._cx.bind_class (aClass)
+    self._cx.bind_object (name, aObject)
 
   def bindFunction(self, name, object):
     self._cx.bind_callable(name, object)

Copied: trunk/gnue-common/src/logic/adapters/python.py (from rev 5517, 
trunk/gnue-common/src/logic/language/python/Adapter.py)
===================================================================
--- trunk/gnue-common/src/logic/language/python/Adapter.py      2004-03-26 
00:57:14 UTC (rev 5517)
+++ trunk/gnue-common/src/logic/adapters/python.py      2004-03-26 09:47:32 UTC 
(rev 5518)
@@ -0,0 +1,208 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2001-2004 Free Software Foundation
+#
+# $Id: $
+
+from string import join
+from copy import copy
+
+import gnue.common.logic.language
+from gnue.common.logic.language.adapters import Base
+
+# =============================================================================
+# Implementation of a language adapter for python
+# =============================================================================
+
+class LanguageAdapter (Base.BaseLanguageAdapter):
+  """
+  Implementation of a language engine for python
+  """
+
+  # ---------------------------------------------------------------------------
+  # Create a new execution context
+  # ---------------------------------------------------------------------------
+
+  def createNewContext (self):
+    """
+    Create a python execution context
+    """
+    return PythonExecutionContext ()
+
+
+# =============================================================================
+# Python Execution Context
+# =============================================================================
+
+class PythonExecutionContext (Base.BaseExecutionContext):
+  """
+  This class implements an ExecutionContext for Python.
+  """
+
+  # ---------------------------------------------------------------------------
+  # Constructor
+  # ---------------------------------------------------------------------------
+
+  def __init__ (self, runtime = None):
+    BaseExecutionContext.__init__ (self, runtime)
+
+    self._globalNS = {}
+    self._localNS  = {}
+
+
+  # ---------------------------------------------------------------------------
+  # Replace the local or global namespace
+  # ---------------------------------------------------------------------------
+
+  def defineNamespace (self, addNS, asGlobal = False):
+    """
+    This function replaces the local or global namespace with @addNS.
+    """
+    if asGlobal:
+      self._globalNS = addNS
+    else:
+      self._localNS = addNS
+
+
+  # ---------------------------------------------------------------------------
+  # Add an object to the namespace
+  # ---------------------------------------------------------------------------
+
+  def bindObject (self, name, aObject, asGlobal = False):
+    """
+    Add @aObject as @name to the local or global namespace.
+    """
+    if asGlobal:
+      self._globalNS [name] = aObject
+    else:
+      self._localNS [name] = aObject
+
+
+  # ---------------------------------------------------------------------------
+  # Add a function to the namespace
+  # ---------------------------------------------------------------------------
+
+  def bindFunction (self, name, aFunction, asGlobal = False):
+    """
+    Add @aFunction as @name to the local or global namespace.
+    """
+    if asGlobal:
+      self._globalNS [name] = aFunction
+    else:
+      self._localNS [name] = aFunction
+
+
+  # ---------------------------------------------------------------------------
+  # Create a function
+  # ---------------------------------------------------------------------------
+
+  def buildFunction (self, name, code, parameters = {}):
+    return PythonFunction (self, name, code, parameters)
+
+
+# =============================================================================
+# This class implements a virtual function using python
+# =============================================================================
+
+class PythonFunction (Base.VirtualFunction):
+  """
+  Implementation of a virtual function using Python.
+  """
+
+  # ---------------------------------------------------------------------------
+  # Prepare a python function
+  # ---------------------------------------------------------------------------
+
+  def _prepare (self):
+    """
+    Preparing a sourcecode for python means compiling. This function compiles
+    the code.
+    """
+    # if name has invalid characters, we won't use it as function name
+    if 1 in [c in self._name for c in " ."]:
+      self.funcName = "tempCode"
+    else:
+      self.funcName = self._name
+
+    paramlist = join (['__namespace'] + self._parameters.keys (), ", ")
+    text      = self._code.rstrip ()
+
+    try:
+      tabPos = text.find ('\t')
+      if tabPos > -1:
+        raise gException, \
+           u_("Sourcecode contains tab character at position %d") % tabPos
+
+
+      # get the indentation level of the first line
+      indent = 0
+      for line in text.splitlines ():
+        if len (line.strip ()) and line.lstrip () [0] != "#":
+          indent = len (line) - len (line.lstrip ())
+          break
+
+      # add the functions header
+      revisedCode  = "# -*- coding: utf-8 -*-\n"
+      revisedCode += "def %s (%s):\n" % (self.funcName, paramlist)
+
+      # add the namespace transformation loop
+      revisedCode += "  for __add in __namespace.keys ():\n"
+      revisedCode += "    exec '%s = __namespace [\"%s\"]' % (__add, __add)\n"
+      revisedCode += "  del __add, __namespace\n\n"
+
+      # add the original code
+      for line in text.splitlines ():
+        revisedCode += "  %s\n" % line [indent:]
+
+      # and finalize the function by a call to it
+      revisedCode += "  pass\n\n"
+      revisedCode += "__result = %s (%s)\n" % (self.funcName, paramlist)
+
+      self._compiled = compile (revisedCode.encode ('utf-8'),
+                     '<%s>' % self._context.shortname.encode ('utf-8'), 'exec')
+
+    except:
+      raise language.CompileError, self._traceback (1)
+          
+
+  # ---------------------------------------------------------------------------
+  # Execute the function
+  # ---------------------------------------------------------------------------
+
+  def execute (self, *args, **params):
+    """
+    This function creates a local namespace as a copy from the execution
+    context's local namespace, adds all parameters to this namespace and
+    executes the code.
+    """
+    try:
+      localNS = copy (self._context._localNS)
+      localNS.update (params)
+      localNS ['__namespace'] = localNS
+
+      exec self._compiled in self._context._globalNS, localNS
+
+      if localNS.has_key ('__result'):
+        return localNS ['__result']
+      else:
+        return None
+
+
+    except:
+      raise language.RuntimeError, self._traceback (1)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]