Skip to content

Commit 6b239b3

Browse files
committed
feat: tests, lints, CI/CD and documentation fixes
1 parent 5e3b620 commit 6b239b3

11 files changed

Lines changed: 96 additions & 342 deletions

File tree

.github/workflows/checks.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ jobs:
1212
strategy:
1313
matrix:
1414
python-version:
15-
- "3.10"
1615
- "3.11"
1716
- "3.12"
1817
- "3.13"
@@ -40,7 +39,6 @@ jobs:
4039
strategy:
4140
matrix:
4241
python-version:
43-
- "3.10"
4442
- "3.11"
4543
- "3.12"
4644
- "3.13"

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ maintainers = [
99
]
1010
description = "Table column annotations for SQLAlchemy"
1111
readme = "README.md"
12-
requires-python = ">=3.10"
12+
requires-python = ">=3.11"
1313
license = "MIT"
1414
license-files = ["LICENSE"]
1515
classifiers = [
@@ -18,7 +18,6 @@ classifiers = [
1818
"Programming Language :: Python :: Implementation :: CPython",
1919
"Programming Language :: Python :: 3",
2020
"Programming Language :: Python :: 3 :: Only",
21-
"Programming Language :: Python :: 3.10",
2221
"Programming Language :: Python :: 3.11",
2322
"Programming Language :: Python :: 3.12",
2423
"Programming Language :: Python :: 3.13",

tests/annotations.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/conftest.py

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +0,0 @@
1-
from typing import Any, TypeAlias
2-
3-
import pytest
4-
from sqlalchemy.orm import MappedColumn
5-
6-
from tests.annotations import CheckAnnotationFn
7-
8-
FIELDS_TO_CHECK = (
9-
'index',
10-
'primary_key',
11-
'unique',
12-
# 'default',
13-
'doc',
14-
'key',
15-
'info',
16-
'nullable',
17-
'onupdate',
18-
'server_default',
19-
'server_onupdate',
20-
# 'type',
21-
'system',
22-
'name',
23-
'autoincrement',
24-
'comment',
25-
'_insert_sentinel',
26-
)
27-
28-
29-
@pytest.fixture(scope='session')
30-
def check_annotation() -> CheckAnnotationFn:
31-
"""Return function that checks annotation."""
32-
33-
def _check_annotation(
34-
column: TypeAlias,
35-
expected_type: type,
36-
expected_column: MappedColumn[Any],
37-
) -> None:
38-
"""Check annotation."""
39-
origin = column.__origin__
40-
metadata = column.__metadata__
41-
42-
assert origin == expected_type
43-
assert len(metadata) == 1
44-
45-
# assert repr(metadata[0].column) == repr(expected_column.column)
46-
# meta_col = metadata[0].column
47-
print()
48-
print()
49-
print(type(expected_column))
50-
print(type(expected_column.column))
51-
# print(dict(expected_column.column))
52-
# print(repr(metadata[0]))
53-
# print(repr(expected_column))
54-
# print()
55-
# print(repr(metadata[0].column))
56-
# print(expected_column.column)
57-
# print(repr(expected_column.column.column))
58-
# e = expected_column.column.__clause_element__()
59-
# print(e)
60-
# print(type(e))
61-
# print(repr(e))
62-
# print()
63-
# for field in FIELDS_TO_CHECK:
64-
# print(field)
65-
# assert getattr(metadata[0].column, field) == getattr(expected_column.column, field)
66-
# print()
67-
# # assert getattr(meta_col, slot) == getattr(expected_column, slot)
68-
69-
return _check_annotation

tests/db.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from sqlalchemy import create_engine
2+
from sqlalchemy.orm import declarative_base, declared_attr
3+
4+
5+
class DeclarativeBase:
6+
"""Base class for models."""
7+
8+
@declared_attr
9+
def __tablename__(cls) -> str: # noqa: N805
10+
"""Return table name generated out of class name."""
11+
return cls.__name__.lower()
12+
13+
14+
Base = declarative_base(cls=DeclarativeBase)
15+
engine = create_engine(
16+
'sqlite:///:memory:',
17+
echo=False,
18+
)

tests/test_booleans.py

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,55 @@
1-
from typing import TypeAlias
2-
3-
import pytest
4-
from sqlalchemy import Boolean
5-
from sqlalchemy.orm import MappedColumn, mapped_column
6-
7-
from sqlalchemy_annotations import BooleanColumn, BooleanDefaultFalseColumn, BooleanDefaultTrueColumn
8-
from tests.annotations import CheckAnnotationFn
9-
10-
11-
@pytest.mark.parametrize(
12-
('column', 'mapped'),
13-
[
14-
(BooleanDefaultTrueColumn, mapped_column(Boolean(), default=True)),
15-
(BooleanDefaultFalseColumn, mapped_column(Boolean(), default=False)),
16-
(BooleanColumn, mapped_column(Boolean())),
17-
],
18-
)
19-
def test_bool(check_annotation: CheckAnnotationFn, column: TypeAlias, mapped: MappedColumn[bool]) -> None:
20-
"""Check boolean columns."""
21-
check_annotation(column, bool, mapped)
1+
from sqlalchemy.orm import Mapped
2+
from sqlalchemy.sql.ddl import CreateTable
3+
4+
from sqlalchemy_annotations import BooleanColumn, BooleanDefaultFalseColumn, BooleanDefaultTrueColumn, SerialPKColumn
5+
from tests.db import Base, engine
6+
7+
8+
def clean_multiline(sql: str) -> str:
9+
"""Strip each line of a multiline string."""
10+
lines = (line.strip() for line in sql.split('\n'))
11+
return '\n'.join(line for line in lines if line != '')
12+
13+
14+
def test_bool_not_null() -> None:
15+
"""Check boolean columns not null."""
16+
17+
class B1(Base):
18+
id: Mapped[SerialPKColumn]
19+
bool_true: Mapped[BooleanDefaultTrueColumn]
20+
bool_false: Mapped[BooleanDefaultFalseColumn]
21+
bool_no_default: Mapped[BooleanColumn]
22+
23+
sql = CreateTable(B1.__table__).compile(engine)
24+
expected = [
25+
'CREATE TABLE b1 (',
26+
'id INTEGER NOT NULL,',
27+
'bool_true BOOLEAN NOT NULL,',
28+
'bool_false BOOLEAN NOT NULL,',
29+
'bool_no_default BOOLEAN NOT NULL,',
30+
'PRIMARY KEY (id)',
31+
')',
32+
]
33+
assert clean_multiline(str(sql)) == '\n'.join(expected)
34+
35+
36+
def test_bool_with_null() -> None:
37+
"""Check boolean columns with nulls."""
38+
39+
class B2(Base):
40+
id: Mapped[SerialPKColumn]
41+
bool_true: Mapped[BooleanDefaultTrueColumn | None]
42+
bool_false: Mapped[BooleanDefaultFalseColumn | None]
43+
bool_no_default: Mapped[BooleanColumn | None]
44+
45+
sql = CreateTable(B2.__table__).compile(engine)
46+
expected = [
47+
'CREATE TABLE b2 (',
48+
'id INTEGER NOT NULL,',
49+
'bool_true BOOLEAN,',
50+
'bool_false BOOLEAN,',
51+
'bool_no_default BOOLEAN,',
52+
'PRIMARY KEY (id)',
53+
')',
54+
]
55+
assert clean_multiline(str(sql)) == '\n'.join(expected)

tests/test_dates.py

Lines changed: 0 additions & 52 deletions
This file was deleted.

tests/test_numbers.py

Lines changed: 0 additions & 35 deletions
This file was deleted.

tests/test_strings.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

tests/test_uuids.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)