(
cls: type, attrs: list[Attribute], frozen: bool, cache_hash: bool
)
| 1609 | |
| 1610 | |
| 1611 | def _make_hash_script( |
| 1612 | cls: type, attrs: list[Attribute], frozen: bool, cache_hash: bool |
| 1613 | ) -> tuple[str, dict]: |
| 1614 | attrs = tuple( |
| 1615 | a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) |
| 1616 | ) |
| 1617 | |
| 1618 | tab = " " |
| 1619 | |
| 1620 | type_hash = hash(_generate_unique_filename(cls, "hash")) |
| 1621 | # If eq is custom generated, we need to include the functions in globs |
| 1622 | globs = {} |
| 1623 | |
| 1624 | hash_def = "def __hash__(self" |
| 1625 | hash_func = "hash((" |
| 1626 | closing_braces = "))" |
| 1627 | if not cache_hash: |
| 1628 | hash_def += "):" |
| 1629 | else: |
| 1630 | hash_def += ", *" |
| 1631 | |
| 1632 | hash_def += ", _cache_wrapper=__import__('attr._make')._make._CacheHashWrapper):" |
| 1633 | hash_func = "_cache_wrapper(" + hash_func |
| 1634 | closing_braces += ")" |
| 1635 | |
| 1636 | method_lines = [hash_def] |
| 1637 | |
| 1638 | def append_hash_computation_lines(prefix, indent): |
| 1639 | """ |
| 1640 | Generate the code for actually computing the hash code. |
| 1641 | Below this will either be returned directly or used to compute |
| 1642 | a value which is then cached, depending on the value of cache_hash |
| 1643 | """ |
| 1644 | |
| 1645 | method_lines.extend( |
| 1646 | [ |
| 1647 | indent + prefix + hash_func, |
| 1648 | indent + f" {type_hash},", |
| 1649 | ] |
| 1650 | ) |
| 1651 | |
| 1652 | for a in attrs: |
| 1653 | if a.eq_key: |
| 1654 | cmp_name = f"_{a.name}_key" |
| 1655 | globs[cmp_name] = a.eq_key |
| 1656 | method_lines.append( |
| 1657 | indent + f" {cmp_name}(self.{a.name})," |
| 1658 | ) |
| 1659 | else: |
| 1660 | method_lines.append(indent + f" self.{a.name},") |
| 1661 | |
| 1662 | method_lines.append(indent + " " + closing_braces) |
| 1663 | |
| 1664 | if cache_hash: |
| 1665 | method_lines.append(tab + f"if self.{_HASH_CACHE_FIELD} is None:") |
| 1666 | if frozen: |
| 1667 | append_hash_computation_lines( |
| 1668 | f"object.__setattr__(self, '{_HASH_CACHE_FIELD}', ", tab * 2 |
no test coverage detected