# HG changeset patch # User catherine@cordelia # Date 1240600169 14400 # Node ID c652478be4fdcae60b3ae6195567906a63b22710 # Parent 1c6e5410619e680e7db1740cb1a2a8423d763f52 migrated \dt to gerald diff -r 1c6e5410619e -r c652478be4fd docs/source/capabilities.rst diff -r 1c6e5410619e -r c652478be4fd docs/source/conf.py diff -r 1c6e5410619e -r c652478be4fd docs/source/index.rst diff -r 1c6e5410619e -r c652478be4fd docs/source/intro.rst diff -r 1c6e5410619e -r c652478be4fd docs/source/limitations.rst diff -r 1c6e5410619e -r c652478be4fd setup.py --- a/setup.py Thu Apr 23 19:10:05 2009 -0400 +++ b/setup.py Fri Apr 24 15:09:29 2009 -0400 @@ -17,8 +17,11 @@ url="http://packages.python.org/sqlpython", packages=find_packages(), include_package_data=True, - install_requires=['pyparsing','cmd2>=0.5.2','cx_Oracle','genshi>=0.5','sqlalchemy',], - keywords = 'client oracle database', + install_requires=['pyparsing','cmd2>=0.5.2','genshi>=0.5','sqlalchemy','gerald'], + extras_require = {'oracle': ['cx_Oracle'], + 'mysql': ['MySQL-python'], + 'postgres': ['psycopg2']}, + keywords = 'client oracle database rdbms sql', license = 'MIT', platforms = ['any'], entry_points = """ diff -r 1c6e5410619e -r c652478be4fd sqlpython/README.txt diff -r 1c6e5410619e -r c652478be4fd sqlpython/completion.py diff -r 1c6e5410619e -r c652478be4fd sqlpython/exampleSession.txt diff -r 1c6e5410619e -r c652478be4fd sqlpython/metadata.py diff -r 1c6e5410619e -r c652478be4fd sqlpython/mysqlpy.py --- a/sqlpython/mysqlpy.py Thu Apr 23 19:10:05 2009 -0400 +++ b/sqlpython/mysqlpy.py Fri Apr 24 15:09:29 2009 -0400 @@ -183,14 +183,9 @@ try: if sys.argv[1][0] != '@': connectstring = sys.argv.pop(1) - try: # attach AS SYSDBA or AS SYSOPER if present - for connectmode in my.connection_modes.keys(): - if connectmode.search(' %s %s' % tuple(sys.argv[1:3])): - for i in (1,2): - connectstring += ' ' + sys.argv.pop(1) - break - except TypeError: - pass + if len(sys.argv) >= 3 and sys.argv[1].lower() == 'as': # attach AS SYSDBA or AS SYSOPER if present + for i in (1,2): + connectstring += ' ' + sys.argv.pop(1) my.do_connect(connectstring) for arg in sys.argv[1:]: if my.onecmd(arg + '\n') == my._STOP_AND_EXIT: diff -r 1c6e5410619e -r c652478be4fd sqlpython/output_templates.py diff -r 1c6e5410619e -r c652478be4fd sqlpython/plothandler.py --- a/sqlpython/plothandler.py Thu Apr 23 19:10:05 2009 -0400 +++ b/sqlpython/plothandler.py Fri Apr 24 15:09:29 2009 -0400 @@ -1,10 +1,9 @@ -import shelve, pickle, cx_Oracle, datetime, sys, itertools +import shelve, pickle, datetime, sys, itertools shelvename = 'plot.shelve' try: import pylab class Plot(object): - plottable_types = (cx_Oracle.NUMBER, datetime.datetime) def __init__(self): self.legends = [] self.yserieslists = [] @@ -14,7 +13,7 @@ self.title = sqlSession.tblname self.xlabel = sqlSession.curs.description[0][0] self.datatypes = [d[1] for d in sqlSession.curs.description] - plottableSeries = [dt in self.plottable_types for dt in self.datatypes] + plottableSeries = [hasattr(dt, '__sub__') for dt in self.datatypes] if plottableSeries.count(True) == 0: raise ValueError, 'At least one quantitative column needed to plot.' elif len(plottableSeries) == 1: # only one column, but it is plottable diff -r 1c6e5410619e -r c652478be4fd sqlpython/setup_test_db.sql diff -r 1c6e5410619e -r c652478be4fd sqlpython/sqlpyPlus.py --- a/sqlpython/sqlpyPlus.py Thu Apr 23 19:10:05 2009 -0400 +++ b/sqlpython/sqlpyPlus.py Fri Apr 24 15:09:29 2009 -0400 @@ -23,7 +23,7 @@ - catherinedevlin.blogspot.com May 31, 2006 """ -import sys, os, re, sqlpython, cx_Oracle, pyparsing, re, completion, datetime, pickle, binascii, subprocess +import sys, os, re, sqlpython, pyparsing, re, completion, datetime, pickle, binascii, subprocess from cmd2 import Cmd, make_option, options, Statekeeper, Cmd2TestCase from output_templates import output_templates from metadata import metaqueries @@ -34,6 +34,18 @@ except (RuntimeError, ImportError): pass +DatabaseErrors = [] +try: + import psycopg2 + DatabaseErrors.append(psycopg2.DatabaseError) +except ImportError: + psycopg2 = None +try: + import cx_Oracle + DatabaseErrors.append(cx_Oracle.DatabaseError) +except ImportError: + cx_Oracle = None + queries = { 'resolve': """ SELECT object_type, object_name, owner FROM ( @@ -258,6 +270,9 @@ return lst[center-width:end] else: return lst[max(center-width,0):center+width+1] + +def oracle_wildcards_to_regex(input): + return re.escape(input.lower().strip()).replace('\\*','.*').replace('\\%','.*').replace('\\_','.') class sqlpyPlus(sqlpython.sqlpython): defaultExtension = 'sql' @@ -757,11 +772,11 @@ return self._pull(arg, opts, vc=None) def _pull(self, arg, opts, vc=None): - for (descrip, objtype, obj) in self.gerald_resolve(arg): + for (descrip, obj) in sorted(self.gerald_resolve(arg)): txt = obj.get_ddl() if vc or opts.dump: try: - os.mkdir(objtype) + os.mkdir(obj.type) except OSError: pass fname = descrip + '.sql' @@ -904,7 +919,7 @@ return self._do_describe_oracle () if opts.refresh: self.connections[self.connection_number]['gerald_result'] = self.connections[self.connection_number]['gerald']() - for (descriptor, objtype, obj) in self.gerald_resolve(arg): + for (descriptor, obj) in sorted(self.gerald_resolve(arg)): self.poutput(descriptor) if hasattr(obj, 'columns'): self.tblname = obj.name @@ -1078,15 +1093,11 @@ except KeyError: self.perror('psql command \%s not yet supported.' % abbrev) - @options([all_users_option]) - def do__dir_tables(self, arg, opts): + def do__dir_tables(self, arg): ''' Lists all tables whose names match argument. ''' - sql = """SELECT table_name, 'TABLE' as type%s FROM %s_tables WHERE table_name LIKE '%%%s%%';""" % \ - (opts.scope['col'], opts.scope['view'], arg.upper()) - self.sqlfeedback(sql) - self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix)) + self.onecmd('ls table/%s' % arg) @options([all_users_option]) def do__dir_views(self, arg, opts): @@ -1185,7 +1196,7 @@ try: self.curs.execute('SELECT %s FROM dual' % val) return True, var, self.curs.fetchone()[0] - except cx_Oracle.DatabaseError: + except DatabaseErrors: return True, var, val # we give up and assume it's a string def do_setbind(self, arg): @@ -1347,23 +1358,26 @@ self.select_output(arg.parsed.raw, terminator=arg.parsed.terminator, rowlimit=arg.parsed.suffix) def gerald_resolve(self, target): - target = target.lower().strip() + target = oracle_wildcards_to_regex(target.rstrip('/')) + typetarget = target + '/?$' + nametarget = target + '$' schema = self.connections[self.connection_number]['gerald_result'].schema for (objname, obj) in schema.items(): - objtype = str(type(obj)).split('.')[-1].rstrip("'>") - descriptor = os.path.join(objtype, objname) - if (not target) or (objname == target) or (descriptor == target): - yield (descriptor, objtype, obj) + if not hasattr(obj, 'type'): + setattr(obj, 'type', str(type(obj)).strip("'>").split('.')[-1]) # would prefer Gerald to give this to us + descriptor = os.path.join(obj.type, objname) + if (not target) or re.match(typetarget, obj.type, re.I) or re.match(nametarget, objname, re.I) or re.match(nametarget, descriptor, re.I): + yield (descriptor, obj) @options([make_option('-l', '--long', action='store_true', help='long descriptions'), make_option('-a', '--all', action='store_true', help="all schemas' objects"), make_option('-t', '--timesort', action='store_true', help="Sort by last_ddl_time"), make_option('-r', '--reverse', action='store_true', help="Reverse order while sorting")]) def do_ls(self, arg, opts): - if self.rdbms == 'oracle': + if False and self.rdbms == 'oracle': return self._do_ls_oracle(arg, opts) rows = [] - for (descriptor, objtype, obj) in self.gerald_resolve(arg): + for (descriptor, obj) in sorted(self.gerald_resolve(arg)): if opts.long: rows.append((descriptor,)) else: diff -r 1c6e5410619e -r c652478be4fd sqlpython/sqlpython.py --- a/sqlpython/sqlpython.py Thu Apr 23 19:10:05 2009 -0400 +++ b/sqlpython/sqlpython.py Fri Apr 24 15:09:29 2009 -0400 @@ -8,7 +8,7 @@ # Best used with the companion modules sqlpyPlus and mysqlpy # See also http://twiki.cern.ch/twiki/bin/view/PSSGroup/SqlPython -import cmd2,getpass,binascii,cx_Oracle,re,os,functools +import cmd2,getpass,binascii,re,os,functools import sqlpyPlus, sqlalchemy, pyparsing, gerald __version__ = '1.6.4' @@ -97,7 +97,9 @@ gerald_classes = {'oracle': (gerald.OracleSchema, 'oracle',), 'postgres': (gerald.PostgresSchema, 'public'), - 'mysql': (gerald.MySQLSchema, 'nil')} + 'mysql': (gerald.MySQLSchema, 'nil'), + 'mssql': None, + 'sqlite': None} def url_connect(self, arg): eng = sqlalchemy.create_engine(arg) self.conn = eng.connect().connection @@ -105,14 +107,20 @@ 'rdbms': eng.url.drivername, 'user': eng.url.username or '', 'eng': eng} gerclass = self.gerald_classes[eng.url.drivername] - conn['gerald'] = functools.partial(gerclass[0], gerclass[1], arg.split('/?')[:1][0]) - conn['gerald_result'] = conn['gerald']() + if gerclass: + conn['gerald'] = functools.partial(gerclass[0], gerclass[1], arg.split('/?')[:1][0]) + else: + conn['gerald'] = list + conn['gerald_result'] = conn['gerald']() return conn def ora_connect(self, arg): + import cx_Oracle + connection_modes = {re.compile(' AS SYSDBA', re.IGNORECASE): cx_Oracle.SYSDBA, + re.compile(' AS SYSOPER', re.IGNORECASE): cx_Oracle.SYSOPER} modeval = 0 oraserv = None - for modere, modevalue in self.connection_modes.items(): + for modere, modevalue in connection_modes.items(): if modere.search(arg): arg = modere.sub('', arg) modeval = modevalue @@ -145,10 +153,9 @@ modeval = cx_Oracle.SYSOPER result = self.url_connect('oracle://%s:%s@%s/?mode=%d' % (orauser, orapass, oraserv, modeval)) result['dbname'] = oraserv + result['sid'] = sid return result - connection_modes = {re.compile(' AS SYSDBA', re.IGNORECASE): cx_Oracle.SYSDBA, - re.compile(' AS SYSOPER', re.IGNORECASE): cx_Oracle.SYSOPER} @cmd2.options([cmd2.make_option('-a', '--add', action='store_true', help='add connection (keep current connection)'), cmd2.make_option('-c', '--close', action='store_true', @@ -176,14 +183,17 @@ return try: connect_info = self.url_connect(arg) - except sqlalchemy.exc.ArgumentError, e: + except sqlalchemy.exc.DatabaseError, e: + self.perror(e) + return + except (sqlalchemy.exc.ArgumentError, ImportError), e: connect_info = self.ora_connect(arg) if opts.add or (self.connection_number is None): try: self.connection_number = max(self.connections.keys()) + 1 except ValueError: self.connection_number = 0 - connect_info['prompt'] = '%d:%s@%s> ' % (self.connection_number, connect_info['user'], connect_info['dbname']) + connect_info['prompt'] = '%d:%s@%s> ' % (self.connection_number, connect_info['user'], connect_info.get('sid') or connect_info['dbname']) self.connections[self.connection_number] = connect_info self.make_connection_current(self.connection_number) self.curs = self.conn.cursor() diff -r 1c6e5410619e -r c652478be4fd sqlpython/test_sqlpyPlus.py diff -r 1c6e5410619e -r c652478be4fd sqlpython/test_sqlpyPlus.txt diff -r 1c6e5410619e -r c652478be4fd sqlpython_epm.list