format_utils.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. from ray.dag import DAGNode
  2. from ray.util.annotations import DeveloperAPI
  3. @DeveloperAPI
  4. def get_dag_node_str(
  5. dag_node: DAGNode,
  6. body_line,
  7. ):
  8. indent = _get_indentation()
  9. other_args_to_resolve_lines = _get_other_args_to_resolve_lines(
  10. dag_node._bound_other_args_to_resolve
  11. )
  12. return (
  13. f"({dag_node.__class__.__name__}, {dag_node._stable_uuid})(\n"
  14. f"{indent}body={body_line}\n"
  15. f"{indent}args={_get_args_lines(dag_node._bound_args)}\n"
  16. f"{indent}kwargs={_get_kwargs_lines(dag_node._bound_kwargs)}\n"
  17. f"{indent}options={_get_options_lines(dag_node._bound_options)}\n"
  18. f"{indent}other_args_to_resolve={other_args_to_resolve_lines}\n"
  19. f")"
  20. )
  21. def _get_indentation(num_spaces=4):
  22. return " " * num_spaces
  23. def _get_args_lines(bound_args):
  24. """Pretty prints bounded args of a DAGNode, and recursively handle
  25. DAGNode in list / dict containers.
  26. """
  27. indent = _get_indentation()
  28. lines = []
  29. for arg in bound_args:
  30. if isinstance(arg, DAGNode):
  31. node_repr_lines = str(arg).split("\n")
  32. for node_repr_line in node_repr_lines:
  33. lines.append(f"{indent}" + node_repr_line)
  34. elif isinstance(arg, list):
  35. for ele in arg:
  36. node_repr_lines = str(ele).split("\n")
  37. for node_repr_line in node_repr_lines:
  38. lines.append(f"{indent}" + node_repr_line)
  39. elif isinstance(arg, dict):
  40. for _, val in arg.items():
  41. node_repr_lines = str(val).split("\n")
  42. for node_repr_line in node_repr_lines:
  43. lines.append(f"{indent}" + node_repr_line)
  44. # TODO: (jiaodong) Handle nested containers and other obj types
  45. else:
  46. lines.append(f"{indent}" + str(arg) + ", ")
  47. if len(lines) == 0:
  48. args_line = "[]"
  49. else:
  50. args_line = "["
  51. for args in lines:
  52. args_line += f"\n{indent}{args}"
  53. args_line += f"\n{indent}]"
  54. return args_line
  55. def _get_kwargs_lines(bound_kwargs):
  56. """Pretty prints bounded kwargs of a DAGNode, and recursively handle
  57. DAGNode in list / dict containers.
  58. """
  59. # TODO: (jiaodong) Nits, we're missing keys and indentation was a bit off.
  60. if not bound_kwargs:
  61. return "{}"
  62. indent = _get_indentation()
  63. kwargs_lines = []
  64. for key, val in bound_kwargs.items():
  65. if isinstance(val, DAGNode):
  66. node_repr_lines = str(val).split("\n")
  67. for index, node_repr_line in enumerate(node_repr_lines):
  68. if index == 0:
  69. kwargs_lines.append(
  70. f"{indent}{key}:" + f"{indent}" + node_repr_line
  71. )
  72. else:
  73. kwargs_lines.append(f"{indent}{indent}" + node_repr_line)
  74. elif isinstance(val, list):
  75. for ele in val:
  76. node_repr_lines = str(ele).split("\n")
  77. for node_repr_line in node_repr_lines:
  78. kwargs_lines.append(f"{indent}" + node_repr_line)
  79. elif isinstance(val, dict):
  80. for _, inner_val in val.items():
  81. node_repr_lines = str(inner_val).split("\n")
  82. for node_repr_line in node_repr_lines:
  83. kwargs_lines.append(f"{indent}" + node_repr_line)
  84. # TODO: (jiaodong) Handle nested containers and other obj types
  85. else:
  86. kwargs_lines.append(val)
  87. if len(kwargs_lines) > 0:
  88. kwargs_line = "{"
  89. for line in kwargs_lines:
  90. kwargs_line += f"\n{indent}{line}"
  91. kwargs_line += f"\n{indent}}}"
  92. else:
  93. kwargs_line = "{}"
  94. return kwargs_line
  95. def _get_options_lines(bound_options):
  96. """Pretty prints .options() in DAGNode. Only prints non-empty values."""
  97. if not bound_options:
  98. return "{}"
  99. indent = _get_indentation()
  100. options_lines = []
  101. for key, val in bound_options.items():
  102. if val:
  103. options_lines.append(f"{indent}{key}: " + str(val))
  104. options_line = "{"
  105. for line in options_lines:
  106. options_line += f"\n{indent}{line}"
  107. options_line += f"\n{indent}}}"
  108. return options_line
  109. def _get_other_args_to_resolve_lines(other_args_to_resolve):
  110. if not other_args_to_resolve:
  111. return "{}"
  112. indent = _get_indentation()
  113. other_args_to_resolve_lines = []
  114. for key, val in other_args_to_resolve.items():
  115. if isinstance(val, DAGNode):
  116. node_repr_lines = str(val).split("\n")
  117. for index, node_repr_line in enumerate(node_repr_lines):
  118. if index == 0:
  119. other_args_to_resolve_lines.append(
  120. f"{indent}{key}:"
  121. + f"{indent}"
  122. + "\n"
  123. + f"{indent}{indent}{indent}"
  124. + node_repr_line
  125. )
  126. else:
  127. other_args_to_resolve_lines.append(
  128. f"{indent}{indent}" + node_repr_line
  129. )
  130. else:
  131. other_args_to_resolve_lines.append(f"{indent}{key}: " + str(val))
  132. other_args_to_resolve_line = "{"
  133. for line in other_args_to_resolve_lines:
  134. other_args_to_resolve_line += f"\n{indent}{line}"
  135. other_args_to_resolve_line += f"\n{indent}}}"
  136. return other_args_to_resolve_line