diff --git a/NEWS b/NEWS index ef24fbcc..76333959 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ What's new in psycopg 2.8.6 - Fixed memory leak changing connection encoding to the current one (:ticket:`#1101`). - Fixed search of mxDateTime headers in virtualenvs (:ticket:`#996`). +- Added missing values from errorcodes (:ticket:`#1133`). - Wheel package compiled against OpenSSL 1.1.1g. diff --git a/lib/errorcodes.py b/lib/errorcodes.py index fc5261ad..38bc7081 100644 --- a/lib/errorcodes.py +++ b/lib/errorcodes.py @@ -43,7 +43,8 @@ def lookup(code, _cache={}): tmp = {} for k, v in globals().items(): if isinstance(v, str) and len(v) in (2, 5): - tmp[v] = k + # Strip trailing underscore used to disambiguate duplicate values + tmp[v] = k.rstrip("_") assert tmp @@ -106,7 +107,7 @@ SUCCESSFUL_COMPLETION = '00000' # Class 01 - Warning WARNING = '01000' NULL_VALUE_ELIMINATED_IN_SET_FUNCTION = '01003' -STRING_DATA_RIGHT_TRUNCATION = '01004' +STRING_DATA_RIGHT_TRUNCATION_ = '01004' PRIVILEGE_NOT_REVOKED = '01006' PRIVILEGE_NOT_GRANTED = '01007' IMPLICIT_ZERO_BIT_PADDING = '01008' @@ -164,7 +165,7 @@ DATA_EXCEPTION = '22000' STRING_DATA_RIGHT_TRUNCATION = '22001' NULL_VALUE_NO_INDICATOR_PARAMETER = '22002' NUMERIC_VALUE_OUT_OF_RANGE = '22003' -NULL_VALUE_NOT_ALLOWED = '22004' +NULL_VALUE_NOT_ALLOWED_ = '22004' ERROR_IN_ASSIGNMENT = '22005' INVALID_DATETIME_FORMAT = '22007' DATETIME_FIELD_OVERFLOW = '22008' @@ -273,9 +274,9 @@ INVALID_TRANSACTION_TERMINATION = '2D000' # Class 2F - SQL Routine Exception SQL_ROUTINE_EXCEPTION = '2F000' -MODIFYING_SQL_DATA_NOT_PERMITTED = '2F002' -PROHIBITED_SQL_STATEMENT_ATTEMPTED = '2F003' -READING_SQL_DATA_NOT_PERMITTED = '2F004' +MODIFYING_SQL_DATA_NOT_PERMITTED_ = '2F002' +PROHIBITED_SQL_STATEMENT_ATTEMPTED_ = '2F003' +READING_SQL_DATA_NOT_PERMITTED_ = '2F004' FUNCTION_EXECUTED_NO_RETURN_STATEMENT = '2F005' # Class 34 - Invalid Cursor Name diff --git a/scripts/make_errorcodes.py b/scripts/make_errorcodes.py index 26269c7e..118ff2f6 100755 --- a/scripts/make_errorcodes.py +++ b/scripts/make_errorcodes.py @@ -36,6 +36,8 @@ def main(): classes, errors = fetch_errors( ['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11', '12']) + disambiguate(errors) + f = open(filename, "w") for line in file_start: print(line, file=f) @@ -116,6 +118,18 @@ def fetch_errors(versions): return classes, errors +def disambiguate(errors): + """ + Change name for exception defined more than once. + + Change the first occurrence, because before introdcing the function + they were pretty much lost (see ticket #1133) + """ + # Note: if some code is missing it will be caught downstream + for code in "01004 22004 2F002 2F003 2F004".split(): + errors[code[:2]][code] += "_" + + def generate_module_data(classes, errors): yield "" yield "# Error classes" @@ -124,11 +138,16 @@ def generate_module_data(classes, errors): .strip().replace(" ", "_").replace('/', "_").upper() yield "CLASS_%s = %r" % (err, clscode) + seen = set() + for clscode, clslabel in sorted(classes.items()): yield "" yield "# %s" % clslabel for errcode, errlabel in sorted(errors[clscode].items()): + if errlabel in seen: + raise Exception("error label already seen: %s" % errlabel) + seen.add(errlabel) yield "%s = %r" % (errlabel, errcode) diff --git a/tests/test_errcodes.py b/tests/test_errcodes.py index 3074bae1..3ce3282e 100755 --- a/tests/test_errcodes.py +++ b/tests/test_errcodes.py @@ -57,6 +57,14 @@ class ErrocodeTests(ConnectingTestCase): len(errs), MAX_CYCLES, errs[0].__class__.__name__, errs[0])) + def test_ambiguous_names(self): + self.assertEqual( + errorcodes.lookup('2F004'), "READING_SQL_DATA_NOT_PERMITTED") + self.assertEqual( + errorcodes.lookup('38004'), "READING_SQL_DATA_NOT_PERMITTED") + self.assertEqual(errorcodes.READING_SQL_DATA_NOT_PERMITTED, '38004') + self.assertEqual(errorcodes.READING_SQL_DATA_NOT_PERMITTED_, '2F004') + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)