commit-gnue
[Top][All Lists]
Advanced

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

r5955 - trunk/gnue-appserver/src


From: johannes
Subject: r5955 - trunk/gnue-appserver/src
Date: Thu, 8 Jul 2004 12:59:36 -0500 (CDT)

Author: johannes
Date: 2004-07-08 12:59:35 -0500 (Thu, 08 Jul 2004)
New Revision: 5955

Modified:
   trunk/gnue-appserver/src/geasGsdGen.py
   trunk/gnue-appserver/src/geasRpcServer.py
Log:
geasGsdGen is now used to export arbitrary class data into a gsd file, 
maintaining the proper order to avoid constraint violations.


Modified: trunk/gnue-appserver/src/geasGsdGen.py
===================================================================
--- trunk/gnue-appserver/src/geasGsdGen.py      2004-07-08 13:50:36 UTC (rev 
5954)
+++ trunk/gnue-appserver/src/geasGsdGen.py      2004-07-08 17:59:35 UTC (rev 
5955)
@@ -24,44 +24,55 @@
 import sys
 
 from gnue.common.apps import i18n
+from gnue.common.schema import Objects
 from gnue.common.apps.GClientApp import *
+from gnue.common.datasources import GDataSource
 
 from gnue.appserver import VERSION
 from gnue.appserver.geasSessionManager import geasSessionManager
-from gnue.appserver.classrep.SchemaSupport import *
-from gnue.appserver.classrep.Namespace import *
 
+
 # =============================================================================
-# Generate GNUe Schema Definition files from appservers class repository 
+# Exceptions 
 # =============================================================================
 
+class CircularReferenceError (gException):
+  def __init__ (self):
+    msg = _("Classes have circular or unresolveable references")
+    gException.__init__ (self, msg)
+
+
+# =============================================================================
+# Generate GNUe Schema Definition files
+# =============================================================================
+
 class geasGsdGen (GClientApp):
 
   NAME    = "geasGsdGen"
   VERSION = VERSION
   COMMAND = "gnue-gsdgen"
   USAGE   = "%s %s" % (GClientApp.USAGE, " [classname] [classname] [...]")
-  SUMMARY = _(
-"""A tool to create GNUe Schema Definition (gsd) files from 
-the appservers class repository.""")
+  SUMMARY = _("A tool to dump data from a database into a GNUe Schema "
+              "Definition (gsd) file.")
 
-  COMMAND_OPTIONS = [
 
-    ['output', 'o', 'output-file', True, None, "file",
-      _('Name of the resulting gsd-file')],
 
-    ['export', 'e', 'export', True, None, "type",
-      _('What to export: "schema", "data", "both". Default is "both"')],
-
-    ['database', None, 'database', 1, None, 'name', _(
-"""Set the Database to use for loading and storing data to <name>.
-gnue-appserver will search for it in connections.conf.""")]]
-
   # ---------------------------------------------------------------------------
   # Constructor
   # ---------------------------------------------------------------------------
+
   def __init__ (self, connections = None):
 
+    self.addCommandOption ('database', 'd', argument = 'database',
+        help = _("Set the Database to use for data to <name>. gnue-appserver "
+                 "will search for it in connections.conf."))
+
+    self.addCommandOption ('output', 'o', argument = 'file',
+        help = _("Name of the resulting gsd-file"))
+
+    self.addCommandOption ('system', 's', default = False,
+        help = _("If flag is set include system classes ('gnue_*')"))
+
     ConfigOptions = {}
 
     GClientApp.__init__ (self, connections, 'appserver', ConfigOptions)
@@ -71,38 +82,262 @@
     # overwrite configuration settings by command line parameters
     cparser = self.configurationManager._loadedConfigs ['gnue.conf']
 
-    if self.OPTIONS ["database"] != None:
+    if self.OPTIONS ["database"] is not None:
       cparser.set ('appserver', 'database', self.OPTIONS ["database"])
 
-  # ---------------------------------------------------------------------------
-  # Print a message to stdout, if output is sent to a file
-  # ---------------------------------------------------------------------------
-  def __message (self, text):
-    if self.__filename:
-      print text
 
   # ---------------------------------------------------------------------------
   # Main program
   # ---------------------------------------------------------------------------
