From 0e518d9ba79221c5a18d843ad544aae6035504f3 Mon Sep 17 00:00:00 2001 From: Markus Beckschulte Date: Wed, 22 Jan 2025 12:01:41 +0100 Subject: [PATCH 1/3] fix `_get_dialects` --- tests/test_early_init.py | 10 ++++- tests/utils/test_describe_model.py | 65 ++++++++++++++++++++++++------ tortoise/fields/base.py | 24 +++++++---- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/tests/test_early_init.py b/tests/test_early_init.py index 831bc032e..87dbd4015 100644 --- a/tests/test_early_init.py +++ b/tests/test_early_init.py @@ -109,7 +109,10 @@ async def test_early_init(self): "description": "The Event NAME", "docstring": "The Event NAME\nIt's pretty important", "constraints": {"max_length": 255}, - "db_field_types": {"": "VARCHAR(255)"}, + "db_field_types": { + "": "VARCHAR(255)", + "oracle": "NVARCHAR2(255)", + }, }, { "name": "created_at", @@ -252,7 +255,10 @@ async def test_early_init(self): "name": "name", "field_type": "CharField", "db_column": "name", - "db_field_types": {"": "VARCHAR(255)"}, + "db_field_types": { + "": "VARCHAR(255)", + "oracle": "NVARCHAR2(255)", + }, "python_type": "str", "generated": False, "nullable": False, diff --git a/tests/utils/test_describe_model.py b/tests/utils/test_describe_model.py index d1be42986..9cd6539c7 100644 --- a/tests/utils/test_describe_model.py +++ b/tests/utils/test_describe_model.py @@ -171,7 +171,10 @@ def test_describe_model_straight(self): "name": "chars", "field_type": "CharField", "db_column": "chars", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": False, @@ -186,7 +189,10 @@ def test_describe_model_straight(self): "name": "blip", "field_type": "CharField", "db_column": "blip", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": False, @@ -201,7 +207,10 @@ def test_describe_model_straight(self): "name": "nullable", "field_type": "CharField", "db_column": "nullable", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": True, @@ -391,7 +400,10 @@ def test_describe_model_straight_native(self): "name": "chars", "field_type": fields.CharField, "db_column": "chars", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": False, @@ -406,7 +418,10 @@ def test_describe_model_straight_native(self): "name": "blip", "field_type": fields.CharField, "db_column": "blip", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": False, @@ -421,7 +436,10 @@ def test_describe_model_straight_native(self): "name": "nullable", "field_type": fields.CharField, "db_column": "nullable", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": True, @@ -611,7 +629,10 @@ def test_describe_model_source(self): "name": "chars", "field_type": "CharField", "db_column": "some_chars_table", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": False, @@ -626,7 +647,10 @@ def test_describe_model_source(self): "name": "blip", "field_type": "CharField", "db_column": "da_blip", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": False, @@ -641,7 +665,10 @@ def test_describe_model_source(self): "name": "nullable", "field_type": "CharField", "db_column": "some_nullable", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": "str", "generated": False, "nullable": True, @@ -831,7 +858,10 @@ def test_describe_model_source_native(self): "name": "chars", "field_type": fields.CharField, "db_column": "some_chars_table", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": False, @@ -846,7 +876,10 @@ def test_describe_model_source_native(self): "name": "blip", "field_type": fields.CharField, "db_column": "da_blip", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": False, @@ -861,7 +894,10 @@ def test_describe_model_source_native(self): "name": "nullable", "field_type": fields.CharField, "db_column": "some_nullable", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "python_type": str, "generated": False, "nullable": True, @@ -1180,7 +1216,10 @@ def test_describe_model_uuidpk_relatednull(self): "data_fields": [ { "db_column": "name", - "db_field_types": {"": "VARCHAR(50)"}, + "db_field_types": { + "": "VARCHAR(50)", + "oracle": "NVARCHAR2(50)", + }, "default": None, "description": None, "docstring": None, diff --git a/tortoise/fields/base.py b/tortoise/fields/base.py index 68f66781c..b134c74a1 100644 --- a/tortoise/fields/base.py +++ b/tortoise/fields/base.py @@ -1,3 +1,4 @@ +import itertools import sys import warnings from collections.abc import Callable @@ -297,16 +298,25 @@ def constraints(self) -> dict: def _get_dialects(self) -> dict[str, dict]: ret = {} for dialect in [key for key in dir(self) if key.startswith("_db_")]: - item = {} cls = getattr(self, dialect) try: - cls = cls(self) + cls_instance = cls(self) + d = itertools.chain( + # dialect class attributes: + cls.__dict__.items(), + # dialect instance attributes: + cls_instance.__dict__.items(), + # dialect instance properties: + ( + (prop, getattr(cls_instance, prop)) + for prop in ( + func for func in dir(cls) if isinstance(getattr(cls, func), property) + ) + ), + ) except TypeError: - pass - for key, val in cls.__dict__.items(): - if not key.startswith("_"): - item[key] = val - ret[dialect[4:]] = item + d = cls.__dict__.items() + ret[dialect[4:]] = {key: val for key, val in d if not key.startswith("_")} return ret def get_db_field_types(self) -> Optional[dict[str, str]]: From f50b40e3f57e09c225ffcc2eea361bede093915b Mon Sep 17 00:00:00 2001 From: Markus Beckschulte Date: Wed, 22 Jan 2025 12:14:59 +0100 Subject: [PATCH 2/3] Update CHANGELOG.rst --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4226e6ac9..a361bde98 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,7 @@ Fixed ^^^^^ - Rename pypika to pypika_tortoise for fixing package name conflict (#1829) - Concurrent connection pool initialization (#1825) +- `_get_dialects`: support properties (#1859) Changed ^^^^^^^ From 6ff7cee4bbf0dbae1c898f74b184f850e886c0e4 Mon Sep 17 00:00:00 2001 From: Waket Zheng Date: Thu, 23 Jan 2025 15:17:45 +0800 Subject: [PATCH 3/3] refactor: update get dialects --- tortoise/fields/base.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tortoise/fields/base.py b/tortoise/fields/base.py index b134c74a1..6912ea4cd 100644 --- a/tortoise/fields/base.py +++ b/tortoise/fields/base.py @@ -1,4 +1,3 @@ -import itertools import sys import warnings from collections.abc import Callable @@ -297,26 +296,25 @@ def constraints(self) -> dict: def _get_dialects(self) -> dict[str, dict]: ret = {} - for dialect in [key for key in dir(self) if key.startswith("_db_")]: + for dialect in dir(self): + if not dialect.startswith("_db_"): + continue cls = getattr(self, dialect) + d = cls.__dict__ try: - cls_instance = cls(self) - d = itertools.chain( - # dialect class attributes: - cls.__dict__.items(), - # dialect instance attributes: - cls_instance.__dict__.items(), - # dialect instance properties: - ( - (prop, getattr(cls_instance, prop)) - for prop in ( - func for func in dir(cls) if isinstance(getattr(cls, func), property) - ) - ), - ) + obj = cls(self) except TypeError: - d = cls.__dict__.items() - ret[dialect[4:]] = {key: val for key, val in d if not key.startswith("_")} + pass + else: + props = { + prop: getattr(obj, prop) + for prop in dir(cls) + if isinstance(getattr(cls, prop), property) + } + d = {**d, **props} + + ret[dialect[4:]] = {k: v for k, v in d.items() if not k.startswith("_")} + return ret def get_db_field_types(self) -> Optional[dict[str, str]]: