Skip to main content

It just provide a pair of pre & post methods around pydantic fields, the rest is up to your imagination

Project description

pypi Downloads Python Versions CI

Pydantic-resolve is a schema based solution for data composition, it can provide you with 3 ~ 5 times the increase in development efficiency and reduce the amount of code by more than 50%.

  1. It manages the deep data inside each schema, instead of visiting from outside by manual traversal.
  2. It runs a Level Order Traversal (BFS) inside and execute resolve and post during this process.
  3. It describes the relationship between data in a form close to ERD (entity relationship diagram)

Install

User of pydantic v2, please use pydantic2-resolve instead.

This lib now supports both pydantic v1 and v2 starts from v1.11.0

pip install pydantic-resolve

Hello world

manage your data inside the schema.

class Tree(BaseModel):
    name: str
    number: int
    description: str = ''
    def resolve_description(self):
        return f"I'm {self.name}, my number is {self.number}"
    children: list['Tree'] = []


tree = dict(
    name='root',
    number=1,
    children=[
        dict(
            name='child1',
            number=2,
            children=[
                dict(
                    name='child1-1',
                    number=3,
                ),
                dict(
                    name='child1-2',
                    number=4,
                ),
            ]
        )
    ]
)

async def main():
    t = Tree.parse_obj(tree)
    t = await Resolver().resolve(t)
    print(t.json(indent=4))

import asyncio
asyncio.run(main())

output

{
  "name": "root",
  "number": 1,
  "description": "I'm root, my number is 1",
  "children": [
    {
      "name": "child1",
      "number": 2,
      "description": "I'm child1, my number is 2",
      "children": [
        {
          "name": "child1-1",
          "number": 3,
          "description": "I'm child1-1, my number is 3",
          "children": []
        },
        {
          "name": "child1-2",
          "number": 4,
          "description": "I'm child1-2, my number is 4",
          "children": []
        }
      ]
    }
  ]
}

Composing a subset from ERD definitions

define elements of ERD, schema (entity), dataloader (relationship).

then pick and compose them together according to your requirement and get the result.

import asyncio
import json
from typing import Optional
from pydantic import BaseModel
from pydantic_resolve import Resolver, build_object, build_list, LoaderDepend
from aiodataloader import DataLoader

# Schema/ Entity
class Comment(BaseModel):
    id: int
    content: str
    user_id: int

class Blog(BaseModel):
    id: int
    title: str
    content: str

class User(BaseModel):
    id: int
    name: str


# Loaders/ relationships
class CommentLoader(DataLoader):
    async def batch_load_fn(self, comment_ids):
        comments = [
            dict(id=1, content="world is beautiful", blog_id=1, user_id=1),
            dict(id=2, content="Mars is beautiful", blog_id=2, user_id=2),
            dict(id=3, content="I love Mars", blog_id=2, user_id=3),
        ]
        return build_list(comments, comment_ids, lambda c: c['blog_id'])

class UserLoader(DataLoader):
    async def batch_load_fn(self, user_ids):
        users = [ dict(id=1, name="Alice"), dict(id=2, name="Bob"), ]
        return build_object(users, user_ids, lambda u: u['id'])


# Compose schemas and dataloaders together
class CommentWithUser(Comment):
    user: Optional[User] = None
    def resolve_user(self, loader=LoaderDepend(UserLoader)):
        return loader.load(self.user_id)

class BlogWithComments(Blog):
    comments: list[CommentWithUser] = []
    def resolve_comments(self, loader=LoaderDepend(CommentLoader)):
        return loader.load(self.id)


# Run
async def main():
    raw_blogs =[
        dict(id=1, title="hello world", content="hello world detail"),
        dict(id=2, title="hello Mars", content="hello Mars detail"),
    ]
    blogs = await Resolver().resolve([BlogWithComments.parse_obj(b) for b in raw_blogs])
    print(json.dumps(blogs, indent=2, default=lambda o: o.dict()))

asyncio.run(main())

output

[
  {
    "id": 1,
    "title": "hello world",
    "content": "hello world detail",
    "comments": [
      {
        "id": 1,
        "content": "world is beautiful",
        "user_id": 1,
        "user": {
          "id": 1,
          "name": "Alice"
        }
      }
    ]
  },
  {
    "id": 2,
    "title": "hello Mars",
    "content": "hello Mars detail",
    "comments": [
      {
        "id": 2,
        "content": "Mars is beautiful",
        "user_id": 2,
        "user": {
          "id": 2,
          "name": "Bob"
        }
      },
      {
        "id": 3,
        "content": "I love Mars",
        "user_id": 3,
        "user": null
      }
    ]
  }
]

Documents

Test and coverage

tox
tox -e coverage
python -m http.server

latest coverage: 98%

Sponsor

If this code helps and you wish to support me

Paypal: https://www.paypal.me/tangkikodo

Discussion

Discord

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydantic_resolve-1.11.1.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

pydantic_resolve-1.11.1-py3-none-any.whl (20.6 kB view details)

Uploaded Python 3

File details

Details for the file pydantic_resolve-1.11.1.tar.gz.

File metadata

  • Download URL: pydantic_resolve-1.11.1.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.10.4 Linux/5.15.167.4-microsoft-standard-WSL2

File hashes

Hashes for pydantic_resolve-1.11.1.tar.gz
Algorithm Hash digest
SHA256 9819e60e272cd63200e8ede9350d04ba6d2d52a38a573d78b650cc50891f81b9
MD5 f6e3c99870f7b3897b1c02c97232012a
BLAKE2b-256 38351df7bd8396773075f98cb7ab5a4726df813c37460cd813fb46f5722d9141

See more details on using hashes here.

File details

Details for the file pydantic_resolve-1.11.1-py3-none-any.whl.

File metadata

  • Download URL: pydantic_resolve-1.11.1-py3-none-any.whl
  • Upload date:
  • Size: 20.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.10.4 Linux/5.15.167.4-microsoft-standard-WSL2

File hashes

Hashes for pydantic_resolve-1.11.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ff00d4620fe72b0febbd2e0f1b6e446b4fd0761d54e6fb4aa0672b3795b9bceb
MD5 bdce35f567bb98b42a2efc9cc5008ba4
BLAKE2b-256 dbbc65c15bac87778da997e94abf2e6ae3a993501a8322f7f1f9a372adddde9c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page