+
   def run (self):
+    if self.OPTIONS ['output'] is None:
+      self.handleStartupError (_("No output file specified."))
+
     self.__filename = self.OPTIONS ['output']
-    self.__type     = self.OPTIONS ['export']
     args = [unicode (a, i18n.encoding) for a in self.ARGUMENTS]
 
-    self.__message (_("Loading class repository ..."))
-    sm = geasSessionManager (self.connections)
-    sSupport = SchemaSupport (sm.modules, sm.classes)
+    print _("Loading class repository ...")
 
-    self.__message (_("Generating schema definition ..."))
+    self.sm = geasSessionManager (self.connections)
+
+    print _("Generating schema definition ...")
+
     try:
-      sSupport.writeSchemaToFile (self.__filename, args, self.__type)
+      self._createClassList (args)
 
+      schema = Objects.GSSchema ()
+      schema.title   = 'Appserver Data Dump'
+      schema.author  = self.COMMAND
+      schema.version = '1.0'
+      self._data = Objects.GSData (schema)
+
+      for classname in self.exports:
+        self._exportClass (classname)
+
+      dest = open (self.__filename, "w")
+      dest.write ("""<?xml version="1.0" encoding="UTF-8"?>\n""")
+      dest.write (schema.dumpXML ().encode ('utf-8'))
+      dest.close ()
+
+
     except Exception:
       msg = "%s\n" % str (sys.exc_info () [1])
       sys.stderr.write (msg)
       sys.exit (1)
 
-    self.__message (_("Generation run complete."))
+    print _("Generation run complete.")
 
