commit-gnue
[Top][All Lists]
Advanced

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

gnue/gnue-common/gnue/common GClientApp.py GCon...


From: Jason Cater
Subject: gnue/gnue-common/gnue/common GClientApp.py GCon...
Date: Tue, 15 May 2001 08:16:38 -0700

CVSROOT:        /home/cvs
Module name:    gnue
Changes by:     Jason Cater <address@hidden>    01/05/15 08:16:38

Modified files:
        gnue-common/gnue/common: GClientApp.py GConnections.py 
                                 GDataObjects.py GLoginHandler.py 

Log message:
        Umm, I wouldn't know where to begin. -- a lot of stuff?

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/gnue/common/GClientApp.py.diff?cvsroot=OldCVS&tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/gnue/common/GConnections.py.diff?cvsroot=OldCVS&tr1=1.2&tr2=1.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/gnue/common/GDataObjects.py.diff?cvsroot=OldCVS&tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/gnue/common/GLoginHandler.py.diff?cvsroot=OldCVS&tr1=1.1&tr2=1.2&r1=text&r2=text

Patches:
Index: gnue/gnue-common/gnue/common/GClientApp.py
diff -u gnue/gnue-common/gnue/common/GClientApp.py:1.4 
gnue/gnue-common/gnue/common/GClientApp.py:1.5
--- gnue/gnue-common/gnue/common/GClientApp.py:1.4      Fri May 11 18:42:55 2001
+++ gnue/gnue-common/gnue/common/GClientApp.py  Tue May 15 08:16:38 2001
@@ -250,6 +250,14 @@
       print "\nFor help, type:\n   %s --help\n" % (sys.argv[0])
       sys.exit()
 
+  # 
+  #  Set the login handler for this session
+  #
+  def setLoginHandler(self, loginHandler): 
+    if self.connections:
+      self.connections.loginHandler = loginHandler
+
+
   #
   #  Used when profiling 
   #
Index: gnue/gnue-common/gnue/common/GConnections.py
diff -u gnue/gnue-common/gnue/common/GConnections.py:1.2 
gnue/gnue-common/gnue/common/GConnections.py:1.3
--- gnue/gnue-common/gnue/common/GConnections.py:1.2    Fri May 11 18:42:55 2001
+++ gnue/gnue-common/gnue/common/GConnections.py        Tue May 15 08:16:38 2001
@@ -22,7 +22,8 @@
 # GConnections.py
 #
 # DESCRIPTION:
-# Class that loads connection definition files. 
+# Class that loads connection definition files and maintains 
+# database connections. 
 #
 # NOTES:
 #
@@ -33,17 +34,28 @@
 import os
 import os.path
 import urllib
+import string
 import GDebug
+import GDataObjects
+import GLoginHandler
+
 
 class NotFoundError (Error): 
+  # Raised if a requested connection name does not  
+  # exist in the Connections Definition File.
   pass
 
 class InvalidFormatError (Error): 
+  # Raised if the Connections Definition File is   
+  # in an unreadable format.
   pass
 
+
 class GConnections:
 
-  def __init__(self, location):     
+  def __init__(self, location, loginHandler=None):     
+
+    self._loginHandler = loginHandler
 
     #
     # This is an ugly hack to make the Python 1.5.2 ConfigParser
@@ -52,11 +64,12 @@
     #
     if (not ConfigParser.__dict__.has_key('readfp') and 
           ConfigParser.__dict__.has_key('_ConfigParser__read')): 
-      GDebug.printMesg(1,'[GConnections] Subclassing ConfigParser to support 
URL''s :(')
-      self.parser = _ConfigParser()
+      GDebug.printMesg(1,'Subclassing ConfigParser to support URL''s')
+      self._parser = _ConfigParser()
     else: 
-      self.parser = ConfigParser()
+      self._parser = ConfigParser()
 
+    GDebug.printMesg(1,'Conn File: "%s"' % location)
     drive = os.path.splitdrive(location) 
     if len(drive[0]):
       fileHandle = open(location,'r')
@@ -64,7 +77,7 @@
       fileHandle = urllib.urlopen(location)
 
     try: 
-      self.parser.readfp(fileHandle) 
+      self._parser.readfp(fileHandle) 
     except DuplicateSectionError: 
       raise InvalidFormatError, 'The file has duplicate source definitions.'
     except MissingSectionError: 
@@ -72,13 +85,21 @@
     except: 
       raise InvalidFormatError, 'The file cannot be parsed.'
 
-  def hasConnection(self, connection_name): 
-    return self.parser.has_section(connection_name)
+    self._openConnections = {}
+
+
+  def setLoginHandler(self, loginHandler): 
+    self._loginHandler = loginHandler
+
 
-  def get(self, connection_name, attribute, default=None): 
-    if self.parser.has_section(connection_name): 
+  def hasConnectionParameters(self, connection_name): 
+    return self._parser.has_section(connection_name)
+
+
+  def getConnectionParameter(self, connection_name, attribute, default=None):
+    if self._parser.has_section(connection_name): 
       try: 
-        return self.parser.get(connection_name, attribute)
+        return self._parser.get(connection_name, attribute)
       except: 
         return default
     else: 
@@ -88,28 +109,95 @@
   # Returns an dictionary of dictionaries describing all connections: 
   #  {connection name: {att name: value}}
   #
-  def getConnections(self): 
+  def getAllConnectionParameters(self): 
     rv = {}
-    for section in self.parser.sections(): 
+    for section in self._parser.sections(): 
        rv[section]={}
-       for att in self.parser.options(section): 
-         rv[section][att] = self.parser.get(section, att)
+       for att in self._parser.options(section): 
+         rv[section][att] = self._parser.get(section, att)
     return rv
 
   #
   # Returns a dictionary describing a connection: 
   #  {att name: value}
   #
-  def getConnection(self, connection_name): 
+  def getConnectionParameters(self, connection_name): 
     rv = {}
-    if self.parser.has_section(connection_name): 
-      for att in self.parser.options(connection_name): 
-        rv[att] = self.parser.get(connection_name, att)
+    if self._parser.has_section(connection_name): 
+      for att in self._parser.options(connection_name): 
+        rv[att] = self._parser.get(connection_name, att)
     else: 
        raise NotFoundError
 
     return rv
 
+
+  #
+  # Return a database provider object
+  #
+  def getDataObject(self, connection_name, connection_type): 
+    # This will throw a GConnections.NotFoundError if an unknown 
+    # connection name is specified.  The calling method should 
+    # catch this exception and handle it properly (exit w/message)
+    return _load_dbdriver(self.getConnectionParameter(connection_name, \
+        'provider'), connection_type, self)
+
+
+  #
+  # Get a data connection for a specified database
+  #
+  def setDataConnection(self, dataSource): 
+    connection_name = dataSource.database
+    dataObject = dataSource.getDataObject()
+    if self._openConnections.has_key(string.lower(connection_name)): 
+
+      # If a database connetion has already been established, use it
+      dataSource.getDataObject().setDataConnection(self._openConnections[ \
+                 string.lower(connection_name)])
+      GDebug.printMesg(5,'Reusing data connection to %s' % connection_name)
+
+    else: 
+      attempts = 4
+
+      GDebug.printMesg(5,'Getting new data connection to %s' % connection_name)
+
+      while attempts: 
+
+        try: 
+          # Ask the UI to prompt for our login data
+          loginData = self._loginHandler.getLogin(
+              [connection_name, 
self.getConnectionParameter(connection_name,'comment',''),
+               dataSource.getDataObject().getLoginFields()])
+
+          # Add the parameters from the Connections Definition File
+          loginData.update(self.getConnectionParameters(connection_name))
+
+          # Ask the data object to connect to the database
+          dataSource.getDataObject().connect(loginData)
+
+          # Save the newly opened connection for future datasources
+          self._openConnections[string.lower(connection_name)] = \
+              dataSource.getDataObject().getDataConnection()
+
+          # We're done!
+          attempts = 0
+
+        except GDataObjects.LoginError, error: 
+          # Oops, they must have entered an invalid user/password.  
+          # Those silly users.
+          attempts = attempts - 1
+
+          if not attempts: 
+            # Four times is plenty...
+            raise GDataObjects.LoginError, error
+
+        except GLoginHandler.UserCanceledLogin:
+          # Guess they changed their minds. Treat as a login error.
+          raise GDataObjects.LoginError, "User canceled the login request" 
+      
+
+
+
 #
 # This is an ugly hack to make the Python 1.5.2 ConfigParser
 # support reading its data from a file handle.  Later versions
@@ -118,4 +206,33 @@
 class _ConfigParser(ConfigParser):
   def readfp (self, fp): 
     self.__read(fp)
+
+
+
+
+#
+# Load the correct DBdriver from gnue/common/dbdrivers/*/
+#
+def _load_dbdriver(driver, type, connectionManager):
+
+  if sys.platform == 'win32':
+    os.putenv('PYTHONCASEOK','1')
+
+  dbdriver = __import__("dbdrivers/%s/DBdriver" % (driver))
+  try: 
+    dbdriver = __import__("dbdrivers/%s/DBdriver" % (driver))
+  except: 
+    raise GDataObjects.ProviderNotSupportedError, \
+       "No drivers found for provider '%s'" % driver
+
+  try: 
+    dd = dbdriver.supportedDataObjects[type]()
+    GDebug.printMesg (1,'Attaching to %s (%s)' % 
(driver,dd.__class__.__name__))
+    return dd
+  except KeyError: 
+    raise GDataObjects.ObjectTypeNotAvailableError, \
+       "DB Driver '%s' does not support source type '%s'" % (driver, type)
+
+
+
 
Index: gnue/gnue-common/gnue/common/GDataObjects.py
diff -u gnue/gnue-common/gnue/common/GDataObjects.py:1.3 
gnue/gnue-common/gnue/common/GDataObjects.py:1.4
--- gnue/gnue-common/gnue/common/GDataObjects.py:1.3    Fri May 11 14:59:04 2001
+++ gnue/gnue-common/gnue/common/GDataObjects.py        Tue May 15 08:16:38 2001
@@ -31,36 +31,68 @@
 
 import GDebug
 from string import lower
-import exceptions
 
-class DataObjectError(StandardError): 
+class LoginError(Exception): 
+  # Raised when invalid login user/pass was provided 
+  # Client should attempt to get better information and
+  # try again
   pass
 
-class ReadOnlyError(DataObjectError): 
+class ConnectError(Exception): 
+  # Raised when connection data is invalid (e.g., host not found, etc).
+  # Client should probably not attempt to relogin.  Exit gracefully
+  # with a reason.
+  pass 
+
+class ProviderNotSupportedError(Exception): 
+  # Raised when a datasource type is requested that the dbdriver 
+  # does not support (e.g., not all dbdrivers support raw sql mode.)
+  pass 
+
+class ObjectTypeNotAvailableError(Exception): 
+  # Raised when a datasource type is requested that the dbdriver 
+  # does not support (e.g., not all dbdrivers support raw sql mode.)
+  pass 
+
+class ReadOnlyError(Exception): 
+  # Raised when an attempt is made to update a read-only data object.
   pass
 
+
+
 ###########################################################
 #
 # 
 # 
 ###########################################################
-class DataSource: 
+class DataObject: 
 
   def __init__(self): 
-    self._detailSources = []
+    self._detailObjects = []
     self._dataConnection = None
     self._resultSetClass = ResultSet
 
   def createResultSet(self, conditions={}, readOnly=0): 
     pass
 
-  def addDetailDataSource(self, ds): 
-    GDebug.printMesg (1,"DataSource: adding a master/detail relationship")
-    self._detailSources.append (ds)
+  def addDetailDataObject(self, ds): 
+    GDebug.printMesg (1,"DataObject: adding a master/detail relationship")
+    self._detailObjects.append (ds)
+
+  # Return a list of necessary login fields (e.g., user/pass). 
+  # Each list item is another list of ["field label", isPassword?]
+  def getLoginFields(self): 
+    return []
 
   def connect(self, connectData={}):
     pass
 
+  def setDataConnection(self, connection): 
+    self._dataConnection = connection
+
+  def getDataConnection(self): 
+    return self._dataConnection
+
   def commit(self):
     pass
 
@@ -83,6 +115,7 @@
      self._defaultValues = defaultValues
      self._masterRecordSet = masterRecordSet
      self._readonly = 0
+     self._boundFields = {}
 
      self.current = None
 
@@ -167,7 +200,7 @@
       return 1
 
 
-  # Returns 1=DataSource has uncommitted changes 
+  # Returns 1=DataObject has uncommitted changes 
   def isPending(self):
     isPending = 0 
     for rec in (self._cachedRecords):
@@ -190,9 +223,14 @@
 
 
   # 
-  def notifyDetailSources(self):
+  def notifyDetailObjects(self):
     pass
-  
+
+
+  # Returns 1=Field is bound to a database field
+  def isFieldBound(self, fieldName):
+    return self._boundFields.has_key(lower(fieldName))
+
 
   ###
   ### Methods below should be overridden by Vendor Specific functions
@@ -217,7 +255,7 @@
 class RecordSet: 
 
   def __init__(self, parent, initialData={}, dbIdentifier=None, 
defaultData={}): 
-    self._detailSources = []
+    self._detailObjects = []
     self._dbIdentifier = dbIdentifier
     self._deleteFlag = 0
     self._updateFlag = 0
@@ -283,14 +321,14 @@
   def setField(self, field, value):
     # If this field is bound to a datasource and the datasource is read only, 
     # generate an error.
-    if self.isFieldBound(field) and self._parent.isReadOnly(): 
+    if self._parent.isFieldBound(field) and self._parent.isReadOnly(): 
       # Provide better feedback??
       raise ReadOnlyError, "Attempted to modify read only field '%s'" % field
     else: 
       self._emptyFlag = 0
       fn = lower(field)
       self._fields[fn] = value
-      if self.isFieldBound(field): 
+      if self._parent.isFieldBound(field): 
         self._updateFlag = 1
       if self._modifiedFlags.has_key(fn): 
         flag = self._modifiedFlags[fn] + 1
@@ -299,11 +337,6 @@
       self._modifiedFlags[fn] = flag
 
 
-  # Returns 1=Field is bound to a database field
-  def isFieldBound(self, fieldName): 
-    return self._boundFields.has_key(lower(fieldName))
-
-
   # Returns 1=Field has been modified
   def isFieldModified(self, fieldName):
     return self._modifiedFlags.has_key (lower(fieldName))   
@@ -328,13 +361,13 @@
       self._postChanges()
 
     # Post all details in 
-    for child in (self._detailSources): 
+    for child in (self._detailObjects): 
       child.post()
 
 
   # Sets the ResultSet associated with this master record
   def addDetailResultSet(self, ds):
-    self._detailSources.append(ds)
+    self._detailObjects.append(ds)
 
 
   ###
Index: gnue/gnue-common/gnue/common/GLoginHandler.py
diff -u gnue/gnue-common/gnue/common/GLoginHandler.py:1.1 
gnue/gnue-common/gnue/common/GLoginHandler.py:1.2
--- gnue/gnue-common/gnue/common/GLoginHandler.py:1.1   Mon May 14 14:59:59 2001
+++ gnue/gnue-common/gnue/common/GLoginHandler.py       Tue May 15 08:16:38 2001
@@ -30,8 +30,16 @@
 # HISTORY:
 #
 
-class LoginHandler: 
 
+#
+# If user stops the login process (cancel button?), raise this exception
+#
+class UserCanceledLogin(Exception): 
+  pass
+
+
+
+class LoginHandler: 
   #
   # getLogin is passed an list consisting of: 
   #   Connection Name



reply via email to

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