_py_util.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # sql/_py_util.py
  2. # Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. from __future__ import annotations
  8. import typing
  9. from typing import Any
  10. from typing import Dict
  11. from typing import Tuple
  12. from typing import Union
  13. from ..util.typing import Literal
  14. if typing.TYPE_CHECKING:
  15. from .cache_key import CacheConst
  16. class prefix_anon_map(Dict[str, str]):
  17. """A map that creates new keys for missing key access.
  18. Considers keys of the form "<ident> <name>" to produce
  19. new symbols "<name>_<index>", where "index" is an incrementing integer
  20. corresponding to <name>.
  21. Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which
  22. is otherwise usually used for this type of operation.
  23. """
  24. def __missing__(self, key: str) -> str:
  25. (ident, derived) = key.split(" ", 1)
  26. anonymous_counter = self.get(derived, 1)
  27. self[derived] = anonymous_counter + 1 # type: ignore
  28. value = f"{derived}_{anonymous_counter}"
  29. self[key] = value
  30. return value
  31. class cache_anon_map(
  32. Dict[Union[int, "Literal[CacheConst.NO_CACHE]"], Union[Literal[True], str]]
  33. ):
  34. """A map that creates new keys for missing key access.
  35. Produces an incrementing sequence given a series of unique keys.
  36. This is similar to the compiler prefix_anon_map class although simpler.
  37. Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which
  38. is otherwise usually used for this type of operation.
  39. """
  40. _index = 0
  41. def get_anon(self, object_: Any) -> Tuple[str, bool]:
  42. idself = id(object_)
  43. if idself in self:
  44. s_val = self[idself]
  45. assert s_val is not True
  46. return s_val, True
  47. else:
  48. # inline of __missing__
  49. self[idself] = id_ = str(self._index)
  50. self._index += 1
  51. return id_, False
  52. def __missing__(self, key: int) -> str:
  53. self[key] = val = str(self._index)
  54. self._index += 1
  55. return val