Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
remote.py635 linesDownload Raw Back to adodbapi
1"""adodbapi.remote - A python DB API 2.0 (PEP 249) interface to Microsoft ADO2 3Copyright (C) 2002 Henrik Ekelund, version 2.1 by Vernon Cole4* http://sourceforge.net/projects/pywin325* http://sourceforge.net/projects/adodbapi6 7    This library is free software; you can redistribute it and/or8    modify it under the terms of the GNU Lesser General Public9    License as published by the Free Software Foundation; either10    version 2.1 of the License, or (at your option) any later version.11 12    This library is distributed in the hope that it will be useful,13    but WITHOUT ANY WARRANTY; without even the implied warranty of14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU15    Lesser General Public License for more details.16 17    You should have received a copy of the GNU Lesser General Public18    License along with this library; if not, write to the Free Software19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA20 21    django adaptations and refactoring thanks to Adam Vandenberg22 23DB-API 2.0 specification: http://www.python.org/dev/peps/pep-0249/24 25This module source should run correctly in CPython versions 2.5 and later,26or IronPython version 2.7 and later,27or, after running through 2to3.py, CPython 3.0 or later.28"""29 30__version__ = "2.6.0.4"31version = "adodbapi.remote v" + __version__32 33import array34import datetime35import os36import sys37import time38 39# Pyro4 is required for server and remote operation --> https://pypi.python.org/pypi/Pyro4/40try:41    import Pyro442except ImportError:43    print('* * * Sorry, server operation requires Pyro4. Please "pip import" it.')44    exit(11)45 46import adodbapi47import adodbapi.apibase as api48import adodbapi.process_connect_string49from adodbapi.apibase import ProgrammingError50 51_BaseException = api._BaseException52 53sys.excepthook = Pyro4.util.excepthook54Pyro4.config.PREFER_IP_VERSION = 0  # allow system to prefer IPv655Pyro4.config.COMMTIMEOUT = 40.0  # a bit longer than the default SQL server Gtimeout56Pyro4.config.SERIALIZER = "pickle"57 58try:59    verbose = int(os.environ["ADODBAPI_VERBOSE"])60except:61    verbose = False62if verbose:63    print(version)64 65# --- define objects to smooth out Python3 <-> Python 2.x differences66unicodeType = str  # this line will be altered by 2to3.py to '= str'67longType = int  # this line will be altered by 2to3.py to '= int'68StringTypes = str69makeByteBuffer = bytes70memoryViewType = memoryview71 72# -----------------------------------------------------------73# conversion functions mandated by PEP 24974Binary = makeByteBuffer  # override the function from apibase.py75 76 77def Date(year, month, day):78    return datetime.date(year, month, day)  # dateconverter.Date(year,month,day)79 80 81def Time(hour, minute, second):82    return datetime.time(hour, minute, second)  # dateconverter.Time(hour,minute,second)83 84 85def Timestamp(year, month, day, hour, minute, second):86    return datetime.datetime(year, month, day, hour, minute, second)87 88 89def DateFromTicks(ticks):90    return Date(*time.gmtime(ticks)[:3])91 92 93def TimeFromTicks(ticks):94    return Time(*time.gmtime(ticks)[3:6])95 96 97def TimestampFromTicks(ticks):98    return Timestamp(*time.gmtime(ticks)[:6])99 100 101def connect(*args, **kwargs):  # --> a remote db-api connection object102    """Create and open a remote db-api database connection object"""103    # process the argument list the programmer gave us104    kwargs = adodbapi.process_connect_string.process(args, kwargs)105    # the "proxy_xxx" keys tell us where to find the PyRO proxy server106    kwargs.setdefault(107        "pyro_connection", "PYRO:ado.connection@%(proxy_host)s:%(proxy_port)s"108    )109    if not "proxy_port" in kwargs:110        try:111            pport = os.environ["PROXY_PORT"]112        except KeyError:113            pport = 9099114        kwargs["proxy_port"] = pport115    if not "proxy_host" in kwargs or not kwargs["proxy_host"]:116        try:117            phost = os.environ["PROXY_HOST"]118        except KeyError:119            phost = "[::1]"  # '127.0.0.1'120        kwargs["proxy_host"] = phost121    ado_uri = kwargs["pyro_connection"] % kwargs122    # ask PyRO make us a remote connection object123    auto_retry = 3124    while auto_retry:125        try:126            dispatcher = Pyro4.Proxy(ado_uri)127            if "comm_timeout" in kwargs:128                dispatcher._pyroTimeout = float(kwargs["comm_timeout"])129            uri = dispatcher.make_connection()130            break131        except Pyro4.core.errors.PyroError:132            auto_retry -= 1133            if auto_retry:134                time.sleep(1)135            else:136                raise api.DatabaseError("Cannot create connection to=%s" % ado_uri)137 138    conn_uri = fix_uri(uri, kwargs)  # get a host connection from the proxy server139    while auto_retry:140        try:141            host_conn = Pyro4.Proxy(142                conn_uri143            )  # bring up an exclusive Pyro connection for my ADO connection144            break145        except Pyro4.core.errors.PyroError:146            auto_retry -= 1147            if auto_retry:148                time.sleep(1)149            else:150                raise api.DatabaseError(151                    "Cannot create ADO connection object using=%s" % conn_uri152                )153    if "comm_timeout" in kwargs:154        host_conn._pyroTimeout = float(kwargs["comm_timeout"])155    # make a local clone156    myConn = Connection()157    while auto_retry:158        try:159            myConn.connect(160                kwargs, host_conn161            )  # call my connect method -- hand him the host connection162            break163        except Pyro4.core.errors.PyroError:164            auto_retry -= 1165            if auto_retry:166                time.sleep(1)167            else:168                raise api.DatabaseError(169                    "Pyro error creating connection to/thru=%s" % repr(kwargs)170                )171        except _BaseException as e:172            raise api.DatabaseError(173                "Error creating remote connection to=%s, e=%s, %s"174                % (repr(kwargs), repr(e), sys.exc_info()[2])175            )176    return myConn177 178 179def fix_uri(uri, kwargs):180    """convert a generic pyro uri with '0.0.0.0' into the address we actually called"""181    u = uri.asString()182    s = u.split("[::0]")  # IPv6 generic address183    if len(s) == 1:  # did not find one184        s = u.split("0.0.0.0")  # IPv4 generic address185    if len(s) > 1:  # found a generic186        return kwargs["proxy_host"].join(s)  # fill in our address for the host187    return uri188 189 190# # # # # ----- the Class that defines a connection ----- # # # # #191class Connection(object):192    # include connection attributes required by api definition.193    Warning = api.Warning194    Error = api.Error195    InterfaceError = api.InterfaceError196    DataError = api.DataError197    DatabaseError = api.DatabaseError198    OperationalError = api.OperationalError199    IntegrityError = api.IntegrityError200    InternalError = api.InternalError201    NotSupportedError = api.NotSupportedError202    ProgrammingError = api.ProgrammingError203    # set up some class attributes204    paramstyle = api.paramstyle205 206    @property207    def dbapi(self):  # a proposed db-api version 3 extension.208        "Return a reference to the DBAPI module for this Connection."209        return api210 211    def __init__(self):212        self.proxy = None213        self.kwargs = {}214        self.errorhandler = None215        self.supportsTransactions = False216        self.paramstyle = api.paramstyle217        self.timeout = 30218        self.cursors = {}219 220    def connect(self, kwargs, connection_maker):221        self.kwargs = kwargs222        if verbose:223            print('%s attempting: "%s"' % (version, repr(kwargs)))224        self.proxy = connection_maker225        ##try:226        ret = self.proxy.connect(kwargs)  # ask the server to hook us up227        ##except ImportError, e:   # Pyro is trying to import pywinTypes.comerrer228        ##    self._raiseConnectionError(api.DatabaseError, 'Proxy cannot connect using=%s' % repr(kwargs))229        if ret is not True:230            self._raiseConnectionError(231                api.OperationalError, "Proxy returns error message=%s" % repr(ret)232            )233 234        self.supportsTransactions = self.getIndexedValue("supportsTransactions")235        self.paramstyle = self.getIndexedValue("paramstyle")236        self.timeout = self.getIndexedValue("timeout")237        if verbose:238            print("adodbapi.remote New connection at %X" % id(self))239 240    def _raiseConnectionError(self, errorclass, errorvalue):241        eh = self.errorhandler242        if eh is None:243            eh = api.standardErrorHandler244        eh(self, None, errorclass, errorvalue)245 246    def close(self):247        """Close the connection now (rather than whenever __del__ is called).248 249        The connection will be unusable from this point forward;250        an Error (or subclass) exception will be raised if any operation is attempted with the connection.251        The same applies to all cursor objects trying to use the connection.252        """253        for crsr in list(self.cursors.values())[254            :255        ]:  # copy the list, then close each one256            crsr.close()257        try:258            """close the underlying remote Connection object"""259            self.proxy.close()260            if verbose:261                print("adodbapi.remote Closed connection at %X" % id(self))262            object.__delattr__(263                self, "proxy"264            )  # future attempts to use closed cursor will be caught by __getattr__265        except Exception:266            pass267 268    def __del__(self):269        try:270            self.proxy.close()271        except:272            pass273 274    def commit(self):275        """Commit any pending transaction to the database.276 277        Note that if the database supports an auto-commit feature,278        this must be initially off. An interface method may be provided to turn it back on.279        Database modules that do not support transactions should implement this method with void functionality.280        """281        if not self.supportsTransactions:282            return283        result = self.proxy.commit()284        if result:285            self._raiseConnectionError(286                api.OperationalError, "Error during commit: %s" % result287            )288 289    def _rollback(self):290        """In case a database does provide transactions this method causes the the database to roll back to291        the start of any pending transaction. Closing a connection without committing the changes first will292        cause an implicit rollback to be performed.293        """294        result = self.proxy.rollback()295        if result:296            self._raiseConnectionError(297                api.OperationalError, "Error during rollback: %s" % result298            )299 300    def __setattr__(self, name, value):301        if name in ("paramstyle", "timeout", "autocommit"):302            if self.proxy:303                self.proxy.send_attribute_to_host(name, value)304        object.__setattr__(self, name, value)  # store attribute locally (too)305 306    def __getattr__(self, item):307        if (308            item == "rollback"309        ):  # the rollback method only appears if the database supports transactions310            if self.supportsTransactions:311                return (312                    self._rollback313                )  # return the rollback method so the caller can execute it.314            else:315                raise self.ProgrammingError(316                    "this data provider does not support Rollback"317                )318        elif item in (319            "dbms_name",320            "dbms_version",321            "connection_string",322            "autocommit",323        ):  # 'messages' ):324            return self.getIndexedValue(item)325        elif item == "proxy":326            raise self.ProgrammingError("Attempting to use closed connection")327        else:328            raise self.ProgrammingError('No remote access for attribute="%s"' % item)329 330    def getIndexedValue(self, index):331        r = self.proxy.get_attribute_for_remote(index)332        return r333 334    def cursor(self):335        "Return a new Cursor Object using the connection."336        myCursor = Cursor(self)337        return myCursor338 339    def _i_am_here(self, crsr):340        "message from a new cursor proclaiming its existence"341        self.cursors[crsr.id] = crsr342 343    def _i_am_closing(self, crsr):344        "message from a cursor giving connection a chance to clean up"345        try:346            del self.cursors[crsr.id]347        except:348            pass349 350    def __enter__(self):  # Connections are context managers351        return self352 353    def __exit__(self, exc_type, exc_val, exc_tb):354        if exc_type:355            self._rollback()  # automatic rollback on errors356        else:357            self.commit()358 359    def get_table_names(self):360        return self.proxy.get_table_names()361 362 363def fixpickle(x):364    """pickle barfs on buffer(x) so we pass as array.array(x) then restore to original form for .execute()"""365    if x is None:366        return None367    if isinstance(x, dict):368        # for 'named' paramstyle user will pass a mapping369        newargs = {}370        for arg, val in list(x.items()):371            if isinstance(val, memoryViewType):372                newval = array.array("B")373                newval.fromstring(val)374                newargs[arg] = newval375            else:376                newargs[arg] = val377        return newargs378    # if not a mapping, then a sequence379    newargs = []380    for arg in x:381        if isinstance(arg, memoryViewType):382            newarg = array.array("B")383            newarg.fromstring(arg)384            newargs.append(newarg)385        else:386            newargs.append(arg)387    return newargs388 389 390class Cursor(object):391    def __init__(self, connection):392        self.command = None393        self.errorhandler = None  ## was: connection.errorhandler394        self.connection = connection395        self.proxy = self.connection.proxy396        self.rs = None  # the fetchable data for this cursor397        self.converters = NotImplemented398        self.id = connection.proxy.build_cursor()399        connection._i_am_here(self)400        self.recordset_format = api.RS_REMOTE401        if verbose:402            print(403                "%s New cursor at %X on conn %X"404                % (version, id(self), id(self.connection))405            )406 407    def prepare(self, operation):408        self.command = operation409        try:410            del self.description411        except AttributeError:412            pass413        self.proxy.crsr_prepare(self.id, operation)414 415    def __iter__(self):  # [2.1 Zamarev]416        return iter(self.fetchone, None)  # [2.1 Zamarev]417 418    def __next__(self):419        r = self.fetchone()420        if r:421            return r422        raise StopIteration423 424    def __enter__(self):425        "Allow database cursors to be used with context managers."426        return self427 428    def __exit__(self, exc_type, exc_val, exc_tb):429        "Allow database cursors to be used with context managers."430        self.close()431 432    def __getattr__(self, key):433        if key == "numberOfColumns":434            try:435                return len(self.rs[0])436            except:437                return 0438        if key == "description":439            try:440                self.description = self.proxy.crsr_get_description(self.id)[:]441                return self.description442            except TypeError:443                return None444        if key == "columnNames":445            try:446                r = dict(447                    self.proxy.crsr_get_columnNames(self.id)448                )  # copy the remote columns449 450            except TypeError:451                r = {}452            self.columnNames = r453            return r454 455        if key == "remote_cursor":456            raise api.OperationalError457        try:458            return self.proxy.crsr_get_attribute_for_remote(self.id, key)459        except AttributeError:460            raise api.InternalError(461                'Failure getting attribute "%s" from proxy cursor.' % key462            )463 464    def __setattr__(self, key, value):465        if key == "arraysize":466            self.proxy.crsr_set_arraysize(self.id, value)467        if key == "paramstyle":468            if value in api.accepted_paramstyles:469                self.proxy.crsr_set_paramstyle(self.id, value)470            else:471                self._raiseCursorError(472                    api.ProgrammingError, 'invalid paramstyle ="%s"' % value473                )474        object.__setattr__(self, key, value)475 476    def _raiseCursorError(self, errorclass, errorvalue):477        eh = self.errorhandler478        if eh is None:479            eh = api.standardErrorHandler480        eh(self.connection, self, errorclass, errorvalue)481 482    def execute(self, operation, parameters=None):483        if self.connection is None:484            self._raiseCursorError(485                ProgrammingError, "Attempted operation on closed cursor"486            )487        self.command = operation488        try:489            del self.description490        except AttributeError:491            pass492        try:493            del self.columnNames494        except AttributeError:495            pass496        fp = fixpickle(parameters)497        if verbose > 2:498            print(499                (500                    '%s executing "%s" with params=%s'501                    % (version, operation, repr(parameters))502                )503            )504        result = self.proxy.crsr_execute(self.id, operation, fp)505        if result:  # an exception was triggered506            self._raiseCursorError(result[0], result[1])507 508    def executemany(self, operation, seq_of_parameters):509        if self.connection is None:510            self._raiseCursorError(511                ProgrammingError, "Attempted operation on closed cursor"512            )513        self.command = operation514        try:515            del self.description516        except AttributeError:517            pass518        try:519            del self.columnNames520        except AttributeError:521            pass522        sq = [fixpickle(x) for x in seq_of_parameters]523        if verbose > 2:524            print(525                (526                    '%s executemany "%s" with params=%s'527                    % (version, operation, repr(seq_of_parameters))528                )529            )530        self.proxy.crsr_executemany(self.id, operation, sq)531 532    def nextset(self):533        try:534            del self.description535        except AttributeError:536            pass537        try:538            del self.columnNames539        except AttributeError:540            pass541        if verbose > 2:542            print(("%s nextset" % version))543        return self.proxy.crsr_nextset(self.id)544 545    def callproc(self, procname, parameters=None):546        if self.connection is None:547            self._raiseCursorError(548                ProgrammingError, "Attempted operation on closed cursor"549            )550        self.command = procname551        try:552            del self.description553        except AttributeError:554            pass555        try:556            del self.columnNames557        except AttributeError:558            pass559        fp = fixpickle(parameters)560        if verbose > 2:561            print(562                (563                    '%s callproc "%s" with params=%s'564                    % (version, procname, repr(parameters))565                )566            )567        return self.proxy.crsr_callproc(self.id, procname, fp)568 569    def fetchone(self):570        try:571            f1 = self.proxy.crsr_fetchone(self.id)572        except _BaseException as e:573            self._raiseCursorError(api.DatabaseError, e)574        else:575            if f1 is None:576                return None577            self.rs = [f1]578            return api.SQLrows(self.rs, 1, self)[579                0580            ]  # new object to hold the results of the fetch581 582    def fetchmany(self, size=None):583        try:584            self.rs = self.proxy.crsr_fetchmany(self.id, size)585            if not self.rs:586                return []587            r = api.SQLrows(self.rs, len(self.rs), self)588            return r589        except Exception as e:590            self._raiseCursorError(api.DatabaseError, e)591 592    def fetchall(self):593        try:594            self.rs = self.proxy.crsr_fetchall(self.id)595            if not self.rs:596                return []597            return api.SQLrows(self.rs, len(self.rs), self)598        except Exception as e:599            self._raiseCursorError(api.DatabaseError, e)600 601    def close(self):602        if self.connection is None:603            return604        self.connection._i_am_closing(self)  # take me off the connection's cursors list605        try:606            self.proxy.crsr_close(self.id)607        except:608            pass609        try:610            del self.description611        except:612            pass613        try:614            del self.rs  # let go of the recordset615        except:616            pass617        self.connection = (618            None  # this will make all future method calls on me throw an exception619        )620        self.proxy = None621        if verbose:622            print("adodbapi.remote Closed cursor at %X" % id(self))623 624    def __del__(self):625        try:626            self.close()627        except:628            pass629 630    def setinputsizes(self, sizes):631        pass632 633    def setoutputsize(self, size, column=None):634        pass635 
codekingpro/portable-devtools · Team Ai