datamodel-code-generator icon indicating copy to clipboard operation
datamodel-code-generator copied to clipboard

Missing hash function for a class

Open yogeshVU opened this issue 2 years ago • 2 comments

Describe the bug

When working with Set collection, It is not possible to perform add operations on the set collection due to missing hash function. One gets following error:

    myModel.vocab.fruits.category.add(model.Apple(apple={}))
TypeError: unhashable type: 'Apple'

To Reproduce

Example schema:


{
    "title": "FruitVocab",
    "type": "object",
    "properties": {
        "Vocab": {
            "type": "object",
            "properties": {
                "Fruits": {
                    "title": "Fruits",
                    "type": "object",
                    "properties": {
                        "Category": {
                            "title": "Type",
                            "type": "array",
                            "uniqueItems": true,
                            "items": {
                                "type": "object",
                                "anyOf": [
                                    {
                                        "title": "Apple",
                                        "type": "object",
                                        "properties": {
                                            "Apple": {
                                                "title": "Apple",
                                                "type": "object",
                                                "properties": {},
                                                "required": [],
                                                "additionalProperties": false
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    {
                                        "title": "Mango",
                                        "type": "object",
                                        "properties": {
                                            "Mango": {
                                                "title": "Mango",
                                                "type": "object",
                                                "properties": {},
                                                "required": [],
                                                "additionalProperties": false
                                            }
                                        },
                                        "additionalProperties": false
                                    },
                                    {
                                        "title": "Banana",
                                        "type": "object",
                                        "properties": {
                                            "Banana": {
                                                "title": "Banana",
                                                "type": "object",
                                                "properties": {},
                                                "required": [],
                                                "additionalProperties": false
                                            }
                                        },
                                        "additionalProperties": false
                                    }
                                ],
                                "default": {
                                    "Apple": {}
                                }
                            }
                        }
                    },
                    "required": [],
                    "additionalProperties": false
                }
            },
            "required": []
        }
    },
    "additionalProperties": false,
    "required": []
}

Used commandline:

$ datamodel-codegen  --use-standard-collections --use-unique-items-as-set --use-annotated --use-title-as-name --use-subclass-enum --disable-appending-item-suffix --input-file-type jsonschema  --input errorJsonSchema.json --output TestMain.py --output-model-type pydantic_v2.BaseModel --allow-population-by-field-name --snake-case-field

Used Model Code:


import TestMain as model
myModel = model.FruitVocab()
myModel.vocab = model.Vocab()
myModel.vocab.fruits = model.Fruits()
myModel.vocab.fruits.category = set()
myModel.vocab.fruits.category.add(model.Apple(apple={}))

Expected behavior One should be able to add objects to a set.

import TestMain as model
myModel = model.FruitVocab()
myModel.vocab = model.Vocab()
myModel.vocab.fruits = model.Fruits()
myModel.vocab.fruits.category = set()
myModel.vocab.fruits.category.add(model.Apple(apple={}))

print(myModel.model_dump_json(indent=2,by_alias=True))

Currently adding __hash__ = object.__hash__ to the Apple Class solves the error.

class Apple(BaseModel):
# ADDING THIS WORKS
    __hash__ = object.__hash__
    model_config = ConfigDict(
        extra='forbid',
        populate_by_name=True,
    )
    apple: Annotated[
        Optional[dict[str, Any]], Field(alias='Apple', title='Apple')
    ] = None

So this __hash__ = object.__hash__ needs to be autogenerated by the code-generator

Version:

  • OS: MacOS
  • Python version: 3.10
  • datamodel-code-generator version: 0.22.0

Additional context Add any other context about the problem here.

yogeshVU avatar Oct 11 '23 20:10 yogeshVU

Is there any workaround for this? Can I somehow add the hash method programatically?

tcamise-gpsw avatar Aug 29 '24 17:08 tcamise-gpsw

__hash__ = object.__hash__ would also be a nice addition to RootModel .

I'm getting TypeError: unhashable type: for a RootModel, and adding the __hash__ function manually solves the issues.

kampelmuehler avatar Mar 05 '25 07:03 kampelmuehler