+
+  # ---------------------------------------------------------------------------
+  # Create a list of classes to be exported
+  # ---------------------------------------------------------------------------
+
+  def _createClassList (self, args):
+    """
+    This function creates a sequence of classnames to be dumped. This sequence
+    is in a proper order so no constraint-violations should occur.
+    """
+    if not len (args):
+      for c in self.sm.classes.values ():
+        if not self.OPTIONS ['system'] and c.module.fullName == 'gnue':
+          continue
+
+        args.append (c.fullName)
+
+    self.classes = {}
+    for cName in args:
+      self._addClass (cName)
+
+    self.exports = []
+    res = self._shrinkList ()
+
+    while len (res):
+      self.exports.extend (res)
+      res = self._shrinkList ()
+
+
+
+  # ---------------------------------------------------------------------------
+  # add a class to the classlist and iterate over all references
+  # ---------------------------------------------------------------------------
+
+  def _addClass (self, className):
+    """
+    This function adds a class to the list of classes respecting all
+    dependencies given by class-references.
+    """
+    cDef = self.sm.classes [className]
+    if not self.classes.has_key (className):
+      self.classes [className] = []
+
+    for p in cDef.properties.values ():
+      if p.isReference:
+        refClass = p.referencedClass.fullName
+        if not refClass in self.classes [className]:
+          self.classes [className].append (refClass)
+        self._addClass (refClass)
+
+
+  # ---------------------------------------------------------------------------
+  # Return all items from the classlist, which have no dependencies
+  # ---------------------------------------------------------------------------
+
+  def _shrinkList (self):
+    """
+    This function returns a sequence of all classes without any dependencies.
+    If no such classes were found but there are still classes in the dictionary
+    a CircularReferenceError will be raised.
+    """
+    result = []
+
+    for (classname, refs) in self.classes.items ():
+      if not len (refs):
+        result.append (classname)
+
+        for ref in self.classes.values ():
+          if classname in ref:
+            ref.remove (classname)
+
+        del self.classes [classname]
+
+    if not len (result) and len (self.classes.keys ()):
+      raise CircularReferenceError
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Export data of a given class
+  # ---------------------------------------------------------------------------
+
+  def _exportClass (self, className):
+    """
+    Create a TableData object tree with all data of the given class.
+    """
+    cDef  = self.sm.classes [className]
+    print u_("Exporting data of class '%s' ...") % className
+
+    # Prepare the tabledata- and it's definition tags
+    table = Objects.GSTableData (self._data)
+    table.name      = "%s_dump" % cDef.table
+    table.tablename = cDef.table
+
+    columns = Objects.GSDefinition (table)
+
+    fieldlist = []
+    for prop in cDef.properties.values ():
+      if prop.isCalculated: continue
+
+      column = Objects.GSColumn (columns)
+      column.field = prop.column
+      column.type  = prop.dbFullType
+
+      fieldlist.append (prop.column)
+
+    rows = Objects.GSRows (table)
+
+    # Create a datasource for the given class
+    attrs = {'name'    : "dts_%s" % cDef.table,
+             'database': self.sm._internalSession.database,
+             'table'   : cDef.table}
+    dts = GDataSource.DataSourceWrapper ( \
+        connections = self.connections,
+        attributes  = attrs,
+        fields      = fieldlist,
+        unicodeMode = True)
+
+    rs = dts.createResultSet ()
+
+    rec = rs.firstRecord ()
+
+    while rec is not None:
+      row = Objects.GSRow (rows)
+
+      for prop in cDef.properties.values ():
+        if prop.isCalculated: continue
+
+        data = rec.getField (prop.column)
+        if data is not None:
+          value = Objects.GSValue (row)
+          value.field = prop.column
+          if prop.column == 'gnue_id':
+            value.key = True
+          GParserHelpers.GContent ( \
+            value, self.__nativeToString (data, prop.dbFullType))
+
+      rec = rs.nextRecord ()
+
+
+
+  # ---------------------------------------------------------------------------
+  # Convert a native python object to a string according to datatype
+  # ---------------------------------------------------------------------------
+
+  def __nativeToString (self, native, datatype):
+    """
+    This function creates a unicode string to be used in a <value>-tag of a GSD
+    file.  The native python object will be treated and theirfore converted as
+    'datatype'.
+    """
+    if datatype [:6] == "string" or datatype == "id":
+      checktype (native, [types.NoneType, types.UnicodeType])
+
+      if native is None:
+        return u''
+
+      if isinstance (native, types.UnicodeType):
+        return native
+
+    elif datatype [:6] == "number":
+      if native is None:
+        return "0"
+      else:
+        return str (native)
+
+
+    elif datatype == "boolean":
+      if native is not None and native:
+        return u'TRUE'
+      else:
+        return u'FALSE'
+
+
+    elif datatype == "date":
+      if isinstance (native, mx.DateTime.DateTimeType):
+        return native.date
+
+      else:
+        raise ValueError (u_("%s is not a valid date object") % repr (native))
+
+
+    elif datatype == "time":
+      if isinstance (native, mx.DateTime.DateTimeType):
+        return native.time
+
+      elif isinstance (native, mx.DateTime.DateTimeDeltaType):
+        return str (native)
+
+      else:
+        raise ValueError (u_("%s is not a valid time object") % repr (native))
+
+
+    elif datatype == "datetime":
+      if isinstance (native, mx.DateTime.DateTimeType):
+        return str (native)
+
+      else:
+        raise ValueError (u_("%s is not a valid datetime object") % \
+                                    repr (native))
+
+    else:
+      # must be reference property
+      return native.gnue_id
+
+
+# =============================================================================
+# Main program
+# =============================================================================
+
 if __name__ == "__main__":
   geasGsdGen ().run ()

Modified: trunk/gnue-appserver/src/geasRpcServer.py
===================================================================
--- trunk/gnue-appserver/src/geasRpcServer.py   2004-07-08 13:50:36 UTC (rev 
5954)
+++ trunk/gnue-appserver/src/geasRpcServer.py   2004-07-08 17:59:35 UTC (rev 
5955)
@@ -156,7 +156,7 @@
 
   def htmlStatus (self):
     out = "<HTML><HEAD></HEAD><BODY>"
-    out += _("Status: %s Sessions opened") % self.sm._sessNo 
+    out += _("Status: %s Sessions opened") % self.sm._sessNo
     out += "</BODY></HTML>"
     return out
 





reply via email to

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