You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

131 lines
2.8 KiB

  1. # imports - standard imports
  2. import sys
  3. from io import StringIO
  4. # imports - third party imports
  5. import click
  6. # imports - module imports
  7. import bench
  8. class Capturing(list):
  9. """
  10. Util to consume the stdout encompassed in it and push it to a list
  11. with Capturing() as output:
  12. subprocess.check_output("ls", shell=True)
  13. print(output)
  14. # ["b'Applications\\nDesktop\\nDocuments\\nDownloads\\n'"]
  15. """
  16. def __enter__(self):
  17. self._stdout = sys.stdout
  18. sys.stdout = self._stringio = StringIO()
  19. return self
  20. def __exit__(self, *args):
  21. self.extend(self._stringio.getvalue().splitlines())
  22. del self._stringio # free up some memory
  23. sys.stdout = self._stdout
  24. class Rendering:
  25. def __init__(self, success, title, is_parent, args, kwargs):
  26. import bench.cli
  27. self.dynamic_feed = bench.cli.from_command_line and bench.cli.dynamic_feed
  28. if not self.dynamic_feed:
  29. return
  30. try:
  31. self.kw = args[0].__dict__
  32. except Exception:
  33. self.kw = kwargs
  34. self.is_parent = is_parent
  35. self.title = title
  36. self.success = success
  37. def __enter__(self, *args, **kwargs):
  38. if not self.dynamic_feed:
  39. return
  40. _prefix = click.style("⏼", fg="bright_yellow")
  41. _hierarchy = "" if self.is_parent else " "
  42. self._title = self.title.format(**self.kw)
  43. click.secho(f"{_hierarchy}{_prefix} {self._title}")
  44. bench.LOG_BUFFER.append(
  45. {
  46. "message": self._title,
  47. "prefix": _prefix,
  48. "color": None,
  49. "is_parent": self.is_parent,
  50. }
  51. )
  52. def __exit__(self, *args, **kwargs):
  53. if not self.dynamic_feed:
  54. return
  55. self._prefix = click.style("✔", fg="green")
  56. self._success = self.success.format(**self.kw)
  57. self.render_screen()
  58. def render_screen(self):
  59. click.clear()
  60. for l in bench.LOG_BUFFER:
  61. if l["message"] == self._title:
  62. l["prefix"] = self._prefix
  63. l["message"] = self._success
  64. _hierarchy = "" if l.get("is_parent") else " "
  65. click.secho(f'{_hierarchy}{l["prefix"]} {l["message"]}', fg=l["color"])
  66. def job(title: str = None, success: str = None):
  67. """Supposed to be wrapped around an atomic job in a given process.
  68. For instance, the `get-app` command consists of two jobs: `initializing bench`
  69. and `fetching and installing app`.
  70. """
  71. def innfn(fn):
  72. def wrapper_fn(*args, **kwargs):
  73. with Rendering(
  74. success=success,
  75. title=title,
  76. is_parent=True,
  77. args=args,
  78. kwargs=kwargs,
  79. ):
  80. return fn(*args, **kwargs)
  81. return wrapper_fn
  82. return innfn
  83. def step(title: str = None, success: str = None):
  84. """Supposed to be wrapped around the smallest possible atomic step in a given operation.
  85. For instance, `building assets` is a step in the update operation.
  86. """
  87. def innfn(fn):
  88. def wrapper_fn(*args, **kwargs):
  89. with Rendering(
  90. success=success,
  91. title=title,
  92. is_parent=False,
  93. args=args,
  94. kwargs=kwargs,
  95. ):
  96. return fn(*args, **kwargs)
  97. return wrapper_fn
  98. return innfn