[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r5955 - trunk/gnue-appserver/src,
johannes <=