diff --git a/pyproject.toml b/pyproject.toml index 6a85b91..feba7ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,9 @@ docs = [ "mkdocstrings", "mkdocstrings-python", ] -mysql = [ "mysqlclient" ] +mysql = [ + "mysqlclient", +] [project.urls] Homepage = "https://www.ensembl.org" diff --git a/src/ensembl/utils/__init__.py b/src/ensembl/utils/__init__.py index 4884b80..2ea7832 100644 --- a/src/ensembl/utils/__init__.py +++ b/src/ensembl/utils/__init__.py @@ -14,7 +14,7 @@ # limitations under the License. """Ensembl Python general-purpose utils library.""" -__version__ = "0.4.1" +__version__ = "0.4.2" __all__ = [ "StrPath", diff --git a/src/ensembl/utils/database/unittestdb.py b/src/ensembl/utils/database/unittestdb.py index 13ddb89..8ff32f3 100644 --- a/src/ensembl/utils/database/unittestdb.py +++ b/src/ensembl/utils/database/unittestdb.py @@ -52,6 +52,7 @@ from ensembl.utils import StrPath from ensembl.utils.database.dbconnection import DBConnection, StrURL + TEST_USERNAME = os.environ.get("USER", "pytestuser") diff --git a/tests/database/test_dbconnection.py b/tests/database/test_dbconnection.py index 13a3f06..f7746d6 100644 --- a/tests/database/test_dbconnection.py +++ b/tests/database/test_dbconnection.py @@ -18,28 +18,38 @@ import pytest from pytest import FixtureRequest, param -from sqlalchemy import text, VARCHAR -from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column +from sqlalchemy_utils import create_database, database_exists, drop_database +from sqlalchemy import Integer, text, Sequence, String +from sqlalchemy.orm import Mapped from sqlalchemy.engine.url import make_url from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.automap import automap_base -from sqlalchemy_utils import create_database, database_exists, drop_database -from ensembl.utils.database import DBConnection, UnitTestDB -from ensembl.utils.database.unittestdb import TEST_USERNAME +# Support both SQLAlchemy 1.4+ and 2.0+ +try: + from sqlalchemy.orm import DeclarativeBase, mapped_column + class MockBase(DeclarativeBase): + """Mock Base for testing.""" -class MockBase(DeclarativeBase): - """Mock Base for testing.""" +except ImportError: + from sqlalchemy.orm import declarative_base + from sqlalchemy.schema import Column as mapped_column # type: ignore + + MockBase = declarative_base() # type: ignore + +from ensembl.utils.database import DBConnection, UnitTestDB +from ensembl.utils.database.unittestdb import TEST_USERNAME class MockTable(MockBase): """Mock Table for testing.""" __tablename__ = "mock_table" - id: Mapped[int] = mapped_column(primary_key=True) - grp: Mapped[str] = mapped_column(VARCHAR(30)) - value: Mapped[int] + + id: Mapped[int] = mapped_column(Integer, Sequence("id_seq"), primary_key=True) + grp: Mapped[str] = mapped_column(String(30)) + value: Mapped[int] = mapped_column(Integer) mock_metadata = MockBase.metadata @@ -93,7 +103,7 @@ def test_db_name(self) -> None: def test_url(self) -> None: """Tests `DBConnection.url` property.""" expected_url = make_url(self.server).set(database=self.dbc.db_name) - assert self.dbc.url == expected_url.render_as_string(hide_password=False) + assert self.dbc.url == expected_url.render_as_string(hide_password=False) # pylint: disable=no-member @pytest.mark.dependency(depends=["test_init"], scope="class") def test_host(self) -> None: @@ -230,7 +240,7 @@ def test_test_session_scope(self) -> None: self.dbc.dialect == "mysql" and self.dbc.tables["gibberish"].dialect_options["mysql"]["engine"] == "MyISAM" ): - assert len(results.all()) == 2, f"SQLite/MyISAM: 2 rows permanently added to ID {identifier}" + assert len(results.all()) == 2, f"MyISAM: 2 rows permanently added to ID {identifier}" else: assert ( not results.fetchall() diff --git a/tests/database/test_unittestdb.py b/tests/database/test_unittestdb.py index e75b434..e527690 100644 --- a/tests/database/test_unittestdb.py +++ b/tests/database/test_unittestdb.py @@ -20,25 +20,35 @@ import pytest from pytest import FixtureRequest, param, raises -from sqlalchemy import text, VARCHAR -from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column -from sqlalchemy.schema import MetaData from sqlalchemy_utils.functions import database_exists +from sqlalchemy import Integer, text, Sequence, String +from sqlalchemy.orm import Mapped +from sqlalchemy.schema import MetaData -from ensembl.utils.database import UnitTestDB +# Support both SQLAlchemy 1.4+ and 2.0+ +try: + from sqlalchemy.orm import DeclarativeBase, mapped_column + class MockBase(DeclarativeBase): + """Mock Base for testing.""" -class MockBase(DeclarativeBase): - """Mock Base for testing.""" +except ImportError: + from sqlalchemy.orm import declarative_base + from sqlalchemy.schema import Column as mapped_column # type: ignore + + MockBase = declarative_base() # type: ignore + +from ensembl.utils.database import UnitTestDB class MockTable(MockBase): """Mock Table for testing.""" __tablename__ = "mock_table" - id: Mapped[int] = mapped_column(primary_key=True) - grp: Mapped[str] = mapped_column(VARCHAR(30)) - value: Mapped[int] + + id: Mapped[int] = mapped_column(Integer, Sequence("id_seq"), primary_key=True) + grp: Mapped[str] = mapped_column(String(30)) + value: Mapped[int] = mapped_column(Integer) mock_metadata = MockBase.metadata diff --git a/tests/database/test_unittestdb/mock_db/table.sql b/tests/database/test_unittestdb/mock_db/table.sql index 7b1e856..738e7ab 100644 --- a/tests/database/test_unittestdb/mock_db/table.sql +++ b/tests/database/test_unittestdb/mock_db/table.sql @@ -1,7 +1,7 @@ -CREATE TABLE `gibberish` ( - `id` INTEGER NOT NULL, - `grp` VARCHAR(20) DEFAULT "", - `value` INT DEFAULT NULL, - PRIMARY KEY (`id`, `grp`) +CREATE TABLE gibberish ( + id INTEGER NOT NULL, + grp VARCHAR(20) DEFAULT '', + value INT DEFAULT NULL, + PRIMARY KEY (id, grp) ); -CREATE INDEX `id_idx` ON `gibberish` (`id`); +CREATE INDEX id_idx ON gibberish (id);