From: Federico Caselli Date: Sun, 21 Nov 2021 20:17:27 +0000 (+0100) Subject: Clean up most py3k compat X-Git-Tag: rel_2_0_0b1~635^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31acba8ff7c123a20ae308b7f4ab6df3df264b48;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Clean up most py3k compat Change-Id: I8172fdcc3103ff92aa049827728484c8779af6b7 --- diff --git a/examples/elementtree/adjacency_list.py b/examples/elementtree/adjacency_list.py index 9d2c78157e..0502e3e9e3 100644 --- a/examples/elementtree/adjacency_list.py +++ b/examples/elementtree/adjacency_list.py @@ -18,7 +18,6 @@ class. """ # PART I - Imports/Configuration -from __future__ import print_function import os import re diff --git a/examples/elementtree/optimized_al.py b/examples/elementtree/optimized_al.py index 1c16e1c8a4..8aea977f12 100644 --- a/examples/elementtree/optimized_al.py +++ b/examples/elementtree/optimized_al.py @@ -8,9 +8,6 @@ """ # PART I - Imports/Configuration - -from __future__ import print_function - import os import re from xml.etree import ElementTree diff --git a/examples/vertical/dictlike.py b/examples/vertical/dictlike.py index 9d2eb4a229..b74b317762 100644 --- a/examples/vertical/dictlike.py +++ b/examples/vertical/dictlike.py @@ -30,7 +30,6 @@ accessing them like a Python dict can be very convenient. The example below can be used with many common vertical schemas as-is or with minor adaptations. """ -from __future__ import unicode_literals class ProxiedDictMixin: diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py index 411985b5dc..3aff7b479e 100644 --- a/lib/sqlalchemy/connectors/pyodbc.py +++ b/lib/sqlalchemy/connectors/pyodbc.py @@ -6,6 +6,7 @@ # the MIT License: https://www.opensource.org/licenses/mit-license.php import re +from urllib.parse import unquote_plus from . import Connector from .. import util @@ -49,7 +50,7 @@ class PyODBCConnector(Connector): connect_args[param] = util.asbool(keys.pop(param)) if "odbc_connect" in keys: - connectors = [util.unquote_plus(keys.pop("odbc_connect"))] + connectors = [unquote_plus(keys.pop("odbc_connect"))] else: def check_quote(token): diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index e5745bf698..353c78c76f 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -847,7 +847,6 @@ from ...types import NVARCHAR from ...types import SMALLINT from ...types import TEXT from ...types import VARCHAR -from ...util import compat from ...util import update_wrapper from ...util.langhelpers import public_factory @@ -1084,7 +1083,7 @@ class _MSDate(sqltypes.Date): def process(value): if isinstance(value, datetime.datetime): return value.date() - elif isinstance(value, util.string_types): + elif isinstance(value, str): m = self._reg.match(value) if not m: raise ValueError( @@ -1126,7 +1125,7 @@ class TIME(sqltypes.TIME): def process(value): if isinstance(value, datetime.datetime): return value.time() - elif isinstance(value, util.string_types): + elif isinstance(value, str): m = self._reg.match(value) if not m: raise ValueError( @@ -2383,9 +2382,7 @@ class MSDDLCompiler(compiler.DDLCompiler): # handle other included columns if index.dialect_options["mssql"]["include"]: inclusions = [ - index.table.c[col] - if isinstance(col, util.string_types) - else col + index.table.c[col] if isinstance(col, str) else col for col in index.dialect_options["mssql"]["include"] ] @@ -3256,8 +3253,8 @@ class MSDialect(default.DefaultDialect): cdict["identity"] = {} else: if isinstance(coltype, sqltypes.BigInteger): - start = compat.long_type(identity_start) - increment = compat.long_type(identity_increment) + start = int(identity_start) + increment = int(identity_increment) elif isinstance(coltype, sqltypes.Integer): start = int(identity_start) increment = int(identity_increment) diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 6ce55d3925..7bcc2a4675 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -398,7 +398,7 @@ class _ODBCDateTimeBindProcessor: def process(value): if value is None: return None - elif isinstance(value, util.string_types): + elif isinstance(value, str): # if a string was passed directly, allow it through return value elif not value.tzinfo or (not self.timezone and not self.has_tz): @@ -577,7 +577,7 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect): tup[4], tup[5], tup[6] // 1000, - util.timezone( + datetime.timezone( datetime.timedelta(hours=tup[7], minutes=tup[8]) ), ) diff --git a/lib/sqlalchemy/dialects/mysql/__init__.py b/lib/sqlalchemy/dialects/mysql/__init__.py index 9fe6f6d849..3897202139 100644 --- a/lib/sqlalchemy/dialects/mysql/__init__.py +++ b/lib/sqlalchemy/dialects/mysql/__init__.py @@ -5,6 +5,8 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +from . import aiomysql # noqa +from . import asyncmy # noqa from . import base # noqa from . import cymysql # noqa from . import mariadbconnector # noqa @@ -51,10 +53,6 @@ from .dml import insert from .expression import match from ...util import compat -if compat.py3k: - from . import aiomysql # noqa - from . import asyncmy # noqa - # default dialect base.dialect = dialect = mysqldb.dialect diff --git a/lib/sqlalchemy/dialects/mysql/asyncmy.py b/lib/sqlalchemy/dialects/mysql/asyncmy.py index 0fca338f56..b595714603 100644 --- a/lib/sqlalchemy/dialects/mysql/asyncmy.py +++ b/lib/sqlalchemy/dialects/mysql/asyncmy.py @@ -28,11 +28,12 @@ This dialect should normally be used only with the """ # noqa +from contextlib import asynccontextmanager + from .pymysql import MySQLDialect_pymysql from ... import pool from ... import util from ...engine import AdaptedConnection -from ...util.concurrency import asynccontextmanager from ...util.concurrency import asyncio from ...util.concurrency import await_fallback from ...util.concurrency import await_only diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 54fe1f57f8..f77d839f33 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1469,7 +1469,7 @@ class MySQLCompiler(compiler.SQLCompiler): keywords at the start of a SELECT. """ - if isinstance(select._distinct, util.string_types): + if isinstance(select._distinct, str): util.warn_deprecated( "Sending string values for 'distinct' is deprecated in the " "MySQL dialect and will be removed in a future release. " @@ -2425,7 +2425,7 @@ class MySQLDialect(default.DefaultDialect): raise NotImplementedError() val = row[0] cursor.close() - if util.py3k and isinstance(val, bytes): + if isinstance(val, bytes): val = val.decode() return val.upper().replace("-", " ") @@ -2456,7 +2456,7 @@ class MySQLDialect(default.DefaultDialect): cursor.execute("SELECT VERSION()") val = cursor.fetchone()[0] cursor.close() - if util.py3k and isinstance(val, bytes): + if isinstance(val, bytes): val = val.decode() return self._parse_server_version(val) @@ -2607,8 +2607,8 @@ class MySQLDialect(default.DefaultDialect): sql.bindparam("table_name", type_=Unicode), ), { - "table_schema": util.text_type(schema), - "table_name": util.text_type(table_name), + "table_schema": str(schema), + "table_name": str(table_name), }, ) return bool(rs.scalar()) @@ -2627,8 +2627,8 @@ class MySQLDialect(default.DefaultDialect): "TABLE_SCHEMA=:schema_name" ), dict( - name=util.text_type(sequence_name), - schema_name=util.text_type(schema), + name=str(sequence_name), + schema_name=str(schema), ), ) return cursor.first() is not None @@ -3228,7 +3228,7 @@ class _DecodingRow: if isinstance(item, _array): item = item.tostring() - if self.charset and isinstance(item, util.binary_type): + if self.charset and isinstance(item, bytes): return item.decode(self.charset) else: return item @@ -3237,7 +3237,7 @@ class _DecodingRow: item = getattr(self.rowproxy, attr) if isinstance(item, _array): item = item.tostring() - if self.charset and isinstance(item, util.binary_type): + if self.charset and isinstance(item, bytes): return item.decode(self.charset) else: return item diff --git a/lib/sqlalchemy/dialects/mysql/cymysql.py b/lib/sqlalchemy/dialects/mysql/cymysql.py index f729e4a18c..4fe4410317 100644 --- a/lib/sqlalchemy/dialects/mysql/cymysql.py +++ b/lib/sqlalchemy/dialects/mysql/cymysql.py @@ -33,7 +33,7 @@ class _cymysqlBIT(BIT): def process(value): if value is not None: v = 0 - for i in util.iterbytes(value): + for i in iter(value): v = v << 8 | i return v return value diff --git a/lib/sqlalchemy/dialects/mysql/enumerated.py b/lib/sqlalchemy/dialects/mysql/enumerated.py index 9f9a838c5d..b84608f580 100644 --- a/lib/sqlalchemy/dialects/mysql/enumerated.py +++ b/lib/sqlalchemy/dialects/mysql/enumerated.py @@ -201,7 +201,7 @@ class SET(_StringType): super_convert = super(SET, self).result_processor(dialect, coltype) def process(value): - if isinstance(value, util.string_types): + if isinstance(value, str): # MySQLdb returns a string, let's parse if super_convert: value = super_convert(value) @@ -222,7 +222,7 @@ class SET(_StringType): def process(value): if value is None: return None - elif isinstance(value, util.int_types + util.string_types): + elif isinstance(value, (int, str)): if super_convert: return super_convert(value) else: @@ -237,9 +237,7 @@ class SET(_StringType): def process(value): # accept strings and int (actually bitflag) values directly - if value is not None and not isinstance( - value, util.int_types + util.string_types - ): + if value is not None and not isinstance(value, (int, str)): value = ",".join(value) if super_convert: diff --git a/lib/sqlalchemy/dialects/mysql/json.py b/lib/sqlalchemy/dialects/mysql/json.py index 384d3b9b62..c46878fc38 100644 --- a/lib/sqlalchemy/dialects/mysql/json.py +++ b/lib/sqlalchemy/dialects/mysql/json.py @@ -4,9 +4,6 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php - -from __future__ import absolute_import - from ... import types as sqltypes diff --git a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py index fef4f14ca0..7b62e9ed1d 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py +++ b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py @@ -32,36 +32,17 @@ from ... import util class MySQLCompiler_mysqlconnector(MySQLCompiler): def visit_mod_binary(self, binary, operator, **kw): - if self.dialect._mysqlconnector_double_percents: - return ( - self.process(binary.left, **kw) - + " %% " - + self.process(binary.right, **kw) - ) - else: - return ( - self.process(binary.left, **kw) - + " % " - + self.process(binary.right, **kw) - ) - - def post_process_text(self, text): - if self.dialect._mysqlconnector_double_percents: - return text.replace("%", "%%") - else: - return text - - def escape_literal_column(self, text): - if self.dialect._mysqlconnector_double_percents: - return text.replace("%", "%%") - else: - return text + return ( + self.process(binary.left, **kw) + + " % " + + self.process(binary.right, **kw) + ) class MySQLIdentifierPreparer_mysqlconnector(MySQLIdentifierPreparer): @property def _double_percents(self): - return self.dialect._mysqlconnector_double_percents + return False @_double_percents.setter def _double_percents(self, value): @@ -69,10 +50,7 @@ class MySQLIdentifierPreparer_mysqlconnector(MySQLIdentifierPreparer): def _escape_identifier(self, value): value = value.replace(self.escape_quote, self.escape_to_quote) - if self.dialect._mysqlconnector_double_percents: - return value.replace("%", "%%") - else: - return value + return value class _myconnpyBIT(BIT): @@ -163,10 +141,6 @@ class MySQLDialect_mysqlconnector(MySQLDialect): if m: return tuple(int(x) for x in m.group(1, 2, 3) if x is not None) - @util.memoized_property - def _mysqlconnector_double_percents(self): - return not util.py3k and self._mysqlconnector_version_info < (2, 0) - def _detect_charset(self, connection): return connection.connection.charset diff --git a/lib/sqlalchemy/dialects/mysql/pymysql.py b/lib/sqlalchemy/dialects/mysql/pymysql.py index 3c30fb9ea1..dd7bd8bda5 100644 --- a/lib/sqlalchemy/dialects/mysql/pymysql.py +++ b/lib/sqlalchemy/dialects/mysql/pymysql.py @@ -39,7 +39,6 @@ to the pymysql driver as well. from .mysqldb import MySQLDialect_mysqldb from ...util import langhelpers -from ...util import py3k class MySQLDialect_pymysql(MySQLDialect_mysqldb): @@ -81,12 +80,10 @@ class MySQLDialect_pymysql(MySQLDialect_mysqldb): else: return False - if py3k: - - def _extract_error_code(self, exception): - if isinstance(exception.args[0], Exception): - exception = exception.args[0] - return exception.args[0] + def _extract_error_code(self, exception): + if isinstance(exception.args[0], Exception): + exception = exception.args[0] + return exception.args[0] dialect = MySQLDialect_pymysql diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index a1d0f80d62..7df2422b3d 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -564,7 +564,6 @@ from ...types import NCHAR from ...types import NVARCHAR from ...types import TIMESTAMP from ...types import VARCHAR -from ...util import compat RESERVED_WORDS = set( "SHARE RAW DROP BETWEEN FROM DESC OPTION PRIOR LONG THEN " @@ -1414,7 +1413,7 @@ class OracleIdentifierPreparer(compiler.IdentifierPreparer): return ( lc_value in self.reserved_words or value[0] in self.illegal_initial_characters - or not self.legal_characters.match(util.text_type(value)) + or not self.legal_characters.match(str(value)) ) def format_savepoint(self, savepoint): @@ -2029,17 +2028,17 @@ class OracleDialect(default.DefaultDialect): value = value.strip() if "START WITH" in option: - identity["start"] = compat.long_type(value) + identity["start"] = int(value) elif "INCREMENT BY" in option: - identity["increment"] = compat.long_type(value) + identity["increment"] = int(value) elif "MAX_VALUE" in option: - identity["maxvalue"] = compat.long_type(value) + identity["maxvalue"] = int(value) elif "MIN_VALUE" in option: - identity["minvalue"] = compat.long_type(value) + identity["minvalue"] = int(value) elif "CYCLE_FLAG" in option: identity["cycle"] = value == "Y" elif "CACHE_SIZE" in option: - identity["cache"] = compat.long_type(value) + identity["cache"] = int(value) elif "ORDER_FLAG" in option: identity["order"] = value == "Y" return identity diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 2cfcb0e5c3..07317126d9 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -430,9 +430,6 @@ SQLAlchemy type (or a subclass of such). as better integration of outputtypehandlers. """ # noqa - -from __future__ import absolute_import - import decimal import random import re @@ -1127,7 +1124,7 @@ class OracleDialect_cx_oracle(OracleDialect): and default_type is not cx_Oracle.NCLOB ): return cursor.var( - util.text_type, + str, size, cursor.arraysize, **dialect._cursor_var_unicode_kwargs @@ -1213,7 +1210,7 @@ class OracleDialect_cx_oracle(OracleDialect): opts.setdefault("threaded", self._cx_oracle_threaded) def convert_cx_oracle_constant(value): - if isinstance(value, util.string_types): + if isinstance(value, str): try: int_val = int(value) except ValueError: diff --git a/lib/sqlalchemy/dialects/postgresql/__init__.py b/lib/sqlalchemy/dialects/postgresql/__init__.py index 056de66be1..08b05dc748 100644 --- a/lib/sqlalchemy/dialects/postgresql/__init__.py +++ b/lib/sqlalchemy/dialects/postgresql/__init__.py @@ -4,6 +4,7 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +from . import asyncpg # noqa from . import base from . import pg8000 # noqa from . import psycopg2 # noqa @@ -57,9 +58,6 @@ from .ranges import TSRANGE from .ranges import TSTZRANGE from ...util import compat -if compat.py3k: - from . import asyncpg # noqa - base.dialect = dialect = psycopg2.dialect diff --git a/lib/sqlalchemy/dialects/postgresql/array.py b/lib/sqlalchemy/dialects/postgresql/array.py index 0cb574dacf..6145590354 100644 --- a/lib/sqlalchemy/dialects/postgresql/array.py +++ b/lib/sqlalchemy/dialects/postgresql/array.py @@ -374,12 +374,12 @@ class ARRAY(sqltypes.ARRAY): def process(value): if value is None: return value - # isinstance(value, util.string_types) is required to handle + # isinstance(value, str) is required to handle # the case where a TypeDecorator for and Array of Enum is # used like was required in sa < 1.3.17 return super_rp( handle_raw_string(value) - if isinstance(value, util.string_types) + if isinstance(value, str) else value ) diff --git a/lib/sqlalchemy/dialects/postgresql/asyncpg.py b/lib/sqlalchemy/dialects/postgresql/asyncpg.py index fe1f9fd5ad..d6cde00873 100644 --- a/lib/sqlalchemy/dialects/postgresql/asyncpg.py +++ b/lib/sqlalchemy/dialects/postgresql/asyncpg.py @@ -99,6 +99,7 @@ To disable the prepared statement cache, use a value of zero:: """ # noqa import collections +import collections.abc as collections_abc import decimal import json as _py_json import re @@ -216,8 +217,8 @@ class AsyncpgJSONStrIndexType(sqltypes.JSON.JSONStrIndexType): class AsyncpgJSONPathType(json.JSONPathType): def bind_processor(self, dialect): def process(value): - assert isinstance(value, util.collections_abc.Sequence) - tokens = [util.text_type(elem) for elem in value] + assert isinstance(value, collections_abc.Sequence) + tokens = [str(elem) for elem in value] return tokens return process diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 583d9c2630..d00318fc80 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1721,7 +1721,7 @@ class UUID(sqltypes.TypeEngine): def coerce_compared_value(self, op, value): """See :meth:`.TypeEngine.coerce_compared_value` for a description.""" - if isinstance(value, util.string_types): + if isinstance(value, str): return self else: return super(UUID, self).coerce_compared_value(op, value) @@ -1731,7 +1731,7 @@ class UUID(sqltypes.TypeEngine): def process(value): if value is not None: - value = util.text_type(value) + value = str(value) return value return process @@ -2375,7 +2375,7 @@ class PGCompiler(compiler.SQLCompiler): target_text = "(%s)" % ", ".join( ( self.preparer.quote(c) - if isinstance(c, util.string_types) + if isinstance(c, str) else self.process(c, include_table=False, use_schema=False) ) for c in clause.inferred_target_elements @@ -2451,7 +2451,7 @@ class PGCompiler(compiler.SQLCompiler): for k, v in set_parameters.items(): key_text = ( self.preparer.quote(k) - if isinstance(k, util.string_types) + if isinstance(k, str) else self.process(k, use_schema=False) ) value_text = self.process( @@ -2653,9 +2653,7 @@ class PGDDLCompiler(compiler.DDLCompiler): includeclause = index.dialect_options["postgresql"]["include"] if includeclause: inclusions = [ - index.table.c[col] - if isinstance(col, util.string_types) - else col + index.table.c[col] if isinstance(col, str) else col for col in includeclause ] text += " INCLUDE (%s)" % ", ".join( @@ -3326,7 +3324,7 @@ class PGDialect(default.DefaultDialect): sql.text(query).bindparams( sql.bindparam( "schema", - util.text_type(schema.lower()), + str(schema.lower()), type_=sqltypes.Unicode, ) ) @@ -3347,7 +3345,7 @@ class PGDialect(default.DefaultDialect): ).bindparams( sql.bindparam( "name", - util.text_type(table_name), + str(table_name), type_=sqltypes.Unicode, ) ) @@ -3361,12 +3359,12 @@ class PGDialect(default.DefaultDialect): ).bindparams( sql.bindparam( "name", - util.text_type(table_name), + str(table_name), type_=sqltypes.Unicode, ), sql.bindparam( "schema", - util.text_type(schema), + str(schema), type_=sqltypes.Unicode, ), ) @@ -3384,12 +3382,12 @@ class PGDialect(default.DefaultDialect): ).bindparams( sql.bindparam( "name", - util.text_type(sequence_name), + str(sequence_name), type_=sqltypes.Unicode, ), sql.bindparam( "schema", - util.text_type(schema), + str(schema), type_=sqltypes.Unicode, ), ) @@ -3418,15 +3416,11 @@ class PGDialect(default.DefaultDialect): """ query = sql.text(query) query = query.bindparams( - sql.bindparam( - "typname", util.text_type(type_name), type_=sqltypes.Unicode - ) + sql.bindparam("typname", str(type_name), type_=sqltypes.Unicode) ) if schema is not None: query = query.bindparams( - sql.bindparam( - "nspname", util.text_type(schema), type_=sqltypes.Unicode - ) + sql.bindparam("nspname", str(schema), type_=sqltypes.Unicode) ) cursor = connection.execute(query) return bool(cursor.scalar()) @@ -3471,9 +3465,9 @@ class PGDialect(default.DefaultDialect): ) # Since we're binding to unicode, table_name and schema_name must be # unicode. - table_name = util.text_type(table_name) + table_name = str(table_name) if schema is not None: - schema = util.text_type(schema) + schema = str(schema) s = sql.text(query).bindparams(table_name=sqltypes.Unicode) s = s.columns(oid=sqltypes.Integer) if schema: @@ -3573,7 +3567,7 @@ class PGDialect(default.DefaultDialect): ).bindparams( sql.bindparam( "schema", - util.text_type(schema), + str(schema), type_=sqltypes.Unicode, ), ) diff --git a/lib/sqlalchemy/dialects/postgresql/dml.py b/lib/sqlalchemy/dialects/postgresql/dml.py index bb6345cf43..c561b73a1f 100644 --- a/lib/sqlalchemy/dialects/postgresql/dml.py +++ b/lib/sqlalchemy/dialects/postgresql/dml.py @@ -185,7 +185,7 @@ class OnConflictClause(ClauseElement): def __init__(self, constraint=None, index_elements=None, index_where=None): if constraint is not None: - if not isinstance(constraint, util.string_types) and isinstance( + if not isinstance(constraint, str) and isinstance( constraint, (schema.Index, schema.Constraint, ext.ExcludeConstraint), ): @@ -197,7 +197,7 @@ class OnConflictClause(ClauseElement): "'constraint' and 'index_elements' are mutually exclusive" ) - if isinstance(constraint, util.string_types): + if isinstance(constraint, str): self.constraint_target = constraint self.inferred_target_elements = None self.inferred_target_whereclause = None diff --git a/lib/sqlalchemy/dialects/postgresql/ext.py b/lib/sqlalchemy/dialects/postgresql/ext.py index f9e4c1d6cb..f779a80108 100644 --- a/lib/sqlalchemy/dialects/postgresql/ext.py +++ b/lib/sqlalchemy/dialects/postgresql/ext.py @@ -4,9 +4,9 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +from itertools import zip_longest from .array import ARRAY -from ... import util from ...sql import coercions from ...sql import elements from ...sql import expression @@ -237,7 +237,7 @@ class ExcludeConstraint(ColumnCollectionConstraint): name, operator, ) - for (expr, name, operator), colexpr in util.zip_longest( + for (expr, name, operator), colexpr in zip_longest( self._render_exprs, self.columns ) ] diff --git a/lib/sqlalchemy/dialects/postgresql/hstore.py b/lib/sqlalchemy/dialects/postgresql/hstore.py index 85d678ef54..2ade4b7c18 100644 --- a/lib/sqlalchemy/dialects/postgresql/hstore.py +++ b/lib/sqlalchemy/dialects/postgresql/hstore.py @@ -9,7 +9,6 @@ import re from .array import ARRAY from ... import types as sqltypes -from ... import util from ...sql import functions as sqlfunc from ...sql import operators @@ -413,7 +412,7 @@ def _serialize_hstore(val): def esc(s, position): if position == "value" and s is None: return "NULL" - elif isinstance(s, util.string_types): + elif isinstance(s, str): return '"%s"' % s.replace("\\", "\\\\").replace('"', r"\"") else: raise ValueError( diff --git a/lib/sqlalchemy/dialects/postgresql/json.py b/lib/sqlalchemy/dialects/postgresql/json.py index ef046e3aec..fb7621365a 100644 --- a/lib/sqlalchemy/dialects/postgresql/json.py +++ b/lib/sqlalchemy/dialects/postgresql/json.py @@ -4,10 +4,9 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -from __future__ import absolute_import +import collections.abc as collections_abc from ... import types as sqltypes -from ... import util from ...sql import operators @@ -71,8 +70,8 @@ class JSONPathType(sqltypes.JSON.JSONPathType): super_proc = self.string_bind_processor(dialect) def process(value): - assert isinstance(value, util.collections_abc.Sequence) - tokens = [util.text_type(elem) for elem in value] + assert isinstance(value, collections_abc.Sequence) + tokens = [str(elem) for elem in value] value = "{%s}" % (", ".join(tokens)) if super_proc: value = super_proc(value) @@ -84,8 +83,8 @@ class JSONPathType(sqltypes.JSON.JSONPathType): super_proc = self.string_literal_processor(dialect) def process(value): - assert isinstance(value, util.collections_abc.Sequence) - tokens = [util.text_type(elem) for elem in value] + assert isinstance(value, collections_abc.Sequence) + tokens = [str(elem) for elem in value] value = "{%s}" % (", ".join(tokens)) if super_proc: value = super_proc(value) diff --git a/lib/sqlalchemy/dialects/postgresql/pg8000.py b/lib/sqlalchemy/dialects/postgresql/pg8000.py index 324007e7ea..ac29b28e9e 100644 --- a/lib/sqlalchemy/dialects/postgresql/pg8000.py +++ b/lib/sqlalchemy/dialects/postgresql/pg8000.py @@ -554,7 +554,7 @@ class PGDialect_pg8000(PGDialect): fns = [] def on_connect(conn): - conn.py_types[quoted_name] = conn.py_types[util.text_type] + conn.py_types[quoted_name] = conn.py_types[str] fns.append(on_connect) diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index f62830a0d8..11a5f31a3b 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -441,8 +441,7 @@ place within SQLAlchemy's own marshalling logic, and not that of ``psycopg2`` which may be more performant. """ # noqa -from __future__ import absolute_import - +import collections.abc as collections_abc import decimal import logging import re @@ -466,7 +465,6 @@ from ... import processors from ... import types as sqltypes from ... import util from ...engine import cursor as _cursor -from ...util import collections_abc logger = logging.getLogger("sqlalchemy.dialects.postgresql") diff --git a/lib/sqlalchemy/dialects/sqlite/__init__.py b/lib/sqlalchemy/dialects/sqlite/__init__.py index 6e3ad0e668..e2f59907e2 100644 --- a/lib/sqlalchemy/dialects/sqlite/__init__.py +++ b/lib/sqlalchemy/dialects/sqlite/__init__.py @@ -5,6 +5,7 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +from . import aiosqlite # noqa from . import base # noqa from . import pysqlcipher # noqa from . import pysqlite # noqa @@ -26,10 +27,6 @@ from .base import TIMESTAMP from .base import VARCHAR from .dml import Insert from .dml import insert -from ...util import compat - -if compat.py3k: - from . import aiosqlite # noqa # default dialect base.dialect = dialect = pysqlite.dialect diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 7ded739733..3dea23e18e 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -1324,7 +1324,7 @@ class SQLiteCompiler(compiler.SQLCompiler): target_text = "(%s)" % ", ".join( ( self.preparer.quote(c) - if isinstance(c, util.string_types) + if isinstance(c, str) else self.process(c, include_table=False, use_schema=False) ) for c in clause.inferred_target_elements @@ -1401,7 +1401,7 @@ class SQLiteCompiler(compiler.SQLCompiler): for k, v in set_parameters.items(): key_text = ( self.preparer.quote(k) - if isinstance(k, util.string_types) + if isinstance(k, str) else self.process(k, use_schema=False) ) value_text = self.process( @@ -2110,7 +2110,7 @@ class SQLiteDialect(default.DefaultDialect): coltype = self._resolve_type_affinity(type_) if default is not None: - default = util.text_type(default) + default = str(default) colspec = { "name": name, diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py index 3765191c1b..d3c504fd4d 100644 --- a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py +++ b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py @@ -94,11 +94,8 @@ time, at the expense of slower startup time for new connections. """ # noqa -from __future__ import absolute_import - from .pysqlite import SQLiteDialect_pysqlite from ... import pool -from ... import util class SQLiteDialect_pysqlcipher(SQLiteDialect_pysqlite): @@ -109,18 +106,14 @@ class SQLiteDialect_pysqlcipher(SQLiteDialect_pysqlite): @classmethod def dbapi(cls): - if util.py3k: - try: - import sqlcipher3 as sqlcipher - except ImportError: - pass - else: - return sqlcipher - - from pysqlcipher3 import dbapi2 as sqlcipher - + try: + import sqlcipher3 as sqlcipher + except ImportError: + pass else: - from pysqlcipher import dbapi2 as sqlcipher + return sqlcipher + + from pysqlcipher3 import dbapi2 as sqlcipher return sqlcipher diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 389270e459..d2939c035f 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -4,8 +4,6 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -from __future__ import with_statement - import contextlib import sys @@ -1464,7 +1462,7 @@ class Connection(Connectable): raise except BaseException as e: self._handle_dbapi_exception( - e, util.text_type(statement), parameters, None, None + e, str(statement), parameters, None, None ) return # not reached @@ -2518,7 +2516,7 @@ class Engine(ConnectionEventsTarget, log.Identified): else: yield connection - @util.contextmanager + @contextlib.contextmanager def begin(self): """Return a context manager delivering a :class:`_engine.Connection` with a :class:`.Transaction` established. diff --git a/lib/sqlalchemy/engine/characteristics.py b/lib/sqlalchemy/engine/characteristics.py index 2543f591b1..10455451fd 100644 --- a/lib/sqlalchemy/engine/characteristics.py +++ b/lib/sqlalchemy/engine/characteristics.py @@ -1,9 +1,7 @@ import abc -from ..util import ABC - -class ConnectionCharacteristic(ABC): +class ConnectionCharacteristic(abc.ABC): """An abstract base for an object that can set, get and reset a per-connection characteristic, typically one that gets reset when the connection is returned to the connection pool. diff --git a/lib/sqlalchemy/engine/cursor.py b/lib/sqlalchemy/engine/cursor.py index 54db9f6c27..1f1a2fcf1e 100644 --- a/lib/sqlalchemy/engine/cursor.py +++ b/lib/sqlalchemy/engine/cursor.py @@ -669,7 +669,7 @@ class CursorResultMetaData(ResultMetaData): "_keymap": { key: (rec[MD_INDEX], rec[MD_RESULT_MAP_INDEX], _UNPICKLED, key) for key, rec in self._keymap.items() - if isinstance(key, util.string_types + util.int_types) + if isinstance(key, (str, int)) }, "_keys": self._keys, "_translated_indexes": self._translated_indexes, diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 3af24d9135..a47ed963d9 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -16,6 +16,7 @@ as the base class for their own corresponding classes. import functools import random import re +from time import perf_counter import weakref from . import characteristics @@ -780,7 +781,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): self.execution_options = execution_options - self.unicode_statement = util.text_type(compiled) + self.unicode_statement = str(compiled) if compiled.schema_translate_map: schema_translate_map = self.execution_options.get( "schema_translate_map", {} @@ -1003,7 +1004,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): if self.compiled is None: return "raw sql" - now = util.perf_counter() + now = perf_counter() ch = self.cache_hit @@ -1515,7 +1516,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): for key in compiled_params ) return self._execute_scalar( - util.text_type(compiled), type_, parameters=parameters + str(compiled), type_, parameters=parameters ) current_parameters = None diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index c918f15b3c..7abc404f0a 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -47,7 +47,7 @@ def cache(fn, self, con, *args, **kw): return fn(self, con, *args, **kw) key = ( fn.__name__, - tuple(a for a in args if isinstance(a, util.string_types)), + tuple(a for a in args if isinstance(a, str)), tuple((k, v) for k, v in kw.items() if k != "info_cache"), ) ret = info_cache.get(key) diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index 4187c6c13a..e2f4033e03 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -8,6 +8,7 @@ """Define generic result set constructs.""" +import collections.abc as collections_abc import functools import itertools import operator @@ -19,7 +20,6 @@ from .. import util from ..sql.base import _generative from ..sql.base import HasMemoized from ..sql.base import InPlaceGenerative -from ..util import collections_abc if _baserow_usecext: diff --git a/lib/sqlalchemy/engine/row.py b/lib/sqlalchemy/engine/row.py index 782fc21b8b..1a8c4e5557 100644 --- a/lib/sqlalchemy/engine/row.py +++ b/lib/sqlalchemy/engine/row.py @@ -8,11 +8,11 @@ """Define row constructs including :class:`.Row`.""" +import collections.abc as collections_abc import operator from .. import util from ..sql import util as sql_util -from ..util.compat import collections_abc MD_INDEX = 0 # integer index in cursor.description diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index 7f09b1eac3..c83753bdc9 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -14,15 +14,17 @@ argument; alternatively, the URL is a public-facing construct which can be used directly and is also accepted directly by ``create_engine()``. """ +import collections.abc as collections_abc import re +from urllib.parse import parse_qsl +from urllib.parse import quote_plus +from urllib.parse import unquote from .interfaces import Dialect from .. import exc from .. import util from ..dialects import plugins from ..dialects import registry -from ..util import collections_abc -from ..util import compat class URL( @@ -165,7 +167,7 @@ class URL( @classmethod def _assert_str(cls, v, paramname): - if not isinstance(v, compat.string_types): + if not isinstance(v, str): raise TypeError("%s must be a string" % paramname) return v @@ -193,7 +195,7 @@ class URL( ) def _assert_str(v): - if not isinstance(v, compat.string_types): + if not isinstance(v, str): raise TypeError("Query dictionary keys must be strings") return v @@ -308,9 +310,7 @@ class URL( :meth:`_engine.URL.update_query_dict` """ # noqa: E501 - return self.update_query_pairs( - util.parse_qsl(query_string), append=append - ) + return self.update_query_pairs(parse_qsl(query_string), append=append) def update_query_pairs(self, key_value_pairs, append=False): """Return a new :class:`_engine.URL` object with the @@ -548,7 +548,7 @@ class URL( keys = list(self.query) keys.sort() s += "?" + "&".join( - "%s=%s" % (util.quote_plus(k), util.quote_plus(element)) + "%s=%s" % (quote_plus(k), quote_plus(element)) for k in keys for element in util.to_list(self.query[k]) ) @@ -711,7 +711,7 @@ def make_url(name_or_url): existing URL object is passed, just returns the object. """ - if isinstance(name_or_url, util.string_types): + if isinstance(name_or_url, str): return _parse_rfc1738_args(name_or_url) else: return name_or_url @@ -744,7 +744,7 @@ def _parse_rfc1738_args(name): if components["query"] is not None: query = {} - for key, value in util.parse_qsl(components["query"]): + for key, value in parse_qsl(components["query"]): if key in query: query[key] = util.to_list(query[key]) query[key].append(value) @@ -780,15 +780,14 @@ def _rfc_1738_quote(text): return re.sub(r"[:@/]", lambda m: "%%%X" % ord(m.group(0)), text) -def _rfc_1738_unquote(text): - return util.unquote(text) +_rfc_1738_unquote = unquote def _parse_keyvalue_args(name): m = re.match(r"(\w+)://(.*)", name) if m is not None: (name, args) = m.group(1, 2) - opts = dict(util.parse_qsl(args)) + opts = dict(parse_qsl(args)) return URL(name, *opts) else: return None diff --git a/lib/sqlalchemy/engine/util.py b/lib/sqlalchemy/engine/util.py index 4467bafd35..732ae7fa1b 100644 --- a/lib/sqlalchemy/engine/util.py +++ b/lib/sqlalchemy/engine/util.py @@ -5,9 +5,10 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +import collections.abc as collections_abc + from .. import exc from .. import util -from ..util import collections_abc from ..util import immutabledict diff --git a/lib/sqlalchemy/event/api.py b/lib/sqlalchemy/event/api.py index 5487c9f1af..8c928e3fe4 100644 --- a/lib/sqlalchemy/event/api.py +++ b/lib/sqlalchemy/event/api.py @@ -8,8 +8,6 @@ """Public API functions for the event system. """ -from __future__ import absolute_import - from .base import _registrars from .registry import _EventKey from .. import exc diff --git a/lib/sqlalchemy/event/attr.py b/lib/sqlalchemy/event/attr.py index 77eb0472c7..be36be6614 100644 --- a/lib/sqlalchemy/event/attr.py +++ b/lib/sqlalchemy/event/attr.py @@ -28,10 +28,6 @@ as well as support for subclass propagation (e.g. events assigned to ``Pool`` vs. ``QueuePool``) are all implemented here. """ - -from __future__ import absolute_import -from __future__ import with_statement - import collections from itertools import chain import weakref diff --git a/lib/sqlalchemy/event/base.py b/lib/sqlalchemy/event/base.py index b084207b4e..1041647c8c 100644 --- a/lib/sqlalchemy/event/base.py +++ b/lib/sqlalchemy/event/base.py @@ -15,8 +15,6 @@ at the class level of a particular ``_Dispatch`` class as well as within instances of ``_Dispatch``. """ -from __future__ import absolute_import - import weakref from .attr import _ClsLevelDispatch @@ -218,7 +216,7 @@ def _remove_dispatcher(cls): del _registrars[k] -class Events(util.with_metaclass(_EventMeta, object)): +class Events(metaclass=_EventMeta): """Define event listening functions for a particular target type.""" @staticmethod diff --git a/lib/sqlalchemy/event/registry.py b/lib/sqlalchemy/event/registry.py index d81f27cd48..94cb5cb958 100644 --- a/lib/sqlalchemy/event/registry.py +++ b/lib/sqlalchemy/event/registry.py @@ -14,9 +14,6 @@ membership in all those collections can be revoked at once, based on an equivalent :class:`._EventKey`. """ - -from __future__ import absolute_import - import collections import types import weakref diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py index ef246d04fb..e35c41836b 100644 --- a/lib/sqlalchemy/exc.py +++ b/lib/sqlalchemy/exc.py @@ -53,34 +53,27 @@ class HasDescriptionCode: class SQLAlchemyError(HasDescriptionCode, Exception): """Generic error class.""" - def _message(self, as_unicode=compat.py3k): + def _message(self): # rules: # - # 1. under py2k, for __str__ return single string arg as it was - # given without converting to unicode. for __unicode__ - # do a conversion but check that it's not unicode already just in - # case - # - # 2. under py3k, single arg string will usually be a unicode + # 1. single arg string will usually be a unicode # object, but since __str__() must return unicode, check for # bytestring just in case # - # 3. for multiple self.args, this is not a case in current + # 2. for multiple self.args, this is not a case in current # SQLAlchemy though this is happening in at least one known external # library, call str() which does a repr(). # if len(self.args) == 1: text = self.args[0] - if as_unicode and isinstance(text, compat.binary_types): + if isinstance(text, bytes): text = compat.decode_backslashreplace(text, "utf-8") # This is for when the argument is not a string of any sort. # Otherwise, converting this exception to string would fail for # non-string arguments. - elif compat.py3k or not as_unicode: - text = str(text) else: - text = compat.text_type(text) + text = str(text) return text else: @@ -89,8 +82,8 @@ class SQLAlchemyError(HasDescriptionCode, Exception): # a repr() of the tuple return str(self.args) - def _sql_message(self, as_unicode): - message = self._message(as_unicode) + def _sql_message(self): + message = self._message() if self.code: message = "%s %s" % (message, self._code_str()) @@ -98,10 +91,7 @@ class SQLAlchemyError(HasDescriptionCode, Exception): return message def __str__(self): - return self._sql_message(compat.py3k) - - def __unicode__(self): - return self._sql_message(as_unicode=True) + return self._sql_message() class ArgumentError(SQLAlchemyError): @@ -458,17 +448,12 @@ class StatementError(SQLAlchemyError): ) @_preloaded.preload_module("sqlalchemy.sql.util") - def _sql_message(self, as_unicode): + def _sql_message(self): util = _preloaded.preloaded.sql_util - details = [self._message(as_unicode=as_unicode)] + details = [self._message()] if self.statement: - if not as_unicode and not compat.py3k: - stmt_detail = "[SQL: %s]" % compat.safe_bytestring( - self.statement - ) - else: - stmt_detail = "[SQL: %s]" % self.statement + stmt_detail = "[SQL: %s]" % self.statement details.append(stmt_detail) if self.params: if self.hide_parameters: diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py index 0aa836a3c7..9e8f84f46c 100644 --- a/lib/sqlalchemy/ext/associationproxy.py +++ b/lib/sqlalchemy/ext/associationproxy.py @@ -1093,14 +1093,11 @@ class _AssociationList(_AssociationCollection): col.append(item) def count(self, value): - return sum( - [ - 1 - for _ in util.itertools_filter( - lambda v: v == value, iter(self) - ) - ] - ) + count = 0 + for v in self: + if v == value: + count += 1 + return count def extend(self, values): for v in values: diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index d2c9690561..89da4b4972 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -540,7 +540,7 @@ class AsyncSession(ReversibleProxy): await self.close() def _maker_context_manager(self): - # no @contextlib.asynccontextmanager until python3.7, gr + # TODO: can this use asynccontextmanager ?? return _AsyncSessionContextManager(self) diff --git a/lib/sqlalchemy/ext/baked.py b/lib/sqlalchemy/ext/baked.py index efdafff968..e91277311a 100644 --- a/lib/sqlalchemy/ext/baked.py +++ b/lib/sqlalchemy/ext/baked.py @@ -13,6 +13,7 @@ compiled result to be fully cached. """ +import collections.abc as collections_abc import logging from .. import exc as sa_exc @@ -24,7 +25,6 @@ from ..orm.session import Session from ..sql import func from ..sql import literal_column from ..sql import util as sql_util -from ..util import collections_abc log = logging.getLogger(__name__) diff --git a/lib/sqlalchemy/ext/indexable.py b/lib/sqlalchemy/ext/indexable.py index 313ad11af6..70673ac268 100644 --- a/lib/sqlalchemy/ext/indexable.py +++ b/lib/sqlalchemy/ext/indexable.py @@ -221,8 +221,6 @@ The above query will render:: WHERE CAST(person.data ->> %(data_1)s AS INTEGER) < %(param_1)s """ # noqa -from __future__ import absolute_import - from .. import inspect from .. import util from ..ext.hybrid import hybrid_property diff --git a/lib/sqlalchemy/ext/serializer.py b/lib/sqlalchemy/ext/serializer.py index 18a54e0798..c9bff9d286 100644 --- a/lib/sqlalchemy/ext/serializer.py +++ b/lib/sqlalchemy/ext/serializer.py @@ -53,6 +53,8 @@ needed for: """ +from io import BytesIO +import pickle import re from .. import Column @@ -64,9 +66,6 @@ from ..orm.mapper import Mapper from ..orm.session import Session from ..util import b64decode from ..util import b64encode -from ..util import byte_buffer -from ..util import pickle -from ..util import text_type __all__ = ["Serializer", "Deserializer", "dumps", "loads"] @@ -92,11 +91,9 @@ def Serializer(*args, **kw): pickle.dumps(obj._annotations["parententity"].class_) ) else: - id_ = "table:" + text_type(obj.key) + id_ = f"table:{obj.key}" elif isinstance(obj, Column) and isinstance(obj.table, Table): - id_ = ( - "column:" + text_type(obj.table.key) + ":" + text_type(obj.key) - ) + id_ = f"column:{obj.table.key}:{obj.key}" elif isinstance(obj, Session): id_ = "session:" elif isinstance(obj, Engine): @@ -129,7 +126,7 @@ def Deserializer(file, metadata=None, scoped_session=None, engine=None): return None def persistent_load(id_): - m = our_ids.match(text_type(id_)) + m = our_ids.match(str(id_)) if not m: return None else: @@ -165,13 +162,13 @@ def Deserializer(file, metadata=None, scoped_session=None, engine=None): def dumps(obj, protocol=pickle.HIGHEST_PROTOCOL): - buf = byte_buffer() + buf = BytesIO() pickler = Serializer(buf, protocol) pickler.dump(obj) return buf.getvalue() def loads(data, metadata=None, scoped_session=None, engine=None): - buf = byte_buffer(data) + buf = BytesIO(data) unpickler = Deserializer(buf, metadata, scoped_session, engine) return unpickler.load() diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index dc58138667..aa48bf496d 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -15,6 +15,8 @@ defines a large part of the ORM's interactivity. """ import operator +from typing import Generic +from typing import TypeVar from . import collections from . import exc as orm_exc @@ -366,13 +368,8 @@ def _queryable_attribute_unreduce(key, mapped_class, parententity, entity): return getattr(entity, key) -if util.py3k: - from typing import TypeVar, Generic - - _T = TypeVar("_T") - _Generic_T = Generic[_T] -else: - _Generic_T = type("_Generic_T", (), {}) +_T = TypeVar("_T") +_Generic_T = Generic[_T] class Mapped(QueryableAttribute, _Generic_T): @@ -1555,12 +1552,7 @@ class CollectionAttributeImpl(AttributeImpl): if hasattr(iterable, "_sa_iterator"): iterable = iterable._sa_iterator() elif setting_type is dict: - if util.py3k: - iterable = iterable.values() - else: - iterable = getattr( - iterable, "itervalues", iterable.values - )() + iterable = iterable.values() else: iterable = iter(iterable) new_values = list(iterable) diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py index 01d77e92b7..ccb88866e9 100644 --- a/lib/sqlalchemy/orm/collections.py +++ b/lib/sqlalchemy/orm/collections.py @@ -1615,9 +1615,7 @@ __interfaces = { _set_decorators(), ), # decorators are required for dicts and object collections. - dict: ({"iterator": "values"}, _dict_decorators()) - if util.py3k - else ({"iterator": "itervalues"}, _dict_decorators()), + dict: ({"iterator": "values"}, _dict_decorators()), } diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py index 986daf7eb8..4a3d5286ba 100644 --- a/lib/sqlalchemy/orm/context.py +++ b/lib/sqlalchemy/orm/context.py @@ -1434,11 +1434,9 @@ class ORMSelectCompileState(ORMCompileState, SelectState): aliased_generation = flags["aliased_generation"] # do a quick inspect to accommodate for a lambda - if right is not None and not isinstance(right, util.string_types): + if right is not None and not isinstance(right, str): right = inspect(right) - if onclause is not None and not isinstance( - onclause, util.string_types - ): + if onclause is not None and not isinstance(onclause, str): onclause = inspect(onclause) # legacy vvvvvvvvvvvvvvvvvvvvvvvvvv @@ -1459,9 +1457,7 @@ class ORMSelectCompileState(ORMCompileState, SelectState): # legacy ^^^^^^^^^^^^^^^^^^^^^^^^^^^ if ( - isinstance( - right, (interfaces.PropComparator, util.string_types) - ) + isinstance(right, (interfaces.PropComparator, str)) and onclause is None ): onclause = right @@ -1481,7 +1477,7 @@ class ORMSelectCompileState(ORMCompileState, SelectState): else: of_type = None - if isinstance(onclause, util.string_types): + if isinstance(onclause, str): # string given, e.g. query(Foo).join("bar"). # we look to the left entity or what we last joined # towards diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py index 21bb9d81b2..6bc857094c 100644 --- a/lib/sqlalchemy/orm/decl_api.py +++ b/lib/sqlalchemy/orm/decl_api.py @@ -5,8 +5,6 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php """Public API functions and helpers for declarative.""" -from __future__ import absolute_import - import itertools import re import weakref diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index bab890b828..b92ae5aa48 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -5,8 +5,6 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php """Internal implementation for declarative.""" -from __future__ import absolute_import - import collections import weakref diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index c425f012ba..2641610850 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -16,8 +16,6 @@ are exposed when inspecting mappings. """ -from __future__ import absolute_import - import collections from . import exc as orm_exc diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py index 94ad7b80dd..d6ee9b7a72 100644 --- a/lib/sqlalchemy/orm/loading.py +++ b/lib/sqlalchemy/orm/loading.py @@ -12,7 +12,6 @@ the functions here are called primarily by Query, Mapper, as well as some of the attribute loading strategies. """ -from __future__ import absolute_import from . import attributes from . import exc as orm_exc diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 4de12b88c7..60083bf4db 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -14,9 +14,9 @@ This is a semi-private module; the main configurational API of the ORM is available in :class:`~sqlalchemy.orm.`. """ -from __future__ import absolute_import from collections import deque +from functools import reduce from itertools import chain import sys import weakref @@ -1153,9 +1153,7 @@ class Mapper( if with_polymorphic == "*": self.with_polymorphic = ("*", None) elif isinstance(with_polymorphic, (tuple, list)): - if isinstance( - with_polymorphic[0], util.string_types + (tuple, list) - ): + if isinstance(with_polymorphic[0], (str, tuple, list)): self.with_polymorphic = with_polymorphic else: self.with_polymorphic = (with_polymorphic, None) @@ -1500,7 +1498,7 @@ class Mapper( if self.polymorphic_on is not None: setter = True - if isinstance(self.polymorphic_on, util.string_types): + if isinstance(self.polymorphic_on, str): # polymorphic_on specified as a string - link # it to mapped ColumnProperty try: @@ -3314,7 +3312,7 @@ class Mapper( cols = set(table.c) for m in self.iterate_to_root(): if m._inherits_equated_pairs and cols.intersection( - util.reduce( + reduce( set.union, [l.proxy_set for l, r in m._inherits_equated_pairs], ) diff --git a/lib/sqlalchemy/orm/path_registry.py b/lib/sqlalchemy/orm/path_registry.py index 6bebbd006e..0aa9de817b 100644 --- a/lib/sqlalchemy/orm/path_registry.py +++ b/lib/sqlalchemy/orm/path_registry.py @@ -8,6 +8,7 @@ """ +from functools import reduce from itertools import chain import logging @@ -221,7 +222,7 @@ class PathRegistry(HasCacheKey): @classmethod def coerce(cls, raw): - return util.reduce(lambda prev, next: prev[next], raw, cls.root) + return reduce(lambda prev, next: prev[next], raw, cls.root) def token(self, token): if token.endswith(":" + _WILDCARD_TOKEN): @@ -232,7 +233,7 @@ class PathRegistry(HasCacheKey): raise exc.ArgumentError("invalid token: %s" % token) def __add__(self, other): - return util.reduce(lambda prev, next: prev[next], other.path, self) + return reduce(lambda prev, next: prev[next], other.path, self) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.path) diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py index 3c0c637a22..6dd827b43a 100644 --- a/lib/sqlalchemy/orm/persistence.py +++ b/lib/sqlalchemy/orm/persistence.py @@ -13,9 +13,9 @@ The functions here are called only by the unit of work functions in unitofwork.py. """ - from itertools import chain from itertools import groupby +from itertools import zip_longest import operator from . import attributes @@ -1171,7 +1171,7 @@ def _emit_insert_statements( last_inserted_params, inserted_primary_key, returned_defaults, - ) in util.zip_longest( + ) in zip_longest( records, c.context.compiled_parameters, c.inserted_primary_key_rows, @@ -2189,7 +2189,7 @@ class BulkORMUpdate(UpdateDMLState, BulkUDCompileState): for k, v in kv_iterator: k = coercions.expect(roles.DMLColumnRole, k) - if isinstance(k, util.string_types): + if isinstance(k, str): desc = _entity_namespace_key(mapper, k, default=NO_VALUE) if desc is NO_VALUE: values.append( diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index fa230d1093..de46f84a75 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -11,7 +11,6 @@ This is a private module which defines the behavior of individual ORM- mapped attributes. """ -from __future__ import absolute_import from . import attributes from .descriptor_props import CompositeProperty diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 8cf253efb0..38eb33bc41 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -18,6 +18,7 @@ ORM session, whereas the ``Select`` construct interacts directly with the database to return iterable result sets. """ +import collections.abc as collections_abc import itertools import operator import types @@ -68,7 +69,6 @@ from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL from ..sql.selectable import SelectBase from ..sql.selectable import SelectStatementGrouping from ..sql.visitors import InternalTraversal -from ..util import collections_abc __all__ = ["Query", "QueryContext", "aliased"] diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index b692daf21b..b4aef874f1 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -13,8 +13,6 @@ SQL annotation and aliasing behavior focused on the `primaryjoin` and `secondaryjoin` aspects of :func:`_orm.relationship`. """ -from __future__ import absolute_import - import collections import re import weakref @@ -2108,7 +2106,7 @@ class RelationshipProperty(StrategizedProperty): mapperlib = util.preloaded.orm_mapper - if isinstance(self.argument, util.string_types): + if isinstance(self.argument, str): argument = self._clsregistry_resolve_name(self.argument)() elif callable(self.argument) and not isinstance( @@ -2183,7 +2181,7 @@ class RelationshipProperty(StrategizedProperty): ): attr_value = getattr(self, attr) - if isinstance(attr_value, util.string_types): + if isinstance(attr_value, str): setattr( self, attr, @@ -2420,7 +2418,7 @@ class RelationshipProperty(StrategizedProperty): if self.parent.non_primary: return if self.backref is not None and not self.back_populates: - if isinstance(self.backref, util.string_types): + if isinstance(self.backref, str): backref_key, kwargs = self.backref, {} else: backref_key, kwargs = self.backref diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index e18e358471..8212a111d5 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -6,7 +6,7 @@ # the MIT License: https://www.opensource.org/licenses/mit-license.php """Provides the Session class and related utilities.""" - +import contextlib import itertools import sys import weakref @@ -1134,7 +1134,7 @@ class Session(_SessionClassMethods): def __exit__(self, type_, value, traceback): self.close() - @util.contextmanager + @contextlib.contextmanager def _maker_context_manager(self): with self: with self.begin(): @@ -2113,7 +2113,7 @@ class Session(_SessionClassMethods): return loading.get_from_identity(self, mapper, key, passive) @property - @util.contextmanager + @contextlib.contextmanager def no_autoflush(self): """Return a context manager that disables autoflush. diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 130ff2d1eb..ff4ac9d335 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -7,7 +7,6 @@ """sqlalchemy.orm.interfaces.LoaderStrategy implementations, and related MapperOptions.""" -from __future__ import absolute_import import collections import itertools diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 997fca1ac2..eccb42164d 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -301,7 +301,7 @@ class Load(Generative, LoaderOption): "refer to a mapped entity" % (path.prop,) ) - if isinstance(attr, util.string_types): + if isinstance(attr, str): default_token = attr.endswith(_DEFAULT_TOKEN) attr_str_name = attr @@ -643,7 +643,7 @@ class Load(Generative, LoaderOption): i = -1 for i, (c_token, p_token) in enumerate(zip(to_chop, path.path)): - if isinstance(c_token, util.string_types): + if isinstance(c_token, str): # TODO: this is approximated from the _UnboundLoad # version and probably has issues, not fully covered. @@ -816,9 +816,7 @@ class _UnboundLoad(Load): cloned.strategy = self.strategy if self.path: attr = self.path[-1] - if isinstance(attr, util.string_types) and attr.endswith( - _DEFAULT_TOKEN - ): + if isinstance(attr, str) and attr.endswith(_DEFAULT_TOKEN): attr = attr.split(":")[0] + ":" + _WILDCARD_TOKEN cloned._generate_path( parent.path + self.path[0:-1], attr, self.strategy, None @@ -851,7 +849,7 @@ class _UnboundLoad(Load): def _generate_path(self, path, attr, for_strategy, wildcard_key): if ( wildcard_key - and isinstance(attr, util.string_types) + and isinstance(attr, str) and attr in (_WILDCARD_TOKEN, _DEFAULT_TOKEN) ): if attr == _DEFAULT_TOKEN: @@ -914,7 +912,7 @@ class _UnboundLoad(Load): opt = _UnboundLoad() def _split_key(key): - if isinstance(key, util.string_types): + if isinstance(key, str): # coerce fooload('*') into "default loader strategy" if key == _WILDCARD_TOKEN: return (_DEFAULT_TOKEN,) @@ -945,7 +943,7 @@ class _UnboundLoad(Load): for i, (c_token, (p_entity, p_prop)) in enumerate( zip(to_chop, path.pairs()) ): - if isinstance(c_token, util.string_types): + if isinstance(c_token, str): if i == 0 and c_token.endswith(":" + _DEFAULT_TOKEN): return to_chop elif ( @@ -1045,7 +1043,7 @@ class _UnboundLoad(Load): # what entity we are referring towards. token = start_path[0] - if isinstance(token, util.string_types): + if isinstance(token, str): entity = self._find_entity_basestring(entities, token, raiseerr) elif isinstance(token, PropComparator): prop = token.property diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 3295bd39e7..8403dd5ac8 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -82,7 +82,7 @@ class CascadeOptions(frozenset): ) def __new__(cls, value_list): - if isinstance(value_list, util.string_types) or value_list is None: + if isinstance(value_list, str) or value_list is None: return cls.from_string(value_list) values = set(value_list) if values.difference(cls._allowed_cascades): @@ -1645,7 +1645,7 @@ class _ORMJoin(expression.Join): # then the "_joined_from_info" concept can go left_orm_info = getattr(left, "_joined_from_info", left_info) self._joined_from_info = right_info - if isinstance(onclause, util.string_types): + if isinstance(onclause, str): onclause = getattr(left_orm_info.entity, onclause) # #### @@ -1870,7 +1870,7 @@ def with_parent(instance, prop, from_entity=None): .. versionadded:: 1.2 """ - if isinstance(prop, util.string_types): + if isinstance(prop, str): util.warn_deprecated_20( "Using strings to indicate relationship names in the ORM " "with_parent() function is deprecated and will be removed " diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py index b57da3289b..2c74dd523b 100644 --- a/lib/sqlalchemy/sql/base.py +++ b/lib/sqlalchemy/sql/base.py @@ -10,7 +10,10 @@ """ +import collections.abc as collections_abc +from functools import reduce import itertools +from itertools import zip_longest import operator import re @@ -27,7 +30,6 @@ from .. import util from ..util import HasMemoized from ..util import hybridmethod - coercions = None elements = None type_api = None @@ -176,7 +178,7 @@ def _cloned_difference(a, b): ) -class _DialectArgView(util.collections_abc.MutableMapping): +class _DialectArgView(collections_abc.MutableMapping): """A dictionary view of dialect-level arguments in the form _. @@ -236,7 +238,7 @@ class _DialectArgView(util.collections_abc.MutableMapping): ) -class _DialectArgDict(util.collections_abc.MutableMapping): +class _DialectArgDict(collections_abc.MutableMapping): """A dictionary view of dialect-level arguments for a specific dialect. @@ -615,7 +617,7 @@ class _MetaOptions(type): return o1 -class Options(util.with_metaclass(_MetaOptions)): +class Options(metaclass=_MetaOptions): """A cacheable option dictionary with defaults.""" def __init__(self, **kw): @@ -638,7 +640,7 @@ class Options(util.with_metaclass(_MetaOptions)): def __eq__(self, other): # TODO: very inefficient. This is used only in test suites # right now. - for a, b in util.zip_longest(self._cache_attrs, other._cache_attrs): + for a, b in zip_longest(self._cache_attrs, other._cache_attrs): if getattr(self, a) != getattr(other, b): return False return True @@ -1238,7 +1240,7 @@ class ColumnCollection: try: return self._index[key] except KeyError as err: - if isinstance(key, util.int_types): + if isinstance(key, int): util.raise_(IndexError(key), replace_context=err) else: raise @@ -1251,7 +1253,7 @@ class ColumnCollection: def __contains__(self, key): if key not in self._index: - if not isinstance(key, util.string_types): + if not isinstance(key, str): raise exc.ArgumentError( "__contains__ requires a string argument" ) @@ -1263,7 +1265,7 @@ class ColumnCollection: """Compare this :class:`_expression.ColumnCollection` to another based on the names of the keys""" - for l, r in util.zip_longest(self, other): + for l, r in zip_longest(self, other): if l is not r: return False else: @@ -1359,7 +1361,7 @@ class ColumnCollection: def contains_column(self, col): """Checks if a column object exists in this collection""" if col not in self._colset: - if isinstance(col, util.string_types): + if isinstance(col, str): raise exc.ArgumentError( "contains_column cannot be used with string arguments. " "Use ``col_name in table.c`` instead." @@ -1451,7 +1453,7 @@ class ColumnCollection: # columns that have no reference to the target # column (also occurs with CompoundSelect) - col_distance = util.reduce( + col_distance = reduce( operator.add, [ sc._annotations.get("weight", 1) @@ -1459,7 +1461,7 @@ class ColumnCollection: if sc.shares_lineage(column) ], ) - c_distance = util.reduce( + c_distance = reduce( operator.add, [ sc._annotations.get("weight", 1) diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index f051ba12f3..480d2c680e 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -5,6 +5,7 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +import collections.abc as collections_abc import numbers import re @@ -17,7 +18,6 @@ from .visitors import Visitable from .. import exc from .. import inspection from .. import util -from ..util import collections_abc elements = None @@ -224,7 +224,7 @@ def expect_col_expression_collection(role, expressions): column = None resolved = expect(role, expr) - if isinstance(resolved, util.string_types): + if isinstance(resolved, str): strname = resolved = expr else: cols = [] @@ -303,7 +303,7 @@ class _ReturnsStringKey: def _implicit_coercions( self, original_element, resolved, argname=None, **kw ): - if isinstance(original_element, util.string_types): + if isinstance(original_element, str): return original_element else: self._raise_for_expected(original_element, argname, resolved) @@ -362,7 +362,7 @@ class _NoTextCoercion: __slots__ = () def _literal_coercion(self, element, argname=None, **kw): - if isinstance(element, util.string_types) and issubclass( + if isinstance(element, str) and issubclass( elements.TextClause, self._role_class ): _no_text_coercion(element, argname) @@ -380,7 +380,7 @@ class _CoerceLiterals: return _no_text_coercion(element, argname) def _literal_coercion(self, element, argname=None, **kw): - if isinstance(element, util.string_types): + if isinstance(element, str): if self._coerce_star and element == "*": return elements.ColumnClause("*", is_literal=True) else: @@ -542,7 +542,7 @@ class InElementImpl(RoleImpl): def _literal_coercion(self, element, expr, operator, **kw): if isinstance(element, collections_abc.Iterable) and not isinstance( - element, util.string_types + element, str ): non_literal_expressions = {} element = list(element) @@ -729,7 +729,7 @@ class TruncatedLabelImpl(_StringOnly, RoleImpl): def _implicit_coercions( self, original_element, resolved, argname=None, **kw ): - if isinstance(original_element, util.string_types): + if isinstance(original_element, str): return resolved else: self._raise_for_expected(original_element, argname, resolved) @@ -844,7 +844,7 @@ class StatementImpl(_CoerceLiterals, RoleImpl): def _post_coercion(self, resolved, original_element, argname=None, **kw): if resolved is not original_element and not isinstance( - original_element, util.string_types + original_element, str ): # use same method as Connection uses; this will later raise # ObjectNotExecutableError diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 29aa57faab..0dd61d6758 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -22,12 +22,13 @@ To generate user-defined SQL strings, see :doc:`/ext/compiler`. """ - import collections +import collections.abc as collections_abc import contextlib import itertools import operator import re +from time import perf_counter from . import base from . import coercions @@ -453,7 +454,7 @@ class Compiled: self.string = self.preparer._render_schema_translates( self.string, schema_translate_map ) - self._gen_time = util.perf_counter() + self._gen_time = perf_counter() def _execute_on_connection( self, connection, distilled_params, execution_options @@ -505,7 +506,7 @@ class Compiled: return self.construct_params() -class TypeCompiler(util.with_metaclass(util.EnsureKWArgType, object)): +class TypeCompiler(metaclass=util.EnsureKWArgType): """Produces DDL specification for TypeEngine objects.""" ensure_kwarg = r"visit_\w+" @@ -2026,10 +2027,8 @@ class SQLCompiler(Compiled): elif typ_dialect_impl._is_tuple_type or ( typ_dialect_impl._isnull - and isinstance(values[0], util.collections_abc.Sequence) - and not isinstance( - values[0], util.string_types + util.binary_types - ) + and isinstance(values[0], collections_abc.Sequence) + and not isinstance(values[0], (str, bytes)) ): replacement_expression = ( @@ -2077,10 +2076,8 @@ class SQLCompiler(Compiled): elif typ_dialect_impl._is_tuple_type or ( typ_dialect_impl._isnull - and isinstance(values[0], util.collections_abc.Sequence) - and not isinstance( - values[0], util.string_types + util.binary_types - ) + and isinstance(values[0], collections_abc.Sequence) + and not isinstance(values[0], (str, bytes)) ): assert not typ_dialect_impl._is_array to_update = [ @@ -4355,7 +4352,7 @@ class DDLCompiler(Compiled): except exc.CompileError as ce: util.raise_( exc.CompileError( - util.u("(in table '%s', column '%s'): %s") + "(in table '%s', column '%s'): %s" % (table.description, column.name, ce.args[0]) ), from_=ce, @@ -4628,7 +4625,7 @@ class DDLCompiler(Compiled): def get_column_default_string(self, column): if isinstance(column.server_default, schema.DefaultClause): - if isinstance(column.server_default.arg, util.string_types): + if isinstance(column.server_default.arg, str): return self.sql_compiler.render_literal_value( column.server_default.arg, sqltypes.STRINGTYPE ) @@ -5126,14 +5123,14 @@ class IdentifierPreparer: return ( lc_value in self.reserved_words or value[0] in self.illegal_initial_characters - or not self.legal_characters.match(util.text_type(value)) + or not self.legal_characters.match(str(value)) or (lc_value != value) ) def _requires_quotes_illegal_chars(self, value): """Return True if the given identifier requires quoting, but not taking case convention into account.""" - return not self.legal_characters.match(util.text_type(value)) + return not self.legal_characters.match(str(value)) def quote_schema(self, schema, force=None): """Conditionally quote a schema name. diff --git a/lib/sqlalchemy/sql/crud.py b/lib/sqlalchemy/sql/crud.py index a9c9cb4c13..a313257ca3 100644 --- a/lib/sqlalchemy/sql/crud.py +++ b/lib/sqlalchemy/sql/crud.py @@ -373,7 +373,7 @@ def _scan_cols( cols = [ stmt.table.c[key] for key in parameter_ordering - if isinstance(key, util.string_types) and key in stmt.table.c + if isinstance(key, str) and key in stmt.table.c ] + [c for c in stmt.table.c if c.key not in ordered_keys] else: diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py index f732ff2b0f..74e7df821a 100644 --- a/lib/sqlalchemy/sql/ddl.py +++ b/lib/sqlalchemy/sql/ddl.py @@ -180,7 +180,7 @@ class DDLElement(roles.DDLRole, Executable, _DDLCompiles): self.state = state def _should_execute(self, target, bind, **kw): - if isinstance(self.dialect, util.string_types): + if isinstance(self.dialect, str): if self.dialect != bind.engine.name: return False elif isinstance(self.dialect, (tuple, list, set)): @@ -288,7 +288,7 @@ class DDL(DDLElement): """ - if not isinstance(statement, util.string_types): + if not isinstance(statement, str): raise exc.ArgumentError( "Expected a string or unicode SQL statement, got '%r'" % statement diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index e45c6b8883..93cd912a72 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -9,6 +9,8 @@ Provide :class:`_expression.Insert`, :class:`_expression.Update` and :class:`_expression.Delete`. """ +import collections.abc as collections_abc + from sqlalchemy.types import NullType from . import coercions from . import roles @@ -31,7 +33,6 @@ from .selectable import ReturnsRows from .visitors import InternalTraversal from .. import exc from .. import util -from ..util import collections_abc class DMLState(CompileState): diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index ca65f21122..76633cdd81 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -10,8 +10,6 @@ """ -from __future__ import unicode_literals - import itertools import operator import re @@ -3869,7 +3867,7 @@ class BinaryExpression(ColumnElement): ): # allow compatibility with libraries that # refer to BinaryExpression directly and pass strings - if isinstance(operator, util.string_types): + if isinstance(operator, str): operator = operators.custom_op(operator) self._orig = (left.__hash__(), right.__hash__()) self._propagate_attrs = left._propagate_attrs or right._propagate_attrs @@ -4638,10 +4636,7 @@ class NamedColumn(ColumnElement): @util.memoized_property def description(self): - if util.py3k: - return self.name - else: - return self.name.encode("ascii", "backslashreplace") + return self.name @HasMemoized.memoized_attribute def _tq_key_label(self): @@ -5068,7 +5063,7 @@ class ReleaseSavepointClause(_IdentifiedClause): __visit_name__ = "release_savepoint" -class quoted_name(util.MemoizedSlots, util.text_type): +class quoted_name(util.MemoizedSlots, str): """Represent a SQL identifier combined with quoting preferences. :class:`.quoted_name` is a Python unicode/str subclass which @@ -5138,19 +5133,19 @@ class quoted_name(util.MemoizedSlots, util.text_type): return self def __reduce__(self): - return quoted_name, (util.text_type(self), self.quote) + return quoted_name, (str(self), self.quote) def _memoized_method_lower(self): if self.quote: return self else: - return util.text_type(self).lower() + return str(self).lower() def _memoized_method_upper(self): if self.quote: return self else: - return util.text_type(self).upper() + return str(self).upper() def _find_columns(clause): @@ -5238,7 +5233,7 @@ class _truncated_label(quoted_name): return super(_truncated_label, cls).__new__(cls, value, quote) def __reduce__(self): - return self.__class__, (util.text_type(self), self.quote) + return self.__class__, (str(self), self.quote) def apply_map(self, map_): return self @@ -5324,26 +5319,26 @@ class _anonymous_label(_truncated_label): def __add__(self, other): if "%" in other and not isinstance(other, _anonymous_label): - other = util.text_type(other).replace("%", "%%") + other = str(other).replace("%", "%%") else: - other = util.text_type(other) + other = str(other) return _anonymous_label( quoted_name( - util.text_type.__add__(self, other), + str.__add__(self, other), self.quote, ) ) def __radd__(self, other): if "%" in other and not isinstance(other, _anonymous_label): - other = util.text_type(other).replace("%", "%%") + other = str(other).replace("%", "%%") else: - other = util.text_type(other) + other = str(other) return _anonymous_label( quoted_name( - util.text_type.__add__(other, self), + str.__add__(other, self), self.quote, ) ) diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index 31f4fab0d4..901a3a77ce 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -55,7 +55,7 @@ def register_function(identifier, fn, package="_default"): """ reg = _registry[package] - identifier = util.text_type(identifier).lower() + identifier = str(identifier).lower() # Check if a function with the same identifier is registered. if identifier in reg: @@ -909,7 +909,7 @@ class _GenericMeta(TraversibleType): super(_GenericMeta, cls).__init__(clsname, bases, clsdict) -class GenericFunction(util.with_metaclass(_GenericMeta, Function)): +class GenericFunction(Function, metaclass=_GenericMeta): """Define a 'generic' function. A generic function is a pre-established :class:`.Function` diff --git a/lib/sqlalchemy/sql/lambdas.py b/lib/sqlalchemy/sql/lambdas.py index 1102607993..2256fb5a9b 100644 --- a/lib/sqlalchemy/sql/lambdas.py +++ b/lib/sqlalchemy/sql/lambdas.py @@ -5,6 +5,7 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +import collections.abc as collections_abc import itertools import operator import sys @@ -24,8 +25,6 @@ from .operators import ColumnOperators from .. import exc from .. import inspection from .. import util -from ..util import collections_abc -from ..util import compat _closure_per_cache_key = util.LRUCache(1000) @@ -1111,7 +1110,7 @@ class AnalyzedFunction: code += " return %s\n" % ", ".join("i%d" % i for i in argrange) code += " return closure.__closure__" vars_ = {"o%d" % i: cell_values[i] for i in argrange} - compat.exec_(code, vars_, vars_) + exec(code, vars_, vars_) closure = vars_["make_cells"]() func = type(f)( diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py index 675048cd02..6d45cd033c 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -1394,7 +1394,7 @@ def _escaped_like_impl(fn, other, escape, autoescape): if escape is None: escape = "/" - if not isinstance(other, util.compat.string_types): + if not isinstance(other, str): raise TypeError("String value expected when autoescape=True") if escape not in ("%", "_"): diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 4bd49c4688..eed2fbba1e 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -28,8 +28,6 @@ Since these objects are part of the SQL expression language, they are usable as components in SQL expressions. """ -from __future__ import absolute_import - import collections import sqlalchemy @@ -1572,7 +1570,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): type_ = kwargs.pop("type_", None) args = list(args) if args: - if isinstance(args[0], util.string_types): + if isinstance(args[0], str): if name is not None: raise exc.ArgumentError( "May not pass name positionally and as a keyword." @@ -1819,7 +1817,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): ) if self.index: - if isinstance(self.index, util.string_types): + if isinstance(self.index, str): raise exc.ArgumentError( "The 'index' keyword argument on Column is boolean only. " "To create indexes with a specific name, create an " @@ -1832,7 +1830,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): ) elif self.unique: - if isinstance(self.unique, util.string_types): + if isinstance(self.unique, str): raise exc.ArgumentError( "The 'unique' keyword argument on Column is boolean " "only. To create unique constraints or indexes with a " @@ -2125,7 +2123,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): self._colspec = coercions.expect(roles.DDLReferredColumnRole, column) - if isinstance(self._colspec, util.string_types): + if isinstance(self._colspec, str): self._table_column = None else: self._table_column = self._colspec @@ -2395,7 +2393,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): """ - if isinstance(self._colspec, util.string_types): + if isinstance(self._colspec, str): parenttable, tablekey, colname = self._resolve_col_tokens() @@ -2472,7 +2470,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): table.foreign_keys.add(self) # set up remote ".column" attribute, or a note to pick it # up when the other Table/Column shows up - if isinstance(self._colspec, util.string_types): + if isinstance(self._colspec, str): parenttable, table_key, colname = self._resolve_col_tokens() fk_key = (table_key, colname) if table_key in parenttable.metadata.tables: @@ -3068,9 +3066,7 @@ class DefaultClause(FetchedValue): has_argument = True def __init__(self, arg, for_update=False, _reflected=False): - util.assert_arg_type( - arg, (util.string_types[0], ClauseElement, TextClause), "arg" - ) + util.assert_arg_type(arg, (str, ClauseElement, TextClause), "arg") super(DefaultClause, self).__init__(for_update) self.arg = arg self.reflected = _reflected @@ -3264,7 +3260,7 @@ class ColumnCollectionMixin: def _col_expressions(self, table): return [ - table.c[col] if isinstance(col, util.string_types) else col + table.c[col] if isinstance(col, str) else col for col in self._pending_colargs ] @@ -4422,7 +4418,7 @@ class MetaData(SchemaItem): return "MetaData()" def __contains__(self, table_or_key): - if not isinstance(table_or_key, util.string_types): + if not isinstance(table_or_key, str): table_or_key = table_or_key.key return table_or_key in self.tables @@ -4501,7 +4497,7 @@ class MetaData(SchemaItem): def _bind_to(self, bind): """Bind this MetaData to an Engine, Connection, string or URL.""" url = util.preloaded.engine_url - if isinstance(bind, util.string_types + (url.URL,)): + if isinstance(bind, (str, url.URL)): self._bind = sqlalchemy.create_engine(bind) else: self._bind = bind @@ -4838,7 +4834,7 @@ class ThreadLocalMetaData(MetaData): def _bind_to(self, bind): """Bind to a Connectable in the caller's thread.""" url = util.preloaded.engine_url - if isinstance(bind, util.string_types + (url.URL,)): + if isinstance(bind, (str, url.URL)): try: self.context._engine = self.__engines[bind] except KeyError: diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index a04b205b5f..a77cd173be 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -1624,10 +1624,7 @@ class AliasedReturnsRows(NoInit, FromClause): if isinstance(name, _anonymous_label): name = "anon_1" - if util.py3k: - return name - else: - return name.encode("ascii", "backslashreplace") + return name @property def original(self): @@ -2728,10 +2725,7 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): @util.memoized_property def description(self): - if util.py3k: - return self.name - else: - return self.name.encode("ascii", "backslashreplace") + return self.name def append_column(self, c, **kw): existing = c.table @@ -5267,9 +5261,7 @@ class Select( isinstance(args[0], list) or ( hasattr(args[0], "__iter__") - and not isinstance( - args[0], util.string_types + (ClauseElement,) - ) + and not isinstance(args[0], (str, ClauseElement)) and inspect(args[0], raiseerr=False) is None and not hasattr(args[0], "__clause_element__") ) diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 1687c9f29d..8874f0a83d 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -9,9 +9,11 @@ """ +import collections.abc as collections_abc import datetime as dt import decimal import json +import pickle from . import coercions from . import elements @@ -38,10 +40,8 @@ from .. import exc from .. import inspection from .. import processors from .. import util -from ..util import compat from ..util import langhelpers from ..util import OrderedDict -from ..util import pickle class _LookupExpressionAdapter: @@ -192,7 +192,7 @@ class String(Concatenable, TypeEngine): @property def python_type(self): - return util.text_type + return str def get_dbapi_type(self, dbapi): return dbapi.STRING @@ -721,7 +721,7 @@ class _Binary(TypeEngine): @property def python_type(self): - return util.binary_type + return bytes # Python 3 - sqlite3 doesn't need the `Binary` conversion # here, though pg8000 does to indicate "bytea" @@ -753,7 +753,7 @@ class _Binary(TypeEngine): def coerce_compared_value(self, op, value): """See :meth:`.TypeEngine.coerce_compared_value` for a description.""" - if isinstance(value, util.string_types): + if isinstance(value, str): return self else: return super(_Binary, self).coerce_compared_value(op, value) @@ -1328,9 +1328,7 @@ class Enum(Emulated, String, SchemaType): # here between an INSERT statement and a criteria used in a SELECT, # for now we're staying conservative w/ behavioral changes (perhaps # someone has a trigger that handles strings on INSERT) - if not self.validate_strings and isinstance( - elem, compat.string_types - ): + if not self.validate_strings and isinstance(elem, str): return elem else: util.raise_( @@ -1513,8 +1511,7 @@ class PickleType(TypeDecorator): :param protocol: defaults to ``pickle.HIGHEST_PROTOCOL``. - :param pickler: defaults to cPickle.pickle or pickle.pickle if - cPickle is not available. May be any object with + :param pickler: defaults to pickle. May be any object with pickle-compatible ``dumps`` and ``loads`` methods. :param comparator: a 2-arg callable predicate used @@ -2123,7 +2120,7 @@ class JSON(Indexable, TypeEngine): def process(value): if int_processor and isinstance(value, int): value = int_processor(value) - elif string_processor and isinstance(value, util.string_types): + elif string_processor and isinstance(value, str): value = string_processor(value) return value @@ -2136,7 +2133,7 @@ class JSON(Indexable, TypeEngine): def process(value): if int_processor and isinstance(value, int): value = int_processor(value) - elif string_processor and isinstance(value, util.string_types): + elif string_processor and isinstance(value, str): value = string_processor(value) return value @@ -2178,8 +2175,8 @@ class JSON(Indexable, TypeEngine): """Define comparison operations for :class:`_types.JSON`.""" def _setup_getitem(self, index): - if not isinstance(index, util.string_types) and isinstance( - index, compat.collections_abc.Sequence + if not isinstance(index, str) and isinstance( + index, collections_abc.Sequence ): index = coercions.expect( roles.BinaryElementRole, @@ -2982,15 +2979,10 @@ _type_map = { dt.time: Time(), dt.timedelta: Interval(), util.NoneType: NULLTYPE, + bytes: LargeBinary(), + str: Unicode(), } -if util.py3k: - _type_map[bytes] = LargeBinary() # noqa - _type_map[str] = Unicode() -else: - _type_map[unicode] = Unicode() # noqa - _type_map[str] = String() - _type_map_get = _type_map.get diff --git a/lib/sqlalchemy/sql/traversals.py b/lib/sqlalchemy/sql/traversals.py index 7973b535f7..914a78dae5 100644 --- a/lib/sqlalchemy/sql/traversals.py +++ b/lib/sqlalchemy/sql/traversals.py @@ -1,6 +1,8 @@ from collections import deque from collections import namedtuple +import collections.abc as collections_abc import itertools +from itertools import zip_longest import operator from . import operators @@ -8,9 +10,7 @@ from .visitors import ExtendedInternalTraversal from .visitors import InternalTraversal from .. import util from ..inspection import inspect -from ..util import collections_abc from ..util import HasMemoized -from ..util import py37 SKIP_TRAVERSE = util.symbol("skip_traverse") COMPARE_FAILED = False @@ -331,7 +331,7 @@ class CacheKey(namedtuple("CacheKey", ["key", "bindparams"])): s1 = s1[idx] s2 = s2[idx] - for idx, (e1, e2) in enumerate(util.zip_longest(s1, s2)): + for idx, (e1, e2) in enumerate(zip_longest(s1, s2)): if idx < pickup_index: continue if e1 != e2: @@ -669,38 +669,20 @@ class _CacheKey(ExtendedInternalTraversal): ) def visit_dml_values(self, attrname, obj, parent, anon_map, bindparams): - if py37: - # in py37 we can assume two dictionaries created in the same - # insert ordering will retain that sorting - return ( - attrname, - tuple( - ( - k._gen_cache_key(anon_map, bindparams) - if hasattr(k, "__clause_element__") - else k, - obj[k]._gen_cache_key(anon_map, bindparams), - ) - for k in obj - ), - ) - else: - expr_values = {k for k in obj if hasattr(k, "__clause_element__")} - if expr_values: - # expr values can't be sorted deterministically right now, - # so no cache - anon_map[NO_CACHE] = True - return () - - str_values = expr_values.symmetric_difference(obj) - - return ( - attrname, - tuple( - (k, obj[k]._gen_cache_key(anon_map, bindparams)) - for k in sorted(str_values) - ), - ) + # in py37 we can assume two dictionaries created in the same + # insert ordering will retain that sorting + return ( + attrname, + tuple( + ( + k._gen_cache_key(anon_map, bindparams) + if hasattr(k, "__clause_element__") + else k, + obj[k]._gen_cache_key(anon_map, bindparams), + ) + for k in obj + ), + ) def visit_dml_multi_values( self, attrname, obj, parent, anon_map, bindparams @@ -1040,7 +1022,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): for ( (left_attrname, left_visit_sym), (right_attrname, right_visit_sym), - ) in util.zip_longest( + ) in zip_longest( left._traverse_internals, right._traverse_internals, fillvalue=(None, None), @@ -1098,7 +1080,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_has_cache_key_list( self, attrname, left_parent, left, right_parent, right, **kw ): - for l, r in util.zip_longest(left, right, fillvalue=None): + for l, r in zip_longest(left, right, fillvalue=None): if l._gen_cache_key(self.anon_map[0], []) != r._gen_cache_key( self.anon_map[1], [] ): @@ -1114,7 +1096,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_fromclause_canonical_column_collection( self, attrname, left_parent, left, right_parent, right, **kw ): - for lcol, rcol in util.zip_longest(left, right, fillvalue=None): + for lcol, rcol in zip_longest(left, right, fillvalue=None): self.stack.append((lcol, rcol)) def visit_fromclause_derived_column_collection( @@ -1125,7 +1107,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_string_clauseelement_dict( self, attrname, left_parent, left, right_parent, right, **kw ): - for lstr, rstr in util.zip_longest( + for lstr, rstr in zip_longest( sorted(left), sorted(right), fillvalue=None ): if lstr != rstr: @@ -1135,23 +1117,23 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_clauseelement_tuples( self, attrname, left_parent, left, right_parent, right, **kw ): - for ltup, rtup in util.zip_longest(left, right, fillvalue=None): + for ltup, rtup in zip_longest(left, right, fillvalue=None): if ltup is None or rtup is None: return COMPARE_FAILED - for l, r in util.zip_longest(ltup, rtup, fillvalue=None): + for l, r in zip_longest(ltup, rtup, fillvalue=None): self.stack.append((l, r)) def visit_clauseelement_list( self, attrname, left_parent, left, right_parent, right, **kw ): - for l, r in util.zip_longest(left, right, fillvalue=None): + for l, r in zip_longest(left, right, fillvalue=None): self.stack.append((l, r)) def visit_clauseelement_tuple( self, attrname, left_parent, left, right_parent, right, **kw ): - for l, r in util.zip_longest(left, right, fillvalue=None): + for l, r in zip_longest(left, right, fillvalue=None): self.stack.append((l, r)) def _compare_unordered_sequences(self, seq1, seq2, **kw): @@ -1174,7 +1156,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_fromclause_ordered_set( self, attrname, left_parent, left, right_parent, right, **kw ): - for l, r in util.zip_longest(left, right, fillvalue=None): + for l, r in zip_longest(left, right, fillvalue=None): self.stack.append((l, r)) def visit_string( @@ -1256,7 +1238,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): def visit_prefix_sequence( self, attrname, left_parent, left, right_parent, right, **kw ): - for (l_clause, l_str), (r_clause, r_str) in util.zip_longest( + for (l_clause, l_str), (r_clause, r_str) in zip_longest( left, right, fillvalue=(None, None) ): if l_str != r_str: @@ -1271,7 +1253,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): for ( (l_target, l_onclause, l_from, l_flags), (r_target, r_onclause, r_from, r_flags), - ) in util.zip_longest(left, right, fillvalue=(None, None, None, None)): + ) in zip_longest(left, right, fillvalue=(None, None, None, None)): if l_flags != r_flags: return COMPARE_FAILED self.stack.append((l_target, r_target)) @@ -1292,7 +1274,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): right_keys = sorted( right, key=lambda elem: (elem[0].fullname, elem[1]) ) - for (ltable, ldialect), (rtable, rdialect) in util.zip_longest( + for (ltable, ldialect), (rtable, rdialect) in zip_longest( left_keys, right_keys, fillvalue=(None, None) ): if ldialect != rdialect: @@ -1317,7 +1299,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): ): # sequence of tuple pairs - for (lk, lv), (rk, rv) in util.zip_longest( + for (lk, lv), (rk, rv) in zip_longest( left, right, fillvalue=(None, None) ): if not self._compare_dml_values_or_ce(lk, rk, **kw): @@ -1349,7 +1331,7 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): return COMPARE_FAILED elif isinstance(right, collections_abc.Sequence): return COMPARE_FAILED - elif py37: + else: # dictionaries guaranteed to support insert ordering in # py37 so that we can compare the keys in order. without # this, we can't compare SQL expression keys because we don't @@ -1359,25 +1341,15 @@ class TraversalComparatorStrategy(InternalTraversal, util.MemoizedSlots): return COMPARE_FAILED if not self._compare_dml_values_or_ce(lv, rv, **kw): return COMPARE_FAILED - else: - for lk in left: - lv = left[lk] - - if lk not in right: - return COMPARE_FAILED - rv = right[lk] - - if not self._compare_dml_values_or_ce(lv, rv, **kw): - return COMPARE_FAILED def visit_dml_multi_values( self, attrname, left_parent, left, right_parent, right, **kw ): - for lseq, rseq in util.zip_longest(left, right, fillvalue=None): + for lseq, rseq in zip_longest(left, right, fillvalue=None): if lseq is None or rseq is None: return COMPARE_FAILED - for ld, rd in util.zip_longest(lseq, rseq, fillvalue=None): + for ld, rd in zip_longest(lseq, rseq, fillvalue=None): if ( self.visit_dml_values( attrname, left_parent, ld, right_parent, rd, **kw diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index 01763f2662..82b8f538a1 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -981,9 +981,7 @@ class ExternalType: return NO_CACHE -class UserDefinedType( - util.with_metaclass(VisitableCheckKWArg, ExternalType, TypeEngine) -): +class UserDefinedType(ExternalType, TypeEngine, metaclass=VisitableCheckKWArg): """Base for user defined types. This should be the base of new types. Note that diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 6394c43a0e..8aee6a97af 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -454,7 +454,7 @@ def bind_values(clause): def _quote_ddl_expr(element): - if isinstance(element, util.string_types): + if isinstance(element, str): element = element.replace("'", "''") return "'%s'" % element else: diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py index deb92b0811..b080807535 100644 --- a/lib/sqlalchemy/sql/visitors.py +++ b/lib/sqlalchemy/sql/visitors.py @@ -59,7 +59,7 @@ def _generate_compiler_dispatch(cls): cls._original_compiler_dispatch = cls._compiler_dispatch return - if not isinstance(visit_name, util.compat.string_types): + if not isinstance(visit_name, str): raise exc.InvalidRequestError( "__visit_name__ on class %s must be a string at the class level" % cls.__name__ @@ -114,7 +114,7 @@ class TraversibleType(type): super(TraversibleType, cls).__init__(clsname, bases, clsdict) -class Traversible(util.with_metaclass(TraversibleType)): +class Traversible(metaclass=TraversibleType): """Base class for visitable objects, applies the :class:`.visitors.TraversibleType` metaclass. @@ -200,7 +200,7 @@ def _generate_dispatcher(visitor, internal_dispatch, method_name): return langhelpers._exec_code_in_env(meth_text, {}, method_name) -class InternalTraversal(util.with_metaclass(_InternalTraversalType, object)): +class InternalTraversal(metaclass=_InternalTraversalType): r"""Defines visitor symbols used for internal traversal. The :class:`.InternalTraversal` class is used in two ways. One is that diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index d78e241819..cf7494f57c 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -5,9 +5,9 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php +from unittest import mock from . import config -from . import mock from .assertions import assert_raises from .assertions import assert_raises_context_ok from .assertions import assert_raises_message diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index ed634befe3..234ab4b933 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -5,9 +5,8 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -from __future__ import absolute_import - import contextlib +from itertools import filterfalse import re import sys import warnings @@ -26,7 +25,6 @@ from .. import util from ..engine import default from ..engine import url from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL -from ..util import compat from ..util import decorator @@ -58,7 +56,7 @@ def expect_warnings_on(db, *messages, **kw): """ spec = db_spec(db) - if isinstance(db, util.string_types) and not spec(config._current): + if isinstance(db, str) and not spec(config._current): yield else: with expect_warnings(*messages, **kw): @@ -144,7 +142,6 @@ def _expect_warnings( messages, regex=True, assert_=True, - py2konly=False, raise_on_any_unexpected=False, ): @@ -210,7 +207,7 @@ def _expect_warnings( finally: _SEEN = _FILTERS = _EXC_CLS = None - if assert_ and (not py2konly or not compat.py3k): + if assert_: assert not seen, "Warnings were not seen: %s" % ", ".join( "%r" % (s.pattern if regex else s) for s in seen ) @@ -325,9 +322,6 @@ def _assert_proper_exception_context(exception): """ - if not util.py3k: - return - if ( exception.__context__ is not exception.__cause__ and not exception.__suppress_context__ @@ -386,14 +380,14 @@ def _expect_raises(except_cls, msg=None, check_context=False): if msg is not None: # I'm often pdbing here, and "err" above isn't # in scope, so assign the string explicitly - error_as_string = util.text_type(err) + error_as_string = str(err) assert re.search(msg, error_as_string, re.UNICODE), "%r !~ %s" % ( msg, error_as_string, ) if check_context and not are_we_already_in_a_traceback: _assert_proper_exception_context(err) - print(util.text_type(err).encode("utf-8")) + print(str(err).encode("utf-8")) # it's generally a good idea to not carry traceback objects outside # of the except: block, but in this case especially we seem to have @@ -456,7 +450,7 @@ class AssertsCompiledSQL: dialect.supports_default_metavalue = supports_default_metavalue elif dialect == "default_enhanced": dialect = default.StrCompileDialect() - elif isinstance(dialect, util.string_types): + elif isinstance(dialect, str): dialect = url.URL.create(dialect).get_dialect()() if default_schema_name: @@ -553,21 +547,10 @@ class AssertsCompiledSQL: c = CheckCompilerAccess(clause).compile(dialect=dialect, **kw) param_str = repr(getattr(c, "params", {})) - if util.py3k: - param_str = param_str.encode("utf-8").decode("ascii", "ignore") - print( - ("\nSQL String:\n" + util.text_type(c) + param_str).encode( - "utf-8" - ) - ) - else: - print( - "\nSQL String:\n" - + util.text_type(c).encode("utf-8") - + param_str - ) + param_str = param_str.encode("utf-8").decode("ascii", "ignore") + print(("\nSQL String:\n" + str(c) + param_str).encode("utf-8")) - cc = re.sub(r"[\n\t]", "", util.text_type(c)) + cc = re.sub(r"[\n\t]", "", str(c)) eq_(cc, result, "%r != %r on dialect %r" % (cc, result, dialect)) @@ -687,9 +670,7 @@ class AssertsExecutionResults: found = util.IdentitySet(result) expected = {immutabledict(e) for e in expected} - for wrong in util.itertools_filterfalse( - lambda o: isinstance(o, cls), found - ): + for wrong in filterfalse(lambda o: isinstance(o, cls), found): fail( 'Unexpected type "%s", expected "%s"' % (type(wrong).__name__, cls.__name__) diff --git a/lib/sqlalchemy/testing/assertsql.py b/lib/sqlalchemy/testing/assertsql.py index 485a13f82f..46fdf6b9b3 100644 --- a/lib/sqlalchemy/testing/assertsql.py +++ b/lib/sqlalchemy/testing/assertsql.py @@ -10,7 +10,6 @@ import contextlib import re from .. import event -from .. import util from ..engine import url from ..engine.default import DefaultDialect from ..schema import _DDLCompiles @@ -123,7 +122,7 @@ class CompiledSQL(SQLMatchRule): for_executemany=context.compiled.for_executemany, schema_translate_map=map_, ) - _received_statement = re.sub(r"[\n\t]", "", util.text_type(compiled)) + _received_statement = re.sub(r"[\n\t]", "", str(compiled)) parameters = execute_observed.parameters if not parameters: diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index 98de5df5c4..e17c09be78 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -5,8 +5,6 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -from __future__ import absolute_import - import collections import re import warnings diff --git a/lib/sqlalchemy/testing/entities.py b/lib/sqlalchemy/testing/entities.py index 15b6388fb4..a87d853c35 100644 --- a/lib/sqlalchemy/testing/entities.py +++ b/lib/sqlalchemy/testing/entities.py @@ -7,7 +7,6 @@ import sqlalchemy as sa from .. import exc as sa_exc -from ..util import compat _repr_stack = set() @@ -87,9 +86,7 @@ class ComparableMixin: except (AttributeError, sa_exc.UnboundExecutionError): return False - if hasattr(value, "__iter__") and not isinstance( - value, compat.string_types - ): + if hasattr(value, "__iter__") and not isinstance(value, str): if hasattr(value, "__getitem__") and not hasattr( value, "keys" ): diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index 7b2343128a..c20cd920c6 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -201,7 +201,7 @@ class Predicate: ) elif isinstance(predicate, tuple): return SpecPredicate(*predicate) - elif isinstance(predicate, util.string_types): + elif isinstance(predicate, str): tokens = re.match( r"([\+\w]+)\s*(?:(>=|==|!=|<=|<|>)\s*([\d\.]+))?", predicate ) diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py index d5e8e376a3..1d56d923e3 100644 --- a/lib/sqlalchemy/testing/fixtures.py +++ b/lib/sqlalchemy/testing/fixtures.py @@ -429,7 +429,7 @@ class TablesTest(TestBase): try: conn.execute(table.delete()) except sa.exc.DBAPIError as ex: - util.print_( + print( ("Error emptying table %s: %r" % (table, ex)), file=sys.stderr, ) @@ -483,7 +483,7 @@ class TablesTest(TestBase): for table, data in cls.fixtures().items(): if len(data) < 2: continue - if isinstance(table, util.string_types): + if isinstance(table, str): table = cls.tables[table] headers[table] = data[0] rows[table] = data[1:] @@ -654,7 +654,7 @@ class MappedTest(TablesTest, assertions.AssertsExecutionResults): cls_registry[classname] = cls type.__init__(cls, classname, bases, dict_) - class _Base(util.with_metaclass(FindFixture, object)): + class _Base(metaclass=FindFixture): pass class Basic(BasicEntity, _Base): diff --git a/lib/sqlalchemy/testing/mock.py b/lib/sqlalchemy/testing/mock.py deleted file mode 100644 index 8fe08a6789..0000000000 --- a/lib/sqlalchemy/testing/mock.py +++ /dev/null @@ -1,32 +0,0 @@ -# testing/mock.py -# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors -# -# -# This module is part of SQLAlchemy and is released under -# the MIT License: https://www.opensource.org/licenses/mit-license.php - -"""Import stub for mock library. -""" -from __future__ import absolute_import - -from ..util import py3k - - -if py3k: - from unittest.mock import MagicMock - from unittest.mock import Mock - from unittest.mock import call - from unittest.mock import patch - from unittest.mock import ANY -else: - try: - from mock import MagicMock # noqa - from mock import Mock # noqa - from mock import call # noqa - from mock import patch # noqa - from mock import ANY # noqa - except ImportError: - raise ImportError( - "SQLAlchemy's test suite requires the " - "'mock' library as of 0.8.2." - ) diff --git a/lib/sqlalchemy/testing/plugin/plugin_base.py b/lib/sqlalchemy/testing/plugin/plugin_base.py index b382e97f63..32ed2c3159 100644 --- a/lib/sqlalchemy/testing/plugin/plugin_base.py +++ b/lib/sqlalchemy/testing/plugin/plugin_base.py @@ -13,35 +13,20 @@ created so that multiple test frameworks can be supported at once is pytest. """ - -from __future__ import absolute_import - import abc +import configparser import logging import re import sys +from sqlalchemy.testing import asyncio + # flag which indicates we are in the SQLAlchemy testing suite, # and not that of Alembic or a third party dialect. bootstrapped_as_sqlalchemy = False log = logging.getLogger("sqlalchemy.testing.plugin_base") - -py3k = sys.version_info >= (3, 0) - -if py3k: - import configparser - - ABC = abc.ABC -else: - import ConfigParser as configparser - import collections as collections_abc # noqa - - class ABC: - __metaclass__ = abc.ABCMeta - - # late imports fixtures = None engines = None @@ -393,8 +378,7 @@ def _init_symbols(options, file_config): @post def _set_disable_asyncio(opt, file_config): - if opt.disable_asyncio or not py3k: - from sqlalchemy.testing import asyncio + if opt.disable_asyncio: asyncio.ENABLE_ASYNCIO = False @@ -756,7 +740,7 @@ def _setup_config(config_obj, ctx): config._current.push(config_obj, testing) -class FixtureFunctions(ABC): +class FixtureFunctions(abc.ABC): @abc.abstractmethod def skip_test_exception(self, *arg, **kw): raise NotImplementedError() diff --git a/lib/sqlalchemy/testing/plugin/pytestplugin.py b/lib/sqlalchemy/testing/plugin/pytestplugin.py index 36aaa5d2a4..ba774b118d 100644 --- a/lib/sqlalchemy/testing/plugin/pytestplugin.py +++ b/lib/sqlalchemy/testing/plugin/pytestplugin.py @@ -344,7 +344,6 @@ _current_class = None def pytest_runtest_setup(item): from sqlalchemy.testing import asyncio - from sqlalchemy.util import string_types if not isinstance(item, pytest.Function): return @@ -382,7 +381,7 @@ def pytest_runtest_setup(item): "__Original test failure__:\n" + _current_report.longreprtext, ) - elif e.args[-1] and isinstance(e.args[-1], string_types): + elif e.args[-1] and isinstance(e.args[-1], str): args = list(e.args) args[-1] += ( "\n__Original test failure__:\n" diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index b6a6e75b17..2761d49875 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -279,7 +279,7 @@ def count_functions(variance=0.05): # ended = time.time() pr.disable() - # s = compat.StringIO() + # s = StringIO() stats = pstats.Stats(pr, stream=sys.stdout) # timespent = ended - began diff --git a/lib/sqlalchemy/testing/provision.py b/lib/sqlalchemy/testing/provision.py index 15613957c6..e51eb172e4 100644 --- a/lib/sqlalchemy/testing/provision.py +++ b/lib/sqlalchemy/testing/provision.py @@ -9,7 +9,6 @@ from .. import inspect from ..engine import url as sa_url from ..sql import ddl from ..sql import schema -from ..util import compat log = logging.getLogger(__name__) @@ -34,7 +33,7 @@ class register: return decorate def __call__(self, cfg, *arg): - if isinstance(cfg, compat.string_types): + if isinstance(cfg, str): url = sa_url.make_url(cfg) elif isinstance(cfg, sa_url.URL): url = cfg diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 325c0a9bb0..8cb72d1633 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -16,7 +16,6 @@ to provide specific inclusion/exclusions. """ import platform -import sys from . import exclusions from . import only_on @@ -1272,12 +1271,12 @@ class SuiteRequirements(Requirements): @property def threading_with_mock(self): """Mark tests that use threading and mock at the same time - stability - issues have been observed with coverage + python 3.3 + issues have been observed with coverage """ return exclusions.skip_if( - lambda config: util.py3k and config.options.has_coverage, - "Stability issues with coverage + py3k", + lambda config: config.options.has_coverage, + "Stability issues with coverage", ) @property @@ -1316,17 +1315,6 @@ class SuiteRequirements(Requirements): return exclusions.only_if(check_lib, "patch library needed") - @property - def non_broken_pickle(self): - from sqlalchemy.util import pickle - - return exclusions.only_if( - lambda: util.cpython - and pickle.__name__ == "cPickle" - or sys.version_info >= (3, 2), - "Needs cPickle+cPython or newer Python 3 pickle", - ) - @property def predictable_gc(self): """target platform must remove all cycles unconditionally when @@ -1505,8 +1493,3 @@ class SuiteRequirements(Requirements): sequence. This should be false only for oracle. """ return exclusions.open() - - @property - def generic_classes(self): - "If X[Y] can be implemented with ``__class_getitem__``. py3.7+" - return exclusions.only_if(lambda: util.py37) diff --git a/lib/sqlalchemy/testing/suite/test_results.py b/lib/sqlalchemy/testing/suite/test_results.py index f470432d2e..5ad68034b9 100644 --- a/lib/sqlalchemy/testing/suite/test_results.py +++ b/lib/sqlalchemy/testing/suite/test_results.py @@ -14,7 +14,6 @@ from ... import sql from ... import String from ... import testing from ... import text -from ... import util class RowFetchTest(fixtures.TablesTest): @@ -306,7 +305,7 @@ class ServerSideCursorsTest( ): engine = self._fixture(engine_ss_arg) with engine.begin() as conn: - if isinstance(statement, util.string_types): + if isinstance(statement, str): result = conn.exec_driver_sql(statement) else: result = conn.execute(statement) diff --git a/lib/sqlalchemy/testing/suite/test_select.py b/lib/sqlalchemy/testing/suite/test_select.py index b5a3dca3a1..c1228f5df3 100644 --- a/lib/sqlalchemy/testing/suite/test_select.py +++ b/lib/sqlalchemy/testing/suite/test_select.py @@ -1,3 +1,4 @@ +import collections.abc as collections_abc import itertools from .. import AssertsCompiledSQL @@ -32,11 +33,9 @@ from ... import true from ... import tuple_ from ... import TupleType from ... import union -from ... import util from ... import values from ...exc import DatabaseError from ...exc import ProgrammingError -from ...util import collections_abc class CollateTest(fixtures.TablesTest): @@ -131,7 +130,7 @@ class OrderByLabelTest(fixtures.TablesTest): ly = (func.lower(table.c.q) + table.c.p).label("ly") self._assert_result( select(lx, ly).order_by(lx, ly.desc()), - [(3, util.u("q1p3")), (5, util.u("q2p2")), (7, util.u("q3p1"))], + [(3, "q1p3"), (5, "q2p2"), (7, "q3p1")], ) def test_plain_desc(self): diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 4a5396ed82..7989b1e399 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -39,10 +39,8 @@ from ... import type_coerce from ... import TypeDecorator from ... import Unicode from ... import UnicodeText -from ... import util from ...orm import declarative_base from ...orm import Session -from ...util import u class _LiteralRoundTripFixture: @@ -93,7 +91,7 @@ class _LiteralRoundTripFixture: class _UnicodeFixture(_LiteralRoundTripFixture, fixtures.TestBase): __requires__ = ("unicode_data",) - data = u( + data = ( "Alors vous imaginez ma 🐍 surprise, au lever du jour, " "quand une drôle de petite 🐍 voix m’a réveillé. Elle " "disait: « S’il vous plaît… dessine-moi 🐍 un mouton! »" @@ -124,7 +122,7 @@ class _UnicodeFixture(_LiteralRoundTripFixture, fixtures.TestBase): row = connection.execute(select(unicode_table.c.unicode_data)).first() eq_(row, (self.data,)) - assert isinstance(row[0], util.text_type) + assert isinstance(row[0], str) def test_round_trip_executemany(self, connection): unicode_table = self.tables.unicode_table @@ -139,7 +137,7 @@ class _UnicodeFixture(_LiteralRoundTripFixture, fixtures.TestBase): ).fetchall() eq_(rows, [(self.data,) for i in range(1, 4)]) for row in rows: - assert isinstance(row[0], util.text_type) + assert isinstance(row[0], str) def _test_null_strings(self, connection): unicode_table = self.tables.unicode_table @@ -154,18 +152,16 @@ class _UnicodeFixture(_LiteralRoundTripFixture, fixtures.TestBase): unicode_table = self.tables.unicode_table connection.execute( - unicode_table.insert(), {"id": 1, "unicode_data": u("")} + unicode_table.insert(), {"id": 1, "unicode_data": ""} ) row = connection.execute(select(unicode_table.c.unicode_data)).first() - eq_(row, (u(""),)) + eq_(row, ("",)) def test_literal(self, literal_round_trip): literal_round_trip(self.datatype, [self.data], [self.data]) def test_literal_non_ascii(self, literal_round_trip): - literal_round_trip( - self.datatype, [util.u("réve🐍 illé")], [util.u("réve🐍 illé")] - ) + literal_round_trip(self.datatype, ["réve🐍 illé"], ["réve🐍 illé"]) class UnicodeVarcharTest(_UnicodeFixture, fixtures.TablesTest): @@ -243,9 +239,7 @@ class TextTest(_LiteralRoundTripFixture, fixtures.TablesTest): literal_round_trip(Text, ["some text"], ["some text"]) def test_literal_non_ascii(self, literal_round_trip): - literal_round_trip( - Text, [util.u("réve🐍 illé")], [util.u("réve🐍 illé")] - ) + literal_round_trip(Text, ["réve🐍 illé"], ["réve🐍 illé"]) def test_literal_quoting(self, literal_round_trip): data = """some 'text' hey "hi there" that's text""" @@ -277,9 +271,7 @@ class StringTest(_LiteralRoundTripFixture, fixtures.TestBase): literal_round_trip(String(40), ["some text"], ["some text"]) def test_literal_non_ascii(self, literal_round_trip): - literal_round_trip( - String(40), [util.u("réve🐍 illé")], [util.u("réve🐍 illé")] - ) + literal_round_trip(String(40), ["réve🐍 illé"], ["réve🐍 illé"]) def test_literal_quoting(self, literal_round_trip): data = """some 'text' hey "hi there" that's text""" @@ -474,10 +466,7 @@ class IntegerTest(_LiteralRoundTripFixture, fixtures.TestBase): eq_(row, (data,)) - if util.py3k: - assert isinstance(row[0], int) - else: - assert isinstance(row[0], (long, int)) # noqa + assert isinstance(row[0], int) return run @@ -880,10 +869,10 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): ("boolean", None), ("string", "some string"), ("string", None), - ("string", util.u("réve illé")), + ("string", "réve illé"), ( "string", - util.u("réve🐍 illé"), + "réve🐍 illé", testing.requires.json_index_supplementary_unicode_element, ), ("integer", 15), @@ -1080,8 +1069,8 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): (-1.0,), (15.052,), ("a string",), - (util.u("réve illé"),), - (util.u("réve🐍 illé"),), + ("réve illé",), + ("réve🐍 illé",), ) def test_single_element_round_trip(self, element): data_table = self.tables.data_table @@ -1243,8 +1232,8 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): { "name": "r1", "data": { - util.u("réve🐍 illé"): util.u("réve🐍 illé"), - "data": {"k1": util.u("drôl🐍e")}, + "réve🐍 illé": "réve🐍 illé", + "data": {"k1": "drôl🐍e"}, }, }, ) @@ -1252,8 +1241,8 @@ class JSONTest(_LiteralRoundTripFixture, fixtures.TablesTest): eq_( conn.scalar(select(self.tables.data_table.c.data)), { - util.u("réve🐍 illé"): util.u("réve🐍 illé"), - "data": {"k1": util.u("drôl🐍e")}, + "réve🐍 illé": "réve🐍 illé", + "data": {"k1": "drôl🐍e"}, }, ) diff --git a/lib/sqlalchemy/testing/suite/test_unicode_ddl.py b/lib/sqlalchemy/testing/suite/test_unicode_ddl.py index 1334eb8dbf..a0cd6734a5 100644 --- a/lib/sqlalchemy/testing/suite/test_unicode_ddl.py +++ b/lib/sqlalchemy/testing/suite/test_unicode_ddl.py @@ -10,8 +10,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import u -from sqlalchemy.util import ue class UnicodeSchemaTest(fixtures.TablesTest): @@ -23,20 +21,20 @@ class UnicodeSchemaTest(fixtures.TablesTest): global t1, t2, t3 t1 = Table( - u("unitable1"), + "unitable1", metadata, - Column(u("méil"), Integer, primary_key=True), - Column(ue("\u6e2c\u8a66"), Integer), + Column("méil", Integer, primary_key=True), + Column("\u6e2c\u8a66", Integer), test_needs_fk=True, ) t2 = Table( - u("Unitéble2"), + "Unitéble2", metadata, - Column(u("méil"), Integer, primary_key=True, key="a"), + Column("méil", Integer, primary_key=True, key="a"), Column( - ue("\u6e2c\u8a66"), + "\u6e2c\u8a66", Integer, - ForeignKey(u("unitable1.méil")), + ForeignKey("unitable1.méil"), key="b", ), test_needs_fk=True, @@ -45,55 +43,53 @@ class UnicodeSchemaTest(fixtures.TablesTest): # Few DBs support Unicode foreign keys if testing.against("sqlite"): t3 = Table( - ue("\u6e2c\u8a66"), + "\u6e2c\u8a66", metadata, Column( - ue("\u6e2c\u8a66_id"), + "\u6e2c\u8a66_id", Integer, primary_key=True, autoincrement=False, ), Column( - ue("unitable1_\u6e2c\u8a66"), + "unitable1_\u6e2c\u8a66", Integer, - ForeignKey(ue("unitable1.\u6e2c\u8a66")), + ForeignKey("unitable1.\u6e2c\u8a66"), ), + Column("Unitéble2_b", Integer, ForeignKey("Unitéble2.b")), Column( - u("Unitéble2_b"), Integer, ForeignKey(u("Unitéble2.b")) - ), - Column( - ue("\u6e2c\u8a66_self"), + "\u6e2c\u8a66_self", Integer, - ForeignKey(ue("\u6e2c\u8a66.\u6e2c\u8a66_id")), + ForeignKey("\u6e2c\u8a66.\u6e2c\u8a66_id"), ), test_needs_fk=True, ) else: t3 = Table( - ue("\u6e2c\u8a66"), + "\u6e2c\u8a66", metadata, Column( - ue("\u6e2c\u8a66_id"), + "\u6e2c\u8a66_id", Integer, primary_key=True, autoincrement=False, ), - Column(ue("unitable1_\u6e2c\u8a66"), Integer), - Column(u("Unitéble2_b"), Integer), - Column(ue("\u6e2c\u8a66_self"), Integer), + Column("unitable1_\u6e2c\u8a66", Integer), + Column("Unitéble2_b", Integer), + Column("\u6e2c\u8a66_self", Integer), test_needs_fk=True, ) def test_insert(self, connection): - connection.execute(t1.insert(), {u("méil"): 1, ue("\u6e2c\u8a66"): 5}) - connection.execute(t2.insert(), {u("a"): 1, u("b"): 1}) + connection.execute(t1.insert(), {"méil": 1, "\u6e2c\u8a66": 5}) + connection.execute(t2.insert(), {"a": 1, "b": 1}) connection.execute( t3.insert(), { - ue("\u6e2c\u8a66_id"): 1, - ue("unitable1_\u6e2c\u8a66"): 5, - u("Unitéble2_b"): 1, - ue("\u6e2c\u8a66_self"): 1, + "\u6e2c\u8a66_id": 1, + "unitable1_\u6e2c\u8a66": 5, + "Unitéble2_b": 1, + "\u6e2c\u8a66_self": 1, }, ) @@ -102,42 +98,42 @@ class UnicodeSchemaTest(fixtures.TablesTest): eq_(connection.execute(t3.select()).fetchall(), [(1, 5, 1, 1)]) def test_col_targeting(self, connection): - connection.execute(t1.insert(), {u("méil"): 1, ue("\u6e2c\u8a66"): 5}) - connection.execute(t2.insert(), {u("a"): 1, u("b"): 1}) + connection.execute(t1.insert(), {"méil": 1, "\u6e2c\u8a66": 5}) + connection.execute(t2.insert(), {"a": 1, "b": 1}) connection.execute( t3.insert(), { - ue("\u6e2c\u8a66_id"): 1, - ue("unitable1_\u6e2c\u8a66"): 5, - u("Unitéble2_b"): 1, - ue("\u6e2c\u8a66_self"): 1, + "\u6e2c\u8a66_id": 1, + "unitable1_\u6e2c\u8a66": 5, + "Unitéble2_b": 1, + "\u6e2c\u8a66_self": 1, }, ) row = connection.execute(t1.select()).first() - eq_(row._mapping[t1.c[u("méil")]], 1) - eq_(row._mapping[t1.c[ue("\u6e2c\u8a66")]], 5) + eq_(row._mapping[t1.c["méil"]], 1) + eq_(row._mapping[t1.c["\u6e2c\u8a66"]], 5) row = connection.execute(t2.select()).first() - eq_(row._mapping[t2.c[u("a")]], 1) - eq_(row._mapping[t2.c[u("b")]], 1) + eq_(row._mapping[t2.c["a"]], 1) + eq_(row._mapping[t2.c["b"]], 1) row = connection.execute(t3.select()).first() - eq_(row._mapping[t3.c[ue("\u6e2c\u8a66_id")]], 1) - eq_(row._mapping[t3.c[ue("unitable1_\u6e2c\u8a66")]], 5) - eq_(row._mapping[t3.c[u("Unitéble2_b")]], 1) - eq_(row._mapping[t3.c[ue("\u6e2c\u8a66_self")]], 1) + eq_(row._mapping[t3.c["\u6e2c\u8a66_id"]], 1) + eq_(row._mapping[t3.c["unitable1_\u6e2c\u8a66"]], 5) + eq_(row._mapping[t3.c["Unitéble2_b"]], 1) + eq_(row._mapping[t3.c["\u6e2c\u8a66_self"]], 1) def test_reflect(self, connection): - connection.execute(t1.insert(), {u("méil"): 2, ue("\u6e2c\u8a66"): 7}) - connection.execute(t2.insert(), {u("a"): 2, u("b"): 2}) + connection.execute(t1.insert(), {"méil": 2, "\u6e2c\u8a66": 7}) + connection.execute(t2.insert(), {"a": 2, "b": 2}) connection.execute( t3.insert(), { - ue("\u6e2c\u8a66_id"): 2, - ue("unitable1_\u6e2c\u8a66"): 7, - u("Unitéble2_b"): 2, - ue("\u6e2c\u8a66_self"): 2, + "\u6e2c\u8a66_id": 2, + "unitable1_\u6e2c\u8a66": 7, + "Unitéble2_b": 2, + "\u6e2c\u8a66_self": 2, }, ) @@ -146,42 +142,36 @@ class UnicodeSchemaTest(fixtures.TablesTest): tt2 = Table(t2.name, meta, autoload_with=connection) tt3 = Table(t3.name, meta, autoload_with=connection) - connection.execute(tt1.insert(), {u("méil"): 1, ue("\u6e2c\u8a66"): 5}) - connection.execute(tt2.insert(), {u("méil"): 1, ue("\u6e2c\u8a66"): 1}) + connection.execute(tt1.insert(), {"méil": 1, "\u6e2c\u8a66": 5}) + connection.execute(tt2.insert(), {"méil": 1, "\u6e2c\u8a66": 1}) connection.execute( tt3.insert(), { - ue("\u6e2c\u8a66_id"): 1, - ue("unitable1_\u6e2c\u8a66"): 5, - u("Unitéble2_b"): 1, - ue("\u6e2c\u8a66_self"): 1, + "\u6e2c\u8a66_id": 1, + "unitable1_\u6e2c\u8a66": 5, + "Unitéble2_b": 1, + "\u6e2c\u8a66_self": 1, }, ) eq_( - connection.execute( - tt1.select().order_by(desc(u("méil"))) - ).fetchall(), + connection.execute(tt1.select().order_by(desc("méil"))).fetchall(), [(2, 7), (1, 5)], ) eq_( - connection.execute( - tt2.select().order_by(desc(u("méil"))) - ).fetchall(), + connection.execute(tt2.select().order_by(desc("méil"))).fetchall(), [(2, 2), (1, 1)], ) eq_( connection.execute( - tt3.select().order_by(desc(ue("\u6e2c\u8a66_id"))) + tt3.select().order_by(desc("\u6e2c\u8a66_id")) ).fetchall(), [(2, 7, 2, 2), (1, 5, 1, 1)], ) def test_repr(self): meta = MetaData() - t = Table( - ue("\u6e2c\u8a66"), meta, Column(ue("\u6e2c\u8a66_id"), Integer) - ) + t = Table("\u6e2c\u8a66", meta, Column("\u6e2c\u8a66_id", Integer)) eq_( repr(t), ( diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index 2c41337e42..c8e481a900 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -4,9 +4,6 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php - -from __future__ import absolute_import - import warnings from . import assertions diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py index 8a18a584a2..a82e040df2 100644 --- a/lib/sqlalchemy/util/__init__.py +++ b/lib/sqlalchemy/util/__init__.py @@ -7,13 +7,11 @@ from collections import defaultdict -from contextlib import contextmanager from functools import partial from functools import update_wrapper from ._collections import coerce_generator_arg from ._collections import coerce_to_immutabledict -from ._collections import collections_abc from ._collections import column_dict from ._collections import column_set from ._collections import EMPTY_DICT @@ -47,15 +45,10 @@ from ._collections import WeakPopulateDict from ._collections import WeakSequence from ._preloaded import preload_module from ._preloaded import preloaded -from .compat import ABC from .compat import arm from .compat import b from .compat import b64decode from .compat import b64encode -from .compat import binary_type -from .compat import binary_types -from .compat import byte_buffer -from .compat import callable from .compat import cmp from .compat import cpython from .compat import dataclass_fields @@ -63,42 +56,18 @@ from .compat import decode_backslashreplace from .compat import dottedgetter from .compat import has_refcount_gc from .compat import inspect_getfullargspec -from .compat import int_types -from .compat import iterbytes -from .compat import itertools_filter -from .compat import itertools_filterfalse from .compat import local_dataclass_fields from .compat import namedtuple from .compat import next -from .compat import nullcontext from .compat import osx -from .compat import parse_qsl -from .compat import perf_counter -from .compat import pickle -from .compat import print_ -from .compat import py37 from .compat import py38 from .compat import py39 -from .compat import py3k from .compat import pypy -from .compat import quote_plus from .compat import raise_ from .compat import raise_from_cause -from .compat import reduce from .compat import reraise -from .compat import string_types -from .compat import StringIO -from .compat import text_type from .compat import threading -from .compat import timezone -from .compat import TYPE_CHECKING -from .compat import u -from .compat import ue -from .compat import unquote -from .compat import unquote_plus from .compat import win32 -from .compat import with_metaclass -from .compat import zip_longest from .concurrency import asyncio from .concurrency import await_fallback from .concurrency import await_only diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py index 9efbeb7db4..32e989fca3 100644 --- a/lib/sqlalchemy/util/_collections.py +++ b/lib/sqlalchemy/util/_collections.py @@ -6,21 +6,14 @@ # the MIT License: https://www.opensource.org/licenses/mit-license.php """Collection classes and helpers.""" - -from __future__ import absolute_import - +import collections.abc as collections_abc +from itertools import filterfalse import operator import types import weakref -from .compat import binary_types -from .compat import collections_abc -from .compat import itertools_filterfalse -from .compat import py37 -from .compat import string_types from .compat import threading - EMPTY_SET = frozenset() @@ -245,107 +238,8 @@ def _ordered_dictionary_sort(d, key=None): d.update(items) -if py37: - OrderedDict = dict - sort_dictionary = _ordered_dictionary_sort - -else: - # prevent sort_dictionary from being used against a plain dictionary - # for Python < 3.7 - - def sort_dictionary(d, key=None): - """Sort an OrderedDict in place.""" - - d._ordered_dictionary_sort(key=key) - - class OrderedDict(dict): - """Dictionary that maintains insertion order. - - Superseded by Python dict as of Python 3.7 - - """ - - __slots__ = ("_list",) - - def _ordered_dictionary_sort(self, key=None): - _ordered_dictionary_sort(self, key=key) - - def __reduce__(self): - return OrderedDict, (self.items(),) - - def __init__(self, ____sequence=None, **kwargs): - self._list = [] - if ____sequence is None: - if kwargs: - self.update(**kwargs) - else: - self.update(____sequence, **kwargs) - - def clear(self): - self._list = [] - dict.clear(self) - - def copy(self): - return self.__copy__() - - def __copy__(self): - return OrderedDict(self) - - def update(self, ____sequence=None, **kwargs): - if ____sequence is not None: - if hasattr(____sequence, "keys"): - for key in ____sequence.keys(): - self.__setitem__(key, ____sequence[key]) - else: - for key, value in ____sequence: - self[key] = value - if kwargs: - self.update(kwargs) - - def setdefault(self, key, value): - if key not in self: - self.__setitem__(key, value) - return value - else: - return self.__getitem__(key) - - def __iter__(self): - return iter(self._list) - - def keys(self): - return list(self) - - def values(self): - return [self[key] for key in self._list] - - def items(self): - return [(key, self[key]) for key in self._list] - - def __setitem__(self, key, obj): - if key not in self: - try: - self._list.append(key) - except AttributeError: - # work around Python pickle loads() with - # dict subclass (seems to ignore __setstate__?) - self._list = [key] - dict.__setitem__(self, key, obj) - - def __delitem__(self, key): - dict.__delitem__(self, key) - self._list.remove(key) - - def pop(self, key, *default): - present = key in self - value = dict.pop(self, key, *default) - if present: - self._list.remove(key) - return value - - def popitem(self): - item = dict.popitem(self) - self._list.remove(item[0]) - return item +OrderedDict = dict +sort_dictionary = _ordered_dictionary_sort class OrderedSet(set): @@ -515,7 +409,7 @@ class IdentitySet: if len(self) > len(other): return False - for m in itertools_filterfalse( + for m in filterfalse( other._members.__contains__, iter(self._members.keys()) ): return False @@ -540,7 +434,7 @@ class IdentitySet: if len(self) < len(other): return False - for m in itertools_filterfalse( + for m in filterfalse( self._members.__contains__, iter(other._members.keys()) ): return False @@ -818,7 +712,7 @@ def to_list(x, default=None): if x is None: return default if not isinstance(x, collections_abc.Iterable) or isinstance( - x, string_types + binary_types + x, (str, bytes) ): return [x] elif isinstance(x, list): diff --git a/lib/sqlalchemy/util/_compat_py3k.py b/lib/sqlalchemy/util/_compat_py3k.py deleted file mode 100644 index cd9f3ebc34..0000000000 --- a/lib/sqlalchemy/util/_compat_py3k.py +++ /dev/null @@ -1,67 +0,0 @@ -# util/_compat_py3k.py -# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors -# -# -# This module is part of SQLAlchemy and is released under -# the MIT License: https://www.opensource.org/licenses/mit-license.php - -from functools import wraps - -# vendored from py3.7 - - -class _AsyncGeneratorContextManager: - """Helper for @asynccontextmanager.""" - - def __init__(self, func, args, kwds): - self.gen = func(*args, **kwds) - self.func, self.args, self.kwds = func, args, kwds - doc = getattr(func, "__doc__", None) - if doc is None: - doc = type(self).__doc__ - self.__doc__ = doc - - async def __aenter__(self): - try: - return await self.gen.__anext__() - except StopAsyncIteration: - raise RuntimeError("generator didn't yield") from None - - async def __aexit__(self, typ, value, traceback): - if typ is None: - try: - await self.gen.__anext__() - except StopAsyncIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - if value is None: - value = typ() - # See _GeneratorContextManager.__exit__ for comments on subtleties - # in this implementation - try: - await self.gen.athrow(typ, value, traceback) - raise RuntimeError("generator didn't stop after athrow()") - except StopAsyncIteration as exc: - return exc is not value - except RuntimeError as exc: - if exc is value: - return False - if isinstance(value, (StopIteration, StopAsyncIteration)): - if exc.__cause__ is value: - return False - raise - except BaseException as exc: - if exc is not value: - raise - - -# using the vendored version in all cases at the moment to establish -# full test coverage -def asynccontextmanager(func): - @wraps(func) - def helper(*args, **kwds): - return _AsyncGeneratorContextManager(func, args, kwds) - - return helper diff --git a/lib/sqlalchemy/util/_concurrency_py3k.py b/lib/sqlalchemy/util/_concurrency_py3k.py index 55fe87c6a7..71ed01307c 100644 --- a/lib/sqlalchemy/util/_concurrency_py3k.py +++ b/lib/sqlalchemy/util/_concurrency_py3k.py @@ -6,6 +6,7 @@ # the MIT License: https://www.opensource.org/licenses/mit-license.php import asyncio +from contextvars import copy_context as _copy_context import sys from typing import Any from typing import Callable @@ -13,22 +14,17 @@ from typing import Coroutine import greenlet -from . import compat from .langhelpers import memoized_property from .. import exc -if compat.py37: - try: - from contextvars import copy_context as _copy_context +try: - # If greenlet.gr_context is present in current version of greenlet, - # it will be set with a copy of the current context on creation. - # Refs: https://github.com/python-greenlet/greenlet/pull/198 - getattr(greenlet.greenlet, "gr_context") - except (ImportError, AttributeError): - _copy_context = None -else: - _copy_context = None + # If greenlet.gr_context is present in current version of greenlet, + # it will be set with a copy of the current context on creation. + # Refs: https://github.com/python-greenlet/greenlet/pull/198 + getattr(greenlet.greenlet, "gr_context") +except (ImportError, AttributeError): + _copy_context = None # noqa def is_exit_exception(e): @@ -193,10 +189,7 @@ def get_event_loop(): Python 3.10 deprecates get_event_loop() as a standalone. """ - if compat.py37: - try: - return asyncio.get_running_loop() - except RuntimeError: - return asyncio.get_event_loop_policy().get_event_loop() - else: - return asyncio.get_event_loop() + try: + return asyncio.get_running_loop() + except RuntimeError: + return asyncio.get_event_loop_policy().get_event_loop() diff --git a/lib/sqlalchemy/util/_preloaded.py b/lib/sqlalchemy/util/_preloaded.py index c8da9230a8..ff9f5bdb3d 100644 --- a/lib/sqlalchemy/util/_preloaded.py +++ b/lib/sqlalchemy/util/_preloaded.py @@ -12,8 +12,6 @@ runtime. import sys -from . import compat - class _ModuleRegistry: """Registry of modules to load in a package init file. @@ -60,7 +58,7 @@ class _ModuleRegistry: if ( not path or module.startswith(path) ) and key not in self.__dict__: - compat.import_(module, globals(), locals()) + __import__(module, globals(), locals()) self.__dict__[key] = sys.modules[module] diff --git a/lib/sqlalchemy/util/compat.py b/lib/sqlalchemy/util/compat.py index 75b2a9a8df..e1291de36f 100644 --- a/lib/sqlalchemy/util/compat.py +++ b/lib/sqlalchemy/util/compat.py @@ -6,9 +6,9 @@ # the MIT License: https://www.opensource.org/licenses/mit-license.php """Handle Python version/platform incompatibilities.""" - +import base64 import collections -import contextlib +import dataclasses import inspect import operator import platform @@ -16,19 +16,15 @@ import sys py39 = sys.version_info >= (3, 9) py38 = sys.version_info >= (3, 8) -py37 = sys.version_info >= (3, 7) -py3k = sys.version_info >= (3, 0) pypy = platform.python_implementation() == "PyPy" - - cpython = platform.python_implementation() == "CPython" + win32 = sys.platform.startswith("win") osx = sys.platform.startswith("darwin") arm = "aarch" in platform.machine().lower() has_refcount_gc = bool(cpython) -contextmanager = contextlib.contextmanager dottedgetter = operator.attrgetter namedtuple = collections.namedtuple next = next # noqa @@ -47,23 +43,6 @@ FullArgSpec = collections.namedtuple( ) -class nullcontext: - """Context manager that does no additional processing. - - Vendored from Python 3.7. - - """ - - def __init__(self, enter_result=None): - self.enter_result = enter_result - - def __enter__(self): - return self.enter_result - - def __exit__(self, *excinfo): - pass - - try: import threading except ImportError: @@ -84,7 +63,7 @@ def inspect_getfullargspec(func): nargs = co.co_argcount names = co.co_varnames - nkwargs = co.co_kwonlyargcount if py3k else 0 + nkwargs = co.co_kwonlyargcount args = list(names[:nargs]) kwonlyargs = list(names[nargs : nargs + nkwargs]) @@ -103,8 +82,8 @@ def inspect_getfullargspec(func): varkw, func.__defaults__, kwonlyargs, - func.__kwdefaults__ if py3k else None, - func.__annotations__ if py3k else {}, + func.__kwdefaults__, + func.__annotations__, ) @@ -122,364 +101,163 @@ def importlib_metadata_get(group): return ep.get(group, ()) -if py3k: - import base64 - import builtins - import configparser - import itertools - import pickle - - from functools import reduce - from io import BytesIO as byte_buffer - from io import StringIO - from itertools import zip_longest - from time import perf_counter - from urllib.parse import ( - quote_plus, - unquote_plus, - parse_qsl, - quote, - unquote, - ) - - string_types = (str,) - binary_types = (bytes,) - binary_type = bytes - text_type = str - int_types = (int,) - iterbytes = iter - long_type = int - - itertools_filterfalse = itertools.filterfalse - itertools_filter = filter - itertools_imap = map - - exec_ = getattr(builtins, "exec") - import_ = getattr(builtins, "__import__") - print_ = getattr(builtins, "print") - - def b(s): - return s.encode("latin-1") +def b(s): + return s.encode("latin-1") - def b64decode(x): - return base64.b64decode(x.encode("ascii")) - def b64encode(x): - return base64.b64encode(x).decode("ascii") +def b64decode(x): + return base64.b64decode(x.encode("ascii")) - def decode_backslashreplace(text, encoding): - return text.decode(encoding, errors="backslashreplace") - def cmp(a, b): - return (a > b) - (a < b) +def b64encode(x): + return base64.b64encode(x).decode("ascii") - def raise_( - exception, with_traceback=None, replace_context=None, from_=False - ): - r"""implement "raise" with cause support. - :param exception: exception to raise - :param with_traceback: will call exception.with_traceback() - :param replace_context: an as-yet-unsupported feature. This is - an exception object which we are "replacing", e.g., it's our - "cause" but we don't want it printed. Basically just what - ``__suppress_context__`` does but we don't want to suppress - the enclosing context, if any. So for now we make it the - cause. - :param from\_: the cause. this actually sets the cause and doesn't - hope to hide it someday. +def decode_backslashreplace(text, encoding): + return text.decode(encoding, errors="backslashreplace") - """ - if with_traceback is not None: - exception = exception.with_traceback(with_traceback) - if from_ is not False: - exception.__cause__ = from_ - elif replace_context is not None: - # no good solution here, we would like to have the exception - # have only the context of replace_context.__context__ so that the - # intermediary exception does not change, but we can't figure - # that out. - exception.__cause__ = replace_context +def cmp(a, b): + return (a > b) - (a < b) - try: - raise exception - finally: - # credit to - # https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/ - # as the __traceback__ object creates a cycle - del exception, replace_context, from_, with_traceback - def u(s): - return s +def raise_(exception, with_traceback=None, replace_context=None, from_=False): + r"""implement "raise" with cause support. - def ue(s): - return s + :param exception: exception to raise + :param with_traceback: will call exception.with_traceback() + :param replace_context: an as-yet-unsupported feature. This is + an exception object which we are "replacing", e.g., it's our + "cause" but we don't want it printed. Basically just what + ``__suppress_context__`` does but we don't want to suppress + the enclosing context, if any. So for now we make it the + cause. + :param from\_: the cause. this actually sets the cause and doesn't + hope to hide it someday. - from typing import TYPE_CHECKING - - # Unused. Kept for backwards compatibility. - callable = callable # noqa - - from abc import ABC - - def _qualname(fn): - return fn.__qualname__ - - -else: - import base64 - import ConfigParser as configparser # noqa - import itertools - - from StringIO import StringIO # noqa - from cStringIO import StringIO as byte_buffer # noqa - from itertools import izip_longest as zip_longest # noqa - from time import clock as perf_counter # noqa - from urllib import quote # noqa - from urllib import quote_plus # noqa - from urllib import unquote # noqa - from urllib import unquote_plus # noqa - from urlparse import parse_qsl # noqa - - from abc import ABCMeta - - class ABC: - __metaclass__ = ABCMeta + """ + if with_traceback is not None: + exception = exception.with_traceback(with_traceback) + + if from_ is not False: + exception.__cause__ = from_ + elif replace_context is not None: + # no good solution here, we would like to have the exception + # have only the context of replace_context.__context__ so that the + # intermediary exception does not change, but we can't figure + # that out. + exception.__cause__ = replace_context try: - import cPickle as pickle - except ImportError: - import pickle # noqa - - string_types = (basestring,) # noqa - binary_types = (bytes,) - binary_type = str - text_type = unicode # noqa - int_types = int, long # noqa - long_type = long # noqa - - callable = callable # noqa - cmp = cmp # noqa - reduce = reduce # noqa - - b64encode = base64.b64encode - b64decode = base64.b64decode - - itertools_filterfalse = itertools.ifilterfalse - itertools_filter = itertools.ifilter - itertools_imap = itertools.imap - - def b(s): - return s - - def exec_(func_text, globals_, lcl=None): - if lcl is None: - exec("exec func_text in globals_") - else: - exec("exec func_text in globals_, lcl") - - def iterbytes(buf): - return (ord(byte) for byte in buf) - - def import_(*args): - if len(args) == 4: - args = args[0:3] + ([str(arg) for arg in args[3]],) - return __import__(*args) - - def print_(*args, **kwargs): - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - for arg in enumerate(args): - if not isinstance(arg, basestring): # noqa - arg = str(arg) - fp.write(arg) - - def u(s): - # this differs from what six does, which doesn't support non-ASCII - # strings - we only use u() with - # literal source strings, and all our source files with non-ascii - # in them (all are tests) are utf-8 encoded. - return unicode(s, "utf-8") # noqa - - def ue(s): - return unicode(s, "unicode_escape") # noqa - - def decode_backslashreplace(text, encoding): - try: - return text.decode(encoding) - except UnicodeDecodeError: - # regular "backslashreplace" for an incompatible encoding raises: - # "TypeError: don't know how to handle UnicodeDecodeError in - # error callback" - return repr(text)[1:-1].decode() - - def safe_bytestring(text): - # py2k only - if not isinstance(text, string_types): - return unicode(text).encode( # noqa: F821 - "ascii", errors="backslashreplace" - ) - elif isinstance(text, unicode): # noqa: F821 - return text.encode("ascii", errors="backslashreplace") - else: - return text - - exec( - "def raise_(exception, with_traceback=None, replace_context=None, " - "from_=False):\n" - " if with_traceback:\n" - " raise type(exception), exception, with_traceback\n" - " else:\n" - " raise exception\n" - ) - - TYPE_CHECKING = False - - def _qualname(meth): - """return __qualname__ equivalent for a method on a class""" - - for cls in meth.im_class.__mro__: - if meth.__name__ in cls.__dict__: - break - else: - return meth.__name__ - - return "%s.%s" % (cls.__name__, meth.__name__) - - -if py3k: + raise exception + finally: + # credit to + # https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/ + # as the __traceback__ object creates a cycle + del exception, replace_context, from_, with_traceback + + +def _formatannotation(annotation, base_module=None): + """vendored from python 3.7""" + + if getattr(annotation, "__module__", None) == "typing": + return repr(annotation).replace("typing.", "") + if isinstance(annotation, type): + if annotation.__module__ in ("builtins", base_module): + return annotation.__qualname__ + return annotation.__module__ + "." + annotation.__qualname__ + return repr(annotation) + + +def inspect_formatargspec( + args, + varargs=None, + varkw=None, + defaults=None, + kwonlyargs=(), + kwonlydefaults={}, + annotations={}, + formatarg=str, + formatvarargs=lambda name: "*" + name, + formatvarkw=lambda name: "**" + name, + formatvalue=lambda value: "=" + repr(value), + formatreturns=lambda text: " -> " + text, + formatannotation=_formatannotation, +): + """Copy formatargspec from python 3.7 standard library. + + Python 3 has deprecated formatargspec and requested that Signature + be used instead, however this requires a full reimplementation + of formatargspec() in terms of creating Parameter objects and such. + Instead of introducing all the object-creation overhead and having + to reinvent from scratch, just copy their compatibility routine. + + Ultimately we would need to rewrite our "decorator" routine completely + which is not really worth it right now, until all Python 2.x support + is dropped. - def _formatannotation(annotation, base_module=None): - """vendored from python 3.7""" - - if getattr(annotation, "__module__", None) == "typing": - return repr(annotation).replace("typing.", "") - if isinstance(annotation, type): - if annotation.__module__ in ("builtins", base_module): - return annotation.__qualname__ - return annotation.__module__ + "." + annotation.__qualname__ - return repr(annotation) - - def inspect_formatargspec( - args, - varargs=None, - varkw=None, - defaults=None, - kwonlyargs=(), - kwonlydefaults={}, - annotations={}, - formatarg=str, - formatvarargs=lambda name: "*" + name, - formatvarkw=lambda name: "**" + name, - formatvalue=lambda value: "=" + repr(value), - formatreturns=lambda text: " -> " + text, - formatannotation=_formatannotation, - ): - """Copy formatargspec from python 3.7 standard library. - - Python 3 has deprecated formatargspec and requested that Signature - be used instead, however this requires a full reimplementation - of formatargspec() in terms of creating Parameter objects and such. - Instead of introducing all the object-creation overhead and having - to reinvent from scratch, just copy their compatibility routine. - - Ultimately we would need to rewrite our "decorator" routine completely - which is not really worth it right now, until all Python 2.x support - is dropped. - - """ - - kwonlydefaults = kwonlydefaults or {} - annotations = annotations or {} - - def formatargandannotation(arg): - result = formatarg(arg) - if arg in annotations: - result += ": " + formatannotation(annotations[arg]) - return result - - specs = [] - if defaults: - firstdefault = len(args) - len(defaults) - for i, arg in enumerate(args): - spec = formatargandannotation(arg) - if defaults and i >= firstdefault: - spec = spec + formatvalue(defaults[i - firstdefault]) - specs.append(spec) + """ - if varargs is not None: - specs.append(formatvarargs(formatargandannotation(varargs))) - else: - if kwonlyargs: - specs.append("*") + kwonlydefaults = kwonlydefaults or {} + annotations = annotations or {} - if kwonlyargs: - for kwonlyarg in kwonlyargs: - spec = formatargandannotation(kwonlyarg) - if kwonlydefaults and kwonlyarg in kwonlydefaults: - spec += formatvalue(kwonlydefaults[kwonlyarg]) - specs.append(spec) - - if varkw is not None: - specs.append(formatvarkw(formatargandannotation(varkw))) - - result = "(" + ", ".join(specs) + ")" - if "return" in annotations: - result += formatreturns(formatannotation(annotations["return"])) + def formatargandannotation(arg): + result = formatarg(arg) + if arg in annotations: + result += ": " + formatannotation(annotations[arg]) return result + specs = [] + if defaults: + firstdefault = len(args) - len(defaults) + for i, arg in enumerate(args): + spec = formatargandannotation(arg) + if defaults and i >= firstdefault: + spec = spec + formatvalue(defaults[i - firstdefault]) + specs.append(spec) + + if varargs is not None: + specs.append(formatvarargs(formatargandannotation(varargs))) + else: + if kwonlyargs: + specs.append("*") -else: - from inspect import formatargspec as _inspect_formatargspec - - def inspect_formatargspec(*spec, **kw): - # convert for a potential FullArgSpec from compat.getfullargspec() - return _inspect_formatargspec(*spec[0:4], **kw) # noqa - - -# Fix deprecation of accessing ABCs straight from collections module -# (which will stop working in 3.8). -if py3k: - import collections.abc as collections_abc -else: - import collections as collections_abc # noqa - - -if py37: - import dataclasses + if kwonlyargs: + for kwonlyarg in kwonlyargs: + spec = formatargandannotation(kwonlyarg) + if kwonlydefaults and kwonlyarg in kwonlydefaults: + spec += formatvalue(kwonlydefaults[kwonlyarg]) + specs.append(spec) - def dataclass_fields(cls): - """Return a sequence of all dataclasses.Field objects associated - with a class.""" + if varkw is not None: + specs.append(formatvarkw(formatargandannotation(varkw))) - if dataclasses.is_dataclass(cls): - return dataclasses.fields(cls) - else: - return [] + result = "(" + ", ".join(specs) + ")" + if "return" in annotations: + result += formatreturns(formatannotation(annotations["return"])) + return result - def local_dataclass_fields(cls): - """Return a sequence of all dataclasses.Field objects associated with - a class, excluding those that originate from a superclass.""" - if dataclasses.is_dataclass(cls): - super_fields = set() - for sup in cls.__bases__: - super_fields.update(dataclass_fields(sup)) - return [ - f for f in dataclasses.fields(cls) if f not in super_fields - ] - else: - return [] +def dataclass_fields(cls): + """Return a sequence of all dataclasses.Field objects associated + with a class.""" + if dataclasses.is_dataclass(cls): + return dataclasses.fields(cls) + else: + return [] -else: - def dataclass_fields(cls): - return [] +def local_dataclass_fields(cls): + """Return a sequence of all dataclasses.Field objects associated with + a class, excluding those that originate from a superclass.""" - def local_dataclass_fields(cls): + if dataclasses.is_dataclass(cls): + super_fields = set() + for sup in cls.__bases__: + super_fields.update(dataclass_fields(sup)) + return [f for f in dataclasses.fields(cls) if f not in super_fields] + else: return [] @@ -497,134 +275,3 @@ def reraise(tp, value, tb=None, cause=None): r"""legacy. use raise\_()""" raise_(value, with_traceback=tb, from_=cause) - - -def with_metaclass(meta, *bases, **kw): - """Create a base class with a metaclass. - - Drops the middle class upon creation. - - Source: https://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/ - - """ - - class metaclass(meta): - __call__ = type.__call__ - __init__ = type.__init__ - - def __new__(cls, name, this_bases, d): - if this_bases is None: - cls = type.__new__(cls, name, (), d) - else: - cls = meta(name, bases, d) - - if hasattr(cls, "__init_subclass__") and hasattr( - cls.__init_subclass__, "__func__" - ): - cls.__init_subclass__.__func__(cls, **kw) - return cls - - return metaclass("temporary_class", None, {}) - - -if py3k: - from datetime import timezone -else: - from datetime import datetime - from datetime import timedelta - from datetime import tzinfo - - class timezone(tzinfo): - """Minimal port of python 3 timezone object""" - - __slots__ = "_offset" - - def __init__(self, offset): - if not isinstance(offset, timedelta): - raise TypeError("offset must be a timedelta") - if not self._minoffset <= offset <= self._maxoffset: - raise ValueError( - "offset must be a timedelta " - "strictly between -timedelta(hours=24) and " - "timedelta(hours=24)." - ) - self._offset = offset - - def __eq__(self, other): - if type(other) != timezone: - return False - return self._offset == other._offset - - def __hash__(self): - return hash(self._offset) - - def __repr__(self): - return "sqlalchemy.util.%s(%r)" % ( - self.__class__.__name__, - self._offset, - ) - - def __str__(self): - return self.tzname(None) - - def utcoffset(self, dt): - return self._offset - - def tzname(self, dt): - return self._name_from_offset(self._offset) - - def dst(self, dt): - return None - - def fromutc(self, dt): - if isinstance(dt, datetime): - if dt.tzinfo is not self: - raise ValueError("fromutc: dt.tzinfo " "is not self") - return dt + self._offset - raise TypeError( - "fromutc() argument must be a datetime instance" " or None" - ) - - @staticmethod - def _timedelta_to_microseconds(timedelta): - """backport of timedelta._to_microseconds()""" - return ( - timedelta.days * (24 * 3600) + timedelta.seconds - ) * 1000000 + timedelta.microseconds - - @staticmethod - def _divmod_timedeltas(a, b): - """backport of timedelta.__divmod__""" - - q, r = divmod( - timezone._timedelta_to_microseconds(a), - timezone._timedelta_to_microseconds(b), - ) - return q, timedelta(0, 0, r) - - @staticmethod - def _name_from_offset(delta): - if not delta: - return "UTC" - if delta < timedelta(0): - sign = "-" - delta = -delta - else: - sign = "+" - hours, rest = timezone._divmod_timedeltas( - delta, timedelta(hours=1) - ) - minutes, rest = timezone._divmod_timedeltas( - rest, timedelta(minutes=1) - ) - result = "UTC%s%02d:%02d" % (sign, hours, minutes) - if rest.seconds: - result += ":%02d" % (rest.seconds,) - if rest.microseconds: - result += ".%06d" % (rest.microseconds,) - return result - - _maxoffset = timedelta(hours=23, minutes=59) - _minoffset = -_maxoffset - - timezone.utc = timezone(timedelta(0)) diff --git a/lib/sqlalchemy/util/concurrency.py b/lib/sqlalchemy/util/concurrency.py index 37ecfdbc33..3518f874dc 100644 --- a/lib/sqlalchemy/util/concurrency.py +++ b/lib/sqlalchemy/util/concurrency.py @@ -5,30 +5,25 @@ # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -from . import compat have_greenlet = False -if compat.py3k: - try: - import greenlet # noqa F401 - except ImportError: - pass - else: - have_greenlet = True - from ._concurrency_py3k import await_only - from ._concurrency_py3k import await_fallback - from ._concurrency_py3k import greenlet_spawn - from ._concurrency_py3k import is_exit_exception - from ._concurrency_py3k import AsyncAdaptedLock - from ._concurrency_py3k import _util_async_run # noqa F401 - from ._concurrency_py3k import ( - _util_async_run_coroutine_function, - ) # noqa F401, E501 - from ._concurrency_py3k import asyncio # noqa F401 - - # does not need greennlet, just Python 3 - from ._compat_py3k import asynccontextmanager # noqa F401 +try: + import greenlet # noqa F401 +except ImportError: + pass +else: + have_greenlet = True + from ._concurrency_py3k import await_only + from ._concurrency_py3k import await_fallback + from ._concurrency_py3k import greenlet_spawn + from ._concurrency_py3k import is_exit_exception + from ._concurrency_py3k import AsyncAdaptedLock + from ._concurrency_py3k import _util_async_run # noqa F401 + from ._concurrency_py3k import ( + _util_async_run_coroutine_function, + ) # noqa F401, E501 + from ._concurrency_py3k import asyncio # noqa F401 if not have_greenlet: @@ -40,12 +35,9 @@ if not have_greenlet: if have_greenlet: return None - if not compat.py3k: - raise ValueError("Cannot use this function in py2.") - else: - raise ValueError( - "the greenlet library is required to use this function." - ) + raise ValueError( + "the greenlet library is required to use this function." + ) def is_exit_exception(e): # noqa F811 return not isinstance(e, Exception) diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index ac2c6e6a42..621941b430 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -28,8 +28,7 @@ from .. import exc def md5_hex(x): - if compat.py3k: - x = x.encode("utf-8") + x = x.encode("utf-8") m = hashlib.md5() m.update(x) return m.hexdigest() @@ -72,14 +71,6 @@ class safe_reraise: with_traceback=exc_tb, ) else: - if not compat.py3k and self._exc_info and self._exc_info[1]: - # emulate Py3K's behavior of telling us when an exception - # occurs in an exception handler. - warn( - "An exception has occurred during handling of a " - "previous exception. The previous exception " - "is:\n %s %s\n" % (self._exc_info[0], self._exc_info[1]) - ) self._exc_info = None # remove potential circular references compat.raise_(value, with_traceback=traceback) @@ -99,7 +90,7 @@ def walk_subclasses(cls): def string_or_unprintable(element): - if isinstance(element, compat.string_types): + if isinstance(element, str): return element else: try: @@ -148,7 +139,7 @@ def _unique_symbols(used, *bases): for base in bases: pool = itertools.chain( (base,), - compat.itertools_imap(lambda i: base + str(i), range(1000)), + map(lambda i: base + str(i), range(1000)), ) for sym in pool: if sym not in used: @@ -346,7 +337,7 @@ class PluginLoader: def register(self, name, modulepath, objname): def load(): - mod = compat.import_(modulepath) + mod = __import__(modulepath) for token in modulepath.split(".")[1:]: mod = getattr(mod, token) return getattr(mod, objname) @@ -516,7 +507,7 @@ def format_argspec_plus(fn, grouped=True): 'apply_pos': '(self, a, b, c, **d)'} """ - if compat.callable(fn): + if callable(fn): spec = compat.inspect_getfullargspec(fn) else: spec = fn @@ -899,14 +890,8 @@ def class_hierarchy(cls): process.append(b) hier.add(b) - if compat.py3k: - if c.__module__ == "builtins" or not hasattr(c, "__subclasses__"): - continue - else: - if c.__module__ == "__builtin__" or not hasattr( - c, "__subclasses__" - ): - continue + if c.__module__ == "builtins" or not hasattr(c, "__subclasses__"): + continue for s in [_ for _ in c.__subclasses__() if _ not in hier]: process.append(s) @@ -985,7 +970,7 @@ def monkeypatch_proxied_specials( ) env = from_instance is not None and {name: from_instance} or {} - compat.exec_(py, env) + exec(py, env) try: env[method].__defaults__ = fn.__defaults__ except AttributeError: @@ -1073,7 +1058,7 @@ def as_interface(obj, cls=None, methods=None, required=None): for method, impl in dictlike_iteritems(obj): if method not in interface: raise TypeError("%r: unknown in this interface" % method) - if not compat.callable(impl): + if not callable(impl): raise TypeError("%r=%r is not callable" % (method, impl)) setattr(AnonymousInterface, method, staticmethod(impl)) found.add(method) @@ -1230,7 +1215,7 @@ class MemoizedSlots: # from paste.deploy.converters def asbool(obj): - if isinstance(obj, compat.string_types): + if isinstance(obj, str): obj = obj.strip().lower() if obj in ["true", "yes", "on", "y", "t", "1"]: return True @@ -1375,14 +1360,8 @@ def assert_arg_type(arg, argtype, name): def dictlike_iteritems(dictlike): """Return a (key, value) iterator for almost any dict-like object.""" - if compat.py3k: - if hasattr(dictlike, "items"): - return list(dictlike.items()) - else: - if hasattr(dictlike, "iteritems"): - return dictlike.iteritems() - elif hasattr(dictlike, "items"): - return iter(dictlike.items()) + if hasattr(dictlike, "items"): + return list(dictlike.items()) getter = getattr(dictlike, "__getitem__", getattr(dictlike, "get", None)) if getter is None: @@ -1458,7 +1437,7 @@ class hybridmethod: class _symbol(int): def __new__(self, name, doc=None, canonical=None): """Construct a new named symbol.""" - assert isinstance(name, compat.string_types) + assert isinstance(name, str) if canonical is None: canonical = hash(name) v = int.__new__(_symbol, canonical) @@ -1585,7 +1564,7 @@ def ellipses_string(value, len_=25): return value -class _hash_limit_string(compat.text_type): +class _hash_limit_string(str): """A string subclass that can only be hashed on a maximum amount of unique values. diff --git a/test/aaa_profiling/test_resultset.py b/test/aaa_profiling/test_resultset.py index 1f777e42e4..12921a7dc3 100644 --- a/test/aaa_profiling/test_resultset.py +++ b/test/aaa_profiling/test_resultset.py @@ -12,7 +12,6 @@ from sqlalchemy.testing import AssertsExecutionResults from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import profiling -from sqlalchemy.util import u NUM_FIELDS = 10 @@ -49,7 +48,7 @@ class ResultSetTest(fixtures.TablesTest, AssertsExecutionResults): t.insert(), [ dict( - ("field%d" % fnum, u("value%d" % fnum)) + ("field%d" % fnum, "value%d" % fnum) for fnum in range(NUM_FIELDS) ) for r_num in range(NUM_RECORDS) @@ -59,7 +58,7 @@ class ResultSetTest(fixtures.TablesTest, AssertsExecutionResults): t2.insert(), [ dict( - ("field%d" % fnum, u("value%d" % fnum)) + ("field%d" % fnum, "value%d" % fnum) for fnum in range(NUM_FIELDS) ) for r_num in range(NUM_RECORDS) diff --git a/test/base/test_events.py b/test/base/test_events.py index c94de7dd51..2b785ba0b3 100644 --- a/test/base/test_events.py +++ b/test/base/test_events.py @@ -1,5 +1,8 @@ """Test event registration and listening.""" +from unittest.mock import call +from unittest.mock import Mock + from sqlalchemy import event from sqlalchemy import exc from sqlalchemy import testing @@ -10,8 +13,6 @@ from sqlalchemy.testing import expect_deprecated from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_not -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.util import gc_collect diff --git a/test/base/test_except.py b/test/base/test_except.py index 767fd233c0..6e9a3c5df3 100644 --- a/test/base/test_except.py +++ b/test/base/test_except.py @@ -10,8 +10,6 @@ from sqlalchemy.engine import default from sqlalchemy.testing import combinations_list from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures -from sqlalchemy.util import compat -from sqlalchemy.util import u class Error(Exception): @@ -157,16 +155,13 @@ class WrapTest(fixtures.TestBase): def test_wrap_unicode_arg(self): # this is not supported by the API but oslo_db is doing it orig = sa_exceptions.DBAPIError(False, False, False) - orig.args = [u("méil")] + orig.args = ["méil"] eq_( - compat.text_type(orig), - compat.u( - "méil\n(Background on this error at: " - "https://sqlalche.me/e/%s/dbapi)" - % sa_exceptions._version_token - ), + str(orig), + "méil\n(Background on this error at: " + "https://sqlalche.me/e/%s/dbapi)" % sa_exceptions._version_token, ) - eq_(orig.args, (u("méil"),)) + eq_(orig.args, ("méil",)) def test_tostring_large_dict(self): try: diff --git a/test/base/test_misc_py3k.py b/test/base/test_misc_py3k.py index 11e7b9edda..d0cc5eed95 100644 --- a/test/base/test_misc_py3k.py +++ b/test/base/test_misc_py3k.py @@ -1,10 +1,8 @@ from sqlalchemy import Column from sqlalchemy.testing import fixtures -from sqlalchemy.testing import requires class TestGenerics(fixtures.TestBase): - @requires.generic_classes def test_traversible_is_generic(self): col = Column[int] assert col is Column diff --git a/test/base/test_tutorials.py b/test/base/test_tutorials.py index c8c51b0b5f..bf4503fe65 100644 --- a/test/base/test_tutorials.py +++ b/test/base/test_tutorials.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import doctest import logging import os @@ -69,7 +67,7 @@ class DocTest(fixtures.TestBase): checker=_get_unicode_checker(), ) parser = doctest.DocTestParser() - globs = {"print_function": print_function} + globs = {"print_function": print} for fname in fnames: path = os.path.join(sqla_base, "doc/build", fname) diff --git a/test/base/test_utils.py b/test/base/test_utils.py index 8674f47796..3bbcbe3fbb 100644 --- a/test/base/test_utils.py +++ b/test/base/test_utils.py @@ -1,8 +1,8 @@ #! coding: utf-8 import copy -import datetime import inspect +import pickle import sys from sqlalchemy import exc @@ -28,7 +28,6 @@ from sqlalchemy.util import classproperty from sqlalchemy.util import compat from sqlalchemy.util import get_callable_argspec from sqlalchemy.util import langhelpers -from sqlalchemy.util import timezone from sqlalchemy.util import WeakSequence @@ -1741,14 +1740,9 @@ class IdentitySetTest(fixtures.TestBase): return super_, sub_, twin1, twin2, unique1, unique2 def _assert_unorderable_types(self, callable_): - if util.py3k: - assert_raises_message( - TypeError, "not supported between instances of", callable_ - ) - else: - assert_raises_message( - TypeError, "cannot compare sets using cmp()", callable_ - ) + assert_raises_message( + TypeError, "not supported between instances of", callable_ + ) def test_basic_sanity(self): IdentitySet = util.IdentitySet @@ -2241,13 +2235,13 @@ class SymbolTest(fixtures.TestBase): assert sym1 is sym2 # default - s = util.pickle.dumps(sym1) - util.pickle.loads(s) + s = pickle.dumps(sym1) + pickle.loads(s) for protocol in 0, 1, 2: print(protocol) - serial = util.pickle.dumps(sym1) - rt = util.pickle.loads(serial) + serial = pickle.dumps(sym1) + rt = pickle.loads(serial) assert rt is sym1 assert rt is sym2 @@ -2336,34 +2330,16 @@ class SymbolTest(fixtures.TestBase): class _Py3KFixtures: - def _kw_only_fixture(self): + def _kw_only_fixture(self, a, *, b, c): pass - def _kw_plus_posn_fixture(self): + def _kw_plus_posn_fixture(self, a, *args, b, c): pass - def _kw_opt_fixture(self): + def _kw_opt_fixture(self, a, *, b, c="c"): pass -if util.py3k: - _locals = {} - exec( - """ -def _kw_only_fixture(self, a, *, b, c): - pass - -def _kw_plus_posn_fixture(self, a, *args, b, c): - pass - -def _kw_opt_fixture(self, a, *, b, c="c"): - pass -""", - _locals, - ) - for k in _locals: - setattr(_Py3KFixtures, k, _locals[k]) - py3k_fixtures = _Py3KFixtures() @@ -3138,100 +3114,43 @@ class BackslashReplaceTest(fixtures.TestBase): def test_ascii_to_utf8(self): eq_( compat.decode_backslashreplace(util.b("hello world"), "utf-8"), - util.u("hello world"), + "hello world", ) def test_utf8_to_utf8(self): eq_( compat.decode_backslashreplace( - util.u("some message méil").encode("utf-8"), "utf-8" + "some message méil".encode("utf-8"), "utf-8" ), - util.u("some message méil"), + "some message méil", ) def test_latin1_to_utf8(self): eq_( compat.decode_backslashreplace( - util.u("some message méil").encode("latin-1"), "utf-8" + "some message méil".encode("latin-1"), "utf-8" ), - util.u("some message m\\xe9il"), + "some message m\\xe9il", ) eq_( compat.decode_backslashreplace( - util.u("some message méil").encode("latin-1"), "latin-1" + "some message méil".encode("latin-1"), "latin-1" ), - util.u("some message méil"), + "some message méil", ) def test_cp1251_to_utf8(self): - message = util.u("some message П").encode("cp1251") + message = "some message П".encode("cp1251") eq_(message, b"some message \xcf") eq_( compat.decode_backslashreplace(message, "utf-8"), - util.u("some message \\xcf"), + "some message \\xcf", ) eq_( compat.decode_backslashreplace(message, "cp1251"), - util.u("some message П"), - ) - - -class TimezoneTest(fixtures.TestBase): - """test the python 2 backport of the "timezone" class. - - Note under python 3, these tests work against the builtin timezone, - thereby providing confirmation that the tests are correct. - - """ - - @testing.combinations( - (datetime.timedelta(0), "UTC"), - (datetime.timedelta(hours=5), "UTC+05:00"), - (datetime.timedelta(hours=5, minutes=10), "UTC+05:10"), - ( - datetime.timedelta(hours=5, minutes=10, seconds=27), - "UTC+05:10:27", - testing.requires.granular_timezone, - ), - (datetime.timedelta(hours=-3, minutes=10), "UTC-02:50"), - ( - datetime.timedelta( - hours=5, minutes=10, seconds=27, microseconds=550 - ), - "UTC+05:10:27.000550", - testing.requires.granular_timezone, - ), - ) - def test_tzname(self, td, expected): - eq_(timezone(td).tzname(None), expected) - - def test_utcoffset(self): - eq_( - timezone(datetime.timedelta(hours=5)).utcoffset(None), - datetime.timedelta(hours=5), - ) - - def test_fromutc(self): - tzinfo = timezone(datetime.timedelta(hours=5)) - dt = datetime.datetime(2017, 10, 5, 12, 55, 38, tzinfo=tzinfo) - eq_( - dt.astimezone(timezone.utc), - datetime.datetime(2017, 10, 5, 7, 55, 38, tzinfo=timezone.utc), - ) - - # this is the same as hours=-3 - del_ = datetime.timedelta(days=-1, seconds=75600) - eq_( - dt.astimezone(timezone(datetime.timedelta(hours=-3))), - datetime.datetime(2017, 10, 5, 4, 55, 38, tzinfo=timezone(del_)), - ) - - def test_repr(self): - eq_( - repr(timezone(datetime.timedelta(hours=5))), - "datetime.timezone(%r)" % (datetime.timedelta(hours=5)), + "some message П", ) diff --git a/test/conftest.py b/test/conftest.py index 0db4486a92..6f08a7c0dd 100755 --- a/test/conftest.py +++ b/test/conftest.py @@ -16,11 +16,6 @@ os.environ["SQLALCHEMY_WARN_20"] = "true" collect_ignore_glob = [] -# minimum version for a py3k only test is at -# 3.6 because these are asyncio tests anyway -if sys.version_info[0:2] < (3, 6): - collect_ignore_glob.append("*_py3k.py") - pytest.register_assert_rewrite("sqlalchemy.testing.assertions") diff --git a/test/dialect/mssql/test_deprecations.py b/test/dialect/mssql/test_deprecations.py index 24625d65c7..972ce413ba 100644 --- a/test/dialect/mssql/test_deprecations.py +++ b/test/dialect/mssql/test_deprecations.py @@ -1,4 +1,6 @@ # -*- encoding: utf-8 +from unittest.mock import Mock + from sqlalchemy import Column from sqlalchemy import engine_from_config from sqlalchemy import Integer @@ -17,7 +19,6 @@ from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ -from sqlalchemy.testing.mock import Mock def _legacy_schema_aliasing_warning(): diff --git a/test/dialect/mssql/test_engine.py b/test/dialect/mssql/test_engine.py index e14fd164a0..b40981a99c 100644 --- a/test/dialect/mssql/test_engine.py +++ b/test/dialect/mssql/test_engine.py @@ -1,6 +1,7 @@ # -*- encoding: utf-8 from decimal import Decimal +from unittest.mock import Mock from sqlalchemy import Column from sqlalchemy import event @@ -26,7 +27,6 @@ from sqlalchemy.testing import expect_raises from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import mock -from sqlalchemy.testing.mock import Mock class ParseConnectTest(fixtures.TestBase): diff --git a/test/dialect/mssql/test_reflection.py b/test/dialect/mssql/test_reflection.py index 1789166ee1..f877d2c5c7 100644 --- a/test/dialect/mssql/test_reflection.py +++ b/test/dialect/mssql/test_reflection.py @@ -19,7 +19,6 @@ from sqlalchemy import Table from sqlalchemy import testing from sqlalchemy import types from sqlalchemy import types as sqltypes -from sqlalchemy import util from sqlalchemy.dialects import mssql from sqlalchemy.dialects.mssql import base from sqlalchemy.dialects.mssql.information_schema import tables @@ -782,8 +781,8 @@ class IdentityReflectionTest(fixtures.TablesTest): eq_(type(col["identity"]["increment"]), int) elif col["name"] == "id3": eq_(col["identity"], {"start": 1, "increment": 1}) - eq_(type(col["identity"]["start"]), util.compat.long_type) - eq_(type(col["identity"]["increment"]), util.compat.long_type) + eq_(type(col["identity"]["start"]), int) + eq_(type(col["identity"]["increment"]), int) elif col["name"] == "id4": eq_(col["identity"], {"start": 1, "increment": 1}) eq_(type(col["identity"]["start"]), int) diff --git a/test/dialect/mssql/test_types.py b/test/dialect/mssql/test_types.py index 57a1f1284f..63c6cf26d7 100644 --- a/test/dialect/mssql/test_types.py +++ b/test/dialect/mssql/test_types.py @@ -31,7 +31,6 @@ from sqlalchemy import Time from sqlalchemy import types from sqlalchemy import Unicode from sqlalchemy import UnicodeText -from sqlalchemy import util from sqlalchemy.dialects.mssql import base as mssql from sqlalchemy.dialects.mssql import ROWVERSION from sqlalchemy.dialects.mssql import TIMESTAMP @@ -790,7 +789,7 @@ class TypeRoundTripTest( 2, 32, 123456, - util.timezone(datetime.timedelta(hours=-5)), + datetime.timezone(datetime.timedelta(hours=-5)), ) return t, (d1, t1, d2, d3) @@ -828,7 +827,7 @@ class TypeRoundTripTest( 11, 2, 32, - tzinfo=util.timezone(datetime.timedelta(hours=-5)), + tzinfo=datetime.timezone(datetime.timedelta(hours=-5)), ), ), (datetime.datetime(2007, 10, 30, 11, 2, 32)), @@ -849,7 +848,7 @@ class TypeRoundTripTest( ).first() if not date.tzinfo: - eq_(row, (date, date.replace(tzinfo=util.timezone.utc))) + eq_(row, (date, date.replace(tzinfo=datetime.timezone.utc))) else: eq_(row, (date.replace(tzinfo=None), date)) @@ -875,7 +874,7 @@ class TypeRoundTripTest( 2, 32, 123456, - util.timezone(datetime.timedelta(hours=1)), + datetime.timezone(datetime.timedelta(hours=1)), ), 1, False, @@ -890,7 +889,7 @@ class TypeRoundTripTest( 2, 32, 123456, - util.timezone(datetime.timedelta(hours=-5)), + datetime.timezone(datetime.timedelta(hours=-5)), ), -5, False, @@ -905,7 +904,7 @@ class TypeRoundTripTest( 2, 32, 123456, - util.timezone(datetime.timedelta(seconds=4000)), + datetime.timezone(datetime.timedelta(seconds=4000)), ), None, True, @@ -973,7 +972,7 @@ class TypeRoundTripTest( 2, 32, 123456, - util.timezone( + datetime.timezone( datetime.timedelta(hours=expected_offset_hours) ), ), @@ -1168,7 +1167,7 @@ class StringTest(fixtures.TestBase, AssertsCompiledSQL): def test_string_text_literal_binds_explicit_unicode_right(self): self.assert_compile( - column("x", String()) == util.u("foo"), + column("x", String()) == "foo", "x = 'foo'", literal_binds=True, ) @@ -1178,7 +1177,7 @@ class StringTest(fixtures.TestBase, AssertsCompiledSQL): # Unicode on Python 3 for plain string, test with unicode # string just to confirm literal is doing this self.assert_compile( - column("x", String()) == literal(util.u("foo")), + column("x", String()) == literal("foo"), "x = N'foo'", literal_binds=True, ) diff --git a/test/dialect/mysql/test_reflection.py b/test/dialect/mysql/test_reflection.py index 60d7e3a5dd..08c7d9a4d2 100644 --- a/test/dialect/mysql/test_reflection.py +++ b/test/dialect/mysql/test_reflection.py @@ -30,7 +30,6 @@ from sqlalchemy import types from sqlalchemy import Unicode from sqlalchemy import UnicodeText from sqlalchemy import UniqueConstraint -from sqlalchemy import util from sqlalchemy.dialects.mysql import base as mysql from sqlalchemy.dialects.mysql import reflection as _reflection from sqlalchemy.schema import CreateIndex @@ -848,8 +847,8 @@ class ReflectionTest(fixtures.TestBase, AssertsCompiledSQL): }, ] ischema_casing_1 = [ - (util.u("Test"), util.u("Track"), "TrackID"), - (util.u("Test_Schema"), util.u("Track"), "TrackID"), + ("Test", "Track", "TrackID"), + ("Test_Schema", "Track", "TrackID"), ] return fkeys_casing_1, ischema_casing_1 diff --git a/test/dialect/mysql/test_types.py b/test/dialect/mysql/test_types.py index c83de7f49e..3d26e1d07f 100644 --- a/test/dialect/mysql/test_types.py +++ b/test/dialect/mysql/test_types.py @@ -21,7 +21,6 @@ from sqlalchemy import TIMESTAMP from sqlalchemy import TypeDecorator from sqlalchemy import types as sqltypes from sqlalchemy import UnicodeText -from sqlalchemy import util from sqlalchemy.dialects.mysql import base as mysql from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message @@ -31,7 +30,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import eq_regex from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ -from sqlalchemy.util import u class TypeCompileTest(fixtures.TestBase, AssertsCompiledSQL): @@ -520,8 +518,8 @@ class TypeRoundTripTest(fixtures.TestBase, AssertsExecutionResults): # in order to test the condition here, need to use # MySQLdb 1.2.3 and also need to pass either use_unicode=1 # or charset=utf8 to the URL. - connection.execute(t.insert(), dict(id=1, data=u("some text"))) - assert isinstance(connection.scalar(select(t.c.data)), util.text_type) + connection.execute(t.insert(), dict(id=1, data="some text")) + assert isinstance(connection.scalar(select(t.c.data)), str) @testing.metadata_fixture(ddl="class") def bit_table(self, metadata): @@ -1077,17 +1075,17 @@ class EnumSetTest( "t", metadata, Column("id", Integer, primary_key=True), - Column("data", mysql.SET(u("réveillé"), u("drôle"), u("S’il"))), + Column("data", mysql.SET("réveillé", "drôle", "S’il")), ) set_table.create(connection) connection.execute( - set_table.insert(), {"data": set([u("réveillé"), u("drôle")])} + set_table.insert(), {"data": set(["réveillé", "drôle"])} ) row = connection.execute(set_table.select()).first() - eq_(row, (1, set([u("réveillé"), u("drôle")]))) + eq_(row, (1, set(["réveillé", "drôle"]))) def test_int_roundtrip(self, metadata, connection): set_table = self._set_fixture_one(metadata) @@ -1159,25 +1157,25 @@ class EnumSetTest( "table", metadata, Column("id", Integer, primary_key=True), - Column("value", Enum(u("réveillé"), u("drôle"), u("S’il"))), - Column("value2", mysql.ENUM(u("réveillé"), u("drôle"), u("S’il"))), + Column("value", Enum("réveillé", "drôle", "S’il")), + Column("value2", mysql.ENUM("réveillé", "drôle", "S’il")), ) metadata.create_all(connection) connection.execute( t1.insert(), [ - dict(value=u("drôle"), value2=u("drôle")), - dict(value=u("réveillé"), value2=u("réveillé")), - dict(value=u("S’il"), value2=u("S’il")), + dict(value="drôle", value2="drôle"), + dict(value="réveillé", value2="réveillé"), + dict(value="S’il", value2="S’il"), ], ) eq_( connection.execute(t1.select().order_by(t1.c.id)).fetchall(), [ - (1, u("drôle"), u("drôle")), - (2, u("réveillé"), u("réveillé")), - (3, u("S’il"), u("S’il")), + (1, "drôle", "drôle"), + (2, "réveillé", "réveillé"), + (3, "S’il", "S’il"), ], ) @@ -1189,11 +1187,11 @@ class EnumSetTest( # latin-1 stuff forcing its way in ? eq_( - t2.c.value.type.enums[0:2], [u("réveillé"), u("drôle")] + t2.c.value.type.enums[0:2], ["réveillé", "drôle"] ) # u'S’il') # eh ? eq_( - t2.c.value2.type.enums[0:2], [u("réveillé"), u("drôle")] + t2.c.value2.type.enums[0:2], ["réveillé", "drôle"] ) # u'S’il') # eh ? def test_enum_compile(self): diff --git a/test/dialect/oracle/test_dialect.py b/test/dialect/oracle/test_dialect.py index 52162a2866..18996c3f9c 100644 --- a/test/dialect/oracle/test_dialect.py +++ b/test/dialect/oracle/test_dialect.py @@ -1,6 +1,7 @@ # coding: utf-8 import re +from unittest.mock import Mock from sqlalchemy import bindparam from sqlalchemy import Computed @@ -30,12 +31,9 @@ from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import mock -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.suite import test_select -from sqlalchemy.util import u -from sqlalchemy.util import ue class DialectTest(fixtures.TestBase): @@ -242,7 +240,7 @@ class EncodingErrorsTest(fixtures.TestBase): ) def _assert_errorhandler(self, outconverter, has_errorhandler): - data = ue("\uee2c\u9a66") # this is u"\uee2c\u9a66" + data = "\uee2c\u9a66" # this is u"\uee2c\u9a66" utf8_w_errors = data.encode("utf-16") @@ -757,25 +755,25 @@ class UnicodeSchemaTest(fixtures.TestBase): ) metadata.create_all(connection) - connection.execute(table.insert(), {"_underscorecolumn": u("’é")}) + connection.execute(table.insert(), {"_underscorecolumn": "’é"}) result = connection.execute( - table.select().where(table.c._underscorecolumn == u("’é")) + table.select().where(table.c._underscorecolumn == "’é") ).scalar() - eq_(result, u("’é")) + eq_(result, "’é") def test_quoted_column_unicode(self, metadata, connection): table = Table( "atable", metadata, - Column(u("méil"), Unicode(255), primary_key=True), + Column("méil", Unicode(255), primary_key=True), ) metadata.create_all(connection) - connection.execute(table.insert(), {u("méil"): u("’é")}) + connection.execute(table.insert(), {"méil": "’é"}) result = connection.execute( - table.select().where(table.c[u("méil")] == u("’é")) + table.select().where(table.c["méil"] == "’é") ).scalar() - eq_(result, u("’é")) + eq_(result, "’é") class CXOracleConnectArgsTest(fixtures.TestBase): diff --git a/test/dialect/oracle/test_types.py b/test/dialect/oracle/test_types.py index 7034720559..db5717e178 100644 --- a/test/dialect/oracle/test_types.py +++ b/test/dialect/oracle/test_types.py @@ -32,7 +32,6 @@ from sqlalchemy import TypeDecorator from sqlalchemy import types as sqltypes from sqlalchemy import Unicode from sqlalchemy import UnicodeText -from sqlalchemy import util from sqlalchemy import VARCHAR from sqlalchemy.dialects.oracle import base as oracle from sqlalchemy.dialects.oracle import cx_oracle @@ -48,7 +47,6 @@ from sqlalchemy.testing.engines import testing_engine from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.util import b -from sqlalchemy.util import u def exec_sql(conn, sql, *args, **kwargs): @@ -784,13 +782,13 @@ class TypesTest(fixtures.TestBase): cx_oracle._OracleNChar, ) - data = u("m’a réveillé.") + data = "m’a réveillé." connection.execute(t2.insert(), dict(nv_data=data, c_data=data)) nv_data, c_data = connection.execute(t2.select()).first() eq_(nv_data, data) eq_(c_data, data + (" " * 7)) # char is space padded - assert isinstance(nv_data, util.text_type) - assert isinstance(c_data, util.text_type) + assert isinstance(nv_data, str) + assert isinstance(c_data, str) def test_reflect_unicode_no_nvarchar(self, metadata, connection): Table("tnv", metadata, Column("data", sqltypes.Unicode(255))) @@ -805,11 +803,11 @@ class TypesTest(fixtures.TestBase): cx_oracle._OracleString, ) - data = u("m’a réveillé.") + data = "m’a réveillé." connection.execute(t2.insert(), {"data": data}) res = connection.execute(t2.select()).first().data eq_(res, data) - assert isinstance(res, util.text_type) + assert isinstance(res, str) def test_char_length(self, metadata, connection): t1 = Table( @@ -1133,7 +1131,7 @@ class EuroNumericTest(fixtures.TestBase): {}, ), ]: - if isinstance(stmt, util.string_types): + if isinstance(stmt, str): test_exp = conn.exec_driver_sql(stmt, kw).scalar() else: test_exp = conn.scalar(stmt, **kw) @@ -1153,13 +1151,13 @@ class SetInputSizesTest(fixtures.TestBase): (oracle.BINARY_DOUBLE, 25.34534, "NATIVE_FLOAT", False), (oracle.BINARY_FLOAT, 25.34534, "NATIVE_FLOAT", False), (oracle.DOUBLE_PRECISION, 25.34534, None, False), - (Unicode(30), u("test"), "NCHAR", True), - (UnicodeText(), u("test"), "NCLOB", True), - (Unicode(30), u("test"), None, False), - (UnicodeText(), u("test"), "CLOB", False), + (Unicode(30), "test", "NCHAR", True), + (UnicodeText(), "test", "NCLOB", True), + (Unicode(30), "test", None, False), + (UnicodeText(), "test", "CLOB", False), (String(30), "test", None, False), (CHAR(30), "test", "FIXED_CHAR", False), - (NCHAR(30), u("test"), "FIXED_NCHAR", False), + (NCHAR(30), "test", "FIXED_NCHAR", False), (oracle.LONG(), "test", None, False), argnames="datatype, value, sis_value_text, set_nchar_flag", ) diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index 7e91f0ebb4..a04e2932a9 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -56,7 +56,6 @@ from sqlalchemy.testing.assertions import AssertsCompiledSQL from sqlalchemy.testing.assertions import expect_warnings from sqlalchemy.testing.assertions import is_ from sqlalchemy.util import OrderedDict -from sqlalchemy.util import u class SequenceTest(fixtures.TestBase, AssertsCompiledSQL): @@ -190,15 +189,10 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_create_drop_enum(self): # test escaping and unicode within CREATE TYPE for ENUM - typ = postgresql.ENUM( - "val1", "val2", "val's 3", u("méil"), name="myname" - ) + typ = postgresql.ENUM("val1", "val2", "val's 3", "méil", name="myname") self.assert_compile( postgresql.CreateEnumType(typ), - u( - "CREATE TYPE myname AS " - "ENUM ('val1', 'val2', 'val''s 3', 'méil')" - ), + "CREATE TYPE myname AS ENUM ('val1', 'val2', 'val''s 3', 'méil')", ) typ = postgresql.ENUM("val1", "val2", "val's 3", name="PleaseQuoteMe") diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index 7d4ea2ced1..57682686c8 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -51,8 +51,6 @@ from sqlalchemy.testing.assertions import AssertsExecutionResults from sqlalchemy.testing.assertions import eq_ from sqlalchemy.testing.assertions import eq_regex from sqlalchemy.testing.assertions import ne_ -from sqlalchemy.util import u -from sqlalchemy.util import ue if True: from sqlalchemy.dialects.postgresql.psycopg2 import ( @@ -313,10 +311,10 @@ class ExecuteManyMode: ) Table( - u("Unitéble2"), + "Unitéble2", metadata, - Column(u("méil"), Integer, primary_key=True), - Column(ue("\u6e2c\u8a66"), Integer), + Column("méil", Integer, primary_key=True), + Column("\u6e2c\u8a66", Integer), ) def test_insert(self, connection): @@ -478,16 +476,16 @@ class ExecuteManyMode: ) def test_insert_unicode_keys(self, connection): - table = self.tables[u("Unitéble2")] + table = self.tables["Unitéble2"] stmt = table.insert() connection.execute( stmt, [ - {u("méil"): 1, ue("\u6e2c\u8a66"): 1}, - {u("méil"): 2, ue("\u6e2c\u8a66"): 2}, - {u("méil"): 3, ue("\u6e2c\u8a66"): 3}, + {"méil": 1, "\u6e2c\u8a66": 1}, + {"méil": 2, "\u6e2c\u8a66": 2}, + {"méil": 3, "\u6e2c\u8a66": 3}, ], ) diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 4c0b91f93d..acca0926e3 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -1,6 +1,7 @@ # coding: utf-8 import datetime import decimal +from enum import Enum as _PY_Enum import re import uuid @@ -319,30 +320,30 @@ class EnumTest(fixtures.TestBase, AssertsExecutionResults): Column( "value", Enum( - util.u("réveillé"), - util.u("drôle"), - util.u("S’il"), + "réveillé", + "drôle", + "S’il", name="onetwothreetype", ), ), ) metadata.create_all(connection) - connection.execute(t1.insert(), dict(value=util.u("drôle"))) - connection.execute(t1.insert(), dict(value=util.u("réveillé"))) - connection.execute(t1.insert(), dict(value=util.u("S’il"))) + connection.execute(t1.insert(), dict(value="drôle")) + connection.execute(t1.insert(), dict(value="réveillé")) + connection.execute(t1.insert(), dict(value="S’il")) eq_( connection.execute(t1.select().order_by(t1.c.id)).fetchall(), [ - (1, util.u("drôle")), - (2, util.u("réveillé")), - (3, util.u("S’il")), + (1, "drôle"), + (2, "réveillé"), + (3, "S’il"), ], ) m2 = MetaData() t2 = Table("table", m2, autoload_with=connection) eq_( t2.c.value.type.enums, - [util.u("réveillé"), util.u("drôle"), util.u("S’il")], + ["réveillé", "drôle", "S’il"], ) def test_non_native_enum(self, metadata, connection): @@ -390,7 +391,7 @@ class EnumTest(fixtures.TestBase, AssertsExecutionResults): "bar", Enum( "B", - util.u("Ü"), + "Ü", name="myenum", create_constraint=True, native_enum=False, @@ -406,18 +407,16 @@ class EnumTest(fixtures.TestBase, AssertsExecutionResults): go, [ ( - util.u( - "CREATE TABLE foo (\tbar " - "VARCHAR(1), \tCONSTRAINT myenum CHECK " - "(bar IN ('B', 'Ü')))" - ), + "CREATE TABLE foo (\tbar " + "VARCHAR(1), \tCONSTRAINT myenum CHECK " + "(bar IN ('B', 'Ü')))", {}, ) ], ) - connection.execute(t1.insert(), {"bar": util.u("Ü")}) - eq_(connection.scalar(select(t1.c.bar)), util.u("Ü")) + connection.execute(t1.insert(), {"bar": "Ü"}) + eq_(connection.scalar(select(t1.c.bar)), "Ü") def test_disable_create(self, metadata, connection): metadata = self.metadata @@ -1628,13 +1627,13 @@ class ArrayRoundTripTest: arrtable.insert(), dict( intarr=[1, 2, 3], - strarr=[util.u("abc"), util.u("def")], + strarr=["abc", "def"], ), ) results = connection.execute(arrtable.select()).fetchall() eq_(len(results), 1) eq_(results[0].intarr, [1, 2, 3]) - eq_(results[0].strarr, [util.u("abc"), util.u("def")]) + eq_(results[0].strarr, ["abc", "def"]) def test_insert_array_w_null(self, connection): arrtable = self.tables.arrtable @@ -1642,13 +1641,13 @@ class ArrayRoundTripTest: arrtable.insert(), dict( intarr=[1, None, 3], - strarr=[util.u("abc"), None], + strarr=["abc", None], ), ) results = connection.execute(arrtable.select()).fetchall() eq_(len(results), 1) eq_(results[0].intarr, [1, None, 3]) - eq_(results[0].strarr, [util.u("abc"), None]) + eq_(results[0].strarr, ["abc", None]) def test_array_where(self, connection): arrtable = self.tables.arrtable @@ -1656,11 +1655,11 @@ class ArrayRoundTripTest: arrtable.insert(), dict( intarr=[1, 2, 3], - strarr=[util.u("abc"), util.u("def")], + strarr=["abc", "def"], ), ) connection.execute( - arrtable.insert(), dict(intarr=[4, 5, 6], strarr=util.u("ABC")) + arrtable.insert(), dict(intarr=[4, 5, 6], strarr="ABC") ) results = connection.execute( arrtable.select().where(arrtable.c.intarr == [1, 2, 3]) @@ -1672,7 +1671,7 @@ class ArrayRoundTripTest: arrtable = self.tables.arrtable connection.execute( arrtable.insert(), - dict(intarr=[1, 2, 3], strarr=[util.u("abc"), util.u("def")]), + dict(intarr=[1, 2, 3], strarr=["abc", "def"]), ) results = connection.execute( select(arrtable.c.intarr + [4, 5, 6]) @@ -1684,9 +1683,7 @@ class ArrayRoundTripTest: arrtable = self.tables.arrtable connection.execute( arrtable.insert(), - dict( - id=5, intarr=[1, 2, 3], strarr=[util.u("abc"), util.u("def")] - ), + dict(id=5, intarr=[1, 2, 3], strarr=["abc", "def"]), ) results = connection.execute( select(arrtable.c.id).where(arrtable.c.intarr < [4, 5, 6]) @@ -1700,24 +1697,24 @@ class ArrayRoundTripTest: arrtable.insert(), dict( intarr=[4, 5, 6], - strarr=[[util.ue("m\xe4\xe4")], [util.ue("m\xf6\xf6")]], + strarr=[["m\xe4\xe4"], ["m\xf6\xf6"]], ), ) connection.execute( arrtable.insert(), dict( intarr=[1, 2, 3], - strarr=[util.ue("m\xe4\xe4"), util.ue("m\xf6\xf6")], + strarr=["m\xe4\xe4", "m\xf6\xf6"], ), ) results = connection.execute( arrtable.select().order_by(arrtable.c.intarr) ).fetchall() eq_(len(results), 2) - eq_(results[0].strarr, [util.ue("m\xe4\xe4"), util.ue("m\xf6\xf6")]) + eq_(results[0].strarr, ["m\xe4\xe4", "m\xf6\xf6"]) eq_( results[1].strarr, - [[util.ue("m\xe4\xe4")], [util.ue("m\xf6\xf6")]], + [["m\xe4\xe4"], ["m\xf6\xf6"]], ) def test_array_literal_roundtrip(self, connection): @@ -1790,7 +1787,7 @@ class ArrayRoundTripTest: arrtable.insert(), dict( intarr=[4, 5, 6], - strarr=[util.u("abc"), util.u("def")], + strarr=["abc", "def"], ), ) eq_(connection.scalar(select(arrtable.c.intarr[2:3])), [5, 6]) @@ -1909,11 +1906,11 @@ class ArrayRoundTripTest: def unicode_values(x): return [ - util.u("réveillé"), - util.u("drôle"), - util.u("S’il %s" % x), - util.u("🐍 %s" % x), - util.u("« S’il vous"), + "réveillé", + "drôle", + "S’il %s" % x, + "🐍 %s" % x, + "« S’il vous", ] def json_values(x): @@ -2328,6 +2325,11 @@ class ArrayEnum(fixtures.TestBase): @testing.fixture def array_of_enum_fixture(self, metadata, connection): def go(array_cls, enum_cls): + class MyEnum(_PY_Enum): + a = "aaa" + b = "bbb" + c = "ccc" + tbl = Table( "enum_table", metadata, @@ -2336,23 +2338,11 @@ class ArrayEnum(fixtures.TestBase): "enum_col", array_cls(enum_cls("foo", "bar", "baz", name="an_enum")), ), + Column( + "pyenum_col", + array_cls(enum_cls(MyEnum)), + ), ) - if util.py3k: - from enum import Enum - - class MyEnum(Enum): - a = "aaa" - b = "bbb" - c = "ccc" - - tbl.append_column( - Column( - "pyenum_col", - array_cls(enum_cls(MyEnum)), - ), - ) - else: - MyEnum = None metadata.create_all(connection) connection.execute( @@ -3151,16 +3141,16 @@ class HStoreRoundTripTest(fixtures.TablesTest): def _test_unicode_round_trip(self, connection): s = select( hstore( - array([util.u("réveillé"), util.u("drôle"), util.u("S’il")]), - array([util.u("réveillé"), util.u("drôle"), util.u("S’il")]), + array(["réveillé", "drôle", "S’il"]), + array(["réveillé", "drôle", "S’il"]), ) ) eq_( connection.scalar(s), { - util.u("réveillé"): util.u("réveillé"), - util.u("drôle"): util.u("drôle"), - util.u("S’il"): util.u("S’il"), + "réveillé": "réveillé", + "drôle": "drôle", + "S’il": "S’il", }, ) @@ -3826,7 +3816,7 @@ class JSONRoundTripTest(fixtures.TablesTest): result = connection.execute( select(data_table.c.data["k1"].astext) ).first() - assert isinstance(result[0], util.text_type) + assert isinstance(result[0], str) def test_query_returned_as_int(self, connection): self._fixture_data(connection) @@ -3854,8 +3844,8 @@ class JSONRoundTripTest(fixtures.TablesTest): s = select( cast( { - util.u("réveillé"): util.u("réveillé"), - "data": {"k1": util.u("drôle")}, + "réveillé": "réveillé", + "data": {"k1": "drôle"}, }, self.data_type, ) @@ -3863,8 +3853,8 @@ class JSONRoundTripTest(fixtures.TablesTest): eq_( connection.scalar(s), { - util.u("réveillé"): util.u("réveillé"), - "data": {"k1": util.u("drôle")}, + "réveillé": "réveillé", + "data": {"k1": "drôle"}, }, ) diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index f827533d48..141033c1b6 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -34,7 +34,6 @@ from sqlalchemy import text from sqlalchemy import tuple_ from sqlalchemy import types as sqltypes from sqlalchemy import UniqueConstraint -from sqlalchemy import util from sqlalchemy.dialects.sqlite import base as sqlite from sqlalchemy.dialects.sqlite import insert from sqlalchemy.dialects.sqlite import provision @@ -60,8 +59,6 @@ from sqlalchemy.types import DateTime from sqlalchemy.types import Integer from sqlalchemy.types import String from sqlalchemy.types import Time -from sqlalchemy.util import u -from sqlalchemy.util import ue def exec_sql(engine, sql, *args, **kwargs): @@ -160,7 +157,7 @@ class TestTypes(fixtures.TestBase, AssertsExecutionResults): ), ) r = conn.execute(func.current_date()).scalar() - assert isinstance(r, util.string_types) + assert isinstance(r, str) @testing.provide_metadata def test_custom_datetime(self, connection): @@ -281,9 +278,7 @@ class TestTypes(fixtures.TestBase, AssertsExecutionResults): sqltypes.UnicodeText(), ): bindproc = t.dialect_impl(dialect).bind_processor(dialect) - assert not bindproc or isinstance( - bindproc(util.u("some string")), util.text_type - ) + assert not bindproc or isinstance(bindproc("some string"), str) class JSONTest(fixtures.TestBase): @@ -700,14 +695,14 @@ class DialectTest( t = Table( "x", self.metadata, - Column(u("méil"), Integer, primary_key=True), - Column(ue("\u6e2c\u8a66"), Integer), + Column("méil", Integer, primary_key=True), + Column("\u6e2c\u8a66", Integer), ) self.metadata.create_all(testing.db) result = connection.execute(t.select()) - assert u("méil") in result.keys() - assert ue("\u6e2c\u8a66") in result.keys() + assert "méil" in result.keys() + assert "\u6e2c\u8a66" in result.keys() def test_pool_class(self): e = create_engine("sqlite+pysqlite://") diff --git a/test/engine/test_deprecations.py b/test/engine/test_deprecations.py index d0cbe1a773..77c5c6a222 100644 --- a/test/engine/test_deprecations.py +++ b/test/engine/test_deprecations.py @@ -1,4 +1,5 @@ import re +from unittest.mock import Mock import sqlalchemy as tsa import sqlalchemy as sa @@ -36,7 +37,6 @@ from sqlalchemy.testing import mock from sqlalchemy.testing.assertions import expect_deprecated from sqlalchemy.testing.assertions import expect_raises_message from sqlalchemy.testing.engines import testing_engine -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index e1c86444d5..4670297c18 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -1,8 +1,14 @@ # coding: utf-8 +import collections.abc as collections_abc from contextlib import contextmanager +from contextlib import nullcontext +from io import StringIO import re import threading +from unittest.mock import call +from unittest.mock import Mock +from unittest.mock import patch import weakref import sqlalchemy as tsa @@ -46,14 +52,10 @@ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing.assertions import expect_deprecated from sqlalchemy.testing.assertsql import CompiledSQL -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import gc_collect from sqlalchemy.testing.util import picklers -from sqlalchemy.util import collections_abc class SomeException(Exception): @@ -65,7 +67,7 @@ class Foo: return "foo" def __unicode__(self): - return util.u("fóó") + return "fóó" class ExecuteTest(fixtures.TablesTest): @@ -444,7 +446,7 @@ class ExecuteTest(fixtures.TablesTest): eq_(conn.execute(obj).scalar(), 1) def test_stmt_exception_bytestring_raised(self): - name = util.u("méil") + name = "méil" users = self.tables.users with testing.db.connect() as conn: assert_raises_message( @@ -461,26 +463,26 @@ class ExecuteTest(fixtures.TablesTest): def test_stmt_exception_bytestring_utf8(self): # uncommon case for Py3K, bytestring object passed # as the error message - message = util.u("some message méil").encode("utf-8") + message = "some message méil".encode("utf-8") err = tsa.exc.SQLAlchemyError(message) - eq_(str(err), util.u("some message méil")) + eq_(str(err), "some message méil") def test_stmt_exception_bytestring_latin1(self): # uncommon case for Py3K, bytestring object passed # as the error message - message = util.u("some message méil").encode("latin-1") + message = "some message méil".encode("latin-1") err = tsa.exc.SQLAlchemyError(message) - eq_(str(err), util.u("some message m\\xe9il")) + eq_(str(err), "some message m\\xe9il") def test_stmt_exception_unicode_hook_unicode(self): # uncommon case for Py2K, Unicode object passed # as the error message - message = util.u("some message méil") + message = "some message méil" err = tsa.exc.SQLAlchemyError(message) - eq_(str(err), util.u("some message méil")) + eq_(str(err), "some message méil") def test_stmt_exception_object_arg(self): err = tsa.exc.SQLAlchemyError(Foo()) @@ -491,13 +493,13 @@ class ExecuteTest(fixtures.TablesTest): eq_(str(err), "('some message', 206)") def test_stmt_exception_str_multi_args_bytestring(self): - message = util.u("some message méil").encode("utf-8") + message = "some message méil".encode("utf-8") err = tsa.exc.SQLAlchemyError(message, 206) eq_(str(err), str((message, 206))) def test_stmt_exception_str_multi_args_unicode(self): - message = util.u("some message méil") + message = "some message méil" err = tsa.exc.SQLAlchemyError(message, 206) eq_(str(err), str((message, 206))) @@ -1156,10 +1158,10 @@ class CompiledCacheTest(fixtures.TestBase): class MockStrategyTest(fixtures.TestBase): def _engine_fixture(self): - buf = util.StringIO() + buf = StringIO() def dump(sql, *multiparams, **params): - buf.write(util.text_type(sql.compile(dialect=engine.dialect))) + buf.write(str(sql.compile(dialect=engine.dialect))) engine = create_mock_engine("postgresql+psycopg2://", executor=dump) return engine, buf @@ -1667,7 +1669,7 @@ class EngineEventsTest(fixtures.TestBase): lambda self: None, ) else: - patcher = util.nullcontext() + patcher = nullcontext() with patcher: e1 = testing_engine(config.db_url) diff --git a/test/engine/test_logging.py b/test/engine/test_logging.py index bd5bde775e..0c3d5e43be 100644 --- a/test/engine/test_logging.py +++ b/test/engine/test_logging.py @@ -10,7 +10,6 @@ from sqlalchemy import select from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.sql import util as sql_util from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message @@ -353,31 +352,17 @@ class LogParamsTest(fixtures.TestBase): % (largeparam[0:149], largeparam[-149:]), ) - if util.py3k: - eq_( - self.buf.buffer[5].message, - "Row ('%s ... (4702 characters truncated) ... %s',)" - % (largeparam[0:149], largeparam[-149:]), - ) - else: - eq_( - self.buf.buffer[5].message, - "Row (u'%s ... (4703 characters truncated) ... %s',)" - % (largeparam[0:148], largeparam[-149:]), - ) + eq_( + self.buf.buffer[5].message, + "Row ('%s ... (4702 characters truncated) ... %s',)" + % (largeparam[0:149], largeparam[-149:]), + ) - if util.py3k: - eq_( - repr(row), - "('%s ... (4702 characters truncated) ... %s',)" - % (largeparam[0:149], largeparam[-149:]), - ) - else: - eq_( - repr(row), - "(u'%s ... (4703 characters truncated) ... %s',)" - % (largeparam[0:148], largeparam[-149:]), - ) + eq_( + repr(row), + "('%s ... (4702 characters truncated) ... %s',)" + % (largeparam[0:149], largeparam[-149:]), + ) def test_error_large_dict(self): assert_raises_message( diff --git a/test/engine/test_parseconnect.py b/test/engine/test_parseconnect.py index f0a1dba4bb..c69b332a8f 100644 --- a/test/engine/test_parseconnect.py +++ b/test/engine/test_parseconnect.py @@ -1,3 +1,7 @@ +from unittest.mock import call +from unittest.mock import MagicMock +from unittest.mock import Mock + import sqlalchemy as tsa from sqlalchemy import create_engine from sqlalchemy import engine_from_config @@ -19,9 +23,6 @@ from sqlalchemy.testing import mock from sqlalchemy.testing import ne_ from sqlalchemy.testing.assertions import expect_deprecated from sqlalchemy.testing.assertions import expect_raises_message -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import MagicMock -from sqlalchemy.testing.mock import Mock dialect = None diff --git a/test/engine/test_pool.py b/test/engine/test_pool.py index b1a099d31f..c2ac6637f6 100644 --- a/test/engine/test_pool.py +++ b/test/engine/test_pool.py @@ -2,6 +2,10 @@ import collections import random import threading import time +from unittest.mock import ANY +from unittest.mock import call +from unittest.mock import Mock +from unittest.mock import patch import weakref import sqlalchemy as tsa @@ -25,10 +29,6 @@ from sqlalchemy.testing import is_not_none from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing.engines import testing_engine -from sqlalchemy.testing.mock import ANY -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.util import gc_collect from sqlalchemy.testing.util import lazy_gc diff --git a/test/engine/test_reconnect.py b/test/engine/test_reconnect.py index c9894b0f28..afd027698e 100644 --- a/test/engine/test_reconnect.py +++ b/test/engine/test_reconnect.py @@ -1,4 +1,6 @@ import time +from unittest.mock import call +from unittest.mock import Mock import sqlalchemy as tsa from sqlalchemy import create_engine @@ -26,8 +28,6 @@ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing import ne_ from sqlalchemy.testing.engines import testing_engine -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import gc_collect diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index 3072eba276..efd30071ef 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -36,7 +36,6 @@ from sqlalchemy.testing import not_in from sqlalchemy.testing import skip from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import ue class ReflectionTest(fixtures.TestBase, ComparesTables): @@ -1515,33 +1514,33 @@ class UnicodeReflectionTest(fixtures.TablesTest): no_has_table = [ ( "no_has_table_1", - ue("col_Unit\u00e9ble"), - ue("ix_Unit\u00e9ble"), + "col_Unit\u00e9ble", + "ix_Unit\u00e9ble", ), - ("no_has_table_2", ue("col_\u6e2c\u8a66"), ue("ix_\u6e2c\u8a66")), + ("no_has_table_2", "col_\u6e2c\u8a66", "ix_\u6e2c\u8a66"), ] no_case_sensitivity = [ ( - ue("\u6e2c\u8a66"), - ue("col_\u6e2c\u8a66"), - ue("ix_\u6e2c\u8a66"), + "\u6e2c\u8a66", + "col_\u6e2c\u8a66", + "ix_\u6e2c\u8a66", ), ( - ue("unit\u00e9ble"), - ue("col_unit\u00e9ble"), - ue("ix_unit\u00e9ble"), + "unit\u00e9ble", + "col_unit\u00e9ble", + "ix_unit\u00e9ble", ), ] full = [ ( - ue("Unit\u00e9ble"), - ue("col_Unit\u00e9ble"), - ue("ix_Unit\u00e9ble"), + "Unit\u00e9ble", + "col_Unit\u00e9ble", + "ix_Unit\u00e9ble", ), ( - ue("\u6e2c\u8a66"), - ue("col_\u6e2c\u8a66"), - ue("ix_\u6e2c\u8a66"), + "\u6e2c\u8a66", + "col_\u6e2c\u8a66", + "ix_\u6e2c\u8a66", ), ] diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index e3be847e8a..ca242c2c0a 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -302,9 +302,8 @@ class TransactionTest(fixtures.TablesTest): savepoint = savepoint[0] assert not savepoint.is_active - if util.py3k: - # ensure cause comes from the DBAPI - assert isinstance(exc_.__cause__, testing.db.dialect.dbapi.Error) + # ensure cause comes from the DBAPI + assert isinstance(exc_.__cause__, testing.db.dialect.dbapi.Error) def test_retains_through_options(self, local_connection): connection = local_connection diff --git a/test/ext/mypy/incremental/ticket_6435/enum_col_import2.py b/test/ext/mypy/incremental/ticket_6435/enum_col_import2.py index 4f29932e56..161dce0875 100644 --- a/test/ext/mypy/incremental/ticket_6435/enum_col_import2.py +++ b/test/ext/mypy/incremental/ticket_6435/enum_col_import2.py @@ -1,8 +1,10 @@ from sqlalchemy import Column from sqlalchemy import Enum -from sqlalchemy.orm import declarative_base, Mapped +from sqlalchemy.orm import declarative_base +from sqlalchemy.orm import Mapped from . import enum_col_import1 -from .enum_col_import1 import IntEnum, StrEnum +from .enum_col_import1 import IntEnum +from .enum_col_import1 import StrEnum Base = declarative_base() diff --git a/test/ext/test_associationproxy.py b/test/ext/test_associationproxy.py index ae5e6c8483..93da104de7 100644 --- a/test/ext/test_associationproxy.py +++ b/test/ext/test_associationproxy.py @@ -1,5 +1,7 @@ import copy import pickle +from unittest.mock import call +from unittest.mock import Mock from sqlalchemy import cast from sqlalchemy import exc @@ -35,8 +37,6 @@ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_false from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import gc_collect diff --git a/test/ext/test_automap.py b/test/ext/test_automap.py index eaafa34778..625bb8da25 100644 --- a/test/ext/test_automap.py +++ b/test/ext/test_automap.py @@ -1,6 +1,8 @@ import random import threading import time +from unittest.mock import Mock +from unittest.mock import patch from sqlalchemy import create_engine from sqlalchemy import ForeignKey @@ -19,8 +21,6 @@ from sqlalchemy.orm import Session from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ -from sqlalchemy.testing.mock import Mock -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from ..orm._fixtures import FixtureTest diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py index 6545d45458..3370fa1b55 100644 --- a/test/ext/test_mutable.py +++ b/test/ext/test_mutable.py @@ -7,7 +7,6 @@ from sqlalchemy import func from sqlalchemy import Integer from sqlalchemy import String from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.ext.mutable import MutableComposite from sqlalchemy.ext.mutable import MutableDict from sqlalchemy.ext.mutable import MutableList @@ -573,44 +572,24 @@ class _MutableListTestBase(_MutableListTestFixture): # print(repr(pickles)) # return - if util.py3k: - pickles = [ - b"\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\x16" - b"sqlalchemy.ext.mutable\x94\x8c\x0bMutableList\x94\x93\x94)" - b"\x81\x94(K\x01K\x02e]\x94(K\x01K\x02eb.", - b"ccopy_reg\n_reconstructor\np0\n(csqlalchemy.ext.mutable\n" - b"MutableList\np1\nc__builtin__\nlist\np2\n(lp3\nI1\naI2\n" - b"atp4\nRp5\n(lp6\nI1\naI2\nab.", - b"ccopy_reg\n_reconstructor\nq\x00(csqlalchemy.ext.mutable\n" - b"MutableList\nq\x01c__builtin__\nlist\nq\x02]q\x03(K\x01K" - b"\x02etq\x04Rq\x05]q\x06(K\x01K\x02eb.", - b"\x80\x02csqlalchemy.ext.mutable\nMutableList\nq\x00)\x81q" - b"\x01(K\x01K\x02e]q\x02(K\x01K\x02eb.", - b"\x80\x03csqlalchemy.ext.mutable\nMutableList\nq\x00)\x81q" - b"\x01(K\x01K\x02e]q\x02(K\x01K\x02eb.", - b"\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\x16" - b"sqlalchemy.ext.mutable\x94\x8c\x0bMutableList\x94\x93\x94)" - b"\x81\x94(K\x01K\x02e]\x94(K\x01K\x02eb.", - ] - else: - pickles = [ - "\x80\x02csqlalchemy.ext.mutable\nMutableList\nq\x00]q\x01" - "(K\x01K\x02e\x85q\x02Rq\x03.", - "\x80\x02csqlalchemy.ext.mutable\nMutableList" - "\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.", - "csqlalchemy.ext.mutable\nMutableList\np0\n" - "((lp1\nI1\naI2\natp2\nRp3\n.", - "csqlalchemy.ext.mutable\nMutableList\nq\x00(]" - "q\x01(K\x01K\x02etq\x02Rq\x03.", - "\x80\x02csqlalchemy.ext.mutable\nMutableList" - "\nq\x01]q\x02(K\x01K\x02e\x85Rq\x03.", - "\x80\x02csqlalchemy.ext.mutable\nMutableList\n" - "q\x01]q\x02(K\x01K\x02e\x85Rq\x03.", - "csqlalchemy.ext.mutable\nMutableList\np1\n" - "((lp2\nI1\naI2\natRp3\n.", - "csqlalchemy.ext.mutable\nMutableList\nq\x01" - "(]q\x02(K\x01K\x02etRq\x03.", - ] + pickles = [ + b"\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\x16" + b"sqlalchemy.ext.mutable\x94\x8c\x0bMutableList\x94\x93\x94)" + b"\x81\x94(K\x01K\x02e]\x94(K\x01K\x02eb.", + b"ccopy_reg\n_reconstructor\np0\n(csqlalchemy.ext.mutable\n" + b"MutableList\np1\nc__builtin__\nlist\np2\n(lp3\nI1\naI2\n" + b"atp4\nRp5\n(lp6\nI1\naI2\nab.", + b"ccopy_reg\n_reconstructor\nq\x00(csqlalchemy.ext.mutable\n" + b"MutableList\nq\x01c__builtin__\nlist\nq\x02]q\x03(K\x01K" + b"\x02etq\x04Rq\x05]q\x06(K\x01K\x02eb.", + b"\x80\x02csqlalchemy.ext.mutable\nMutableList\nq\x00)\x81q" + b"\x01(K\x01K\x02e]q\x02(K\x01K\x02eb.", + b"\x80\x03csqlalchemy.ext.mutable\nMutableList\nq\x00)\x81q" + b"\x01(K\x01K\x02e]q\x02(K\x01K\x02eb.", + b"\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\x16" + b"sqlalchemy.ext.mutable\x94\x8c\x0bMutableList\x94\x93\x94)" + b"\x81\x94(K\x01K\x02e]\x94(K\x01K\x02eb.", + ] for pickle_ in pickles: obj = pickle.loads(pickle_) diff --git a/test/ext/test_serializer.py b/test/ext/test_serializer.py index 03ad96b3cc..9a05e1fae3 100644 --- a/test/ext/test_serializer.py +++ b/test/ext/test_serializer.py @@ -24,7 +24,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import ue def pickle_protocols(): @@ -195,7 +194,6 @@ class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest): ], ) - @testing.requires.non_broken_pickle def test_query_two(self): q = ( Session.query(User) @@ -206,7 +204,6 @@ class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest): eq_(q2.all(), [User(name="fred")]) eq_(list(q2.with_entities(User.id, User.name)), [(9, "fred")]) - @testing.requires.non_broken_pickle def test_query_three(self): ua = aliased(User) q = ( @@ -233,7 +230,6 @@ class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest): pickled_failing = serializer.dumps(j, prot) serializer.loads(pickled_failing, users.metadata, None) - @testing.requires.non_broken_pickle def test_orm_join(self): from sqlalchemy.orm.util import join @@ -264,7 +260,6 @@ class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest): [(u7, u8), (u7, u9), (u7, u10), (u8, u9), (u8, u10)], ) - @testing.requires.non_broken_pickle def test_any(self): r = User.addresses.any(Address.email == "x") ser = serializer.dumps(r, -1) @@ -273,20 +268,16 @@ class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest): def test_unicode(self): m = MetaData() - t = Table( - ue("\u6e2c\u8a66"), m, Column(ue("\u6e2c\u8a66_id"), Integer) - ) + t = Table("\u6e2c\u8a66", m, Column("\u6e2c\u8a66_id", Integer)) - expr = select(t).where(t.c[ue("\u6e2c\u8a66_id")] == 5) + expr = select(t).where(t.c["\u6e2c\u8a66_id"] == 5) expr2 = serializer.loads(serializer.dumps(expr, -1), m) self.assert_compile( expr2, - ue( - 'SELECT "\u6e2c\u8a66"."\u6e2c\u8a66_id" FROM "\u6e2c\u8a66" ' - 'WHERE "\u6e2c\u8a66"."\u6e2c\u8a66_id" = :\u6e2c\u8a66_id_1' - ), + 'SELECT "\u6e2c\u8a66"."\u6e2c\u8a66_id" FROM "\u6e2c\u8a66" ' + 'WHERE "\u6e2c\u8a66"."\u6e2c\u8a66_id" = :\u6e2c\u8a66_id_1', dialect="default", ) diff --git a/test/orm/declarative/test_basic.py b/test/orm/declarative/test_basic.py index f8cbdee365..902caca6fb 100644 --- a/test/orm/declarative/test_basic.py +++ b/test/orm/declarative/test_basic.py @@ -10,7 +10,6 @@ from sqlalchemy import Integer from sqlalchemy import String from sqlalchemy import testing from sqlalchemy import UniqueConstraint -from sqlalchemy import util from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref from sqlalchemy.orm import class_mapper @@ -46,7 +45,6 @@ from sqlalchemy.testing import mock from sqlalchemy.testing.fixtures import fixture_session from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import with_metaclass Base = None @@ -71,7 +69,7 @@ class DeclarativeTestBase( elif self.base_style == "explicit": mapper_registry = registry() - class Base(with_metaclass(DeclarativeMeta)): + class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = mapper_registry metadata = mapper_registry.metadata @@ -252,7 +250,7 @@ class DeclarativeTest(DeclarativeTestBase): "id", Integer, primary_key=True, test_needs_autoincrement=True ) name = Column("name", String(50)) - addresses = relationship(util.u("Address"), backref="user") + addresses = relationship("Address", backref="user") class Address(Base, fixtures.ComparableEntity): __tablename__ = "addresses" @@ -288,7 +286,7 @@ class DeclarativeTest(DeclarativeTestBase): ) user = relationship( User, - backref=backref("addresses", order_by=util.u("Address.email")), + backref=backref("addresses", order_by="Address.email"), ) assert Address.user.property.mapper.class_ is User @@ -534,7 +532,7 @@ class DeclarativeTest(DeclarativeTestBase): # even though this class has an xyzzy attribute, getattr(cls,"xyzzy") # fails - class BrokenParent(with_metaclass(BrokenMeta)): + class BrokenParent(metaclass=BrokenMeta): xyzzy = "magic" # _as_declarative() inspects obj.__class__.__bases__ @@ -1076,7 +1074,7 @@ class DeclarativeTest(DeclarativeTestBase): r"registry is not a sqlalchemy.orm.registry\(\) object", ): - class Base(with_metaclass(DeclarativeMeta)): + class Base(metaclass=DeclarativeMeta): metadata = sa.MetaData() def test_shared_class_registry(self): @@ -1183,7 +1181,7 @@ class DeclarativeTest(DeclarativeTestBase): try: hasattr(User.addresses, "property") except exc.InvalidRequestError: - assert sa.util.compat.py3k + assert True # the exception is preserved. Remains the # same through repeated calls. diff --git a/test/orm/inheritance/test_relationship.py b/test/orm/inheritance/test_relationship.py index d12cb1999a..6d071a1e22 100644 --- a/test/orm/inheritance/test_relationship.py +++ b/test/orm/inheritance/test_relationship.py @@ -1,10 +1,11 @@ +from contextlib import nullcontext + from sqlalchemy import ForeignKey from sqlalchemy import func from sqlalchemy import Integer from sqlalchemy import select from sqlalchemy import String from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.orm import aliased from sqlalchemy.orm import backref from sqlalchemy.orm import configure_mappers @@ -2922,7 +2923,7 @@ class BetweenSubclassJoinWExtraJoinedLoad( with _aliased_join_warning( "Manager->managers" - ) if autoalias else util.nullcontext(): + ) if autoalias else nullcontext(): self.assert_compile( q, "SELECT people.type AS people_type, engineers.id AS " diff --git a/test/orm/inheritance/test_single.py b/test/orm/inheritance/test_single.py index fbafdd85be..93ec643045 100644 --- a/test/orm/inheritance/test_single.py +++ b/test/orm/inheritance/test_single.py @@ -1,3 +1,5 @@ +from contextlib import nullcontext + from sqlalchemy import and_ from sqlalchemy import ForeignKey from sqlalchemy import func @@ -10,7 +12,6 @@ from sqlalchemy import select from sqlalchemy import String from sqlalchemy import testing from sqlalchemy import true -from sqlalchemy import util from sqlalchemy.orm import aliased from sqlalchemy.orm import Bundle from sqlalchemy.orm import joinedload @@ -1826,7 +1827,7 @@ class SingleFromPolySelectableTest( with _aliased_join_warning( "Engineer->engineer" - ) if autoalias else util.nullcontext(): + ) if autoalias else nullcontext(): self.assert_compile( q, "SELECT manager.id AS manager_id, employee.id AS employee_id, " @@ -1891,7 +1892,7 @@ class SingleFromPolySelectableTest( with _aliased_join_warning( "Boss->manager" - ) if autoalias else util.nullcontext(): + ) if autoalias else nullcontext(): self.assert_compile( q, "SELECT engineer.id AS engineer_id, " diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index 4d0a1b03cc..08de5d3d97 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -1,4 +1,6 @@ import pickle +from unittest.mock import call +from unittest.mock import Mock from sqlalchemy import event from sqlalchemy import exc as sa_exc @@ -17,8 +19,6 @@ from sqlalchemy.testing import is_false from sqlalchemy.testing import is_not from sqlalchemy.testing import is_true from sqlalchemy.testing import not_in -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.util import all_partial_orderings from sqlalchemy.testing.util import gc_collect diff --git a/test/orm/test_bind.py b/test/orm/test_bind.py index 4179863389..11e34645dc 100644 --- a/test/orm/test_bind.py +++ b/test/orm/test_bind.py @@ -1,3 +1,5 @@ +from unittest.mock import Mock + import sqlalchemy as sa from sqlalchemy import delete from sqlalchemy import ForeignKey @@ -23,7 +25,6 @@ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import mock from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from test.orm import _fixtures diff --git a/test/orm/test_cascade.py b/test/orm/test_cascade.py index c64c5a03a2..51ed50255f 100644 --- a/test/orm/test_cascade.py +++ b/test/orm/test_cascade.py @@ -7,7 +7,6 @@ from sqlalchemy import Integer from sqlalchemy import select from sqlalchemy import String from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.orm import attributes from sqlalchemy.orm import backref from sqlalchemy.orm import class_mapper @@ -170,7 +169,7 @@ class CascadeArgTest(fixtures.MappedTest): Address = self.classes.Address rel = relationship(Address) - rel.cascade = util.u("save-update, merge, expunge") + rel.cascade = "save-update, merge, expunge" eq_(rel.cascade, set(["save-update", "merge", "expunge"])) diff --git a/test/orm/test_collection.py b/test/orm/test_collection.py index ca14d7658f..9babe6366e 100644 --- a/test/orm/test_collection.py +++ b/test/orm/test_collection.py @@ -1,4 +1,5 @@ import contextlib +from functools import reduce from operator import and_ from sqlalchemy import event @@ -251,7 +252,7 @@ class CollectionsTest(OrderedDictFixture, fixtures.ORMTest): control[0] = e assert_eq() - if util.reduce( + if reduce( and_, [ hasattr(direct, a) diff --git a/test/orm/test_deprecations.py b/test/orm/test_deprecations.py index 962161f7b9..fc0720ce67 100644 --- a/test/orm/test_deprecations.py +++ b/test/orm/test_deprecations.py @@ -1,3 +1,8 @@ +from contextlib import nullcontext +import pickle +from unittest.mock import call +from unittest.mock import Mock + import sqlalchemy as sa from sqlalchemy import and_ from sqlalchemy import cast @@ -21,7 +26,6 @@ from sqlalchemy import table from sqlalchemy import testing from sqlalchemy import text from sqlalchemy import true -from sqlalchemy import util from sqlalchemy.engine import default from sqlalchemy.engine import result_tuple from sqlalchemy.orm import aliased @@ -77,12 +81,9 @@ from sqlalchemy.testing import mock from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.fixtures import ComparableEntity from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import resolve_lambda -from sqlalchemy.util import pickle from . import _fixtures from .inheritance import _poly_fixtures from .inheritance._poly_fixtures import _Polymorphic @@ -433,7 +434,6 @@ class PickleTest(fixtures.MappedTest): sess.expunge_all() return sess, User, Address, Dingaling - @testing.requires.non_broken_pickle def test_became_bound_options(self): sess, User, Address, Dingaling = self._option_test_fixture() @@ -457,7 +457,6 @@ class PickleTest(fixtures.MappedTest): u1 = sess.query(User).options(opt).first() pickle.loads(pickle.dumps(u1)) - @testing.requires.non_broken_pickle @testing.combinations( lambda: sa.orm.joinedload("addresses"), lambda: sa.orm.defer("name"), @@ -477,7 +476,6 @@ class PickleTest(fixtures.MappedTest): u1 = sess.query(User).options(opt).first() pickle.loads(pickle.dumps(u1)) - @testing.requires.non_broken_pickle @testing.combinations( lambda User: sa.orm.Load(User).joinedload("addresses"), lambda User: sa.orm.Load(User).joinedload("addresses").raiseload("*"), @@ -8413,7 +8411,7 @@ class CollectionCascadesDespiteBackrefTest(fixtures.TestBase): b3 = B(key="b3") if future: - dep_ctx = util.nullcontext + dep_ctx = nullcontext else: def dep_ctx(): diff --git a/test/orm/test_events.py b/test/orm/test_events.py index aa17f2b6ce..3437d79427 100644 --- a/test/orm/test_events.py +++ b/test/orm/test_events.py @@ -1,3 +1,7 @@ +from unittest.mock import ANY +from unittest.mock import call +from unittest.mock import Mock + import sqlalchemy as sa from sqlalchemy import delete from sqlalchemy import event @@ -39,9 +43,6 @@ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_not from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import ANY -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import gc_collect diff --git a/test/orm/test_instrumentation.py b/test/orm/test_instrumentation.py index 6b999f9f86..8f5455850c 100644 --- a/test/orm/test_instrumentation.py +++ b/test/orm/test_instrumentation.py @@ -3,7 +3,6 @@ from sqlalchemy import event from sqlalchemy import ForeignKey from sqlalchemy import Integer from sqlalchemy import MetaData -from sqlalchemy import util from sqlalchemy.orm import attributes from sqlalchemy.orm import class_mapper from sqlalchemy.orm import clear_mappers @@ -655,39 +654,32 @@ class Py3KFunctionInstTest(fixtures.ORMTest): assert_raises(TypeError, cls, "a", "b", c="c") + def _kw_only_fixture(self): + class A(object): + def __init__(self, a, *, b, c): + self.a = a + self.b = b + self.c = c -if util.py3k: - _locals = {} - exec( - """ -def _kw_only_fixture(self): - class A: - def __init__(self, a, *, b, c): - self.a = a - self.b = b - self.c = c - return self._instrument(A) - -def _kw_plus_posn_fixture(self): - class A: - def __init__(self, a, *args, b, c): - self.a = a - self.b = b - self.c = c - return self._instrument(A) - -def _kw_opt_fixture(self): - class A: - def __init__(self, a, *, b, c="c"): - self.a = a - self.b = b - self.c = c - return self._instrument(A) -""", - _locals, - ) - for k in _locals: - setattr(Py3KFunctionInstTest, k, _locals[k]) + return self._instrument(A) + + def _kw_plus_posn_fixture(self): + class A(object): + def __init__(self, a, *args, b, c): + self.a = a + self.b = b + self.c = c + + return self._instrument(A) + + def _kw_opt_fixture(self): + class A(object): + def __init__(self, a, *, b, c="c"): + self.a = a + self.b = b + self.c = c + + return self._instrument(A) class MiscTest(fixtures.MappedTest): diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index 073f481191..e5e819bbbf 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -256,7 +256,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): try: hasattr(Address.user, "property") except sa.orm.exc.UnmappedClassError: - assert util.compat.py3k + assert True for i in range(3): assert_raises_message( @@ -460,11 +460,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): self.mapper( User, users, - properties={ - util.u("addresses"): relationship( - Address, backref=util.u("user") - ) - }, + properties={"addresses": relationship(Address, backref="user")}, ) u1 = User() a1 = Address() diff --git a/test/orm/test_pickled.py b/test/orm/test_pickled.py index 2072b60e38..4bccb5ee71 100644 --- a/test/orm/test_pickled.py +++ b/test/orm/test_pickled.py @@ -1,4 +1,5 @@ import copy +import pickle import sqlalchemy as sa from sqlalchemy import ForeignKey @@ -34,7 +35,6 @@ from sqlalchemy.testing.pickleable import User from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import picklers -from sqlalchemy.util import pickle from test.orm import _fixtures from .inheritance._poly_fixtures import _Polymorphic from .inheritance._poly_fixtures import Company @@ -324,7 +324,6 @@ class PickleTest(fixtures.MappedTest): u2.addresses.append(Address()) eq_(len(u2.addresses), 2) - @testing.requires.non_broken_pickle def test_instance_deferred_cols(self): users, addresses = (self.tables.users, self.tables.addresses) @@ -495,7 +494,6 @@ class PickleTest(fixtures.MappedTest): u2 = state.obj() eq_(sa.inspect(u2).info["some_key"], "value") - @testing.requires.non_broken_pickle @testing.combinations( lambda User: sa.orm.joinedload(User.addresses), lambda User: sa.orm.defer(User.name), @@ -515,7 +513,6 @@ class PickleTest(fixtures.MappedTest): u1 = sess.query(User).options(opt).first() pickle.loads(pickle.dumps(u1)) - @testing.requires.non_broken_pickle @testing.combinations( lambda User: sa.orm.Load(User).joinedload(User.addresses), lambda User: sa.orm.Load(User) @@ -542,7 +539,6 @@ class PickleTest(fixtures.MappedTest): u1 = sess.query(User).options(opt).first() pickle.loads(pickle.dumps(u1)) - @testing.requires.non_broken_pickle def test_became_bound_options(self): sess, User, Address, Dingaling = self._option_test_fixture() @@ -695,7 +691,6 @@ class PickleTest(fixtures.MappedTest): class OptionsTest(_Polymorphic): - @testing.requires.non_broken_pickle def test_options_of_type(self): with_poly = with_polymorphic(Person, [Engineer, Manager], flat=True) diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 5bbe150c05..32a46463df 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -1,3 +1,4 @@ +import collections.abc as collections_abc import contextlib import functools @@ -82,7 +83,6 @@ from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.types import NullType from sqlalchemy.types import TypeDecorator -from sqlalchemy.util import collections_abc from test.orm import _fixtures diff --git a/test/orm/test_scoping.py b/test/orm/test_scoping.py index 1558da6552..c5458f5ced 100644 --- a/test/orm/test_scoping.py +++ b/test/orm/test_scoping.py @@ -1,3 +1,5 @@ +from unittest.mock import Mock + import sqlalchemy as sa from sqlalchemy import ForeignKey from sqlalchemy import Integer @@ -13,7 +15,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import mock -from sqlalchemy.testing.mock import Mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table diff --git a/test/orm/test_session.py b/test/orm/test_session.py index c11897ea55..1b92da2483 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -1,4 +1,5 @@ import inspect as _py_inspect +import pickle import sqlalchemy as sa from sqlalchemy import event @@ -40,7 +41,6 @@ from sqlalchemy.testing.fixtures import fixture_session from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.testing.util import gc_collect -from sqlalchemy.util import pickle from sqlalchemy.util.compat import inspect_getfullargspec from test.orm import _fixtures diff --git a/test/orm/test_unitofwork.py b/test/orm/test_unitofwork.py index 4ae842c4be..c0a347e240 100644 --- a/test/orm/test_unitofwork.py +++ b/test/orm/test_unitofwork.py @@ -32,8 +32,6 @@ from sqlalchemy.testing.fixtures import fixture_session from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy.util import OrderedDict -from sqlalchemy.util import u -from sqlalchemy.util import ue from test.orm import _fixtures @@ -124,7 +122,7 @@ class UnicodeTest(fixtures.MappedTest): self.mapper_registry.map_imperatively(Test, uni_t1) - txt = ue("\u0160\u0110\u0106\u010c\u017d") + txt = "\u0160\u0110\u0106\u010c\u017d" t1 = Test(id=1, txt=txt) self.assert_(t1.txt == txt) @@ -147,7 +145,7 @@ class UnicodeTest(fixtures.MappedTest): ) self.mapper_registry.map_imperatively(Test2, uni_t2) - txt = ue("\u0160\u0110\u0106\u010c\u017d") + txt = "\u0160\u0110\u0106\u010c\u017d" t1 = Test(txt=txt) t1.t2s.append(Test2()) t1.t2s.append(Test2()) @@ -172,31 +170,31 @@ class UnicodeSchemaTest(fixtures.MappedTest): "unitable1", metadata, Column( - u("méil"), + "méil", Integer, primary_key=True, key="a", test_needs_autoincrement=True, ), - Column(ue("\u6e2c\u8a66"), Integer, key="b"), + Column("\u6e2c\u8a66", Integer, key="b"), Column("type", String(20)), test_needs_fk=True, test_needs_autoincrement=True, ) t2 = Table( - u("Unitéble2"), + "Unitéble2", metadata, Column( - u("méil"), + "méil", Integer, primary_key=True, key="cc", test_needs_autoincrement=True, ), Column( - ue("\u6e2c\u8a66"), Integer, ForeignKey("unitable1.a"), key="d" + "\u6e2c\u8a66", Integer, ForeignKey("unitable1.a"), key="d" ), - Column(ue("\u6e2c\u8a66_2"), Integer, key="e"), + Column("\u6e2c\u8a66_2", Integer, key="e"), test_needs_fk=True, test_needs_autoincrement=True, ) @@ -3594,21 +3592,18 @@ class EnsurePKSortableTest(fixtures.MappedTest): a.data = "bar" b.data = "foo" - if sa.util.py3k: - message = ( - r"Could not sort objects by primary key; primary key " - r"values must be sortable in Python \(was: '<' not " - r"supported between instances of 'MyNotSortableEnum'" - r" and 'MyNotSortableEnum'\)" - ) + message = ( + r"Could not sort objects by primary key; primary key " + r"values must be sortable in Python \(was: '<' not " + r"supported between instances of 'MyNotSortableEnum'" + r" and 'MyNotSortableEnum'\)" + ) - assert_raises_message( - sa.exc.InvalidRequestError, - message, - s.flush, - ) - else: - s.flush() + assert_raises_message( + sa.exc.InvalidRequestError, + message, + s.flush, + ) s.close() def test_persistent_flush_sortable(self): diff --git a/test/orm/test_unitofworkv2.py b/test/orm/test_unitofworkv2.py index efd581db2a..c93cc2edfc 100644 --- a/test/orm/test_unitofworkv2.py +++ b/test/orm/test_unitofworkv2.py @@ -1,3 +1,6 @@ +from unittest.mock import Mock +from unittest.mock import patch + from sqlalchemy import cast from sqlalchemy import DateTime from sqlalchemy import event @@ -34,8 +37,6 @@ from sqlalchemy.testing.assertsql import AllOf from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.assertsql import Conditional from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import Mock -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from test.orm import _fixtures diff --git a/test/orm/test_utils.py b/test/orm/test_utils.py index 748ef152db..122524cc05 100644 --- a/test/orm/test_utils.py +++ b/test/orm/test_utils.py @@ -23,7 +23,6 @@ from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.util import compat from test.orm import _fixtures from .inheritance import _poly_fixtures @@ -313,7 +312,7 @@ class AliasedClassTest(fixtures.MappedTest, AssertsCompiledSQL): return cls.x raise AttributeError(key) - class Point(compat.with_metaclass(MetaPoint)): + class Point(metaclass=MetaPoint): pass self._fixture(Point) @@ -354,7 +353,7 @@ class AliasedClassTest(fixtures.MappedTest, AssertsCompiledSQL): return cls._impl_double_x raise AttributeError(key) - class Point(compat.with_metaclass(MetaPoint)): + class Point(metaclass=MetaPoint): @hybrid_property def _impl_double_x(self): return self.x * 2 @@ -387,7 +386,7 @@ class AliasedClassTest(fixtures.MappedTest, AssertsCompiledSQL): return double_x.__get__(None, cls) raise AttributeError(key) - class Point(compat.with_metaclass(MetaPoint)): + class Point(metaclass=MetaPoint): pass self._fixture(Point) diff --git a/test/orm/test_validators.py b/test/orm/test_validators.py index 817d0fbc53..6b0fee49db 100644 --- a/test/orm/test_validators.py +++ b/test/orm/test_validators.py @@ -1,3 +1,6 @@ +from unittest.mock import call +from unittest.mock import Mock + from sqlalchemy import exc from sqlalchemy.orm import collections from sqlalchemy.orm import relationship @@ -8,8 +11,6 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import ne_ from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import call -from sqlalchemy.testing.mock import Mock from test.orm import _fixtures diff --git a/test/orm/test_versioning.py b/test/orm/test_versioning.py index 0d11f68a7d..9d14ceba15 100644 --- a/test/orm/test_versioning.py +++ b/test/orm/test_versioning.py @@ -1,5 +1,6 @@ import contextlib import datetime +from unittest.mock import patch import uuid import sqlalchemy as sa @@ -29,7 +30,6 @@ from sqlalchemy.testing import is_false from sqlalchemy.testing import is_true from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.fixtures import fixture_session -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table diff --git a/test/perf/invalidate_stresstest.py b/test/perf/invalidate_stresstest.py index c7e1482c7e..2e11b7ca93 100644 --- a/test/perf/invalidate_stresstest.py +++ b/test/perf/invalidate_stresstest.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import logging import random import sys diff --git a/test/sql/test_compare.py b/test/sql/test_compare.py index 814d9a2ad2..af78ea19b9 100644 --- a/test/sql/test_compare.py +++ b/test/sql/test_compare.py @@ -957,8 +957,7 @@ class CoreFixtures: .where(table_b_b.c.c > 10), ) - if util.py37: - fixtures.append(_update_dml_w_dicts) + fixtures.append(_update_dml_w_dicts) def _lambda_fixtures(): def one(): diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index 23a2833ca3..6779ea7bf7 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -97,7 +97,6 @@ from sqlalchemy.testing import is_ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing import ne_ -from sqlalchemy.util import u table1 = table( "mytable", @@ -5002,10 +5001,10 @@ class DDLTest(fixtures.TestBase, AssertsCompiledSQL): def test_reraise_of_column_spec_issue_unicode(self): MyType = self._illegal_type_fixture() - t1 = Table("t", MetaData(), Column(u("méil"), MyType())) + t1 = Table("t", MetaData(), Column("méil", MyType())) assert_raises_message( exc.CompileError, - u(r"\(in table 't', column 'méil'\): Couldn't compile type"), + r"\(in table 't', column 'méil'\): Couldn't compile type", schema.CreateTable(t1).compile, ) diff --git a/test/sql/test_ddlemit.py b/test/sql/test_ddlemit.py index 6678912363..8e70ed9b48 100644 --- a/test/sql/test_ddlemit.py +++ b/test/sql/test_ddlemit.py @@ -1,3 +1,5 @@ +from unittest.mock import Mock + from sqlalchemy import Column from sqlalchemy import ForeignKey from sqlalchemy import Index @@ -9,7 +11,6 @@ from sqlalchemy import Table from sqlalchemy.sql.ddl import SchemaDropper from sqlalchemy.sql.ddl import SchemaGenerator from sqlalchemy.testing import fixtures -from sqlalchemy.testing.mock import Mock class EmitDDLTest(fixtures.TestBase): diff --git a/test/sql/test_deprecations.py b/test/sql/test_deprecations.py index 89938ee5e1..5828fbdccd 100644 --- a/test/sql/test_deprecations.py +++ b/test/sql/test_deprecations.py @@ -49,7 +49,6 @@ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import compat from .test_update import _UpdateFromTestBase @@ -178,7 +177,7 @@ class DeprecationWarningsTest(fixtures.TestBase, AssertsCompiledSQL): obj = cls.__new__(cls) with mock.patch.object(cls, "_copy") as _copy: with testing.expect_deprecated( - r"The %s\(\) method is deprecated" % compat._qualname(cls.copy) + r"The %s\(\) method is deprecated" % cls.copy.__qualname__ ): obj.copy(schema="s", target_table="tt", arbitrary="arb") diff --git a/test/sql/test_external_traversal.py b/test/sql/test_external_traversal.py index e01ec0738e..0ac73fc165 100644 --- a/test/sql/test_external_traversal.py +++ b/test/sql/test_external_traversal.py @@ -1,3 +1,4 @@ +import pickle import re from sqlalchemy import and_ @@ -44,7 +45,6 @@ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_not from sqlalchemy.testing.schema import eq_clause_element -from sqlalchemy.util import pickle A = B = t1 = t2 = t3 = table1 = table2 = table3 = table4 = None diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index 6c794717cd..9378cfc38d 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -1,6 +1,7 @@ from copy import deepcopy import datetime import decimal +import pickle from sqlalchemy import ARRAY from sqlalchemy import bindparam @@ -26,7 +27,6 @@ from sqlalchemy import testing from sqlalchemy import Text from sqlalchemy import true from sqlalchemy import types as sqltypes -from sqlalchemy import util from sqlalchemy.dialects import mysql from sqlalchemy.dialects import oracle from sqlalchemy.dialects import postgresql @@ -510,7 +510,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): # test pickling self.assert_compile( - util.pickle.loads(util.pickle.dumps(f1)), + pickle.loads(pickle.dumps(f1)), "my_func(:my_func_1, :my_func_2, NULL, :my_func_3)", ) @@ -533,7 +533,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): f1 = func.row_number().over() self.assert_compile( - util.pickle.loads(util.pickle.dumps(f1)), + pickle.loads(pickle.dumps(f1)), "row_number() OVER ()", ) @@ -550,7 +550,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): f1 = func.percentile_cont(literal(1)).within_group() self.assert_compile( - util.pickle.loads(util.pickle.dumps(f1)), + pickle.loads(pickle.dumps(f1)), "percentile_cont(:param_1) WITHIN GROUP (ORDER BY )", ) @@ -558,7 +558,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): column("q"), column("p").desc() ) self.assert_compile( - util.pickle.loads(util.pickle.dumps(f1)), + pickle.loads(pickle.dumps(f1)), "percentile_cont(:param_1) WITHIN GROUP (ORDER BY q, p DESC)", ) diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index b86e8d075a..831b75e7e0 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -1,5 +1,7 @@ +import collections.abc as collections_abc import datetime import operator +import pickle from sqlalchemy import and_ from sqlalchemy import between @@ -14,7 +16,6 @@ from sqlalchemy import or_ from sqlalchemy import String from sqlalchemy import testing from sqlalchemy import text -from sqlalchemy import util from sqlalchemy.dialects import mssql from sqlalchemy.dialects import mysql from sqlalchemy.dialects import oracle @@ -677,7 +678,7 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): return self.op("->")(index) col = Column("x", MyType()) - assert not isinstance(col, util.collections_abc.Iterable) + assert not isinstance(col, collections_abc.Iterable) def test_lshift(self): class MyType(UserDefinedType): @@ -2234,11 +2235,11 @@ class ComparisonOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): & self.table1.c.myid.between(15, 20) & self.table1.c.myid.like("hoho") ) - eq_(str(clause), str(util.pickle.loads(util.pickle.dumps(clause)))) + eq_(str(clause), str(pickle.loads(pickle.dumps(clause)))) def test_pickle_operators_two(self): clause = tuple_(1, 2, 3) - eq_(str(clause), str(util.pickle.loads(util.pickle.dumps(clause)))) + eq_(str(clause), str(pickle.loads(pickle.dumps(clause)))) @testing.combinations( (operator.lt, "<", ">"), diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py index 9d4e14517e..c5dd35ce15 100644 --- a/test/sql/test_resultset.py +++ b/test/sql/test_resultset.py @@ -1,7 +1,12 @@ import collections +import collections.abc as collections_abc from contextlib import contextmanager import csv +from io import StringIO import operator +import pickle +from unittest.mock import Mock +from unittest.mock import patch from sqlalchemy import CHAR from sqlalchemy import column @@ -24,7 +29,6 @@ from sqlalchemy import true from sqlalchemy import tuple_ from sqlalchemy import type_coerce from sqlalchemy import TypeDecorator -from sqlalchemy import util from sqlalchemy import VARCHAR from sqlalchemy.engine import cursor as _cursor from sqlalchemy.engine import default @@ -54,11 +58,8 @@ from sqlalchemy.testing import le_ from sqlalchemy.testing import mock from sqlalchemy.testing import ne_ from sqlalchemy.testing import not_in -from sqlalchemy.testing.mock import Mock -from sqlalchemy.testing.mock import patch from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table -from sqlalchemy.util import collections_abc class CursorResultTest(fixtures.TablesTest): @@ -290,7 +291,7 @@ class CursorResultTest(fixtures.TablesTest): ], ) - for pickle in False, True: + for use_pickle in False, True: for use_labels in False, True: result = connection.execute( users.select() @@ -302,8 +303,8 @@ class CursorResultTest(fixtures.TablesTest): ) ).fetchall() - if pickle: - result = util.pickle.loads(util.pickle.dumps(result)) + if use_pickle: + result = pickle.loads(pickle.dumps(result)) eq_(result, [(7, "jack"), (8, "ed"), (9, "fred")]) if use_labels: @@ -325,7 +326,7 @@ class CursorResultTest(fixtures.TablesTest): # previously would warn - if pickle: + if use_pickle: with expect_raises_message( exc.NoSuchColumnError, "Row was unpickled; lookup by ColumnElement is " @@ -335,7 +336,7 @@ class CursorResultTest(fixtures.TablesTest): else: eq_(result[0]._mapping[users.c.user_id], 7) - if pickle: + if use_pickle: with expect_raises_message( exc.NoSuchColumnError, "Row was unpickled; lookup by ColumnElement is " @@ -972,7 +973,7 @@ class CursorResultTest(fixtures.TablesTest): lambda: r._mapping[fake_table.c.user_id], ) - r = util.pickle.loads(util.pickle.dumps(r)) + r = pickle.loads(pickle.dumps(r)) assert_raises_message( exc.InvalidRequestError, "Ambiguous column name", @@ -1605,7 +1606,7 @@ class CursorResultTest(fixtures.TablesTest): users.select().where(users.c.user_id == 1) ).fetchone() - s = util.StringIO() + s = StringIO() writer = csv.writer(s) # csv performs PySequenceCheck call writer.writerow(row) diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index f0df92b705..eca4623c43 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -1,4 +1,6 @@ """Test various algorithmic properties of selectables.""" +from itertools import zip_longest + from sqlalchemy import and_ from sqlalchemy import bindparam from sqlalchemy import Boolean @@ -627,7 +629,7 @@ class SelectableTest( """tests for #6808""" s1 = select(*cols_expr).select_from(*select_from) - for ff, efp in util.zip_longest(s1.get_final_froms(), exp_final_froms): + for ff, efp in zip_longest(s1.get_final_froms(), exp_final_froms): assert ff.compare(efp) eq_(s1.columns_clause_froms, exp_cc_froms) diff --git a/test/sql/test_sequences.py b/test/sql/test_sequences.py index c5c76ad081..d11961862a 100644 --- a/test/sql/test_sequences.py +++ b/test/sql/test_sequences.py @@ -5,7 +5,6 @@ from sqlalchemy import MetaData from sqlalchemy import Sequence from sqlalchemy import String from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.dialects import sqlite from sqlalchemy.schema import CreateSequence from sqlalchemy.schema import DropSequence @@ -113,7 +112,7 @@ class SequenceExecTest(fixtures.TestBase): def _assert_seq_result(self, ret): """asserts return of next_value is an int""" - assert isinstance(ret, util.int_types) + assert isinstance(ret, int) assert ret >= testing.db.dialect.default_sequence_base def test_execute(self, connection): diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 0891defc29..f63e1e01bc 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -275,13 +275,13 @@ class AdaptTest(fixtures.TestBase): eq_(types.Integer().python_type, int) eq_(types.Numeric().python_type, decimal.Decimal) eq_(types.Numeric(asdecimal=False).python_type, float) - eq_(types.LargeBinary().python_type, util.binary_type) + eq_(types.LargeBinary().python_type, bytes) eq_(types.Float().python_type, float) eq_(types.Interval().python_type, datetime.timedelta) eq_(types.Date().python_type, datetime.date) eq_(types.DateTime().python_type, datetime.datetime) eq_(types.String().python_type, str) - eq_(types.Unicode().python_type, util.text_type) + eq_(types.Unicode().python_type, str) eq_(types.Enum("one", "two", "three").python_type, str) assert_raises( @@ -624,8 +624,8 @@ class UserDefinedRoundTripTest(_UserDefinedTypeFixture, fixtures.TablesTest): user_id=2, goofy="jack", goofy2="jack", - goofy4=util.u("jack"), - goofy7=util.u("jack"), + goofy4="jack", + goofy7="jack", goofy8=12, goofy9=12, goofy10=12, @@ -637,8 +637,8 @@ class UserDefinedRoundTripTest(_UserDefinedTypeFixture, fixtures.TablesTest): user_id=3, goofy="lala", goofy2="lala", - goofy4=util.u("lala"), - goofy7=util.u("lala"), + goofy4="lala", + goofy7="lala", goofy8=15, goofy9=15, goofy10=15, @@ -650,8 +650,8 @@ class UserDefinedRoundTripTest(_UserDefinedTypeFixture, fixtures.TablesTest): user_id=4, goofy="fred", goofy2="fred", - goofy4=util.u("fred"), - goofy7=util.u("fred"), + goofy4="fred", + goofy7="fred", goofy8=9, goofy9=9, goofy10=9, @@ -786,8 +786,8 @@ class BindProcessorInsertValuesTest(UserDefinedRoundTripTest): user_id=2, goofy="jack", goofy2="jack", - goofy4=util.u("jack"), - goofy7=util.u("jack"), + goofy4="jack", + goofy7="jack", goofy8=12, goofy9=12, goofy10=12, @@ -798,8 +798,8 @@ class BindProcessorInsertValuesTest(UserDefinedRoundTripTest): user_id=3, goofy="lala", goofy2="lala", - goofy4=util.u("lala"), - goofy7=util.u("lala"), + goofy4="lala", + goofy7="lala", goofy8=15, goofy9=15, goofy10=15, @@ -810,8 +810,8 @@ class BindProcessorInsertValuesTest(UserDefinedRoundTripTest): user_id=4, goofy="fred", goofy2="fred", - goofy4=util.u("fred"), - goofy7=util.u("fred"), + goofy4="fred", + goofy7="fred", goofy8=9, goofy9=9, goofy10=9, @@ -3494,7 +3494,7 @@ class NumericRawSQLTest(fixtures.TestBase): metadata = self.metadata self._fixture(connection, metadata, Integer, 45) val = connection.exec_driver_sql("select val from t").scalar() - assert isinstance(val, util.int_types) + assert isinstance(val, int) eq_(val, 45) @testing.provide_metadata diff --git a/test/sql/test_utils.py b/test/sql/test_utils.py index 24a149ece6..61777def54 100644 --- a/test/sql/test_utils.py +++ b/test/sql/test_utils.py @@ -1,3 +1,5 @@ +from itertools import zip_longest + from sqlalchemy import Column from sqlalchemy import Integer from sqlalchemy import MetaData @@ -5,7 +7,6 @@ from sqlalchemy import select from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import testing -from sqlalchemy import util from sqlalchemy.sql import base as sql_base from sqlalchemy.sql import coercions from sqlalchemy.sql import column @@ -146,5 +147,5 @@ class MiscTest(fixtures.TestBase): unwrapped = sql_util.unwrap_order_by(expr) - for a, b in util.zip_longest(unwrapped, expected): + for a, b in zip_longest(unwrapped, expected): assert a is not None and a.compare(b)