Skip to content

Some forms do not follow Python's __hash__ contract #4864

Description

@bickelj

In another context (creation of a new one of these forms), an LLM (Qwen3.6) raised a concern about the Python contract around __hash__ overrides.

See hypha/apply/funds/models/forms.py where this function is defined in several classes:

    def __hash__(self):
        fields = [field.id for field in self.fields]
        return hash((tuple(fields), self.sort_order, self.pk))

The issue is the inclusion of self.pk which is a mutable field. It starts as None and then is assigned a value on save.

See https://docs.python.org/3/reference/datamodel.html#object.__hash__:

If a class defines mutable objects and implements an eq() method, it should not implement hash(), since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).

For a bit I thought Django itself violated this, but on closer inspection, Django follows the contract.

Do we need to simply remove self.pk from the args and return hash((fields, self.sort_order))? What bad thing would happen then?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions