]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
ensure single import per line
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 28 Feb 2023 16:05:48 +0000 (11:05 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 28 Feb 2023 16:50:54 +0000 (11:50 -0500)
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

27 files changed:
.pre-commit-config.yaml
examples/custom_attributes/active_column_defaults.py
examples/custom_attributes/listen_for_events.py
examples/dogpile_caching/local_session_caching.py
examples/extending_query/filter_public.py
examples/extending_query/temporal_range.py
examples/vertical/dictlike-polymorphic.py
examples/vertical/dictlike.py
lib/sqlalchemy/orm/clsregistry.py
lib/sqlalchemy/orm/loading.py
lib/sqlalchemy/testing/fixtures.py
test/aaa_profiling/test_memusage.py
test/dialect/postgresql/test_types.py
test/ext/asyncio/test_engine_py3k.py
test/ext/test_hybrid.py
test/orm/declarative/test_basic.py
test/orm/test_cache_key.py
test/orm/test_deprecations.py
test/orm/test_inspect.py
test/orm/test_mapper.py
test/orm/test_options.py
test/perf/compiled_extensions.py
test/sql/test_compiler.py
test/sql/test_defaults.py
test/sql/test_functions.py
test/sql/test_metadata.py
tox.ini

index 2c77fada3e4feb02ac5ddfa3eb361fd53b5316ae..c734beb041c11ec0294c7d8f5909e779e067deda 100644 (file)
@@ -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
index dea79ee952fd1781a4f7c8a831555f8b8eda5974..d5322d331ba144d5e4f57580449c017b8c65b517 100644 (file)
@@ -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)
index b2d2b690b6e8b3844d01bc3de6a6c5db49e101a7..a94a3dab20ce6fcd856fb257907fd34706ec3460 100644 (file)
@@ -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)
index e603cef642d9be2a2dd1ae45a3488e979dfde498..1bcb3bb9a0380fe2193ddfe3adbfcb1c76faeb1b 100644 (file)
@@ -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
index a420e9da4abce2d27d74e390d6d3a33db599f486..1ac8115834324c596e8dec469514b074ca61f43e 100644 (file)
@@ -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):
index 01d0eadf87c1b4cd064ea085d4778238d132cc5a..dc6d8166f82c670742b57ad4970921f0c8ead079 100644 (file)
@@ -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):
index afd23c4e1c20f48017bfaeb2e37158073e72c011..a3873da2a3ba5260e8425c4d57791d8777ef57a4 100644 (file)
@@ -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()
 
index d0a952d7c7dec0dfb1dc3c0ad25c91ae24f8d0b0..dd19b9ee3187ca3aab01679533ba738280acd368 100644 (file)
@@ -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()
 
index e5fff4a5eed18a22806d3342532a1cb33bbcd83e..c4d6c29ebe71c7924ca41b898ad6a221cd13f2ea 100644 (file)
@@ -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}
index 7974d94c5ae7d99e6c5754f1a2c860bbcd9af65d..3d9ff7b0abd8d303d90307bed1107f8d148a355d 100644 (file)
@@ -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
 
index 3b58052b8d5931178b43036ed3f367a014d73982..a8bc6c50a78bd586f8d64bb693d77d0444e4993e 100644 (file)
@@ -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
 
index d30ccb3b8c0603477d95c359476dd105402dd285..9b2cb31befa7abc8ec004c42d859e0bdd14668a3 100644 (file)
@@ -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):
index 22993ae7bb5770dcb126bc7e74a7c00a6c060d59..2b15c7d735af2c9bffc3a5bc7c3cad701a800d64 100644 (file)
@@ -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)
index bce669e4f4595c66057d5aa3f1de7ad44899a7fc..9511fed74208c3281c52f546dd81a68f784a66c8 100644 (file)
@@ -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
 
index c0928506679593a69fab24681d39fed4b8e4374e..73967cdd0072e9eabcb074d4b0e46d0bf0032266 100644 (file)
@@ -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, '
index 7e8cd49f38b877ccb68f3b25ed9724108e968743..4aca4daa6d09ab5832c8c87ddf011d1d5df78c7e 100644 (file)
@@ -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
index 1a44b5d23b6411274698dda0365e1aaafcea7639..f1c3e6a54e0d5a1b6173b628350d795b5293a4eb 100644 (file)
@@ -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)
 
index a23bb7a24dd3382e35ab421bbaa40ab26b33a732..72256396410396b478df8fa691c9b15b5dae59dd 100644 (file)
@@ -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,
index 8644b36e5548437b816b60f08c620a88a555cdfa..6ae0d1d3ffdbab881ddaaed537b259caa9520546 100644 (file)
@@ -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()
index e645556b5e543936d1bf74ae1e7a48113183b70a..e89e26ec9e88e22821231011d1e8bd2e581a4ea5 100644 (file)
@@ -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"
 
index 1446565ac8a2a1bfadbdebe6c16e62b4ac8cd0dd..47ffedb07c6325d6cc0e639942716df13c6564c3 100644 (file)
@@ -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,
index 14b8ed693e68a8ac1546591893ac04618cea3de3..1f79d460be1f645705240000d852624d2a2af185 100644 (file)
@@ -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")
index 9947f34b6bfda8f3220067a94e228389a1fc0a63..e05fafbdf4c9ce6b42ac7ca8d167959704edc6b0 100644 (file)
@@ -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
 
index e52499ab48a468d95dab782d1d4c8df8ea419c99..1fe1b33230df1ac47204f468acf8e52347b56277 100644 (file)
@@ -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(
index 1dafe3e8a532f146eb50a46427a826ec65067dc5..f7acfb1aec30e6d4fdfd56fc1cacaa9a7456306e 100644 (file)
@@ -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)])
 
index 04a464bbb2690ebc863f2b2213510ddd956725b6..bd5920f136a2c2aea26af2e281b9e523bde16a7a 100644 (file)
@@ -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 0ea29080367219c7779ab9cc62d6e9ec135e2d4a..74ea3b960aa9441dffe332efd4a925dae81eeb72 100644 (file)
--- 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