def test_config() -> None: class Config: orm_mode = True allow_population_by_field_name = True @classmethod def alias_generator(cls, string: str) -> str: pascal_case = "".join(word.capitalize() for word in string.split("_")) camel_case = pascal_case[0].lower() + pascal_case[1:] return camel_case PydanticUser = sqlalchemy_to_pydantic(User) PydanticAddress = sqlalchemy_to_pydantic(Address, config=Config) class PydanticUserWithAddresses(PydanticUser): addresses: List[PydanticAddress] = [] user = db.query(User).first() pydantic_user_with_addresses = PydanticUserWithAddresses.from_orm(user) data = pydantic_user_with_addresses.dict(by_alias=True) assert isinstance(data["created"], datetime) assert isinstance(data["updated"], datetime) check_data = data.copy() del check_data["created"] del check_data["updated"] assert check_data == { "fullname": "Ed Jones", "id": 1, "name": "ed", "nickname": "edsnickname", "addresses": [ {"emailAddress": "*****@*****.**", "id": 1, "userId": 1}, {"emailAddress": "*****@*****.**", "id": 2, "userId": 1}, ], }
def test_schema() -> None: PydanticUser = sqlalchemy_to_pydantic(User) PydanticAddress = sqlalchemy_to_pydantic(Address) assert PydanticUser.schema() == { "title": "User", "type": "object", "properties": { "id": {"title": "Id", "type": "integer"}, "name": {"title": "Name", "type": "string"}, "fullname": {"title": "Fullname", "type": "string"}, "nickname": {"title": "Nickname", "type": "string"}, "created": {"title": "Created", "type": "string", "format": "date-time"}, "updated": {"title": "Updated", "type": "string", "format": "date-time"}, }, "required": ["id"], } assert PydanticAddress.schema() == { "title": "Address", "type": "object", "properties": { "id": {"title": "Id", "type": "integer"}, "email_address": {"title": "Email Address", "type": "string"}, "user_id": {"title": "User Id", "type": "integer"}, }, "required": ["id", "email_address"], }
def test_exclude() -> None: PydanticUser = sqlalchemy_to_pydantic(User, exclude={"nickname"}) PydanticAddress = sqlalchemy_to_pydantic(Address, exclude={"user_id"}) class PydanticUserWithAddresses(PydanticUser): addresses: List[PydanticAddress] = [] user = db.query(User).first() pydantic_user_with_addresses = PydanticUserWithAddresses.from_orm(user) data = pydantic_user_with_addresses.dict(by_alias=True) assert isinstance(data["updated"], datetime) check_data = data.copy() del check_data["updated"] assert check_data == { "fullname": "Ed Jones", "id": 1, "name": "ed", "addresses": [ { "email_address": "*****@*****.**", "id": 1 }, { "email_address": "*****@*****.**", "id": 2 }, ], }
def test_defaults(User, Address, default_user_with_addresses, create_db) -> None: db = create_db([default_user_with_addresses]) PydanticUser = sqlalchemy_to_pydantic(User) PydanticAddress = sqlalchemy_to_pydantic(Address) class PydanticUserWithAddresses(PydanticUser): addresses: List[PydanticAddress] = [] user = db.query(User).first() pydantic_user = PydanticUser.from_orm(user) data = pydantic_user.dict() assert isinstance(data["created"], datetime) assert isinstance(data["updated"], datetime) check_data = data.copy() del check_data["created"] del check_data["updated"] assert check_data == { "fullname": "Ed Jones", "id": 1, "name": "ed", "nickname": "edsnickname", } pydantic_user_with_addresses = PydanticUserWithAddresses.from_orm(user) data = pydantic_user_with_addresses.dict() assert isinstance(data["updated"], datetime) assert isinstance(data["created"], datetime) check_data = data.copy() del check_data["updated"] del check_data["created"] assert check_data == { "fullname": "Ed Jones", "id": 1, "name": "ed", "nickname": "edsnickname", "addresses": [ { "email_address": "*****@*****.**", "id": 1, "user_id": 1 }, { "email_address": "*****@*****.**", "id": 2, "user_id": 1 }, ], }
class ContextParticipant(sqlalchemy_to_pydantic(db.Participant) ): # type: ignore user: ContextUser challenge: ContextChallenge @property def completed_challenge(self) -> bool: return self.finished_at is not None
class DraftModel(sqlalchemy_to_pydantic(Draft)): # type: ignore """ Model for :class:`Draft` row. """ id: int feature_id: int test_run_id: int pr_url: Optional[str] published_by: str published_at: Optional[datetime]
class ContextUser(sqlalchemy_to_pydantic(db.User)): # type: ignore @property def full_name(self) -> str: name = self.first_name or '' if self.last_name: name += f' {self.last_name}' if self.nick_name: name += f' @{self.nick_name}' return name
def create_pydantic_models(self): self.pydantic_models = {} for suite_name, sqla_model in self.sqla_models.items(): orm_table_class = sqla_core_to_orm(suite_name, sqla_model) self.pydantic_models[suite_name] = sqlalchemy_to_pydantic( orm_table_class) return list(self.pydantic_models.keys())
class FeatureModel(sqlalchemy_to_pydantic(Feature)): # type: ignore """ Model for :class:`Feature` row. """ id: int name: str author: str feature_type: FeatureTypeModel last_edited_by: str task: List[str] feature_tags: List[TagsTypeModel] file_path: str
class ContextChallenge(sqlalchemy_to_pydantic(db.Challenge)): # type: ignore @property def finished(self) -> bool: return self.finished_at is not None @property def finish_after(self) -> datetime.timedelta: return cast(datetime.timedelta, self.created_at + self.duration - get_now()) @property def out_of_date(self) -> bool: return not self.finished and self.finish_after.total_seconds() < 0
class TestRunModel(sqlalchemy_to_pydantic(TestRun)): # type: ignore """ Model for :class:`TestRun` row. """ __test__ = False id: int created_at: datetime name: str executed_by: str start: Optional[datetime] end: Optional[datetime] status: TestRunStatus report_status: TestReportStatus report: Optional[str] traceback: Optional[str] scenario_id: int
def test_model_with_hybrid_property_exclude(Base) -> None: class Person(Base): __tablename__ = "persons" id = Column(Integer, primary_key=True) name = Column(String) firstname = Column(String) @hybrid_property def full_name(self) -> str: return self.firstname + " " + self.name PydanticPerson = sqlalchemy_to_pydantic(Person, exclude=["full_name"]) person = Person(id=1, name="Doe", firstname="John") pydantic_person = PydanticPerson.from_orm(person) data = pydantic_person.dict() assert data["id"] == 1 assert data["name"] == "Doe" assert data["firstname"] == "John" assert "full_name" not in data
class EmulationRunModel(sqlalchemy_to_pydantic(EmulationRun)): # type: ignore """ Model for :class:`EmulationRun` row. """ emulation: EmulationModel
class MeterSnapshotModel(sqlalchemy_to_pydantic(MeterSnapshot)): heat_meter_snapshot: Optional[HeatMeterSnapshotModel] electricity_meter_snapshot: Optional[ElectricityMeterSnapshotModel]
class MeterModel(sqlalchemy_to_pydantic(Meter)): electricity: Optional[ElectricityMeterModel] snapshots: List[MeterSnapshotModel]
class ScenarioModel(sqlalchemy_to_pydantic(Scenario)): # type: ignore """ Model for :class:`Scenario` row. """ id: int text: str feature_id: int
class ChangeMeterModel(make_change_model(sqlalchemy_to_pydantic(Meter))): electricity: Optional[AddElectricityMeterModel]
class TagsTypeModel(sqlalchemy_to_pydantic(Tags)): # type: ignore """ Model for :class:`Tags` row. """ value: str
class FeatureTypeModel(sqlalchemy_to_pydantic(FeatureType)): # type: ignore """ Model for :class:`FeatureType` row. """ name: FeatureTypeName
from datetime import datetime from typing import List, Optional from pydantic.main import BaseModel from pydantic_sqlalchemy import sqlalchemy_to_pydantic from models.metrics import Meter, ElectricityMeter, MeterSnapshot, HeatMeterSnapshot, \ ElectricityMeterSnapshot, EnvironmentalReading from request_models import make_change_model, make_add_model ElectricityMeterModel = sqlalchemy_to_pydantic(ElectricityMeter) HeatMeterSnapshotModel = sqlalchemy_to_pydantic(HeatMeterSnapshot) ElectricityMeterSnapshotModel = sqlalchemy_to_pydantic(ElectricityMeterSnapshot) EnvironmentalReadingModel = sqlalchemy_to_pydantic(EnvironmentalReading) class MeterSnapshotModel(sqlalchemy_to_pydantic(MeterSnapshot)): heat_meter_snapshot: Optional[HeatMeterSnapshotModel] electricity_meter_snapshot: Optional[ElectricityMeterSnapshotModel] class RecognizeMeterModel(BaseModel): meter_exists: bool class MeterModel(sqlalchemy_to_pydantic(Meter)): electricity: Optional[ElectricityMeterModel] snapshots: List[MeterSnapshotModel] class AddReadingModel(BaseModel):
class AddMeterModel(make_add_model(sqlalchemy_to_pydantic(Meter))): electricity: Optional[AddElectricityMeterModel]
class TestUserModel(sqlalchemy_to_pydantic(TestUser)): # type: ignore """ Model for :class:`TestUser` row. """ feature_type: FeatureTypeModel
def model(cls) -> Type[BaseModel]: if not cls._model: cls._model = sqlalchemy_to_pydantic( cls, config=PydanticConfig, exclude=["id"] ) return cls._model
from typing import List from pydantic import BaseModel from pydantic_sqlalchemy import sqlalchemy_to_pydantic from .models import Route RouteSchema = sqlalchemy_to_pydantic(Route, exclude={"id"}) class RouteCheapestSchema(BaseModel): route: List[str] cost: float
class ChangeMeterSnapshotModel(make_change_model(sqlalchemy_to_pydantic(MeterSnapshot), fields_to_remove=['meter_id', 'automatic'])): heat: Optional[ChangeHeatMeterSnapshotModel] electricity: Optional[ChangeElectricityMeterSnapshotModel]
class AddAutoMeterSnapshotModel(make_add_model(sqlalchemy_to_pydantic(MeterSnapshot), fields_to_remove=['automatic', 'meter_id'])): heat: Optional[AddHeatMeterSnapshotModel] electricity: Optional[AddElectricityMeterSnapshotModel]
from pydantic import BaseModel from pydantic_sqlalchemy import sqlalchemy_to_pydantic from models import Item class ItemModel(BaseModel): id: int name: str ItemModel = sqlalchemy_to_pydantic(Item)
class SystemUserModel(sqlalchemy_to_pydantic(UserRole)): # type: ignore """ Model for :class:`UserRole`. """ login: str password: SecretStr role: Role
class EmulationModel(sqlalchemy_to_pydantic(Emulation)): # type: ignore """ Model for :class:`Emulation` row. """ test_user: TestUserModel
# project/app/models/tortoise.py import datetime from pydantic_sqlalchemy import sqlalchemy_to_pydantic from sqlalchemy import Column, DateTime, Integer, String from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class TextSummary(Base): __tablename__ = "textsummary" id = Column(Integer, primary_key=True, index=True) url = Column(String, index=True) summary = Column(String, index=True) created_date = Column(DateTime, default=datetime.datetime.utcnow) def __str__(self): return self.url SummarySchema = sqlalchemy_to_pydantic(TextSummary)