I haven't found a way to make the Globals class use the extended definition of the table

You can change the type of a field in a subclass if you declare the field again using the desired type.

Also, simply adding new fields to the subclass does not seem to work

It looks like you are setting instance attributes in the __init__() method, but fields are declared as class attributes.

This example shows a way to add a calculated field records_by_id to ExtendedTable and use ExtendedTable in ExtendedGlobals:

# File: extensions.py
import json
from typing import Any, Dict, List, Optional

from pydantic import Field, validator

from datamodel import Globals, Record, Table


class ExtendedTable(Table):
    # New fields are declared as class attributes not as instance attributes inside the __init__()
    # Calculated fields usually have a default value or default factory so that you don't have to provide a value
    # I prefer a default_factory for mutable values
    records_by_id: Dict[int, Record] = Field(default_factory=dict)

    # A validator can populate a calculated field
    # Use always=True to run the validator even if a value is not supplied and the default value is used
    @validator("records_by_id", always=True)
    def _calculate_records_by_id(
        cls, value: Dict[int, Record], values: Dict[str, Any]
    ) -> Dict[int, Record]:
        records: Optional[List[Record]] = values.get("records")
        if records is None:
            # The records field was not valid
            # Return value or raise a ValueError instead if you want
            return value
        return {record.id: record for record in records}


class ExtendedGlobals(Globals):
    # You can change the type of a field in a subclass if you declare the field again
    table: ExtendedTable


if __name__ == "__main__":
    records = """
    {
        "table": {
            "records": [{"id": 0, "name": "A"}, {"id": 1, "name": "B"}]
        }
    }
    """

    content = json.loads(records)
    extended_globals = ExtendedGlobals.parse_obj(content)
    print(repr(extended_globals))

Output:

