diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py index 5d82260939..c6228f6fef 100644 --- a/adodbapi/adodbapi.py +++ b/adodbapi/adodbapi.py @@ -23,28 +23,18 @@ DB-API 2.0 specification: http://www.python.org/dev/peps/pep-0249/ -This module source should run correctly in CPython versions 2.7 and later, -or CPython 3.4 or later. +This module source should run correctly in CPython 3.4 or later. """ -__version__ = "2.6.2.0" -version = "adodbapi v" + __version__ - import copy import decimal import os import sys import weakref +from collections.abc import Mapping from . import ado_consts as adc, apibase as api, process_connect_string -try: - verbose = int(os.environ["ADODBAPI_VERBOSE"]) -except: - verbose = False -if verbose: - print(version) - try: import pythoncom import pywintypes @@ -54,12 +44,15 @@ warnings.warn("pywin32 package required for adodbapi.", ImportWarning) +__version__ = "3.7.0.0" +version = "adodbapi v" + __version__ -def getIndexedValue(obj, index): - return obj(index) - - -from collections.abc import Mapping +try: + verbose = int(os.environ["ADODBAPI_VERBOSE"]) +except: + verbose = False +if verbose: + print(version) # ----------------- The .connect method ----------------- @@ -271,15 +264,13 @@ def connect(self, kwargs, connection_maker=make_COM_connecter): ) try: # Stefan Fuchs; support WINCCOLEDBProvider - if getIndexedValue(self.connector.Properties, "Transaction DDL").Value != 0: + if self.connector.Properties("Transaction DDL").Value != 0: self.supportsTransactions = True except pywintypes.com_error: pass # Stefan Fuchs - self.dbms_name = getIndexedValue(self.connector.Properties, "DBMS Name").Value + self.dbms_name = self.connector.Properties("DBMS Name").Value try: # Stefan Fuchs - self.dbms_version = getIndexedValue( - self.connector.Properties, "DBMS Version" - ).Value + self.dbms_version = self.connector.Properties("DBMS Version").Value except pywintypes.com_error: pass # Stefan Fuchs self.connector.CursorLocation = defaultCursorLocation # v2.1 Rose @@ -511,7 +502,7 @@ def get_table_names(self): tables = [] while not schema.EOF: - name = getIndexedValue(schema.Fields, "TABLE_NAME").Value + name = schema.Fields("TABLE_NAME").Value tables.append(name) schema.MoveNext() del schema @@ -614,7 +605,7 @@ def build_column_info(self, recordset): except AttributeError: varCon = api.variantConversions for i in range(self.numberOfColumns): - f = getIndexedValue(self.rs.Fields, i) + f = self.rs.Fields(i) try: self.converters.append( varCon[f.Type] @@ -632,7 +623,7 @@ def _makeDescriptionFromRS(self): return desc = [] for i in range(self.numberOfColumns): - f = getIndexedValue(self.rs.Fields, i) + f = self.rs.Fields(i) if self.rs.EOF or self.rs.BOF: display_size = None else: @@ -873,7 +864,7 @@ def _buildADOparameterList(self, parameters, sproc=False): if parameters_known: # use ado parameter list if self._parameter_names: # named parameters for i, pm_name in enumerate(self._parameter_names): - p = getIndexedValue(self.cmd.Parameters, i) + p = self.cmd.Parameters(i) try: _configure_parameter( p, parameters[pm_name], p.Type, parameters_known @@ -893,12 +884,12 @@ def _buildADOparameterList(self, parameters, sproc=False): ) else: # regular sequence of parameters for value in parameters: - p = getIndexedValue(self.cmd.Parameters, i) + p = self.cmd.Parameters(i) if ( p.Direction == adc.adParamReturnValue ): # this is an extra parameter added by ADO i += 1 # skip the extra - p = getIndexedValue(self.cmd.Parameters, i) + p = self.cmd.Parameters(i) try: _configure_parameter(p, value, p.Type, parameters_known) except Exception as e: diff --git a/adodbapi/process_connect_string.py b/adodbapi/process_connect_string.py index 21347d20cd..1f04611742 100644 --- a/adodbapi/process_connect_string.py +++ b/adodbapi/process_connect_string.py @@ -1,5 +1,10 @@ """ a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)""" +import getpass +import os +import platform +import tempfile + from . import is64bit as is64bit @@ -32,13 +37,9 @@ def macro_call(macro_name, args, kwargs): macro_name == "getuser" ): # get the name of the user the server is logged in under if not new_key in kwargs: - import getpass - return new_key, getpass.getuser() elif macro_name == "getnode": # get the name of the computer running the server - import platform - try: return new_key, args[1] % platform.node() except IndexError: @@ -61,9 +62,6 @@ def macro_call(macro_name, args, kwargs): elif ( macro_name == "find_temp_test_path" ): # helper function for testing ado operation -- undocumented - import os - import tempfile - return new_key, os.path.join( tempfile.gettempdir(), "adodbapi_test", args[1] ) diff --git a/adodbapi/quick_reference.md b/adodbapi/quick_reference.md index 436ff0318a..a992f7b85e 100644 --- a/adodbapi/quick_reference.md +++ b/adodbapi/quick_reference.md @@ -99,26 +99,43 @@ access api specification is found at: The PEP requires several module level attributes. Older versions of adodbapi (which was once all one big file) defined a hundred or two. I hate that, but can\'t break old code, so I decided to fix the problem -for Python 3. If using Python3 the programmer must take the time to pick +for Python 3. The programmer must take the time to pick up the symbols she needs from apibase and ado\_consts. Part of the adodbapi package\'s \_\_init\_\_.py looks something like this: ```python -if sys.version_info < (3,0): # in Python 2, define all symbols, just like before - from apibase import * # using this is bad - from ado_consts import * # using this is worse -else: - # but if the user is running Python 3, then keep the dictionary clean - from apibase import apilevel, threadsafety, paramstyle - from apibase import Warning, Error, InterfaceError, DatabaseError, DataError - from apibase import OperationalError, IntegrityError - from apibase import InternalError, ProgrammingError, NotSupportedError - from apibase import NUMBER, STRING, BINARY, DATETIME, ROWID - -from adodbapi import connect, Connection, __version__ -version = 'adodbapi v' + __version__ +from .adodbapi import ( + Connection as Connection, + Cursor as Cursor, + __version__, + connect as connect, + dateconverter, +) +from .apibase import ( + BINARY as BINARY, + DATETIME as DATETIME, + NUMBER as NUMBER, + ROWID as ROWID, + STRING as STRING, + DatabaseError as DatabaseError, + DataError as DataError, + Error as Error, + FetchFailedError as FetchFailedError, + IntegrityError as IntegrityError, + InterfaceError as InterfaceError, + InternalError as InternalError, + NotSupportedError as NotSupportedError, + OperationalError as OperationalError, + ProgrammingError as ProgrammingError, + Warning as Warning, + apilevel as apilevel, + paramstyle as paramstyle, + threadsafety as threadsafety, +) + +version = "adodbapi v" + __version__ ``` Please, use only those last four symbols from adodbapi. All others @@ -816,7 +833,7 @@ Running the tests The test folder contains a set of unittest programs. Setting them up can be a bit complex, because you need several database servers to do a complete test, and each one has a different configuration. Scripts in -this folder try to work in Python 2.7 or Python 3.5(+) +this folder try to work in Python 3.5(+) - dbapi20.py @@ -846,9 +863,8 @@ the database servers are distant, this can take a while. It does some lightweight command line processing (actually the config does it). -"\--package" tries to build a proper Python package in a temporary -location and adds it to sys.path so it can import a test version of the -code. It will run 2to3 when it does this, if needed. +"\--package" tries to build a proper Python package in a temporary location +and adds it to sys.path so it can import a test version of the code. "\--all" run as many of the 12 passes as possible. diff --git a/adodbapi/setup.py b/adodbapi/setup.py index 031ca01315..f6b274661d 100644 --- a/adodbapi/setup.py +++ b/adodbapi/setup.py @@ -41,8 +41,8 @@ def setup_package(): - from setuptools.command.build_py import build_py from setuptools import setup + from setuptools.command.build_py import build_py setup( cmdclass={"build_py": build_py}, diff --git a/adodbapi/test/adodbapitest.py b/adodbapi/test/adodbapitest.py index 424d32ca48..89949fcbf7 100644 --- a/adodbapi/test/adodbapitest.py +++ b/adodbapi/test/adodbapitest.py @@ -27,7 +27,6 @@ import decimal import random import string -import sys import time import unittest @@ -189,49 +188,6 @@ def testUserDefinedConversions(self): pass self.helpRollbackTblTemp() - def testUserDefinedConversionForExactNumericTypes(self): - # variantConversions is a dictionary of conversion functions - # held internally in adodbapi.apibase - # - # !!! this test intentionally alters the value of what should be constant in the module - # !!! no new code should use this example, to is only a test to see that the - # !!! deprecated way of doing this still works. (use connection.variantConversions) - # - if sys.version_info < (3, 0): ### Py3 need different test - oldconverter = adodbapi.variantConversions[ - ado_consts.adNumeric - ] # keep old function to restore later - # By default decimal and "numbers" are returned as decimals. - # Instead, make numbers return as floats - try: - adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtFloat - self.helpTestDataType( - "decimal(18,2)", "NUMBER", 3.45, compareAlmostEqual=1 - ) - self.helpTestDataType( - "numeric(18,2)", "NUMBER", 3.45, compareAlmostEqual=1 - ) - # now return strings - adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtString - self.helpTestDataType("numeric(18,2)", "NUMBER", "3.45") - # now a completly weird user defined convertion - adodbapi.variantConversions[ado_consts.adNumeric] = ( - lambda x: "!!This function returns a funny unicode string %s!!" % x - ) - self.helpTestDataType( - "numeric(18,2)", - "NUMBER", - "3.45", - allowedReturnValues=[ - "!!This function returns a funny unicode string 3.45!!" - ], - ) - finally: - # now reset the converter to its original function - adodbapi.variantConversions[ado_consts.adNumeric] = ( - oldconverter # Restore the original convertion function - ) - def helpTestDataType( self, sqlDataTypeString, @@ -432,7 +388,7 @@ def testDataTypeInt(self): "bigint", "NUMBER", 3000000000, - allowedReturnValues=[3000000000, int(3000000000)], + allowedReturnValues=[3000000000, 3000000000], ) self.helpTestDataType("int", "NUMBER", 2147483647) @@ -922,7 +878,7 @@ def testAutomaticParamstyle(self): 'returned value:"%s" != test value:"%s"' % (rec[0], inParam), ) self.assertEqual(rec[1], trouble) - # inputs = [u'four',u'five',u'six'] + # inputs = ['four','five','six'] fldId = 10 for inParam in inputs: fldId += 1 diff --git a/adodbapi/test/adodbapitestconfig.py b/adodbapi/test/adodbapitestconfig.py index 9ff2521c01..5ae0b54e0c 100644 --- a/adodbapi/test/adodbapitestconfig.py +++ b/adodbapi/test/adodbapitestconfig.py @@ -32,7 +32,7 @@ if "--help" in sys.argv: print( """Valid command-line switches are: - --package - create a temporary test package, run 2to3 if needed. + --package - create a temporary test package --all - run all possible tests --time - do time format test --nojet - do not test against an ACCESS database file @@ -56,7 +56,7 @@ testfolder = setuptestframework.maketemp() if "--package" in sys.argv: - # create a new adodbapi module -- running 2to3 if needed. + # create a new adodbapi module pth = setuptestframework.makeadopackage(testfolder) else: # use the adodbapi module in which this file appears @@ -66,14 +66,9 @@ sys.path.insert(1, pth) # function to clean up the temporary folder -- calling program must run this function before exit. -cleanup = setuptestframework.getcleanupfunction() -try: - import adodbapi # will (hopefully) be imported using the "pth" discovered above -except SyntaxError: - print( - '\n* * * Are you trying to run Python2 code using Python3? Re-run this test using the "--package" switch.' - ) - sys.exit(11) +cleanup = setuptestframework.cleanup_function +import adodbapi # will (hopefully) be imported using the "pth" discovered above + try: print(adodbapi.version) # show version except: diff --git a/adodbapi/test/dbapi20.py b/adodbapi/test/dbapi20.py index a9da81b7b2..6a86e86161 100644 --- a/adodbapi/test/dbapi20.py +++ b/adodbapi/test/dbapi20.py @@ -11,16 +11,18 @@ -- Ian Bicking """ -__version__ = "$Revision: 1.15.0 $"[11:-2] +__version__ = "$Revision: 1.16.0 $"[11:-2] __author__ = "Stuart Bishop " -import sys import time import unittest # set this to "True" to follow API 2.0 to the letter TEST_FOR_NON_IDEMPOTENT_CLOSE = False +# Revision 1.16 2022/12/07 22:00:00 Avasam +# Drop support for EOL Python 3.6 and below + # Revision 1.15 2019/11/22 00:50:00 kf7xm # Make Turn off IDEMPOTENT_CLOSE a proper skipTest @@ -199,12 +201,8 @@ def test_paramstyle(self): def test_Exceptions(self): # Make sure required exceptions exist, and are in the # defined heirarchy. - if sys.version[0] == "3": # under Python 3 StardardError no longer exists - self.assertTrue(issubclass(self.driver.Warning, Exception)) - self.assertTrue(issubclass(self.driver.Error, Exception)) - else: - self.failUnless(issubclass(self.driver.Warning, Exception)) - self.failUnless(issubclass(self.driver.Error, Exception)) + self.assertTrue(issubclass(self.driver.Warning, Exception)) + self.assertTrue(issubclass(self.driver.Error, Exception)) self.assertTrue(issubclass(self.driver.InterfaceError, self.driver.Error)) self.assertTrue(issubclass(self.driver.DatabaseError, self.driver.Error)) diff --git a/adodbapi/test/setuptestframework.py b/adodbapi/test/setuptestframework.py index 53dda825ce..8ef91ead82 100644 --- a/adodbapi/test/setuptestframework.py +++ b/adodbapi/test/setuptestframework.py @@ -1,9 +1,8 @@ -#!/usr/bin/python2 +#!/usr/bin/python3 # Configure this in order to run the testcases. -"setuptestframework.py v 2.6.0.8" +"setuptestframework.py v 3.7.0.0" import os import shutil -import sys import tempfile @@ -17,7 +16,7 @@ def maketemp(): return tempdir -def _cleanup_function(testfolder, mdb_name): +def cleanup_function(testfolder, mdb_name): try: os.unlink(os.path.join(testfolder, mdb_name)) except: @@ -29,10 +28,6 @@ def _cleanup_function(testfolder, mdb_name): pass # test package not present -def getcleanupfunction(): - return _cleanup_function - - def find_ado_path(): adoName = os.path.normpath(os.getcwd() + "/../../adodbapi.py") adoPackage = os.path.dirname(adoName) @@ -54,13 +49,7 @@ def makeadopackage(testfolder): for f in os.listdir(adoPath): if f.endswith(".py"): shutil.copy(os.path.join(adoPath, f), newpackage) - if sys.version_info >= (3, 0): # only when running Py3.n - save = sys.stdout - sys.stdout = None - from lib2to3.main import main # use 2to3 to make test package - main("lib2to3.fixes", args=["-n", "-w", newpackage]) - sys.stdout = save return testfolder else: raise OSError("Connot find source of adodbapi to test.") diff --git a/adodbapi/test/test_adodbapi_dbapi20.py b/adodbapi/test/test_adodbapi_dbapi20.py index e5d36282c9..66548c1487 100644 --- a/adodbapi/test/test_adodbapi_dbapi20.py +++ b/adodbapi/test/test_adodbapi_dbapi20.py @@ -16,7 +16,7 @@ if pth not in sys.path: sys.path.insert(1, pth) # function to clean up the temporary folder -- calling program must run this function before exit. -cleanup = setuptestframework.getcleanupfunction() +cleanup = setuptestframework.cleanup_function import adodbapi import adodbapi.is64bit as is64bit