pydevd_plugin_omegaconf.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # based on https://github.com/fabioz/PyDev.Debugger/tree/main/pydevd_plugins/extensions
  2. import os
  3. import sys
  4. from typing import Any, Dict
  5. from _pydevd_bundle.pydevd_extension_api import ( # type: ignore
  6. StrPresentationProvider,
  7. TypeResolveProvider,
  8. )
  9. DEBUG = False
  10. def print_debug(msg: str) -> None: # pragma: no cover
  11. if DEBUG:
  12. print(msg)
  13. def find_mod_attr(mod_name: str, attr: str) -> Any:
  14. mod = sys.modules.get(mod_name)
  15. return getattr(mod, attr, None)
  16. class OmegaConfDeveloperResolver(object):
  17. def can_provide(self, type_object: Any, type_name: str) -> bool:
  18. Node = find_mod_attr("omegaconf", "Node")
  19. return Node is not None and issubclass(type_object, Node)
  20. def resolve(self, obj: Any, attribute: str) -> Any:
  21. return getattr(obj, attribute)
  22. def get_dictionary(self, obj: Any) -> Any:
  23. return obj.__dict__
  24. class OmegaConfUserResolver(StrPresentationProvider): # type: ignore
  25. def __init__(self) -> None:
  26. self.Node = find_mod_attr("omegaconf", "Node")
  27. self.ValueNode = find_mod_attr("omegaconf", "ValueNode")
  28. self.ListConfig = find_mod_attr("omegaconf", "ListConfig")
  29. self.DictConfig = find_mod_attr("omegaconf", "DictConfig")
  30. self.InterpolationResolutionError = find_mod_attr(
  31. "omegaconf.errors", "InterpolationResolutionError"
  32. )
  33. def can_provide(self, type_object: Any, type_name: str) -> bool:
  34. return self.Node is not None and issubclass(type_object, self.Node)
  35. def resolve(self, obj: Any, attribute: Any) -> Any:
  36. if isinstance(obj, self.ListConfig) and isinstance(attribute, str):
  37. attribute = int(attribute)
  38. if isinstance(obj, self.Node):
  39. obj = obj._dereference_node()
  40. val = obj.__dict__["_content"][attribute]
  41. print_debug(
  42. f"resolving {obj} ({type(obj).__name__}), {attribute} -> {val} ({type(val).__name__})"
  43. )
  44. return val
  45. def _is_simple_value(self, val: Any) -> bool:
  46. return (
  47. isinstance(val, self.ValueNode)
  48. and not val._is_none()
  49. and not val._is_missing()
  50. and not val._is_interpolation()
  51. )
  52. def get_dictionary(self, obj: Any) -> Dict[str, Any]:
  53. d = self._get_dictionary(obj)
  54. print_debug(f"get_dictionary {obj}, ({type(obj).__name__}) -> {d}")
  55. return d
  56. def _get_dictionary(self, obj: Any) -> Dict[str, Any]:
  57. if isinstance(obj, self.Node):
  58. obj = obj._maybe_dereference_node()
  59. if obj is None or obj._is_none() or obj._is_missing():
  60. return {}
  61. if isinstance(obj, self.DictConfig):
  62. d = {}
  63. for k, v in obj.__dict__["_content"].items():
  64. if self._is_simple_value(v):
  65. v = v._value()
  66. d[k] = v
  67. elif isinstance(obj, self.ListConfig):
  68. d = {}
  69. for idx, v in enumerate(obj.__dict__["_content"]):
  70. if self._is_simple_value(v):
  71. v = v._value()
  72. d[str(idx)] = v
  73. else:
  74. d = {}
  75. return d
  76. def get_str(self, val: Any) -> str:
  77. if val._is_missing():
  78. return "??? <MISSING>"
  79. if val._is_interpolation():
  80. try:
  81. dr = val._dereference_node()
  82. except self.InterpolationResolutionError as e:
  83. dr = f"ERR: {e}"
  84. return f"{val._value()} -> {dr}"
  85. else:
  86. return f"{val}"
  87. # OC_PYDEVD_RESOLVER env can take:
  88. # DISABLE: Do not install a pydevd resolver
  89. # USER: Install a resolver for OmegaConf users (default)
  90. # DEV: Install a resolver for OmegaConf developers. Shows underlying data-model in the debugger.
  91. resolver = os.environ.get("OC_PYDEVD_RESOLVER", "USER").upper()
  92. if resolver != "DISABLE": # pragma: no cover
  93. if resolver == "USER":
  94. TypeResolveProvider.register(OmegaConfUserResolver)
  95. elif resolver == "DEV":
  96. TypeResolveProvider.register(OmegaConfDeveloperResolver)
  97. else:
  98. sys.stderr.write(
  99. f"OmegaConf pydev plugin: Not installing. Unknown mode {resolver}. Supported one of [USER, DEV, DISABLE]\n"
  100. )