From da70478eb2eafe9c76b836217371e029c3c820e3 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 28 Feb 2023 11:05:48 -0500 Subject: [PATCH] ensure single import per line This adds the very small plugin flake8-import-single which will prevent us from having an import with more than one symbol on a line. Flake8 by itself prevents this pattern with E401: import collections, os, sys However does not do anything with this: from sqlalchemy import Column, text Both statements have the same issues generating merge artifacts as well as presenting a manual decision to be made. While zimports generally cleans up such imports at the top level, we don't enforce zimports / pre-commit use. the plugin finds the same issue for imports that are inside of test methods. We shouldn't usually have imports in test methods so most of them here are moved to be top level. The version is pinned at 0.1.5; the project seems to have no activity since 2019, however there are three 0.1.6dev releases on pypi which stopped in September 2019, they seem to be experiments with packaging. The source for 0.1.5 is extremely simple and only reveals one method to flake8 (the run() method). Change-Id: Icea894e43bad9c0b5d4feb5f49c6c666d6ea6aa1 --- .pre-commit-config.yaml | 1 + .../active_column_defaults.py | 13 ++++--- .../custom_attributes/listen_for_events.py | 10 +++-- .../dogpile_caching/local_session_caching.py | 10 +++-- examples/extending_query/filter_public.py | 14 ++++--- examples/extending_query/temporal_range.py | 14 ++++--- examples/vertical/dictlike-polymorphic.py | 37 +++++++++---------- examples/vertical/dictlike.py | 26 ++++++------- lib/sqlalchemy/orm/clsregistry.py | 3 +- lib/sqlalchemy/orm/loading.py | 6 +-- lib/sqlalchemy/testing/fixtures.py | 8 ++-- test/aaa_profiling/test_memusage.py | 12 +++--- test/dialect/postgresql/test_types.py | 16 +++----- test/ext/asyncio/test_engine_py3k.py | 2 - test/ext/test_hybrid.py | 4 +- test/orm/declarative/test_basic.py | 5 ++- test/orm/test_cache_key.py | 4 -- test/orm/test_deprecations.py | 4 +- test/orm/test_inspect.py | 30 +++++++-------- test/orm/test_mapper.py | 4 +- test/orm/test_options.py | 3 +- test/perf/compiled_extensions.py | 4 +- test/sql/test_compiler.py | 4 +- test/sql/test_defaults.py | 3 +- test/sql/test_functions.py | 3 +- test/sql/test_metadata.py | 5 +-- tox.ini | 1 + 27 files changed, 126 insertions(+), 120 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c77fada3e..c734beb041 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,6 +17,7 @@ repos: - id: flake8 additional_dependencies: - flake8-import-order + - flake8-import-single==0.1.5 - flake8-builtins - flake8-future-annotations>=0.0.5 - flake8-docstrings>=1.6.0 diff --git a/examples/custom_attributes/active_column_defaults.py b/examples/custom_attributes/active_column_defaults.py index dea79ee952..d5322d331b 100644 --- a/examples/custom_attributes/active_column_defaults.py +++ b/examples/custom_attributes/active_column_defaults.py @@ -5,7 +5,15 @@ when an un-set attribute is accessed. """ +import datetime + +from sqlalchemy import Column +from sqlalchemy import create_engine +from sqlalchemy import DateTime from sqlalchemy import event +from sqlalchemy import Integer +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import Session def configure_listener(mapper, class_): @@ -67,11 +75,6 @@ def default_listener(col_attr, default): if __name__ == "__main__": - from sqlalchemy import Column, Integer, DateTime, create_engine - from sqlalchemy.orm import Session - from sqlalchemy.ext.declarative import declarative_base - import datetime - Base = declarative_base() event.listen(Base, "mapper_configured", configure_listener, propagate=True) diff --git a/examples/custom_attributes/listen_for_events.py b/examples/custom_attributes/listen_for_events.py index b2d2b690b6..a94a3dab20 100644 --- a/examples/custom_attributes/listen_for_events.py +++ b/examples/custom_attributes/listen_for_events.py @@ -3,7 +3,13 @@ and listen for change events. """ +from sqlalchemy import Column from sqlalchemy import event +from sqlalchemy import ForeignKey +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship def configure_listener(class_, key, inst): @@ -23,10 +29,6 @@ def configure_listener(class_, key, inst): if __name__ == "__main__": - from sqlalchemy import Column, Integer, String, ForeignKey - from sqlalchemy.orm import relationship - from sqlalchemy.ext.declarative import declarative_base - class Base: def receive_change_event(self, verb, key, value, oldvalue): s = "Value '%s' %s on attribute '%s', " % (value, verb, key) diff --git a/examples/dogpile_caching/local_session_caching.py b/examples/dogpile_caching/local_session_caching.py index e603cef642..1bcb3bb9a0 100644 --- a/examples/dogpile_caching/local_session_caching.py +++ b/examples/dogpile_caching/local_session_caching.py @@ -10,10 +10,15 @@ with the basic operation of CachingQuery. """ +from dogpile.cache import make_region from dogpile.cache.api import CacheBackend from dogpile.cache.api import NO_VALUE from dogpile.cache.region import register_backend -from examples.dogpile_caching import environment + +from . import environment +from .caching_query import FromCache +from .environment import regions +from .environment import Session class ScopedSessionBackend(CacheBackend): @@ -59,9 +64,6 @@ register_backend("sqlalchemy.session", __name__, "ScopedSessionBackend") if __name__ == "__main__": - from .environment import Session, regions - from .caching_query import FromCache - from dogpile.cache import make_region # set up a region based on the ScopedSessionBackend, # pointing to the scoped_session declared in the example diff --git a/examples/extending_query/filter_public.py b/examples/extending_query/filter_public.py index a420e9da4a..1ac8115834 100644 --- a/examples/extending_query/filter_public.py +++ b/examples/extending_query/filter_public.py @@ -14,10 +14,18 @@ that should be applied on a per-request basis, etc. from sqlalchemy import Boolean from sqlalchemy import Column +from sqlalchemy import create_engine from sqlalchemy import event +from sqlalchemy import ForeignKey +from sqlalchemy import Integer from sqlalchemy import orm +from sqlalchemy import select +from sqlalchemy import String from sqlalchemy import true +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship from sqlalchemy.orm import Session +from sqlalchemy.orm import sessionmaker @event.listens_for(Session, "do_orm_execute") @@ -58,12 +66,6 @@ class HasPrivate: if __name__ == "__main__": - from sqlalchemy import Integer, Column, String, ForeignKey, Boolean - from sqlalchemy import select - from sqlalchemy import create_engine - from sqlalchemy.orm import relationship, sessionmaker - from sqlalchemy.ext.declarative import declarative_base - Base = declarative_base() class User(HasPrivate, Base): diff --git a/examples/extending_query/temporal_range.py b/examples/extending_query/temporal_range.py index 01d0eadf87..dc6d8166f8 100644 --- a/examples/extending_query/temporal_range.py +++ b/examples/extending_query/temporal_range.py @@ -7,8 +7,16 @@ to selected entities. import datetime from sqlalchemy import Column +from sqlalchemy import create_engine from sqlalchemy import DateTime +from sqlalchemy import ForeignKey +from sqlalchemy import Integer from sqlalchemy import orm +from sqlalchemy import select +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from sqlalchemy.orm import selectinload +from sqlalchemy.orm import sessionmaker class HasTemporal: @@ -29,12 +37,6 @@ def temporal_range(range_lower, range_upper): if __name__ == "__main__": - from sqlalchemy import Integer, Column, ForeignKey - from sqlalchemy import select - from sqlalchemy import create_engine - from sqlalchemy.orm import relationship, sessionmaker, selectinload - from sqlalchemy.ext.declarative import declarative_base - Base = declarative_base() class Parent(HasTemporal, Base): diff --git a/examples/vertical/dictlike-polymorphic.py b/examples/vertical/dictlike-polymorphic.py index afd23c4e1c..a3873da2a3 100644 --- a/examples/vertical/dictlike-polymorphic.py +++ b/examples/vertical/dictlike-polymorphic.py @@ -24,9 +24,27 @@ date. """ +from sqlalchemy import and_ +from sqlalchemy import Boolean +from sqlalchemy import case +from sqlalchemy import cast +from sqlalchemy import Column +from sqlalchemy import create_engine from sqlalchemy import event +from sqlalchemy import ForeignKey +from sqlalchemy import Integer from sqlalchemy import literal_column +from sqlalchemy import null +from sqlalchemy import or_ +from sqlalchemy import String +from sqlalchemy import Unicode +from sqlalchemy import UnicodeText +from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import relationship +from sqlalchemy.orm import Session +from sqlalchemy.orm.collections import attribute_keyed_dict from sqlalchemy.orm.interfaces import PropComparator from .dictlike import ProxiedDictMixin @@ -116,25 +134,6 @@ def on_new_class(mapper, cls_): if __name__ == "__main__": - from sqlalchemy import ( - Column, - Integer, - Unicode, - ForeignKey, - UnicodeText, - and_, - or_, - String, - Boolean, - cast, - null, - case, - create_engine, - ) - from sqlalchemy.orm import relationship, Session - from sqlalchemy.orm.collections import attribute_keyed_dict - from sqlalchemy.ext.declarative import declarative_base - from sqlalchemy.ext.associationproxy import association_proxy Base = declarative_base() diff --git a/examples/vertical/dictlike.py b/examples/vertical/dictlike.py index d0a952d7c7..dd19b9ee31 100644 --- a/examples/vertical/dictlike.py +++ b/examples/vertical/dictlike.py @@ -31,6 +31,19 @@ can be used with many common vertical schemas as-is or with minor adaptations. """ +from sqlalchemy import and_ +from sqlalchemy import Column +from sqlalchemy import create_engine +from sqlalchemy import ForeignKey +from sqlalchemy import Integer +from sqlalchemy import Unicode +from sqlalchemy import UnicodeText +from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from sqlalchemy.orm import Session +from sqlalchemy.orm.collections import attribute_keyed_dict + class ProxiedDictMixin: """Adds obj[key] access to a mapped class. @@ -61,19 +74,6 @@ class ProxiedDictMixin: if __name__ == "__main__": - from sqlalchemy import ( - Column, - Integer, - Unicode, - ForeignKey, - UnicodeText, - and_, - create_engine, - ) - from sqlalchemy.orm import relationship, Session - from sqlalchemy.orm.collections import attribute_keyed_dict - from sqlalchemy.ext.declarative import declarative_base - from sqlalchemy.ext.associationproxy import association_proxy Base = declarative_base() diff --git a/lib/sqlalchemy/orm/clsregistry.py b/lib/sqlalchemy/orm/clsregistry.py index e5fff4a5ee..c4d6c29ebe 100644 --- a/lib/sqlalchemy/orm/clsregistry.py +++ b/lib/sqlalchemy/orm/clsregistry.py @@ -553,7 +553,8 @@ def _resolver( if _fallback_dict is None: import sqlalchemy - from sqlalchemy.orm import foreign, remote + from . import foreign + from . import remote _fallback_dict = util.immutabledict(sqlalchemy.__dict__).union( {"foreign": foreign, "remote": remote} diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py index 7974d94c5a..3d9ff7b0ab 100644 --- a/lib/sqlalchemy/orm/loading.py +++ b/lib/sqlalchemy/orm/loading.py @@ -37,6 +37,8 @@ from .base import _RAISE_FOR_STATE from .base import _SET_DEFERRED_EXPIRED from .base import PassiveFlag from .context import FromStatement +from .context import ORMCompileState +from .context import QueryContext from .util import _none_set from .util import state_str from .. import exc as sa_exc @@ -55,7 +57,6 @@ from ..util import EMPTY_DICT if TYPE_CHECKING: from ._typing import _IdentityKeyType from .base import LoaderCallableStatus - from .context import QueryContext from .interfaces import ORMOption from .mapper import Mapper from .query import Query @@ -519,9 +520,6 @@ def load_on_pk_identity( assert not q._is_lambda_element - # TODO: fix these imports .... - from .context import QueryContext, ORMCompileState - if load_options is None: load_options = QueryContext.default_load_options diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py index 3b58052b8d..a8bc6c50a7 100644 --- a/lib/sqlalchemy/testing/fixtures.py +++ b/lib/sqlalchemy/testing/fixtures.py @@ -24,7 +24,12 @@ from .entities import ComparableEntity from .entities import ComparableMixin # noqa from .util import adict from .util import drop_all_tables_from_metadata +from .. import Column from .. import event +from .. import func +from .. import Integer +from .. import select +from .. import Table from .. import util from ..orm import DeclarativeBase from ..orm import events as orm_events @@ -247,9 +252,6 @@ class TestBase: def trans_ctx_manager_fixture(self, request, metadata): rollback, second_operation, begin_nested = request.param - from sqlalchemy import Table, Column, Integer, func, select - from . import eq_ - t = Table("test", metadata, Column("data", Integer)) eng = getattr(self, "bind", None) or config.db diff --git a/test/aaa_profiling/test_memusage.py b/test/aaa_profiling/test_memusage.py index d30ccb3b8c..9b2cb31bef 100644 --- a/test/aaa_profiling/test_memusage.py +++ b/test/aaa_profiling/test_memusage.py @@ -6,6 +6,7 @@ import pickle import weakref import sqlalchemy as sa +from sqlalchemy import and_ from sqlalchemy import ForeignKey from sqlalchemy import func from sqlalchemy import inspect @@ -14,8 +15,12 @@ from sqlalchemy import MetaData from sqlalchemy import select from sqlalchemy import String from sqlalchemy import testing +from sqlalchemy import types from sqlalchemy import Unicode from sqlalchemy import util +from sqlalchemy.dialects import mysql +from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects import sqlite from sqlalchemy.engine import result from sqlalchemy.engine.processors import to_decimal_processor_factory from sqlalchemy.orm import aliased @@ -34,6 +39,7 @@ from sqlalchemy.orm import subqueryload from sqlalchemy.orm.session import _sessions from sqlalchemy.sql import column from sqlalchemy.sql import util as sql_util +from sqlalchemy.sql.util import visit_binary_product from sqlalchemy.sql.visitors import cloned_traverse from sqlalchemy.sql.visitors import replacement_traverse from sqlalchemy.testing import engines @@ -310,9 +316,6 @@ class MemUsageTest(EnsureZeroed): """test storage of bind processors, result processors in dialect-wide registry.""" - from sqlalchemy.dialects import mysql, postgresql, sqlite - from sqlalchemy import types - eng = engines.testing_engine() for args in ( (types.Integer, {}), @@ -1669,9 +1672,6 @@ class CycleTest(_fixtures.FixtureTest): def test_visit_binary_product(self): a, b, q, e, f, j, r = (column(chr_) for chr_ in "abqefjr") - from sqlalchemy import and_, func - from sqlalchemy.sql.util import visit_binary_product - expr = and_((a + b) == q + func.sum(e + f), j == r) def visit(expr, left, right): diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 22993ae7bb..2b15c7d735 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -38,6 +38,8 @@ from sqlalchemy import util from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import aggregate_order_by from sqlalchemy.dialects.postgresql import array +from sqlalchemy.dialects.postgresql import array_agg +from sqlalchemy.dialects.postgresql import base from sqlalchemy.dialects.postgresql import DATEMULTIRANGE from sqlalchemy.dialects.postgresql import DATERANGE from sqlalchemy.dialects.postgresql import DOMAIN @@ -53,6 +55,9 @@ from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.dialects.postgresql import NamedType from sqlalchemy.dialects.postgresql import NUMMULTIRANGE from sqlalchemy.dialects.postgresql import NUMRANGE +from sqlalchemy.dialects.postgresql import pg8000 +from sqlalchemy.dialects.postgresql import psycopg2 +from sqlalchemy.dialects.postgresql import psycopg2cffi from sqlalchemy.dialects.postgresql import Range from sqlalchemy.dialects.postgresql import TSMULTIRANGE from sqlalchemy.dialects.postgresql import TSRANGE @@ -1225,12 +1230,6 @@ class NumericInterpretationTest(fixtures.TestBase): __backend__ = True def test_numeric_codes(self): - from sqlalchemy.dialects.postgresql import ( - base, - pg8000, - psycopg2, - psycopg2cffi, - ) dialects = ( pg8000.dialect(), @@ -1735,11 +1734,6 @@ class ArrayTest(AssertsCompiledSQL, fixtures.TestBase): argnames="with_enum, using_aggregate_order_by", ) def test_array_agg_specific(self, with_enum, using_aggregate_order_by): - from sqlalchemy.dialects.postgresql import ( - ENUM, - aggregate_order_by, - array_agg, - ) element = ENUM(name="pgenum") if with_enum else Integer() element_type = type(element) diff --git a/test/ext/asyncio/test_engine_py3k.py b/test/ext/asyncio/test_engine_py3k.py index bce669e4f4..9511fed742 100644 --- a/test/ext/asyncio/test_engine_py3k.py +++ b/test/ext/asyncio/test_engine_py3k.py @@ -57,8 +57,6 @@ class AsyncFixture: def async_trans_ctx_manager_fixture(self, request, metadata): rollback, run_second_execute, begin_nested = request.param - from sqlalchemy import Table, Column, Integer, func, select - t = Table("test", metadata, Column("data", Integer)) eng = getattr(self, "bind", None) or config.db diff --git a/test/ext/test_hybrid.py b/test/ext/test_hybrid.py index c092850667..73967cdd00 100644 --- a/test/ext/test_hybrid.py +++ b/test/ext/test_hybrid.py @@ -19,7 +19,9 @@ from sqlalchemy.orm import declarative_base from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import synonym +from sqlalchemy.sql import coercions from sqlalchemy.sql import operators +from sqlalchemy.sql import roles from sqlalchemy.sql import update from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import AssertsCompiledSQL @@ -521,8 +523,6 @@ class PropertyExpressionTest(fixtures.TestBase, AssertsCompiledSQL): def test_expression_isnt_clause_element(self): A = self._wrong_expr_fixture() - from sqlalchemy.sql import coercions, roles - with testing.expect_raises_message( exc.InvalidRequestError, 'When interpreting attribute "A.value" as a SQL expression, ' diff --git a/test/orm/declarative/test_basic.py b/test/orm/declarative/test_basic.py index 7e8cd49f38..4aca4daa6d 100644 --- a/test/orm/declarative/test_basic.py +++ b/test/orm/declarative/test_basic.py @@ -44,6 +44,7 @@ from sqlalchemy.orm.decl_api import DeclarativeMeta from sqlalchemy.orm.decl_base import _DeferredMapperConfig from sqlalchemy.orm.events import InstrumentationEvents from sqlalchemy.orm.events import MapperEvents +from sqlalchemy.schema import PrimaryKeyConstraint from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import assertions @@ -2395,7 +2396,9 @@ class DeclarativeMultiBaseTest( eq_(Foo.__table__.name, "foobat") def test_table_cls_attribute_return_none(self): - from sqlalchemy.schema import Column, PrimaryKeyConstraint + # this is separate from the "fixture" version of Column used in the + # rest of this suite + from sqlalchemy.schema import Column class AutoTable: @declared_attr diff --git a/test/orm/test_cache_key.py b/test/orm/test_cache_key.py index 1a44b5d23b..f1c3e6a54e 100644 --- a/test/orm/test_cache_key.py +++ b/test/orm/test_cache_key.py @@ -157,8 +157,6 @@ class CacheKeyTest(fixtures.CacheKeyFixture, _fixtures.FixtureTest): def test_loader_criteria(self): User, Address = self.classes("User", "Address") - from sqlalchemy import Column, Integer, String - class Foo: id = Column(Integer) name = Column(String) @@ -175,8 +173,6 @@ class CacheKeyTest(fixtures.CacheKeyFixture, _fixtures.FixtureTest): ) def test_loader_criteria_bound_param_thing(self): - from sqlalchemy import Column, Integer - class Foo: id = Column(Integer) diff --git a/test/orm/test_deprecations.py b/test/orm/test_deprecations.py index a23bb7a24d..7225639641 100644 --- a/test/orm/test_deprecations.py +++ b/test/orm/test_deprecations.py @@ -294,7 +294,9 @@ class PickleTest(fixtures.MappedTest): ) # these must be module level for pickling - from .test_pickled import User, Address, Dingaling + from .test_pickled import Address + from .test_pickled import Dingaling + from .test_pickled import User self.mapper_registry.map_imperatively( User, diff --git a/test/orm/test_inspect.py b/test/orm/test_inspect.py index 8644b36e55..6ae0d1d3ff 100644 --- a/test/orm/test_inspect.py +++ b/test/orm/test_inspect.py @@ -1,9 +1,21 @@ """test the inspection registry system.""" +import random +import textwrap + +from sqlalchemy import Column from sqlalchemy import exc from sqlalchemy import ForeignKey from sqlalchemy import inspect +from sqlalchemy import Integer +from sqlalchemy import MetaData +from sqlalchemy import Table from sqlalchemy import testing +from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy.ext.associationproxy import AssociationProxyExtensionType +from sqlalchemy.ext.hybrid import hybrid_method +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.ext.hybrid import HybridExtensionType from sqlalchemy.orm import aliased from sqlalchemy.orm import class_mapper from sqlalchemy.orm import relationship @@ -12,6 +24,7 @@ from sqlalchemy.orm import synonym from sqlalchemy.orm.attributes import instance_state from sqlalchemy.orm.attributes import NO_VALUE from sqlalchemy.orm.base import InspectionAttr +from sqlalchemy.orm.interfaces import NotExtension from sqlalchemy.orm.util import identity_key from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import eq_ @@ -233,18 +246,6 @@ class TestORMInspection(_fixtures.FixtureTest): assert hasattr(prop, "expression") def test_extension_types(self): - from sqlalchemy.ext.associationproxy import ( - association_proxy, - AssociationProxyExtensionType, - ) - from sqlalchemy.ext.hybrid import ( - hybrid_property, - hybrid_method, - HybridExtensionType, - ) - from sqlalchemy import Table, MetaData, Integer, Column - from sqlalchemy.orm.interfaces import NotExtension - class SomeClass(self.classes.User): some_assoc = association_proxy("addresses", "email_address") @@ -449,9 +450,6 @@ class TestORMInspection(_fixtures.FixtureTest): return list(names.difference(keyword.kwlist)) def _ordered_name_fixture(self, glbls, clsname, base, supercls): - import random - from sqlalchemy import Integer, Column - import textwrap names = self._random_names() @@ -550,8 +548,6 @@ class %s(SuperCls): class MyClass: pass - from sqlalchemy import Table, MetaData, Column, Integer - names = self._random_names() m = MetaData() diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index e645556b5e..e89e26ec9e 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -35,6 +35,8 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import RelationshipProperty from sqlalchemy.orm import Session from sqlalchemy.orm import synonym +from sqlalchemy.orm.base import _is_aliased_class +from sqlalchemy.orm.base import _is_mapped_class from sqlalchemy.orm.persistence import _sort_states from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message @@ -220,8 +222,6 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): addresses = self.tables.addresses Address = self.classes.Address - from sqlalchemy.orm.base import _is_mapped_class, _is_aliased_class - class Foo: x = "something" diff --git a/test/orm/test_options.py b/test/orm/test_options.py index 1446565ac8..47ffedb07c 100644 --- a/test/orm/test_options.py +++ b/test/orm/test_options.py @@ -34,6 +34,8 @@ from sqlalchemy.testing.assertions import emits_warning from sqlalchemy.testing.assertions import eq_ from sqlalchemy.testing.assertions import expect_raises_message from sqlalchemy.testing.fixtures import fixture_session +from sqlalchemy.testing.pickleable import Address +from sqlalchemy.testing.pickleable import User from test.orm import _fixtures from .inheritance._poly_fixtures import _Polymorphic from .inheritance._poly_fixtures import Company @@ -1265,7 +1267,6 @@ class PickleTest(fixtures.MappedTest): @testing.fixture def user_address_fixture(self, registry): - from sqlalchemy.testing.pickleable import User, Address registry.map_imperatively( User, diff --git a/test/perf/compiled_extensions.py b/test/perf/compiled_extensions.py index 14b8ed693e..1f79d460be 100644 --- a/test/perf/compiled_extensions.py +++ b/test/perf/compiled_extensions.py @@ -6,6 +6,9 @@ from textwrap import wrap from timeit import timeit from types import MappingProxyType +from sqlalchemy import bindparam +from sqlalchemy import column + def test_case(fn): fn.__test_case__ = True @@ -1012,7 +1015,6 @@ class CacheAnonMap(Case): NUMBER = 1000000 def init_objects(self): - from sqlalchemy import column, bindparam self.object_1 = column("x") self.object_2 = bindparam("y") diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index 9947f34b6b..e05fafbdf4 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -87,6 +87,8 @@ from sqlalchemy.sql.elements import CompilerColumnElement from sqlalchemy.sql.elements import Grouping from sqlalchemy.sql.expression import ClauseElement from sqlalchemy.sql.expression import ClauseList +from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import TableClause from sqlalchemy.sql.selectable import LABEL_STYLE_NONE from sqlalchemy.sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL from sqlalchemy.testing import assert_raises @@ -6045,8 +6047,6 @@ class StringifySpecialTest(fixtures.TestBase): class KwargPropagationTest(fixtures.TestBase): @classmethod def setup_test_class(cls): - from sqlalchemy.sql.expression import ColumnClause, TableClause - class CatchCol(ColumnClause): pass diff --git a/test/sql/test_defaults.py b/test/sql/test_defaults.py index e52499ab48..1fe1b33230 100644 --- a/test/sql/test_defaults.py +++ b/test/sql/test_defaults.py @@ -13,6 +13,8 @@ from sqlalchemy import MetaData from sqlalchemy import Sequence from sqlalchemy import String from sqlalchemy import testing +from sqlalchemy.dialects.postgresql import ARRAY +from sqlalchemy.dialects.postgresql import array from sqlalchemy.schema import CreateTable from sqlalchemy.sql import literal_column from sqlalchemy.sql import select @@ -115,7 +117,6 @@ class DDLTest(fixtures.TestBase, AssertsCompiledSQL): ) def test_literal_binds_pgarray(self): - from sqlalchemy.dialects.postgresql import ARRAY, array m = MetaData() t = Table( diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index 1dafe3e8a5..f7acfb1aec 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -30,6 +30,8 @@ from sqlalchemy.dialects import mysql from sqlalchemy.dialects import oracle from sqlalchemy.dialects import postgresql from sqlalchemy.dialects import sqlite +from sqlalchemy.dialects.postgresql import ARRAY as PG_ARRAY +from sqlalchemy.dialects.postgresql import array from sqlalchemy.ext.compiler import compiles from sqlalchemy.sql import column from sqlalchemy.sql import functions @@ -976,7 +978,6 @@ class ReturnTypeTest(AssertsCompiledSQL, fixtures.TestBase): eq_(expr.type.dimensions, col.type.dimensions) def test_array_agg_array_literal_implicit_type(self): - from sqlalchemy.dialects.postgresql import array, ARRAY as PG_ARRAY expr = array([column("data", Integer), column("d2", Integer)]) diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 04a464bbb2..bd5920f136 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -38,6 +38,8 @@ from sqlalchemy import types as sqltypes from sqlalchemy import Unicode from sqlalchemy import UniqueConstraint from sqlalchemy.engine import default +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.ext.compiler import deregister from sqlalchemy.schema import AddConstraint from sqlalchemy.schema import CreateIndex from sqlalchemy.schema import DefaultClause @@ -3725,7 +3727,6 @@ class ConstraintTest(fixtures.TestBase): assert c in t.indexes def test_auto_append_lowercase_table(self): - from sqlalchemy import table, column t = table("t", column("a")) t2 = table("t2", column("a")) @@ -4319,8 +4320,6 @@ class ColumnDefinitionTest(AssertsCompiledSQL, fixtures.TestBase): ) def test_custom_create(self): - from sqlalchemy.ext.compiler import compiles, deregister - @compiles(schema.CreateColumn) def compile_(element, compiler, **kw): column = element.element diff --git a/tox.ini b/tox.ini index 0ea2908036..74ea3b960a 100644 --- a/tox.ini +++ b/tox.ini @@ -195,6 +195,7 @@ deps= flake8-future-annotations>=0.0.5 flake8-docstrings>=1.6.0 flake8-rst-docstrings + flake8-import-single==0.1.5 # flake8-rst-docstrings dependency, leaving it here # in case it requires a version pin pydocstyle -- 2.47.2