From df4f4d1bd15f94f94f331304060bf199236fad4d Mon Sep 17 00:00:00 2001 From: ManiMozaffar Date: Sat, 8 Jul 2023 12:24:25 +0300 Subject: [PATCH 1/2] first phase: pydantic v2 migration --- redbird/base.py | 7 +++++-- redbird/repos/csv.py | 2 +- redbird/repos/memory.py | 2 +- redbird/repos/mongo.py | 6 +++--- redbird/repos/rest.py | 2 +- redbird/repos/sqlalchemy.py | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/redbird/base.py b/redbird/base.py index f4d9cc0..3594f5b 100644 --- a/redbird/base.py +++ b/redbird/base.py @@ -143,14 +143,14 @@ class BaseRepo(ABC, BaseModel): model: Type = dict id_field: Optional[str] - + query_model: Optional[Type[BaseModel]] = BasicQuery errors_query: Literal['raise', 'warn', 'discard'] = 'raise' field_access: Literal['attr', 'key', 'infer'] = 'infer' # Attributes that specifies how the repo behaves - ordered: bool = Field(default=False, const=True) + ordered: bool = Field(default=False) @validator('id_field', always=True) def set_id_field(cls, value, values): @@ -376,3 +376,6 @@ def set_field_value(self, item: Item, key, value): }[field_access] func(item, key, value) + + class Config: + arbitrary_types_allowed = True diff --git a/redbird/repos/csv.py b/redbird/repos/csv.py index 0892634..3c279d4 100644 --- a/redbird/repos/csv.py +++ b/redbird/repos/csv.py @@ -66,7 +66,7 @@ class CSVFileRepo(TemplateRepo): kwds_csv: dict = {} _session = PrivateAttr() - ordered: bool = Field(default=True, const=True) + ordered: bool = Field(default=True) def insert(self, item): file_non_zero = self.filename.exists() and self.filename.stat().st_size > 0 diff --git a/redbird/repos/memory.py b/redbird/repos/memory.py index 09cba38..072183c 100644 --- a/redbird/repos/memory.py +++ b/redbird/repos/memory.py @@ -56,7 +56,7 @@ class MemoryRepo(TemplateRepo): #cls_result = MemoryResult collection: List[Any] = [] - ordered: bool = Field(default=False, const=True) + ordered: bool = Field(default=False) _session = PrivateAttr() def insert(self, item): diff --git a/redbird/repos/mongo.py b/redbird/repos/mongo.py index b9c24f9..1d99693 100644 --- a/redbird/repos/mongo.py +++ b/redbird/repos/mongo.py @@ -134,8 +134,8 @@ class MongoRepo(TemplateRepo): repo = MongoRepo(client=MongoClient("mongodb://localhost:27017")) """ # cls_result = MongoResult - default_id_field = "_id" - cls_session = MongoSession + default_id_field: str = "_id" + cls_session: MongoSession = MongoSession __operators__ = { GreaterThan: "$gt", @@ -149,7 +149,7 @@ class MongoRepo(TemplateRepo): database: Optional[str] collection: Optional[str] - ordered: bool = Field(default=True, const=True) + ordered: bool = Field(default=True) def __init__(self, *args, uri=None, client=None, session=None, **kwargs): if uri is not None: diff --git a/redbird/repos/rest.py b/redbird/repos/rest.py index cd3bcfc..b2373fc 100644 --- a/redbird/repos/rest.py +++ b/redbird/repos/rest.py @@ -91,7 +91,7 @@ class RESTRepo(TemplateRepo): _session = PrivateAttr() - ordered: bool = Field(default=False, const=True) + ordered: bool = Field(default=False) def insert(self, item): json = self.item_to_dict(item, exclude_unset=False) diff --git a/redbird/repos/sqlalchemy.py b/redbird/repos/sqlalchemy.py index 6348663..b08ceb5 100644 --- a/redbird/repos/sqlalchemy.py +++ b/redbird/repos/sqlalchemy.py @@ -161,7 +161,7 @@ class Car(BaseModel): engine: Optional[Any] autocommit: bool = Field(default=True, description="Whether to automatically commit the writes (create, delete, update)") - ordered: bool = Field(default=True, const=True) + ordered: bool = Field(default=True) _Base = PrivateAttr() @classmethod From 4adbf6764564c2266b74154bdcba6df2f5a770cd Mon Sep 17 00:00:00 2001 From: ManiMozaffar Date: Sat, 8 Jul 2023 12:39:31 +0300 Subject: [PATCH 2/2] more coverage --- redbird/base.py | 10 +++++----- redbird/repos/mongo.py | 6 +++--- redbird/repos/rest.py | 2 +- redbird/repos/sqlalchemy.py | 12 ++++++------ redbird/test/common/conftest.py | 9 ++++----- redbird/test/logging/test_handler.py | 6 +++--- redbird/test/repo/test_csv.py | 2 +- redbird/test/repo/test_json.py | 2 +- redbird/test/repo/test_mongo.py | 4 ++-- redbird/test/repo/test_sql.py | 5 ++--- redbird/test/sql/test_create.py | 2 +- 11 files changed, 29 insertions(+), 31 deletions(-) diff --git a/redbird/base.py b/redbird/base.py index 3594f5b..ba89524 100644 --- a/redbird/base.py +++ b/redbird/base.py @@ -6,7 +6,7 @@ from dataclasses import dataclass import warnings -from pydantic import BaseModel, Field, validator +from pydantic import ConfigDict, BaseModel, Field, validator from redbird.exc import ConversionWarning, DataToItemError, KeyFoundError, ItemToDataError, _handle_conversion_error from redbird.utils.case import to_case @@ -142,7 +142,7 @@ class BaseRepo(ABC, BaseModel): cls_result: ClassVar[Type[BaseResult]] model: Type = dict - id_field: Optional[str] + id_field: Optional[str] = None query_model: Optional[Type[BaseModel]] = BasicQuery @@ -152,6 +152,8 @@ class BaseRepo(ABC, BaseModel): # Attributes that specifies how the repo behaves ordered: bool = Field(default=False) + # TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually. + # Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information. @validator('id_field', always=True) def set_id_field(cls, value, values): if value is None: @@ -376,6 +378,4 @@ def set_field_value(self, item: Item, key, value): }[field_access] func(item, key, value) - - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/redbird/repos/mongo.py b/redbird/repos/mongo.py index 1d99693..fd04c71 100644 --- a/redbird/repos/mongo.py +++ b/redbird/repos/mongo.py @@ -145,9 +145,9 @@ class MongoRepo(TemplateRepo): NotEqual: "$ne", In: "$in", } - session: Any - database: Optional[str] - collection: Optional[str] + session: Any = None + database: Optional[str] = None + collection: Optional[str] = None ordered: bool = Field(default=True) diff --git a/redbird/repos/rest.py b/redbird/repos/rest.py index b2373fc..877db6c 100644 --- a/redbird/repos/rest.py +++ b/redbird/repos/rest.py @@ -84,7 +84,7 @@ class RESTRepo(TemplateRepo): repo = RESTRepo(url="http://example.com/api", url_params={"fields": "car_type,car_model,registration_number"}) """ - result: Optional[Union[str, Callable]] + result: Optional[Union[str, Callable]] = None url: str url_params: dict = {} headers: dict = {} diff --git a/redbird/repos/sqlalchemy.py b/redbird/repos/sqlalchemy.py index b08ceb5..674ec55 100644 --- a/redbird/repos/sqlalchemy.py +++ b/redbird/repos/sqlalchemy.py @@ -155,10 +155,10 @@ class Car(BaseModel): repo = SQLRepo(model=Car, model_orm=CarORM, engine=engine) """ - model_orm: Optional[Any] - table: Optional[str] - session: Any - engine: Optional[Any] + model_orm: Optional[Any] = None + table: Optional[str] = None + session: Any = None + engine: Optional[Any] = None autocommit: bool = Field(default=True, description="Whether to automatically commit the writes (create, delete, update)") ordered: bool = Field(default=True) @@ -303,8 +303,8 @@ def _create_table(self, session, model, name, primary_column=None): class SQLExprRepo(TemplateRepo): - table: Optional[str] - engine: Optional[Any] + table: Optional[str] = None + engine: Optional[Any] = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/redbird/test/common/conftest.py b/redbird/test/common/conftest.py index 419a605..7bc6089 100644 --- a/redbird/test/common/conftest.py +++ b/redbird/test/common/conftest.py @@ -17,7 +17,7 @@ from redbird.repos.mongo import MongoRepo from redbird.oper import greater_equal, greater_than, less_equal, less_than, not_equal -from pydantic import BaseModel, Field +from pydantic import ConfigDict, BaseModel, Field # ------------------------ # TEST ITEMS @@ -27,14 +27,13 @@ class PydanticItem(BaseModel): __colname__ = 'items' id: str name: str - age: Optional[int] + age: Optional[int] = None class PydanticItemORM(BaseModel): id: str name: str - age: Optional[int] - class Config: - orm_mode = True + age: Optional[int] = None + model_config = ConfigDict(from_attributes=True) class MongoItem(BaseModel): __colname__ = 'items' diff --git a/redbird/test/logging/test_handler.py b/redbird/test/logging/test_handler.py index cc61e86..cc90ee5 100644 --- a/redbird/test/logging/test_handler.py +++ b/redbird/test/logging/test_handler.py @@ -17,9 +17,9 @@ class LogRecord(BaseModel): pathname: str filename: str module: str - exc_info: Optional[tuple] - exc_text: Optional[str] - stack_info: Optional[tuple] + exc_info: Optional[tuple] = None + exc_text: Optional[str] = None + stack_info: Optional[tuple] = None lineno: int funcName: str created: float diff --git a/redbird/test/repo/test_csv.py b/redbird/test/repo/test_csv.py index 27d00d1..1d9ca83 100644 --- a/redbird/test/repo/test_csv.py +++ b/redbird/test/repo/test_csv.py @@ -7,7 +7,7 @@ class Item(BaseModel): id: str name: str - age: Optional[int] + age: Optional[int] = None def test_filecontent(tmpdir): file = tmpdir / "test.csv" diff --git a/redbird/test/repo/test_json.py b/redbird/test/repo/test_json.py index 3c877c4..4687a6d 100644 --- a/redbird/test/repo/test_json.py +++ b/redbird/test/repo/test_json.py @@ -10,7 +10,7 @@ class Item(BaseModel): id: str name: str - age: Optional[int] + age: Optional[int] = None def sort_items(items, repo, field="id"): return list(sorted(items, key=lambda x: repo.get_field_value(x, field))) diff --git a/redbird/test/repo/test_mongo.py b/redbird/test/repo/test_mongo.py index 7402ac1..71ce6ce 100644 --- a/redbird/test/repo/test_mongo.py +++ b/redbird/test/repo/test_mongo.py @@ -9,14 +9,14 @@ class Item(BaseModel): id: str name: str - age: Optional[int] + age: Optional[int] = None class ItemWithCol(BaseModel): __colname__ = 'items' id: str name: str - age: Optional[int] + age: Optional[int] = None def test_creation_defaults(): pytest.importorskip("pymongo") diff --git a/redbird/test/repo/test_sql.py b/redbird/test/repo/test_sql.py index 4c19c9f..c25bbd4 100644 --- a/redbird/test/repo/test_sql.py +++ b/redbird/test/repo/test_sql.py @@ -4,7 +4,7 @@ import typing import pytest from redbird.repos import SQLRepo -from pydantic import BaseModel +from pydantic import ConfigDict, BaseModel try: from typing import Literal @@ -20,8 +20,7 @@ class MyItemWithORM(BaseModel): id: str name: str age: int - class Config: - orm_mode = True + model_config = ConfigDict(from_attributes=True) try: from sqlalchemy.orm import declarative_base diff --git a/redbird/test/sql/test_create.py b/redbird/test/sql/test_create.py index f29fc24..1f7d104 100644 --- a/redbird/test/sql/test_create.py +++ b/redbird/test/sql/test_create.py @@ -77,7 +77,7 @@ class MyModel(BaseModel): name: str score: int = 999 birth_date: date - color: Optional[str] + color: Optional[str] = None tbl = Table("mytable", bind=engine) tbl.create_from_model(MyModel)