ExtendedGlobals(table=ExtendedTable(records=[Record(id=0, name='A'), Record(id=1, name='B')], records_by_id={0: Record(id=0, name='A'), 1: Record(id=1, name='B')}))
Answer from Hernán Alarcón on Stack Overflow
🌐
Pydantic
docs.pydantic.dev › latest › integrations › datamodel_code_generator
datamodel-code-generator - Pydantic Validation
What's new — we've launched Pydantic Logfire to help you monitor and understand your Pydantic validations. The datamodel-code-generator project is a library and command-line utility to generate pydantic models from just about any data source, ...
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator
GitHub - koxudaxi/datamodel-code-generator: Python data model generator (Pydantic, dataclasses, TypedDict, msgspec) from OpenAPI, JSON Schema, GraphQL, and raw data (JSON/YAML/CSV). · GitHub
pip install 'datamodel-code-generator[http]' datamodel-codegen --url https://example.com/api/openapi.yaml --output model.py · [tool.datamodel-codegen] input = "schema.yaml" output = "src/models.py" output-model-type = "pydantic_v2.BaseModel"
Starred by 3.8K users
Forked by 429 users
Languages   Python
🌐
PyPI
pypi.org › project › datamodel-code-generator › 0.4.8
datamodel-code-generator · PyPI
This code generator creates pydantic model from an openapi file and others. ... usage: datamodel-codegen [-h] [--input INPUT] [--output OUTPUT] [--base-class BASE_CLASS] [--custom-template-dir CUSTOM_TEMPLATE_DIR] [--extra-template-data ...
      » pip install datamodel-code-generator
    
Published   Apr 18, 2020
Version   0.4.8
🌐
Pydantic
docs.pydantic.dev › 1.10 › datamodel_code_generator
Code Generation - Pydantic
# generated by datamodel-codegen: # filename: person.json # timestamp: 2020-05-19T15:07:31+00:00 from __future__ import annotations from typing import Any, List, Optional from pydantic import BaseModel, Field, conint class Pet(BaseModel): name: Optional[str] = None age: Optional[int] = None class Person(BaseModel): first_name: str = Field(..., description="The person's first name.") last_name: str = Field(..., description="The person's last name.") age: Optional[conint(ge=0)] = Field(None, description='Age in years.') pets: Optional[List[Pet]] = None comment: Optional[Any] = None
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › releases
Releases · koxudaxi/datamodel-code-generator
Python data model generator (Pydantic, dataclasses, TypedDict, msgspec) from OpenAPI, JSON Schema, GraphQL, and raw data (JSON/YAML/CSV). - koxudaxi/datamodel-code-generator
Author   koxudaxi
🌐
GitHub
github.com › tomercagan › datamodel-code-generator
GitHub - tomercagan/datamodel-code-generator: Pydantic model generator for easy conversion of JSON, OpenAPI, JSON Schema, and YAML data sources.
This code generator creates pydantic model from an openapi file and others. See documentation for more details. ... If you want to resolve $ref for remote files then you should specify http extra option.
Author   tomercagan
🌐
GitHub
github.com › pydantic › pydantic › blob › main › docs › integrations › datamodel_code_generator.md
pydantic/docs/integrations/datamodel_code_generator.md at main · pydantic/pydantic
November 20, 2024 - The datamodel-code-generator project is a library and command-line utility to generate pydantic models from just about any data source, including:
Author   pydantic
Top answer
1 of 1
1

I haven't found a way to make the Globals class use the extended definition of the table

You can change the type of a field in a subclass if you declare the field again using the desired type.

Also, simply adding new fields to the subclass does not seem to work

It looks like you are setting instance attributes in the __init__() method, but fields are declared as class attributes.

This example shows a way to add a calculated field records_by_id to ExtendedTable and use ExtendedTable in ExtendedGlobals:

# File: extensions.py
import json
from typing import Any, Dict, List, Optional

from pydantic import Field, validator

from datamodel import Globals, Record, Table


class ExtendedTable(Table):
    # New fields are declared as class attributes not as instance attributes inside the __init__()
    # Calculated fields usually have a default value or default factory so that you don't have to provide a value
    # I prefer a default_factory for mutable values
    records_by_id: Dict[int, Record] = Field(default_factory=dict)

    # A validator can populate a calculated field
    # Use always=True to run the validator even if a value is not supplied and the default value is used
    @validator("records_by_id", always=True)
    def _calculate_records_by_id(
        cls, value: Dict[int, Record], values: Dict[str, Any]
    ) -> Dict[int, Record]:
        records: Optional[List[Record]] = values.get("records")
        if records is None:
            # The records field was not valid
            # Return value or raise a ValueError instead if you want
            return value
        return {record.id: record for record in records}


class ExtendedGlobals(Globals):
    # You can change the type of a field in a subclass if you declare the field again
    table: ExtendedTable


if __name__ == "__main__":
    records = """
    {
        "table": {
            "records": [{"id": 0, "name": "A"}, {"id": 1, "name": "B"}]
        }
    }
    """

    content = json.loads(records)
    extended_globals = ExtendedGlobals.parse_obj(content)
    print(repr(extended_globals))

Output:

ExtendedGlobals(table=ExtendedTable(records=[Record(id=0, name='A'), Record(id=1, name='B')], records_by_id={0: Record(id=0, name='A'), 1: Record(id=1, name='B')}))
Find elsewhere
🌐
PyPI
pypi.org › project › improved-datamodel-codegen
improved-datamodel-codegen · PyPI
# generated by datamodel-codegen: # filename: api.yaml # timestamp: 2020-06-02T05:28:24+00:00 from __future__ import annotations from typing import List, Optional from pydantic import AnyUrl, BaseModel, Field class Pet(BaseModel): id: int name: str tag: Optional[str] = None class Pets(BaseModel): __root__: List[Pet] class Error(BaseModel): code: int message: str class Api(BaseModel): apiKey: Optional[str] = Field( None, description='To be used as a dataset parameter value' ) apiVersionNumber: Optional[str] = Field( None, description='To be used as a version parameter value' ) apiUrl: Optional[AnyUrl] = Field( None, description="The URL describing the dataset's fields" ) apiDocumentationUrl: Optional[AnyUrl] = Field( None, description='A URL to the API console for each API' ) class Apis(BaseModel): __root__: List[Api] This code generator creates FastAPI app from an openapi file.
      » pip install improved-datamodel-codegen
    
Published   Mar 07, 2023
Version   1.2.1
🌐
Pydantic
pydantic.com.cn › en › integrations › datamodel_code_generator
datamodel-code-generator - Pydantic documentation (en)
The datamodel-code-generator project is a library and command-line utility to generate pydantic models from just about any data source, including:
🌐
Koxudaxi
datamodel-code-generator.koxudaxi.dev
datamodel-code-generator - datamodel-code-generator
datamodel-codegen --input pet.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --output model.py ... # generated by datamodel-codegen: # filename: tutorial_pet.json from __future__ import annotations from enum import Enum from typing import Optional from pydantic import BaseModel, Field class Species(Enum): dog = 'dog' cat = 'cat' bird = 'bird' fish = 'fish' class Pet(BaseModel): name: str = Field(..., description="The pet's name") species: Species age: Optional[int] = Field(None, description='Age in years', ge=0) vaccinated: Optional[bool] = False
🌐
Pydantify
pydantify.github.io › pydantify › technologies › dmcg
datamodel-code-generator - pydantify
Datamodel-code-generator (or DMCG for short) is a project which aims to translate data models written in either the ApenAPI 3 or JSONSchema format into Python class structures based on pydantic.
🌐
Ubuntu
manpages.ubuntu.com › manpages › resolute › man1 › datamodel-codegen.1.html
Ubuntu Manpage: datamodel-codegen - pydantic code generator from OpenAPI and more
datamodel-codegen - pydantic code generator from OpenAPI and more · usage: datamodel-codegen [options] Generate Python data models from schema definitions or structured data For detailed usage, see: https://koxudaxi.github.io/datamodel-code-generator · --additional-imports ADDITIONAL_IMPORTS ...
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › issues › 803
Support for Pydantic v2 · Issue #803 · koxudaxi/datamodel-code-generator
July 10, 2022 - koxudaxi / datamodel-code-generator Public · There was an error while loading. Please reload this page. Notifications · You must be signed in to change notification settings · Fork 426 · Star 3.8k · New issueCopy link · New issueCopy link · Closed · Closed · Support for Pydantic v2#803 ·
Author   ofek
🌐
Koxudaxi
koxudaxi.github.io › datamodel-code-generator › openapi
Generate from OpenAPI - datamodel-code-generator
The code generator can create pydantic models from OpenAPI schema definitions, particularly using the data from the schema field. $ datamodel-codegen --input api.yaml --input-file-type openapi --output model.py
Top answer
1 of 1
2

From the datamodel-code-generator "official documentation" mentioned on the page you reference, datamodel-code-generator can be used as a module to get the dictionary to python-code-string (see https://koxudaxi.github.io/datamodel-code-generator/using_as_module/).

Here is there relevant example code (to avoid problems with their pages changing)

from datamodel_code_generator import DataModelType, PythonVersion
from datamodel_code_generator.model import get_data_model_types
from datamodel_code_generator.parser.jsonschema import JsonSchemaParser

json_schema: str = """{
    "type": "object",
    "properties": {
        "number": {"type": "number"},
        "street_name": {"type": "string"},
        "street_type": {"type": "string",
                        "enum": ["Street", "Avenue", "Boulevard"]
                        }
    }
}"""


data_model_types = get_data_model_types(
    DataModelType.PydanticV2BaseModel,
    target_python_version=PythonVersion.PY_311
)
parser = JsonSchemaParser(
   json_schema,
   data_model_type=data_model_types.data_model,
   data_model_root_type=data_model_types.root_model,
   data_model_field_type=data_model_types.field_model,
   data_type_manager_type=data_model_types.data_type_manager,
   dump_resolve_reference_action=data_model_types.dump_resolve_reference_action,
                       )
result = parser.parse()

Then, assuming that there isn't a way to send in a schema that would cause their parser to generate malicious code, you just need to run

exec(result)

EDIT: Here is a worked out example using the example code. I get an error with your schema, which I have not tried to debug.

>>> from datamodel_code_generator import DataModelType, PythonVersion
>>> from datamodel_code_generator.model import get_data_model_types
>>> from datamodel_code_generator.parser.jsonschema import JsonSchemaParser
>>> json_schema: str = """{
...     "type": "object",
...     "properties": {
...         "number": {"type": "number"},
...         "street_name": {"type": "string"},
...         "street_type": {"type": "string",
...                         "enum": ["Street", "Avenue", "Boulevard"]
...                         }
...     }
... }"""
>>> parser = JsonSchemaParser(
...    json_schema,
...    data_model_type=data_model_types.data_model,
...    data_model_root_type=data_model_types.root_model,
...    data_model_field_type=data_model_types.field_model,
...    data_type_manager_type=data_model_types.data_type_manager,
...    dump_resolve_reference_action=data_model_types.dump_resolve_reference_action,
... )
>>> result = parser.parse()
>>> print(result)
from __future__ import annotations

from enum import Enum
from typing import Optional

from pydantic import BaseModel


class StreetType(Enum):
    Street = 'Street'
    Avenue = 'Avenue'
    Boulevard = 'Boulevard'


class Model(BaseModel):
    number: Optional[float] = None
    street_name: Optional[str] = None
    street_type: Optional[StreetType] = None

>>> exec(result)
>>> m = Model(**{'number': 1, 'street_name': 'Main', 'street_type': 'Street'})
>>> print(m)
number=1.0 street_name='Main' street_type=<StreetType.Street: 'Street'>
>>> 
🌐
Pythonrepo
pythonrepo.com › repo › koxudaxi-datamodel-code-generator
Pydantic model generator for easy conversion of JSON, OpenAPI, JSON Schema, and YAML data sources. | PythonRepo
January 4, 2022 - koxudaxi/datamodel-code-generator, datamodel-code-generator This code generator creates pydantic model from an openapi file and others. Help See documentation for more details. Supporte