diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2020-10-30 15:14:18 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2020-10-30 15:14:18 +0000 |
commit | 841eb216644202567ebddfc0badc51a3a35e98c3 (patch) | |
tree | 40f930139e5a5fb707c3c3090bd2aabb455dd9cb /lib/sqlalchemy | |
parent | 163a97c6d57db09d6405124dae9b877bc9629721 (diff) | |
parent | 9ddbd585a62ff1ad56e9ee6fef5898ced1932a88 (diff) | |
download | sqlalchemy-841eb216644202567ebddfc0badc51a3a35e98c3.tar.gz |
Merge "Apply underscore naming to several more operators"
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/__init__.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/firebird/base.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mssql/base.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/oracle/base.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/base.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sqlite/base.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/reflection.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/evaluator.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/__init__.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 32 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/default_comparator.py | 37 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 58 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 14 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/operators.py | 164 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/suite/test_select.py | 4 |
16 files changed, 226 insertions, 125 deletions
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index d2c99b5b2..1146803f5 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -61,8 +61,10 @@ from .sql import literal_column # noqa from .sql import modifier # noqa from .sql import not_ # noqa from .sql import null # noqa -from .sql import nullsfirst # noqa -from .sql import nullslast # noqa +from .sql import nullsfirst # noqa; deprecated 1.4; see #5435 +from .sql import nullslast # noqa; deprecated 1.4; see #5435 +from .sql import nulls_first # noqa +from .sql import nulls_last # noqa from .sql import or_ # noqa from .sql import outerjoin # noqa from .sql import outparam # noqa diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py index 680968b9e..8a110fbd3 100644 --- a/lib/sqlalchemy/dialects/firebird/base.py +++ b/lib/sqlalchemy/dialects/firebird/base.py @@ -439,7 +439,7 @@ class FBCompiler(sql.compiler.SQLCompiler): # def visit_contains_op_binary(self, binary, operator, **kw): # cant use CONTAINING b.c. it's case insensitive. - # def visit_notcontains_op_binary(self, binary, operator, **kw): + # def visit_not_contains_op_binary(self, binary, operator, **kw): # cant use NOT CONTAINING b.c. it's case insensitive. def visit_now_func(self, fn, **kw): @@ -451,7 +451,7 @@ class FBCompiler(sql.compiler.SQLCompiler): binary.right._compiler_dispatch(self, **kw), ) - def visit_notstartswith_op_binary(self, binary, operator, **kw): + def visit_not_startswith_op_binary(self, binary, operator, **kw): return "%s NOT STARTING WITH %s" % ( binary.left._compiler_dispatch(self, **kw), binary.right._compiler_dispatch(self, **kw), diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index a224c00bb..bfe7a00ba 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -2077,7 +2077,7 @@ class MSSQLCompiler(compiler.SQLCompiler): self.process(binary.right), ) - def visit_isnot_distinct_from_binary(self, binary, operator, **kw): + def visit_is_not_distinct_from_binary(self, binary, operator, **kw): return "EXISTS (SELECT %s INTERSECT SELECT %s)" % ( self.process(binary.left), self.process(binary.right), @@ -2165,7 +2165,7 @@ class MSSQLStrictCompiler(MSSQLCompiler): self.process(binary.right, **kw), ) - def visit_notin_op_binary(self, binary, operator, **kw): + def visit_not_in_op_binary(self, binary, operator, **kw): kw["literal_execute"] = True return "%s NOT IN %s" % ( self.process(binary.left, **kw), diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 77f65799c..04175dedf 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1773,7 +1773,7 @@ class MySQLCompiler(compiler.SQLCompiler): self.process(binary.right), ) - def visit_isnot_distinct_from_binary(self, binary, operator, **kw): + def visit_is_not_distinct_from_binary(self, binary, operator, **kw): return "%s <=> %s" % ( self.process(binary.left), self.process(binary.right), diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 1f1f7501b..7bdaafd82 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -1213,7 +1213,7 @@ class OracleCompiler(compiler.SQLCompiler): self.process(binary.right), ) - def visit_isnot_distinct_from_binary(self, binary, operator, **kw): + def visit_is_not_distinct_from_binary(self, binary, operator, **kw): return "DECODE(%s, %s, 0, 1) = 0" % ( self.process(binary.left), self.process(binary.right), diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index ea6921b2d..391361e23 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1865,7 +1865,7 @@ class PGCompiler(compiler.SQLCompiler): else "" ) - def visit_notilike_op_binary(self, binary, operator, **kw): + def visit_not_ilike_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "%s NOT ILIKE %s" % ( self.process(binary.left, **kw), @@ -3850,10 +3850,10 @@ class PGDialect(default.DefaultDialect): if col_flags & 0x01: col_sorting += ("desc",) if not (col_flags & 0x02): - col_sorting += ("nullslast",) + col_sorting += ("nulls_last",) else: if col_flags & 0x02: - col_sorting += ("nullsfirst",) + col_sorting += ("nulls_first",) if col_sorting: sorting[col_idx] = col_sorting if sorting: diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 8a4fbe8e5..5efd0d9c9 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -1043,7 +1043,7 @@ class SQLiteCompiler(compiler.SQLCompiler): self.process(binary.right), ) - def visit_isnot_distinct_from_binary(self, binary, operator, **kw): + def visit_is_not_distinct_from_binary(self, binary, operator, **kw): return "%s IS %s" % ( self.process(binary.left), self.process(binary.right), diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 6af74d052..daebfe263 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -581,7 +581,7 @@ class Inspector(object): * ``column_sorting`` - optional dict mapping column names to tuple of sort keywords, - which may include ``asc``, ``desc``, ``nullsfirst``, ``nullslast``. + which may include ``asc``, ``desc``, ``nulls_first``, ``nulls_last``. .. versionadded:: 1.3.5 @@ -1006,8 +1006,8 @@ class Inspector(object): _index_sort_exprs = [ ("asc", operators.asc_op), ("desc", operators.desc_op), - ("nullsfirst", operators.nullsfirst_op), - ("nullslast", operators.nullslast_op), + ("nulls_first", operators.nulls_first_op), + ("nulls_last", operators.nulls_last_op), ] def _reflect_indexes( diff --git a/lib/sqlalchemy/orm/evaluator.py b/lib/sqlalchemy/orm/evaluator.py index 23c48329d..8763f0a3d 100644 --- a/lib/sqlalchemy/orm/evaluator.py +++ b/lib/sqlalchemy/orm/evaluator.py @@ -56,9 +56,9 @@ _notimplemented_ops = set( getattr(operators, op) for op in ( "like_op", - "notlike_op", + "not_like_op", "ilike_op", - "notilike_op", + "not_ilike_op", "startswith_op", "between_op", "endswith_op", diff --git a/lib/sqlalchemy/sql/__init__.py b/lib/sqlalchemy/sql/__init__.py index 8f6dc8e72..8cfd20054 100644 --- a/lib/sqlalchemy/sql/__init__.py +++ b/lib/sqlalchemy/sql/__init__.py @@ -55,8 +55,10 @@ from .expression import literal_column # noqa from .expression import modifier # noqa from .expression import not_ # noqa from .expression import null # noqa -from .expression import nullsfirst # noqa -from .expression import nullslast # noqa +from .expression import nullsfirst # noqa; deprecated 1.4; see #5435 +from .expression import nullslast # noqa; deprecated 1.4; see #5435 +from .expression import nulls_first # noqa +from .expression import nulls_last # noqa from .expression import or_ # noqa from .expression import outerjoin # noqa from .expression import outparam # noqa diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 10499975c..23c9d5c0a 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -185,10 +185,10 @@ OPERATORS = { operators.ge: " >= ", operators.eq: " = ", operators.is_distinct_from: " IS DISTINCT FROM ", - operators.isnot_distinct_from: " IS NOT DISTINCT FROM ", + operators.is_not_distinct_from: " IS NOT DISTINCT FROM ", operators.concat_op: " || ", operators.match_op: " MATCH ", - operators.notmatch_op: " NOT MATCH ", + operators.not_match_op: " NOT MATCH ", operators.in_op: " IN ", operators.not_in_op: " NOT IN ", operators.comma_op: ", ", @@ -206,8 +206,8 @@ OPERATORS = { # modifiers operators.desc_op: " DESC", operators.asc_op: " ASC", - operators.nullsfirst_op: " NULLS FIRST", - operators.nullslast_op: " NULLS LAST", + operators.nulls_first_op: " NULLS FIRST", + operators.nulls_last_op: " NULLS LAST", } FUNCTIONS = { @@ -1860,7 +1860,7 @@ class SQLCompiler(Compiled): "Unary expression has no operator or modifier" ) - def visit_istrue_unary_operator(self, element, operator, **kw): + def visit_is_true_unary_operator(self, element, operator, **kw): if ( element._is_implicitly_boolean or self.dialect.supports_native_boolean @@ -1869,7 +1869,7 @@ class SQLCompiler(Compiled): else: return "%s = 1" % self.process(element.element, **kw) - def visit_isfalse_unary_operator(self, element, operator, **kw): + def visit_is_false_unary_operator(self, element, operator, **kw): if ( element._is_implicitly_boolean or self.dialect.supports_native_boolean @@ -1878,7 +1878,7 @@ class SQLCompiler(Compiled): else: return "%s = 0" % self.process(element.element, **kw) - def visit_notmatch_op_binary(self, binary, operator, **kw): + def visit_not_match_op_binary(self, binary, operator, **kw): return "NOT %s" % self.visit_binary( binary, override_operator=operators.match_op ) @@ -2083,11 +2083,11 @@ class SQLCompiler(Compiled): binary.right = percent.__add__(binary.right).__add__(percent) return self.visit_like_op_binary(binary, operator, **kw) - def visit_notcontains_op_binary(self, binary, operator, **kw): + def visit_not_contains_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right).__add__(percent) - return self.visit_notlike_op_binary(binary, operator, **kw) + return self.visit_not_like_op_binary(binary, operator, **kw) def visit_startswith_op_binary(self, binary, operator, **kw): binary = binary._clone() @@ -2095,11 +2095,11 @@ class SQLCompiler(Compiled): binary.right = percent.__radd__(binary.right) return self.visit_like_op_binary(binary, operator, **kw) - def visit_notstartswith_op_binary(self, binary, operator, **kw): + def visit_not_startswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__radd__(binary.right) - return self.visit_notlike_op_binary(binary, operator, **kw) + return self.visit_not_like_op_binary(binary, operator, **kw) def visit_endswith_op_binary(self, binary, operator, **kw): binary = binary._clone() @@ -2107,11 +2107,11 @@ class SQLCompiler(Compiled): binary.right = percent.__add__(binary.right) return self.visit_like_op_binary(binary, operator, **kw) - def visit_notendswith_op_binary(self, binary, operator, **kw): + def visit_not_endswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right) - return self.visit_notlike_op_binary(binary, operator, **kw) + return self.visit_not_like_op_binary(binary, operator, **kw) def visit_like_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) @@ -2126,7 +2126,7 @@ class SQLCompiler(Compiled): else "" ) - def visit_notlike_op_binary(self, binary, operator, **kw): + def visit_not_like_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "%s NOT LIKE %s" % ( binary.left._compiler_dispatch(self, **kw), @@ -2148,7 +2148,7 @@ class SQLCompiler(Compiled): else "" ) - def visit_notilike_op_binary(self, binary, operator, **kw): + def visit_not_ilike_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "lower(%s) NOT LIKE lower(%s)" % ( binary.left._compiler_dispatch(self, **kw), @@ -2165,7 +2165,7 @@ class SQLCompiler(Compiled): binary, " BETWEEN SYMMETRIC " if symmetric else " BETWEEN ", **kw ) - def visit_notbetween_op_binary(self, binary, operator, **kw): + def visit_not_between_op_binary(self, binary, operator, **kw): symmetric = binary.modifiers.get("symmetric", False) return self._generate_generic_binary( binary, diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py index d5762ff1f..be6d0787b 100644 --- a/lib/sqlalchemy/sql/default_comparator.py +++ b/lib/sqlalchemy/sql/default_comparator.py @@ -57,7 +57,10 @@ def _boolean_compare( negate=negate, modifiers=kwargs, ) - elif op in (operators.is_distinct_from, operators.isnot_distinct_from): + elif op in ( + operators.is_distinct_from, + operators.is_not_distinct_from, + ): return BinaryExpression( expr, coercions.expect(roles.ConstExprRole, obj), @@ -87,7 +90,7 @@ def _boolean_compare( else: raise exc.ArgumentError( "Only '=', '!=', 'is_()', 'is_not()', " - "'is_distinct_from()', 'isnot_distinct_from()' " + "'is_distinct_from()', 'is_not_distinct_from()' " "operators can be used with None/True/False" ) else: @@ -205,7 +208,7 @@ def _match_impl(expr, op, other, **kw): operator=operators.match_op, ), result_type=type_api.MATCHTYPE, - negate=operators.notmatch_op + negate=operators.not_match_op if op is operators.match_op else operators.match_op, **kw @@ -241,7 +244,7 @@ def _between_impl(expr, op, cleft, cright, **kw): group_contents=False, ), op, - negate=operators.notbetween_op + negate=operators.not_between_op if op is operators.between_op else operators.between_op, modifiers=kw, @@ -315,29 +318,29 @@ operator_lookup = { "gt": (_boolean_compare, operators.le), "ge": (_boolean_compare, operators.lt), "eq": (_boolean_compare, operators.ne), - "is_distinct_from": (_boolean_compare, operators.isnot_distinct_from), - "isnot_distinct_from": (_boolean_compare, operators.is_distinct_from), - "like_op": (_boolean_compare, operators.notlike_op), - "ilike_op": (_boolean_compare, operators.notilike_op), - "notlike_op": (_boolean_compare, operators.like_op), - "notilike_op": (_boolean_compare, operators.ilike_op), - "contains_op": (_boolean_compare, operators.notcontains_op), - "startswith_op": (_boolean_compare, operators.notstartswith_op), - "endswith_op": (_boolean_compare, operators.notendswith_op), + "is_distinct_from": (_boolean_compare, operators.is_not_distinct_from), + "is_not_distinct_from": (_boolean_compare, operators.is_distinct_from), + "like_op": (_boolean_compare, operators.not_like_op), + "ilike_op": (_boolean_compare, operators.not_ilike_op), + "not_like_op": (_boolean_compare, operators.like_op), + "not_ilike_op": (_boolean_compare, operators.ilike_op), + "contains_op": (_boolean_compare, operators.not_contains_op), + "startswith_op": (_boolean_compare, operators.not_startswith_op), + "endswith_op": (_boolean_compare, operators.not_endswith_op), "desc_op": (_scalar, UnaryExpression._create_desc), "asc_op": (_scalar, UnaryExpression._create_asc), - "nullsfirst_op": (_scalar, UnaryExpression._create_nullsfirst), - "nullslast_op": (_scalar, UnaryExpression._create_nullslast), + "nulls_first_op": (_scalar, UnaryExpression._create_nulls_first), + "nulls_last_op": (_scalar, UnaryExpression._create_nulls_last), "in_op": (_in_impl, operators.not_in_op), "not_in_op": (_in_impl, operators.in_op), "is_": (_boolean_compare, operators.is_), "is_not": (_boolean_compare, operators.is_not), "collate": (_collate_impl,), "match_op": (_match_impl,), - "notmatch_op": (_match_impl,), + "not_match_op": (_match_impl,), "distinct_op": (_distinct_impl,), "between_op": (_between_impl,), - "notbetween_op": (_between_impl,), + "not_between_op": (_between_impl,), "neg": (_neg_impl,), "getitem": (_getitem_impl,), "lshift": (_unsupported_impl,), diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 00e28ac20..e268abc8a 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -766,7 +766,7 @@ class ColumnElement( against in (operators.and_, operators.or_, operators._asbool) and self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity ): - return AsBoolean(self, operators.istrue, operators.isfalse) + return AsBoolean(self, operators.is_true, operators.is_false) elif against in (operators.any_op, operators.all_op): return Grouping(self) else: @@ -774,7 +774,7 @@ class ColumnElement( def _negate(self): if self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity: - return AsBoolean(self, operators.isfalse, operators.istrue) + return AsBoolean(self, operators.is_false, operators.is_true) else: return super(ColumnElement, self)._negate() @@ -3096,7 +3096,7 @@ class UnaryExpression(ColumnElement): :class:`.UnaryExpression` is the basis for several unary operators including those used by :func:`.desc`, :func:`.asc`, :func:`.distinct`, - :func:`.nullsfirst` and :func:`.nullslast`. + :func:`.nulls_first` and :func:`.nulls_last`. """ @@ -3126,31 +3126,35 @@ class UnaryExpression(ColumnElement): self.wraps_column_expression = wraps_column_expression @classmethod - def _create_nullsfirst(cls, column): + def _create_nulls_first(cls, column): """Produce the ``NULLS FIRST`` modifier for an ``ORDER BY`` expression. - :func:`.nullsfirst` is intended to modify the expression produced + :func:`.nulls_first` is intended to modify the expression produced by :func:`.asc` or :func:`.desc`, and indicates how NULL values should be handled when they are encountered during ordering:: - from sqlalchemy import desc, nullsfirst + from sqlalchemy import desc, nulls_first stmt = select(users_table).order_by( - nullsfirst(desc(users_table.c.name))) + nulls_first(desc(users_table.c.name))) The SQL expression from the above would resemble:: SELECT id, name FROM user ORDER BY name DESC NULLS FIRST - Like :func:`.asc` and :func:`.desc`, :func:`.nullsfirst` is typically + Like :func:`.asc` and :func:`.desc`, :func:`.nulls_first` is typically invoked from the column expression itself using - :meth:`_expression.ColumnElement.nullsfirst`, + :meth:`_expression.ColumnElement.nulls_first`, rather than as its standalone function version, as in:: stmt = select(users_table).order_by( - users_table.c.name.desc().nullsfirst()) + users_table.c.name.desc().nulls_first()) + + .. versionchanged:: 1.4 :func:`.nulls_first` is renamed from + :func:`.nullsfirst` in previous releases. + The previous name remains available for backwards compatibility. .. seealso:: @@ -3158,43 +3162,47 @@ class UnaryExpression(ColumnElement): :func:`.desc` - :func:`.nullslast` + :func:`.nulls_last` :meth:`_expression.Select.order_by` """ return UnaryExpression( coercions.expect(roles.ByOfRole, column), - modifier=operators.nullsfirst_op, + modifier=operators.nulls_first_op, wraps_column_expression=False, ) @classmethod - def _create_nullslast(cls, column): + def _create_nulls_last(cls, column): """Produce the ``NULLS LAST`` modifier for an ``ORDER BY`` expression. - :func:`.nullslast` is intended to modify the expression produced + :func:`.nulls_last` is intended to modify the expression produced by :func:`.asc` or :func:`.desc`, and indicates how NULL values should be handled when they are encountered during ordering:: - from sqlalchemy import desc, nullslast + from sqlalchemy import desc, nulls_last stmt = select(users_table).order_by( - nullslast(desc(users_table.c.name))) + nulls_last(desc(users_table.c.name))) The SQL expression from the above would resemble:: SELECT id, name FROM user ORDER BY name DESC NULLS LAST - Like :func:`.asc` and :func:`.desc`, :func:`.nullslast` is typically + Like :func:`.asc` and :func:`.desc`, :func:`.nulls_last` is typically invoked from the column expression itself using - :meth:`_expression.ColumnElement.nullslast`, + :meth:`_expression.ColumnElement.nulls_last`, rather than as its standalone function version, as in:: stmt = select(users_table).order_by( - users_table.c.name.desc().nullslast()) + users_table.c.name.desc().nulls_last()) + + .. versionchanged:: 1.4 :func:`.nulls_last` is renamed from + :func:`.nullslast` in previous releases. + The previous name remains available for backwards compatibility. .. seealso:: @@ -3202,14 +3210,14 @@ class UnaryExpression(ColumnElement): :func:`.desc` - :func:`.nullsfirst` + :func:`.nulls_first` :meth:`_expression.Select.order_by` """ return UnaryExpression( coercions.expect(roles.ByOfRole, column), - modifier=operators.nullslast_op, + modifier=operators.nulls_last_op, wraps_column_expression=False, ) @@ -3243,9 +3251,9 @@ class UnaryExpression(ColumnElement): :func:`.asc` - :func:`.nullsfirst` + :func:`.nulls_first` - :func:`.nullslast` + :func:`.nulls_last` :meth:`_expression.Select.order_by` @@ -3285,9 +3293,9 @@ class UnaryExpression(ColumnElement): :func:`.desc` - :func:`.nullsfirst` + :func:`.nulls_first` - :func:`.nullslast` + :func:`.nulls_last` :meth:`_expression.Select.order_by` diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 31584f072..a3a4ec351 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -67,8 +67,8 @@ __all__ = [ "literal_column", "not_", "null", - "nullsfirst", - "nullslast", + "nulls_first", + "nulls_last", "or_", "outparam", "outerjoin", @@ -220,12 +220,14 @@ union_all = public_factory( CompoundSelect._create_union_all, ".sql.expression.union_all" ) exists = public_factory(Exists, ".sql.expression.exists") -nullsfirst = public_factory( - UnaryExpression._create_nullsfirst, ".sql.expression.nullsfirst" +nulls_first = public_factory( + UnaryExpression._create_nulls_first, ".sql.expression.nulls_first" ) -nullslast = public_factory( - UnaryExpression._create_nullslast, ".sql.expression.nullslast" +nullsfirst = nulls_first # deprecated 1.4; see #5435 +nulls_last = public_factory( + UnaryExpression._create_nulls_last, ".sql.expression.nulls_last" ) +nullslast = nulls_last # deprecated 1.4; see #5435 asc = public_factory(UnaryExpression._create_asc, ".sql.expression.asc") desc = public_factory(UnaryExpression._create_desc, ".sql.expression.desc") distinct = public_factory( diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py index 5f5052c28..29a2f191e 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -379,16 +379,23 @@ class ColumnOperators(Operators): """ return self.operate(is_distinct_from, other) - def isnot_distinct_from(self, other): + def is_not_distinct_from(self, other): """Implement the ``IS NOT DISTINCT FROM`` operator. Renders "a IS NOT DISTINCT FROM b" on most platforms; on some such as SQLite may render "a IS b". + .. versionchanged:: 1.4 The ``is_not_distinct_from()`` operator is + renamed from ``isnot_distinct_from()`` in previous releases. + The previous name remains available for backwards compatibility. + .. versionadded:: 1.1 """ - return self.operate(isnot_distinct_from, other) + return self.operate(is_not_distinct_from, other) + + # deprecated 1.4; see #5435 + isnot_distinct_from = is_not_distinct_from def __gt__(self, other): """Implement the ``>`` operator. @@ -627,12 +634,16 @@ class ColumnOperators(Operators): # deprecated 1.4; see #5429 notin_ = not_in - def notlike(self, other, escape=None): + def not_like(self, other, escape=None): """implement the ``NOT LIKE`` operator. This is equivalent to using negation with :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``. + .. versionchanged:: 1.4 The ``not_like()`` operator is renamed from + ``notlike()`` in previous releases. The previous name remains + available for backwards compatibility. + .. seealso:: :meth:`.ColumnOperators.like` @@ -640,12 +651,19 @@ class ColumnOperators(Operators): """ return self.operate(notlike_op, other, escape=escape) - def notilike(self, other, escape=None): + # deprecated 1.4; see #5435 + notlike = not_like + + def not_ilike(self, other, escape=None): """implement the ``NOT ILIKE`` operator. This is equivalent to using negation with :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``. + .. versionchanged:: 1.4 The ``not_ilike()`` operator is renamed from + ``notilike()`` in previous releases. The previous name remains + available for backwards compatibility. + .. seealso:: :meth:`.ColumnOperators.ilike` @@ -653,6 +671,9 @@ class ColumnOperators(Operators): """ return self.operate(notilike_op, other, escape=escape) + # deprecated 1.4; see #5435 + notilike = not_ilike + def is_(self, other): """Implement the ``IS`` operator. @@ -678,7 +699,6 @@ class ColumnOperators(Operators): ``isnot()`` in previous releases. The previous name remains available for backwards compatibility. - .. seealso:: :meth:`.ColumnOperators.is_` """ @@ -1043,15 +1063,31 @@ class ColumnOperators(Operators): parent object.""" return self.operate(asc_op) - def nullsfirst(self): - """Produce a :func:`_expression.nullsfirst` clause against the - parent object.""" - return self.operate(nullsfirst_op) + def nulls_first(self): + """Produce a :func:`_expression.nulls_first` clause against the + parent object. - def nullslast(self): - """Produce a :func:`_expression.nullslast` clause against the - parent object.""" - return self.operate(nullslast_op) + .. versionchanged:: 1.4 The ``nulls_first()`` operator is + renamed from ``nullsfirst()`` in previous releases. + The previous name remains available for backwards compatibility. + """ + return self.operate(nulls_first_op) + + # deprecated 1.4; see #5435 + nullsfirst = nulls_first + + def nulls_last(self): + """Produce a :func:`_expression.nulls_last` clause against the + parent object. + + .. versionchanged:: 1.4 The ``nulls_last()`` operator is + renamed from ``nullslast()`` in previous releases. + The previous name remains available for backwards compatibility. + """ + return self.operate(nulls_last_op) + + # deprecated 1.4; see #5429 + nullslast = nulls_last def collate(self, collation): """Produce a :func:`_expression.collate` clause against @@ -1260,22 +1296,34 @@ def exists(): raise NotImplementedError() -def istrue(a): +def is_true(a): raise NotImplementedError() -def isfalse(a): +# 1.4 deprecated; see #5435 +istrue = is_true + + +def is_false(a): raise NotImplementedError() +# 1.4 deprecated; see #5435 +isfalse = is_false + + @comparison_op def is_distinct_from(a, b): return a.is_distinct_from(b) @comparison_op -def isnot_distinct_from(a, b): - return a.isnot_distinct_from(b) +def is_not_distinct_from(a, b): + return a.is_not_distinct_from(b) + + +# deprecated 1.4; see #5435 +isnot_distinct_from = is_not_distinct_from @comparison_op @@ -1306,18 +1354,26 @@ def like_op(a, b, escape=None): @comparison_op -def notlike_op(a, b, escape=None): +def not_like_op(a, b, escape=None): return a.notlike(b, escape=escape) +# 1.4 deprecated; see #5435 +notlike_op = not_like_op + + @comparison_op def ilike_op(a, b, escape=None): return a.ilike(b, escape=escape) @comparison_op -def notilike_op(a, b, escape=None): - return a.notilike(b, escape=escape) +def not_ilike_op(a, b, escape=None): + return a.not_ilike(b, escape=escape) + + +# 1.4 deprecated; see #5435 +notilike_op = not_ilike_op @comparison_op @@ -1326,8 +1382,12 @@ def between_op(a, b, c, symmetric=False): @comparison_op -def notbetween_op(a, b, c, symmetric=False): - return a.notbetween(b, c, symmetric=symmetric) +def not_between_op(a, b, c, symmetric=False): + return ~a.between(b, c, symmetric=symmetric) + + +# 1.4 deprecated; see #5435 +notbetween_op = not_between_op @comparison_op @@ -1382,30 +1442,42 @@ def startswith_op(a, b, escape=None, autoescape=False): @comparison_op -def notstartswith_op(a, b, escape=None, autoescape=False): +def not_startswith_op(a, b, escape=None, autoescape=False): return ~_escaped_like_impl(a.startswith, b, escape, autoescape) +# 1.4 deprecated; see #5435 +notstartswith_op = not_startswith_op + + @comparison_op def endswith_op(a, b, escape=None, autoescape=False): return _escaped_like_impl(a.endswith, b, escape, autoescape) @comparison_op -def notendswith_op(a, b, escape=None, autoescape=False): +def not_endswith_op(a, b, escape=None, autoescape=False): return ~_escaped_like_impl(a.endswith, b, escape, autoescape) +# 1.4 deprecated; see #5435 +notendswith_op = not_endswith_op + + @comparison_op def contains_op(a, b, escape=None, autoescape=False): return _escaped_like_impl(a.contains, b, escape, autoescape) @comparison_op -def notcontains_op(a, b, escape=None, autoescape=False): +def not_contains_op(a, b, escape=None, autoescape=False): return ~_escaped_like_impl(a.contains, b, escape, autoescape) +# 1.4 deprecated; see #5435 +notcontains_op = not_contains_op + + @comparison_op def match_op(a, b, **kw): return a.match(b, **kw) @@ -1426,8 +1498,12 @@ def regexp_replace_op(a, b, replacement, flags=None): @comparison_op -def notmatch_op(a, b, **kw): - return a.notmatch(b, **kw) +def not_match_op(a, b, **kw): + return ~a.match(b, **kw) + + +# 1.4 deprecated; see #5429 +notmatch_op = not_match_op def comma_op(a, b): @@ -1450,12 +1526,20 @@ def asc_op(a): return a.asc() -def nullsfirst_op(a): - return a.nullsfirst() +def nulls_first_op(a): + return a.nulls_first() + + +# 1.4 deprecated; see #5435 +nullsfirst_op = nulls_first_op + + +def nulls_last_op(a): + return a.nulls_last() -def nullslast_op(a): - return a.nullslast() +# 1.4 deprecated; see #5435 +nullslast_op = nulls_last_op def json_getitem_op(a, b): @@ -1475,7 +1559,7 @@ def is_commutative(op): def is_ordering_modifier(op): - return op in (asc_op, desc_op, nullsfirst_op, nullslast_op) + return op in (asc_op, desc_op, nulls_first_op, nulls_last_op) def is_natural_self_precedent(op): @@ -1486,7 +1570,7 @@ def is_natural_self_precedent(op): ) -_booleans = (inv, istrue, isfalse, and_, or_) +_booleans = (inv, is_true, is_false, and_, or_) def is_boolean(op): @@ -1543,14 +1627,14 @@ _PRECEDENCE = { concat_op: 6, filter_op: 6, match_op: 5, - notmatch_op: 5, + not_match_op: 5, regexp_match_op: 5, not_regexp_match_op: 5, regexp_replace_op: 5, ilike_op: 5, - notilike_op: 5, + not_ilike_op: 5, like_op: 5, - notlike_op: 5, + not_like_op: 5, in_op: 5, not_in_op: 5, is_: 5, @@ -1558,17 +1642,17 @@ _PRECEDENCE = { eq: 5, ne: 5, is_distinct_from: 5, - isnot_distinct_from: 5, + is_not_distinct_from: 5, gt: 5, lt: 5, ge: 5, le: 5, between_op: 5, - notbetween_op: 5, + not_between_op: 5, distinct_op: 5, inv: 5, - istrue: 5, - isfalse: 5, + is_true: 5, + is_false: 5, and_: 3, or_: 2, comma_op: -1, diff --git a/lib/sqlalchemy/testing/suite/test_select.py b/lib/sqlalchemy/testing/suite/test_select.py index ee9db9111..d15fae3c4 100644 --- a/lib/sqlalchemy/testing/suite/test_select.py +++ b/lib/sqlalchemy/testing/suite/test_select.py @@ -1349,7 +1349,7 @@ class IsOrIsNotDistinctFromTest(fixtures.TablesTest): id_="iaaa", argnames="col_a_value, col_b_value, expected_row_count_for_is", ) - def test_is_or_isnot_distinct_from( + def test_is_or_is_not_distinct_from( self, col_a_value, col_b_value, expected_row_count_for_is, connection ): tbl = self.tables.is_distinct_test @@ -1371,7 +1371,7 @@ class IsOrIsNotDistinctFromTest(fixtures.TablesTest): 1 if expected_row_count_for_is == 0 else 0 ) result = connection.execute( - tbl.select(tbl.c.col_a.isnot_distinct_from(tbl.c.col_b)) + tbl.select(tbl.c.col_a.is_not_distinct_from(tbl.c.col_b)) ).fetchall() eq_( len(result), |