Skip to content

Commit 49bfbf4

Browse files
authored
feat: support psycopg (#425)
1 parent 0364ae3 commit 49bfbf4

File tree

10 files changed

+218
-26
lines changed

10 files changed

+218
-26
lines changed

.github/workflows/ci.yml

+9-2
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,21 @@ jobs:
8989
POSTGRES_PORT: 5432
9090
run: poetry run make _testall
9191
- name: Verify aiomysql support
92+
# Only check the latest version of tortoise
9293
if: matrix.tortoise-orm == 'tortoise024'
9394
run: |
9495
poetry run pip uninstall -y asyncmy
95-
poetry run pip install aiomysql
9696
poetry run make test_mysql
97-
poetry run pip uninstall -y aiomysql
9897
poetry run pip install asyncmy
9998
env:
10099
MYSQL_PASS: root
101100
MYSQL_HOST: 127.0.0.1
102101
MYSQL_PORT: 3306
102+
- name: Verify psycopg support
103+
# Only check the latest version of tortoise
104+
if: matrix.tortoise-orm == 'tortoise024'
105+
run: poetry run make test_psycopg
106+
env:
107+
POSTGRES_PASS: 123456
108+
POSTGRES_HOST: 127.0.0.1
109+
POSTGRES_PORT: 5432

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
### [0.8.2]**(Unreleased)**
66

77
#### Added
8+
- feat: support psycopg. ([#425])
9+
- Support run `poetry add aerich` in project that inited by poetry v2. ([#424])
810
- feat: support command `python -m aerich`. ([#417])
911
- feat: add --fake to upgrade/downgrade. ([#398])
1012
- Support ignore table by settings `managed=False` in `Meta` class. ([#397])
11-
- Support run `poetry add aerich` in project that inited by poetry v2. ([#424])
1213

1314
#### Fixed
1415
- fix: aerich migrate raises tortoise.exceptions.FieldError when `index.INDEX_TYPE` is not empty. ([#415])
@@ -27,6 +28,7 @@
2728
[#415]: https://github.com/tortoise/aerich/pull/415
2829
[#417]: https://github.com/tortoise/aerich/pull/417
2930
[#424]: https://github.com/tortoise/aerich/pull/424
31+
[#425]: https://github.com/tortoise/aerich/pull/425
3032

3133
### [0.8.1](../../releases/tag/v0.8.1) - 2024-12-27
3234

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ test_mysql:
3737
test_postgres:
3838
$(py_warn) TEST_DB="postgres://postgres:$(POSTGRES_PASS)@$(POSTGRES_HOST):$(POSTGRES_PORT)/test_\{\}" pytest -vv -s
3939

40+
test_psycopg:
41+
$(py_warn) TEST_DB="psycopg://postgres:$(POSTGRES_PASS)@$(POSTGRES_HOST):$(POSTGRES_PORT)/test_\{\}" pytest -vv -s
42+
4043
_testall: test_sqlite test_postgres test_mysql
4144
testall: deps _testall
4245

aerich/coder.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,25 @@ def default(self, obj) -> Any:
2222
return super().default(obj)
2323

2424

25+
def object_hook(obj) -> Any:
26+
if (type_ := obj.get("type")) and type_ == "index" and (val := obj.get("val")):
27+
return pickle.loads(base64.b64decode(val)) # nosec: B301
28+
return obj
29+
30+
2531
def load_index(obj: dict) -> Index:
2632
"""Convert a dict that generated by `Index.decribe()` to a Index instance"""
27-
index = Index(fields=obj["fields"] or obj["expressions"], name=obj.get("name"))
33+
try:
34+
index = Index(fields=obj["fields"] or obj["expressions"], name=obj.get("name"))
35+
except KeyError:
36+
return object_hook(obj)
2837
if extra := obj.get("extra"):
2938
index.extra = extra
3039
if idx_type := obj.get("type"):
3140
index.INDEX_TYPE = idx_type
3241
return index
3342

3443

35-
def object_hook(obj) -> Any:
36-
if (type_ := obj.get("type")) and type_ == "index" and (val := obj.get("val")):
37-
return pickle.loads(base64.b64decode(val)) # nosec: B301
38-
return obj
39-
40-
4144
def encoder(obj: dict) -> str:
4245
return json.dumps(obj, cls=JsonEncoder)
4346

aerich/ddl/postgres/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
from typing import cast
44

55
from tortoise import Model
6-
from tortoise.backends.asyncpg.schema_generator import AsyncpgSchemaGenerator
6+
from tortoise.backends.base_postgres.schema_generator import BasePostgresSchemaGenerator
77

88
from aerich.ddl import BaseDDL
99

1010

1111
class PostgresDDL(BaseDDL):
12-
schema_generator_cls = AsyncpgSchemaGenerator
13-
DIALECT = AsyncpgSchemaGenerator.DIALECT
12+
schema_generator_cls = BasePostgresSchemaGenerator
13+
DIALECT = BasePostgresSchemaGenerator.DIALECT
1414
_ADD_INDEX_TEMPLATE = 'CREATE {unique}INDEX IF NOT EXISTS "{index_name}" ON "{table_name}" {index_type}({column_names}){extra}'
1515
_DROP_INDEX_TEMPLATE = 'DROP INDEX IF EXISTS "{index_name}"'
1616
_ALTER_NULL_TEMPLATE = 'ALTER TABLE "{table_name}" ALTER COLUMN "{column}" {set_drop} NOT NULL'

aerich/inspectdb/postgres.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import re
34
from typing import TYPE_CHECKING
45

56
from aerich.inspectdb import Column, FieldMapDict, Inspect
@@ -60,6 +61,8 @@ async def get_columns(self, table: str) -> list[Column]:
6061
where c.table_catalog = $1
6162
and c.table_name = $2
6263
and c.table_schema = $3""" # nosec:B608
64+
if "psycopg" in str(type(self.conn)).lower():
65+
sql = re.sub(r"\$[123]", "%s", sql)
6366
ret = await self.conn.execute_query_dict(sql, [self.database, table, self.schema])
6467
for row in ret:
6568
columns.append(

conftest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010
from tortoise import Tortoise, expand_db_url
11-
from tortoise.backends.asyncpg.schema_generator import AsyncpgSchemaGenerator
11+
from tortoise.backends.base_postgres.schema_generator import BasePostgresSchemaGenerator
1212
from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator
1313
from tortoise.backends.sqlite.schema_generator import SqliteSchemaGenerator
1414
from tortoise.contrib.test import MEMORY_SQLITE
@@ -64,7 +64,7 @@ async def initialize_tests(event_loop, request) -> None:
6464
Migrate.ddl = MysqlDDL(client)
6565
elif client.schema_generator is SqliteSchemaGenerator:
6666
Migrate.ddl = SqliteDDL(client)
67-
elif client.schema_generator is AsyncpgSchemaGenerator:
67+
elif issubclass(client.schema_generator, BasePostgresSchemaGenerator):
6868
Migrate.ddl = PostgresDDL(client)
6969
Migrate.dialect = Migrate.ddl.DIALECT
7070
request.addfinalizer(lambda: event_loop.run_until_complete(Tortoise._drop_databases()))

0 commit comments

Comments
 (0)