| 1726 | return Label(name, self, self.type) |
| 1727 | |
| 1728 | def _anon_label( |
| 1729 | self, seed: Optional[str], add_hash: Optional[int] = None |
| 1730 | ) -> _anonymous_label: |
| 1731 | while self._is_clone_of is not None: |
| 1732 | self = self._is_clone_of |
| 1733 | |
| 1734 | # as of 1.4 anonymous label for ColumnElement uses hash(), not id(), |
| 1735 | # as the identifier, because a column and its annotated version are |
| 1736 | # the same thing in a SQL statement |
| 1737 | hash_value = hash(self) |
| 1738 | |
| 1739 | if add_hash: |
| 1740 | # this path is used for disambiguating anon labels that would |
| 1741 | # otherwise be the same name for the same element repeated. |
| 1742 | # an additional numeric value is factored in for each label. |
| 1743 | |
| 1744 | # shift hash(self) (which is id(self), typically 8 byte integer) |
| 1745 | # 16 bits leftward. fill extra add_hash on right |
| 1746 | assert add_hash < (2 << 15) |
| 1747 | assert seed |
| 1748 | hash_value = (hash_value << 16) | add_hash |
| 1749 | |
| 1750 | # extra underscore is added for labels with extra hash |
| 1751 | # values, to isolate the "deduped anon" namespace from the |
| 1752 | # regular namespace. eliminates chance of these |
| 1753 | # manufactured hash values overlapping with regular ones for some |
| 1754 | # undefined python interpreter |
| 1755 | seed = seed + "_" |
| 1756 | |
| 1757 | if isinstance(seed, _anonymous_label): |
| 1758 | return _anonymous_label.safe_construct( |
| 1759 | hash_value, "", enclosing_label=seed |
| 1760 | ) |
| 1761 | |
| 1762 | return _anonymous_label.safe_construct(hash_value, seed or "anon") |
| 1763 | |
| 1764 | @util.memoized_property |
| 1765 | def _anon_name_label(self) -> str: |