remove .vscode settings, re-dump orjson choices to fix choices, move mypy config into pyproject.toml
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"python.linting.flake8Enabled": true,
|
|
||||||
"python.linting.enabled": true,
|
|
||||||
"python.formatting.provider": "black"
|
|
||||||
}
|
|
||||||
10
mypy.ini
10
mypy.ini
@ -1,10 +0,0 @@
|
|||||||
[mypy]
|
|
||||||
python_version = 3.8
|
|
||||||
plugins = pydantic.mypy
|
|
||||||
|
|
||||||
[mypy-sqlalchemy.*]
|
|
||||||
ignore_missing_imports = True
|
|
||||||
|
|
||||||
[mypy-tests.test_model_definition.*]
|
|
||||||
ignore_errors = True
|
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ from typing import Any, Callable, Optional, TYPE_CHECKING, Type, Union
|
|||||||
|
|
||||||
import sqlalchemy.types as types
|
import sqlalchemy.types as types
|
||||||
from pydantic.utils import lenient_issubclass
|
from pydantic.utils import lenient_issubclass
|
||||||
from sqlalchemy.engine.default import DefaultDialect
|
from sqlalchemy.engine import Dialect
|
||||||
|
|
||||||
import ormar # noqa: I100, I202
|
import ormar # noqa: I100, I202
|
||||||
from ormar import ModelDefinitionError # noqa: I202, I100
|
from ormar import ModelDefinitionError # noqa: I202, I100
|
||||||
@ -146,14 +146,14 @@ class EncryptedString(types.TypeDecorator):
|
|||||||
def __repr__(self) -> str: # pragma: nocover
|
def __repr__(self) -> str: # pragma: nocover
|
||||||
return "TEXT()"
|
return "TEXT()"
|
||||||
|
|
||||||
def load_dialect_impl(self, dialect: DefaultDialect) -> Any:
|
def load_dialect_impl(self, dialect: Dialect) -> Any:
|
||||||
return dialect.type_descriptor(types.TEXT())
|
return dialect.type_descriptor(types.TEXT())
|
||||||
|
|
||||||
def _refresh(self) -> None:
|
def _refresh(self) -> None:
|
||||||
key = self._key() if callable(self._key) else self._key
|
key = self._key() if callable(self._key) else self._key
|
||||||
self.backend._refresh(key)
|
self.backend._refresh(key)
|
||||||
|
|
||||||
def process_bind_param(self, value: Any, dialect: DefaultDialect) -> Optional[str]:
|
def process_bind_param(self, value: Any, dialect: Dialect) -> Optional[str]:
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
self._refresh()
|
self._refresh()
|
||||||
@ -167,7 +167,7 @@ class EncryptedString(types.TypeDecorator):
|
|||||||
encrypted_value = self.backend.encrypt(value)
|
encrypted_value = self.backend.encrypt(value)
|
||||||
return encrypted_value
|
return encrypted_value
|
||||||
|
|
||||||
def process_result_value(self, value: Any, dialect: DefaultDialect) -> Any:
|
def process_result_value(self, value: Any, dialect: Dialect) -> Any:
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
self._refresh()
|
self._refresh()
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import uuid
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from sqlalchemy import CHAR
|
from sqlalchemy import CHAR
|
||||||
from sqlalchemy.engine.default import DefaultDialect
|
from sqlalchemy.engine import Dialect
|
||||||
from sqlalchemy.types import TypeDecorator
|
from sqlalchemy.types import TypeDecorator
|
||||||
|
|
||||||
|
|
||||||
@ -25,22 +25,20 @@ class UUID(TypeDecorator):
|
|||||||
return "CHAR(36)"
|
return "CHAR(36)"
|
||||||
return "CHAR(32)"
|
return "CHAR(32)"
|
||||||
|
|
||||||
def load_dialect_impl(self, dialect: DefaultDialect) -> Any:
|
def load_dialect_impl(self, dialect: Dialect) -> Any:
|
||||||
return (
|
return (
|
||||||
dialect.type_descriptor(CHAR(36))
|
dialect.type_descriptor(CHAR(36))
|
||||||
if self.uuid_format == "string"
|
if self.uuid_format == "string"
|
||||||
else dialect.type_descriptor(CHAR(32))
|
else dialect.type_descriptor(CHAR(32))
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_bind_param(
|
def process_bind_param(self, value: uuid.UUID, dialect: Dialect) -> Optional[str]:
|
||||||
self, value: uuid.UUID, dialect: DefaultDialect
|
|
||||||
) -> Optional[str]:
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return str(value) if self.uuid_format == "string" else "%.32x" % value.int
|
return str(value) if self.uuid_format == "string" else "%.32x" % value.int
|
||||||
|
|
||||||
def process_result_value(
|
def process_result_value(
|
||||||
self, value: Optional[str], dialect: DefaultDialect
|
self, value: Optional[str], dialect: Dialect
|
||||||
) -> Optional[uuid.UUID]:
|
) -> Optional[uuid.UUID]:
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
|
|||||||
@ -64,8 +64,11 @@ def convert_choices_if_needed( # noqa: CCR001
|
|||||||
value = value.isoformat() if not isinstance(value, str) else value
|
value = value.isoformat() if not isinstance(value, str) else value
|
||||||
choices = [o.isoformat() for o in field.choices]
|
choices = [o.isoformat() for o in field.choices]
|
||||||
elif field.__type__ == pydantic.Json:
|
elif field.__type__ == pydantic.Json:
|
||||||
value = json.dumps(value) if not isinstance(value, str) else value
|
value = (
|
||||||
|
json.dumps(value) if not isinstance(value, str) else re_dump_value(value)
|
||||||
|
)
|
||||||
value = value.decode("utf-8") if isinstance(value, bytes) else value
|
value = value.decode("utf-8") if isinstance(value, bytes) else value
|
||||||
|
choices = [re_dump_value(x) for x in field.choices]
|
||||||
elif field.__type__ == uuid.UUID:
|
elif field.__type__ == uuid.UUID:
|
||||||
value = str(value) if not isinstance(value, str) else value
|
value = str(value) if not isinstance(value, str) else value
|
||||||
choices = [str(o) for o in field.choices]
|
choices = [str(o) for o in field.choices]
|
||||||
@ -86,6 +89,21 @@ def convert_choices_if_needed( # noqa: CCR001
|
|||||||
return value, choices
|
return value, choices
|
||||||
|
|
||||||
|
|
||||||
|
def re_dump_value(value: str) -> str:
|
||||||
|
"""
|
||||||
|
Rw-dumps choices due to different string representation in orjson and json
|
||||||
|
:param value: string to re-dump
|
||||||
|
:type value: str
|
||||||
|
:return: re-dumped choices
|
||||||
|
:rtype: List[str]
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result: Union[str, bytes] = json.dumps(json.loads(value))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
result = value
|
||||||
|
return result.decode("utf-8") if isinstance(result, bytes) else result
|
||||||
|
|
||||||
|
|
||||||
def validate_choices(field: "BaseField", value: Any) -> None:
|
def validate_choices(field: "BaseField", value: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Validates if given value is in provided choices.
|
Validates if given value is in provided choices.
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Callable, Collection, Dict, List, Optional, Set, TYPE_CHECKING, cast
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Collection,
|
||||||
|
Dict,
|
||||||
|
List,
|
||||||
|
Optional,
|
||||||
|
Set,
|
||||||
|
TYPE_CHECKING,
|
||||||
|
cast,
|
||||||
|
)
|
||||||
|
|
||||||
import ormar
|
import ormar
|
||||||
from ormar.exceptions import ModelPersistenceError
|
from ormar.exceptions import ModelPersistenceError
|
||||||
@ -93,7 +103,7 @@ class SavePrepareMixin(RelationMixin, AliasMixin):
|
|||||||
if field.__type__ == uuid.UUID and name in model_dict:
|
if field.__type__ == uuid.UUID and name in model_dict:
|
||||||
parsers = {"string": lambda x: str(x), "hex": lambda x: "%.32x" % x.int}
|
parsers = {"string": lambda x: str(x), "hex": lambda x: "%.32x" % x.int}
|
||||||
uuid_format = field.column_type.uuid_format
|
uuid_format = field.column_type.uuid_format
|
||||||
parser = parsers.get(uuid_format, lambda x: x)
|
parser: Callable[..., Any] = parsers.get(uuid_format, lambda x: x)
|
||||||
model_dict[name] = parser(model_dict[name])
|
model_dict[name] = parser(model_dict[name])
|
||||||
return model_dict
|
return model_dict
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, Union, cast
|
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, Union, cast
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from sqlalchemy.engine.result import ResultProxy
|
from sqlalchemy.engine.result import ResultProxy # type: ignore
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
from sqlalchemy.engine.result import Row as ResultProxy # type: ignore
|
from sqlalchemy.engine.result import Row as ResultProxy # type: ignore
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import List, Optional, TYPE_CHECKING, Tuple, Type
|
from typing import List, Optional, TYPE_CHECKING, Tuple, Type, Union
|
||||||
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from sqlalchemy import text
|
from sqlalchemy import Table, text
|
||||||
|
from sqlalchemy.sql import Join
|
||||||
|
|
||||||
import ormar # noqa I100
|
import ormar # noqa I100
|
||||||
from ormar.models.helpers.models import group_related_list
|
from ormar.models.helpers.models import group_related_list
|
||||||
@ -41,7 +42,7 @@ class Query:
|
|||||||
|
|
||||||
self.used_aliases: List[str] = []
|
self.used_aliases: List[str] = []
|
||||||
|
|
||||||
self.select_from: List[str] = []
|
self.select_from: Union[Join, Table, List[str]] = []
|
||||||
self.columns = [sqlalchemy.Column]
|
self.columns = [sqlalchemy.Column]
|
||||||
self.order_columns = order_bys
|
self.order_columns = order_bys
|
||||||
self.sorted_orders: OrderedDict[OrderAction, text] = OrderedDict()
|
self.sorted_orders: OrderedDict[OrderAction, text] = OrderedDict()
|
||||||
|
|||||||
@ -130,3 +130,20 @@ dev = [
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
# TODO: Enable mypy plugin after pydantic release supporting toml file
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = "tests.*"
|
||||||
|
disallow_untyped_calls = false
|
||||||
|
disallow_untyped_defs = false
|
||||||
|
disallow_incomplete_defs = false
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = ["sqlalchemy.*", "asyncpg"]
|
||||||
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import uuid
|
import uuid
|
||||||
from base64 import b64encode
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
import databases
|
import databases
|
||||||
|
|||||||
@ -131,10 +131,6 @@ def test_all_endpoints():
|
|||||||
assert items[0].name == "New name"
|
assert items[0].name == "New name"
|
||||||
assert items[0].category.name is None
|
assert items[0].category.name is None
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(items[0].category.load())
|
|
||||||
assert items[0].category.name is not None
|
|
||||||
|
|
||||||
response = client.get(f"/items/{item.pk}")
|
response = client.get(f"/items/{item.pk}")
|
||||||
new_item = Item(**response.json())
|
new_item = Item(**response.json())
|
||||||
assert new_item == item
|
assert new_item == item
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class Mol(ormar.Model):
|
|||||||
class Meta(BaseMeta):
|
class Meta(BaseMeta):
|
||||||
tablename = "mols"
|
tablename = "mols"
|
||||||
|
|
||||||
id: str = ormar.UUID(primary_key=True, index=True, uuid_format="hex")
|
id: uuid.UUID = ormar.UUID(primary_key=True, index=True, uuid_format="hex")
|
||||||
smiles: str = ormar.String(nullable=False, unique=True, max_length=256)
|
smiles: str = ormar.String(nullable=False, unique=True, max_length=256)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|||||||
@ -19,9 +19,9 @@ class OverwriteTest(ormar.Model):
|
|||||||
database = database
|
database = database
|
||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
my_int: str = ormar.Integer(overwrite_pydantic_type=PositiveInt)
|
my_int: int = ormar.Integer(overwrite_pydantic_type=PositiveInt)
|
||||||
constraint_dict: Json = ormar.JSON(
|
constraint_dict: Json = ormar.JSON(
|
||||||
overwrite_pydantic_type=Optional[Json[Dict[str, int]]]
|
overwrite_pydantic_type=Optional[Json[Dict[str, int]]] # type: ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class ModelTest(ormar.Model):
|
|||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
name: str = ormar.String(max_length=200)
|
name: str = ormar.String(max_length=200)
|
||||||
url: HttpUrl = "https://www.example.com"
|
url: HttpUrl = "https://www.example.com" # type: ignore
|
||||||
number: Optional[PaymentCardNumber]
|
number: Optional[PaymentCardNumber]
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class ModelTest2(ormar.Model):
|
|||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
name: str = ormar.String(max_length=200)
|
name: str = ormar.String(max_length=200)
|
||||||
url: HttpUrl = "https://www.example2.com"
|
url: HttpUrl = "https://www.example2.com" # type: ignore
|
||||||
number: PaymentCardNumber = Field(default_factory=get_number)
|
number: PaymentCardNumber = Field(default_factory=get_number)
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ class ModelTest3(ormar.Model):
|
|||||||
|
|
||||||
id: int = ormar.Integer(primary_key=True)
|
id: int = ormar.Integer(primary_key=True)
|
||||||
name: str = ormar.String(max_length=200)
|
name: str = ormar.String(max_length=200)
|
||||||
url: HttpUrl = "https://www.example3.com"
|
url: HttpUrl = "https://www.example3.com" # type: ignore
|
||||||
number: PaymentCardNumber
|
number: PaymentCardNumber
|
||||||
pydantic_test: PydanticTest
|
pydantic_test: PydanticTest
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user