# HG changeset patch # User catherine.devlin@gmail.com # Date 1283686246 14400 # Node ID 885c275ee790a1d9af2d7bc8b6430398e22d42bf # Parent b7782506b5f33f9566082d54f683ed2a412ede7d pared down connections.py diff -r b7782506b5f3 -r 885c275ee790 sqlpython/connections.py --- a/sqlpython/connections.py Wed Aug 25 23:48:09 2010 -0400 +++ b/sqlpython/connections.py Sun Sep 05 07:30:46 2010 -0400 @@ -58,10 +58,6 @@ compiled.match(self.unqualified_name) or compiled.match(self.unqualified_path)) -class GeraldPlaceholder(object): - current = False - complete = False - class OptionTestDummy(object): mysql = None postgres = None @@ -73,39 +69,39 @@ mode = 0 def __init__(self, *args, **kwargs): self.__dict__.update(kwargs) - -class ConnectionData(object): + +class DatabaseInstance(object): username = None password = None hostname = None port = None database = None mode = 0 - connection_uri_parser = re.compile('(postgres|oracle|mysql|sqlite|mssql):/(.*$)', re.IGNORECASE) + connection_uri_parser = re.compile('(?Ppostgres|oracle|mysql|sqlite|mssql)://?(?P.*$)', re.IGNORECASE) connection_parser = re.compile('((?P\S+)(\s+(?P\S+))?)?') def __init__(self, arg, opts, default_rdbms = 'oracle'): ''' >>> opts = OptionTestDummy(postgres=True, password='password') - >>> ConnectionData('thedatabase theuser', opts).uri() + >>> DatabaseInstance('thedatabase theuser', opts).uri() 'postgres://theuser:password@localhost:5432/thedatabase' >>> opts = OptionTestDummy(password='password') - >>> ConnectionData('oracle://user:password@db', opts).uri() + >>> DatabaseInstance('oracle://user:password@db', opts).uri() 'oracle://user:password@db' - >>> ConnectionData('user/password@db', opts).uri() + >>> DatabaseInstance('user/password@db', opts).uri() 'oracle://user:password@db' - >>> ConnectionData('user/password@db as sysdba', opts).uri() + >>> DatabaseInstance('user/password@db as sysdba', opts).uri() 'oracle://user:password@db?mode=2' - >>> ConnectionData('user/password@thehost/db', opts).uri() + >>> DatabaseInstance('user/password@thehost/db', opts).uri() 'oracle://user:password@thehost:1521/db' >>> opts = OptionTestDummy(postgres=True, hostname='thehost', password='password') - >>> ConnectionData('thedatabase theuser', opts).uri() + >>> DatabaseInstance('thedatabase theuser', opts).uri() 'postgres://theuser:password@thehost:5432/thedatabase' >>> opts = OptionTestDummy(mysql=True, password='password') - >>> ConnectionData('thedatabase theuser', opts).uri() + >>> DatabaseInstance('thedatabase theuser', opts).uri() 'mysql://theuser:password@localhost:3306/thedatabase' >>> opts = OptionTestDummy(mysql=True, password='password') - >>> ConnectionData('thedatabase', opts).uri() - 'mysql://catherine:password@localhost:3306/thedatabase' + >>> DatabaseInstance('thedatabase', opts).uri() + 'mysql://cat:password@localhost:3306/thedatabase' ''' self.arg = arg self.opts = opts @@ -130,35 +126,36 @@ def parse_connect_uri(self, uri): results = self.connection_uri_parser.search(uri) if results: - (self.username, self.password, self.hostname, self.port, self.database - ) = gerald.utilities.dburi.Connection().parse_uri(results.group(2)) - self.set_class_from_rdbms_name(results.group(1)) + r = gerald.utilities.dburi.Connection().parse_uri(results.group('connect_string')) + self.username = r.get('user') or self.username + self.password = r.get('password') or self.password + self.hostname = r.get('host') or self.hostname + self.set_class_from_rdbms_name(results.group('rdbms')) self.port = self.port or self.default_port return True else: return False def set_class_from_rdbms_name(self, rdbms_name): - for cls in (OracleConnectionData, PostgresConnectionData, MySQLConnectionData): + for cls in (OracleInstance, PostgresInstance, MySQLInstance): if cls.rdbms == rdbms_name: self.__class__ = cls def uri(self): return '%s://%s:%s@%s:%s/%s' % (self.rdbms, self.username, self.password, self.hostname, self.port, self.database) - colon_between_username_passwd = re.compile(r':(?=[^/]+@)') - def gerald_uri(self): - result = self.uri().split('?mode=')[0] - return result def determine_rdbms(self): if self.opts.mysql: - self.__class__ = MySQLConnectionData + self.__class__ = MySQLInstance elif self.opts.postgres: - self.__class__ = PostgresConnectionData + self.__class__ = PostgresInstance else: self.set_class_from_rdbms_name(self.default_rdbms) def set_defaults(self): self.port = self.default_port def set_corrections(self): pass + def set_instance_number(self, instance_number): + self.instance_number = instance_number + self.prompt = "%d:%s@%s> " % (self.instance_number, self.username, self.database) parser = optparse.OptionParser() @@ -185,7 +182,7 @@ -class MySQLConnectionData(ConnectionData): +class MySQLInstance(DatabaseInstance): rdbms = 'mysql' default_port = 3306 def set_defaults(self): @@ -193,12 +190,12 @@ self.hostname = 'localhost' self.username = os.getenv('USER') self.database = os.getenv('USER') - def connection(self): - return MySQLdb.connect(host = self.hostname, user = self.username, + def connect(self): + self.connection = MySQLdb.connect(host = self.hostname, user = self.username, passwd = self.password, db = self.database, port = self.port, sql_mode = 'ANSI') -class PostgresConnectionData(ConnectionData): +class PostgresInstance(DatabaseInstance): rdbms = 'postgres' default_port = 5432 def set_defaults(self): @@ -206,12 +203,12 @@ self.database = os.getenv('ORACLE_SID') self.hostname = os.getenv('PGHOST') or 'localhost' self.username = os.getenv('USER') - def connection(self): - return psycopg2.connect(host = self.hostname, user = self.username, + def connect(self): + self.connection = psycopg2.connect(host = self.hostname, user = self.username, password = self.password, database = self.database, port = self.port) -class OracleConnectionData(ConnectionData): +class OracleInstance(DatabaseInstance): rdbms = 'oracle' default_port = 1521 connection_parser = re.compile('(?P[^/\s@]*)(/(?P[^/\s@]*))?(@((?P[^/\s:]*)(:(?P\d{1,4}))?/)?(?P[^/\s:]*))?(\s+as\s+(?Psys(dba|oper)))?', @@ -236,86 +233,16 @@ else: self.dsn = self.database def parse_connect_uri(self, uri): - if ConnectionData.parse_connect_uri(self, uri): + if DatabaseInstance.parse_connect_uri(self, uri): if not self.database: self.database = self.hostname self.hostname = None self.port = self.default_port return True return False - def connection(self): - return cx_Oracle.connect(user = self.username, password = self.password, + def connect(self): + self.connection = cx_Oracle.connect(user = self.username, password = self.password, dsn = self.dsn, mode = self.mode) - -class DatabaseInstance(object): - import_failure = None - username = None - password = None - port = None - uri = None - pickledir = os.path.join(os.path.expanduser('~'), '.sqlpython') - connection_uri_parser = re.compile('(postgres|oracle|mysql|sqlite|mssql):/(.*$)', re.IGNORECASE) - - def __init__(self, arg, opts, default_rdbms = 'oracle'): - #opts.username = opts.username or opts.user - self.conn_data = ConnectionData(arg, opts, default_rdbms) - for v in ('username', 'database', 'rdbms'): - setattr(self, v, getattr(self.conn_data, v)) - self.connection = self.conn_data.connection() - self.gerald = GeraldPlaceholder() - self.discover_metadata() - - def discover_metadata(self): - self.metadata_discovery_thread = MetadataDiscoveryThread(self) - self.metadata_discovery_thread.start() - - def set_instance_number(self, instance_number): - self.instance_number = instance_number - self.prompt = "%d:%s@%s> " % (self.instance_number, self.username, self.database) - def pickle(self): - try: - os.mkdir(self.pickledir) - except OSError: - pass - picklefile = open(self.picklefile(), 'w') - pickle.dump(self.gerald.schema, picklefile) - picklefile.close() - def picklefile(self): - return os.path.join(self.pickledir, ('%s.%s.%s.%s.pickle' % - (self.rdbms, self.username, self.conn_data.hostname, self.database)).lower()) - def retreive_pickled_gerald(self): - picklefile = open(self.picklefile()) - schema = pickle.load(picklefile) - picklefile.close() - newgerald = gerald_classes[self.rdbms](self.username, None, omit_error_objects=True) - newgerald.connect(self.conn_data.gerald_uri()) - newgerald.schema = schema - newgerald.current = False - newgerald.complete = True - newgerald.descriptions = {} - for (name, obj) in newgerald.schema.items(): - newgerald.descriptions[name] = ObjectDescriptor(name, obj) - self.gerald = newgerald - -class MetadataDiscoveryThread(threading.Thread): - def __init__(self, db_instance): - threading.Thread.__init__(self) - self.db_instance = db_instance - def run(self): - if not self.db_instance.gerald.complete: - try: - self.db_instance.retreive_pickled_gerald() - except IOError: - pass - self.db_instance.gerald.current = False - newgerald = gerald_classes[self.db_instance.rdbms](self.db_instance.username, self.db_instance.conn_data.gerald_uri(), omit_error_objects=True) - newgerald.descriptions = {} - for (name, obj) in newgerald.schema.items(): - newgerald.descriptions[name] = ObjectDescriptor(name, obj) - newgerald.current = True - newgerald.complete = True - self.db_instance.gerald = newgerald - self.db_instance.pickle() if __name__ == '__main__': doctest.testmod()