Skip to content

Create ConfDict using json-mode model dump#53

Merged
jrapin merged 3 commits intofacebookresearch:mainfrom
PierreGtch:json-confdict
Mar 31, 2025
Merged

Create ConfDict using json-mode model dump#53
jrapin merged 3 commits intofacebookresearch:mainfrom
PierreGtch:json-confdict

Conversation

@PierreGtch
Copy link
Copy Markdown
Contributor

Hi @jrapin @kingjr,

Super cool library :D

I was playing a bit, but my model had some non-simple types (like date time.timedelta or pydantic.ImportString) that are not compatible with exec.ConfDict' s to_yaml and to_uid methods.

See, before fix:

exca/test_utils.py:417: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
exca/confdict.py:200: in to_yaml
    out: str = _yaml.safe_dump(_to_simplified_dict(self), sort_keys=True)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/__init__.py:269: in safe_dump
    return dump_all([data], stream, Dumper=SafeDumper, **kwds)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/__init__.py:241: in dump_all
    dumper.represent(data)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:27: in represent
    node = self.represent_data(data)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:48: in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:207: in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:118: in represent_mapping
    node_value = self.represent_data(item_value)
../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:58: in represent_data
    node = self.yaml_representers[None](self, data)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <yaml.dumper.SafeDumper object at 0x157555030>
data = datetime.timedelta(seconds=60)

    def represent_undefined(self, data):
>       raise RepresenterError("cannot represent an object", data)
E       yaml.representer.RepresenterError: ('cannot represent an object', datetime.timedelta(seconds=60))

../../miniforge3/envs/exca/lib/python3.10/site-packages/yaml/representer.py:231: RepresenterError

This PR sets model_dump(..., mode="json"), which uses pydantic's logic to convert many types to JSON-compatible ones.

All the current tests pass. Could this change cause issues at non-tested places?

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Meta Open Source bot. label Mar 25, 2025
@kingjr
Copy link
Copy Markdown
Contributor

kingjr commented Mar 26, 2025

Would type casting work? e.g.

from pydantic import BaseModel, field_validator
from datetime import timedelta

class MyModel(BaseModel):
    duration: str

    @field_validator("duration", mode="before")
    @classmethod
    def validate_duration(cls, value):
        if isinstance(value, timedelta):
            return str(value)
        raise ValueError("duration must be a timedelta")

MyModel(duration=timedelta(days=1, hours=2, minutes=30)).duration

@PierreGtch
Copy link
Copy Markdown
Contributor Author

PierreGtch commented Mar 26, 2025

@kingjr this type casting would work but it would mean re-implementing many functionalities already present in pydantic.

For example, this is quite handy:

import pydantic
import math
import datetime

class MyModel(pydantic.BaseModel):
    x: pydantic.ImportString
    y: datetime.timedelta

# Call with strings:
MyModel(x="math.sqrt", y="PT1M")
# MyModel(x=<built-in function sqrt>, y=datetime.timedelta(seconds=60))

# Or with the actual objects:
MyModel(x=math.sqrt, y=datetime.timedelta(minutes=1))
# MyModel(x=<built-in function sqrt>, y=datetime.timedelta(seconds=60))

# Converted back to strings to be JSON-compatible:
MyModel(x=math.sqrt, y=datetime.timedelta(minutes=1)).model_dump(mode='json’)
# {'x': 'math.sqrt', 'y': 'PT1M'}

See all the types natively supported by pydantic for such casting to json-compatible formats:

@jrapin
Copy link
Copy Markdown
Contributor

jrapin commented Mar 31, 2025

Hi @PierreGtch
Thanks for the contribution, I was not aware of this option and that's quite handy indeed + I may be able to remove some special yaml handling of Path type in confdict.py.

@jrapin jrapin merged commit 81810b1 into facebookresearch:main Mar 31, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants