zrb 1.0.0a12__py3-none-any.whl → 1.0.0a15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. zrb/builtin/git.py +22 -20
  2. zrb/builtin/git_subtree.py +12 -9
  3. zrb/builtin/project/add/fastapp.py +32 -17
  4. zrb/builtin/project/add/fastapp_template/_zrb/column/create_column_task.py +11 -0
  5. zrb/builtin/project/add/fastapp_template/_zrb/config.py +4 -4
  6. zrb/builtin/project/add/fastapp_template/_zrb/entity/create_entity_task.py +196 -0
  7. zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/my_entity_usecase.py +66 -0
  8. zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/factory.py +13 -0
  9. zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/my_entity_db_repository.py +33 -0
  10. zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/my_entity_repository.py +39 -0
  11. zrb/builtin/project/add/fastapp_template/_zrb/entity/schema.template.py +29 -0
  12. zrb/builtin/project/add/fastapp_template/_zrb/group.py +9 -5
  13. zrb/builtin/project/add/fastapp_template/_zrb/helper.py +25 -11
  14. zrb/builtin/project/add/fastapp_template/_zrb/input.py +43 -0
  15. zrb/builtin/project/add/fastapp_template/_zrb/main.py +30 -21
  16. zrb/builtin/project/add/fastapp_template/_zrb/module/create_module_task.py +136 -0
  17. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/alembic.ini +117 -0
  18. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/api_client.py +6 -0
  19. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/direct_client.py +6 -0
  20. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/factory.py +9 -0
  21. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/README +1 -0
  22. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/env.py +108 -0
  23. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/script.py.mako +26 -0
  24. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/versions/3093c7336477_add_user_table.py +37 -0
  25. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration_metadata.py +3 -0
  26. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/route.py +19 -0
  27. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/service/__init__.py +0 -0
  28. zrb/builtin/project/add/fastapp_template/_zrb/module/run_module.template.py +26 -0
  29. zrb/builtin/project/add/fastapp_template/_zrb/venv_task.py +2 -5
  30. zrb/builtin/project/add/fastapp_template/common/app.py +3 -1
  31. zrb/builtin/project/add/fastapp_template/config.py +7 -7
  32. zrb/builtin/project/add/fastapp_template/module/auth/client/any_client.py +27 -0
  33. zrb/builtin/project/add/fastapp_template/module/auth/client/api_client.py +2 -2
  34. zrb/builtin/project/add/fastapp_template/module/auth/client/direct_client.py +2 -2
  35. zrb/builtin/project/add/fastapp_template/module/auth/client/factory.py +1 -1
  36. zrb/builtin/project/add/fastapp_template/module/auth/route.py +1 -1
  37. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/factory.py +2 -2
  38. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/{db_repository.py → user_db_repository.py} +2 -2
  39. zrb/builtin/project/add/fastapp_template/module/auth/service/user/{usecase.py → user_usecase.py} +15 -8
  40. zrb/builtin/project/add/fastapp_template/requirements.txt +5 -6
  41. zrb/builtin/project/add/fastapp_template/schema/permission.py +31 -0
  42. zrb/builtin/project/add/fastapp_template/template.env +2 -2
  43. zrb/builtin/project/create/create.py +2 -2
  44. zrb/builtin/project/create/project-template/zrb_init.py +0 -4
  45. zrb/builtin/todo.py +19 -2
  46. zrb/config.py +1 -2
  47. zrb/content_transformer/content_transformer.py +14 -2
  48. zrb/context/context.py +13 -10
  49. zrb/input/base_input.py +2 -1
  50. zrb/runner/cli.py +16 -5
  51. zrb/runner/web_app.py +3 -3
  52. zrb/runner/web_controller/task_ui/controller.py +8 -6
  53. zrb/session/session.py +4 -1
  54. zrb/task/cmd_task.py +17 -50
  55. zrb/task/scaffolder.py +7 -9
  56. zrb/util/cli/style.py +7 -0
  57. zrb/util/cmd/command.py +60 -0
  58. zrb/util/codemod/add_code_to_module.py +12 -0
  59. zrb/util/git.py +115 -133
  60. zrb/util/git_subtree.py +73 -55
  61. zrb/util/load.py +8 -9
  62. zrb/util/string/conversion.py +52 -0
  63. zrb/util/todo.py +2 -2
  64. {zrb-1.0.0a12.dist-info → zrb-1.0.0a15.dist-info}/METADATA +1 -1
  65. {zrb-1.0.0a12.dist-info → zrb-1.0.0a15.dist-info}/RECORD +71 -47
  66. /zrb/builtin/project/add/fastapp_template/{module/auth/client/base_client.py → _zrb/module/module_template/client/any_client.py} +0 -0
  67. /zrb/builtin/project/add/fastapp_template/common/{db_repository.py → base_db_repository.py} +0 -0
  68. /zrb/builtin/project/add/fastapp_template/common/{usecase.py → base_usecase.py} +0 -0
  69. /zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/{repository.py → user_repository.py} +0 -0
  70. {zrb-1.0.0a12.dist-info → zrb-1.0.0a15.dist-info}/WHEEL +0 -0
  71. {zrb-1.0.0a12.dist-info → zrb-1.0.0a15.dist-info}/entry_points.txt +0 -0
zrb/session/session.py CHANGED
@@ -28,6 +28,7 @@ from zrb.util.cli.style import (
28
28
  ICONS,
29
29
  MAGENTA,
30
30
  YELLOW,
31
+ remove_style,
31
32
  )
32
33
  from zrb.util.group import get_node_path
33
34
  from zrb.util.string.name import get_random_name
@@ -165,7 +166,9 @@ class Session(AnySession):
165
166
  main_task_name=self._main_task.name,
166
167
  path=self.task_path,
167
168
  final_result=(
168
- f"{self.final_result}" if self.final_result is not None else ""
169
+ remove_style(f"{self.final_result}")
170
+ if self.final_result is not None
171
+ else ""
169
172
  ),
170
173
  finished=self.is_terminated,
171
174
  log=self.shared_ctx.shared_log,
zrb/task/cmd_task.py CHANGED
@@ -1,6 +1,4 @@
1
- import asyncio
2
1
  import os
3
- import sys
4
2
 
5
3
  from zrb.attr.type import BoolAttr, IntAttr, StrAttr
6
4
  from zrb.cmd.cmd_result import CmdResult
@@ -12,7 +10,7 @@ from zrb.input.any_input import AnyInput
12
10
  from zrb.task.any_task import AnyTask
13
11
  from zrb.task.base_task import BaseTask
14
12
  from zrb.util.attr import get_int_attr, get_str_attr
15
- from zrb.util.cmd.command import check_unrecommended_commands
13
+ from zrb.util.cmd.command import check_unrecommended_commands, run_command
16
14
  from zrb.util.cmd.remote import get_remote_cmd_script
17
15
 
18
16
 
@@ -119,43 +117,25 @@ class CmdTask(BaseTask):
119
117
  ctx.log_debug(f"Working directory: {cwd}")
120
118
  env_map = self.__get_env_map(ctx)
121
119
  ctx.log_debug(f"Environment map: {env_map}")
122
- cmd_process = None
123
120
  if self._get_should_warn_unrecommended_commands():
124
121
  self._check_unrecommended_commands(ctx, shell, cmd_script)
125
- try:
126
- ctx.log_info("Running script")
127
- cmd_process = await asyncio.create_subprocess_exec(
128
- shell,
129
- shell_flag,
130
- cmd_script,
131
- cwd=cwd,
132
- stdin=sys.stdin if sys.stdin.isatty() else None,
133
- stdout=asyncio.subprocess.PIPE,
134
- stderr=asyncio.subprocess.PIPE,
135
- env=env_map,
136
- bufsize=0,
137
- )
138
- stdout_task = asyncio.create_task(
139
- self.__read_stream(cmd_process.stdout, ctx.print, self._max_output_line)
140
- )
141
- stderr_task = asyncio.create_task(
142
- self.__read_stream(cmd_process.stderr, ctx.print, self._max_error_line)
122
+ ctx.log_info("Running script")
123
+ cmd_result, return_code = await run_command(
124
+ cmd=[shell, shell_flag, cmd_script],
125
+ cwd=cwd,
126
+ env_map=env_map,
127
+ log_method=ctx.print,
128
+ max_output_line=self._max_output_line,
129
+ max_error_line=self._max_error_line,
130
+ )
131
+ # Check for errors
132
+ if return_code != 0:
133
+ ctx.log_error(f"Exit status: {return_code}")
134
+ raise Exception(
135
+ f"Process {self._name} exited ({return_code}): {cmd_result.stderr}"
143
136
  )
144
- # Wait for process to complete and gather stdout/stderr
145
- return_code = await cmd_process.wait()
146
- stdout = await stdout_task
147
- stderr = await stderr_task
148
- # Check for errors
149
- if return_code != 0:
150
- ctx.log_error(f"Exit status: {return_code}")
151
- raise Exception(
152
- f"Process {self._name} exited ({return_code}): {stderr}"
153
- )
154
- ctx.log_info(f"Exit status: {return_code}")
155
- return CmdResult(stdout, stderr)
156
- finally:
157
- if cmd_process is not None and cmd_process.returncode is None:
158
- cmd_process.terminate()
137
+ ctx.log_info(f"Exit status: {return_code}")
138
+ return cmd_result
159
139
 
160
140
  def _get_should_warn_unrecommended_commands(self):
161
141
  if self._should_warn_unrecommended_command is None:
@@ -178,19 +158,6 @@ class CmdTask(BaseTask):
178
158
  envs["PYTHONBUFFERED"] = "1"
179
159
  return envs
180
160
 
181
- async def __read_stream(self, stream, log_method, max_lines):
182
- lines = []
183
- while True:
184
- line = await stream.readline()
185
- if not line:
186
- break
187
- line = line.decode("utf-8").rstrip()
188
- lines.append(line)
189
- if len(lines) > max_lines:
190
- lines.pop(0) # Keep only the last max_lines
191
- log_method(line)
192
- return "\n".join(lines)
193
-
194
161
  def _get_shell(self, ctx: AnyContext) -> str:
195
162
  return get_str_attr(
196
163
  ctx, self._shell, DEFAULT_SHELL, auto_render=self._render_shell
zrb/task/scaffolder.py CHANGED
@@ -92,8 +92,8 @@ class Scaffolder(BaseTask):
92
92
  destination_path = self._get_destination_path(ctx)
93
93
  self._copy_path(ctx, source_path, destination_path)
94
94
  transformers = self._get_content_transformers()
95
- file_paths = self._get_all_file_paths(destination_path)
96
- for file_path in file_paths:
95
+ file_path_list = self._get_all_file_paths(destination_path)
96
+ for file_path in file_path_list:
97
97
  for transformer in transformers:
98
98
  if transformer.match(ctx, file_path):
99
99
  try:
@@ -118,14 +118,10 @@ class Scaffolder(BaseTask):
118
118
  dest_dir, self._transform_path(ctx, file_name)
119
119
  )
120
120
  shutil.copy2(src_file, dest_file)
121
- ctx.log_info(f"Copied and renamed {src_file} to {dest_file}")
121
+ ctx.log_info(f"Copied {src_file} to {dest_file}")
122
122
  else:
123
- dest_file = os.path.join(
124
- destination_path,
125
- self._transform_path(ctx, os.path.basename(source_path)),
126
- )
127
- shutil.copy2(source_path, dest_file)
128
- ctx.log_info(f"Copied and renamed {source_path} to {dest_file}")
123
+ shutil.copy2(source_path, destination_path)
124
+ ctx.log_info(f"Copied {source_path} to {destination_path}")
129
125
 
130
126
  def _transform_path(self, ctx: AnyContext, file_path: str):
131
127
  if callable(self._path_transformer):
@@ -139,6 +135,8 @@ class Scaffolder(BaseTask):
139
135
  """
140
136
  Returns a list of absolute file paths for all files in the given path, recursively.
141
137
  """
138
+ if os.path.isfile(path):
139
+ return [os.path.abspath(path)]
142
140
  file_paths = []
143
141
  for root, _, files in os.walk(path):
144
142
  for file in files:
zrb/util/cli/style.py CHANGED
@@ -1,3 +1,5 @@
1
+ import re
2
+
1
3
  BLACK = 30
2
4
  RED = 31
3
5
  GREEN = 32
@@ -118,6 +120,11 @@ ICONS = [
118
120
  ]
119
121
 
120
122
 
123
+ def remove_style(text):
124
+ ansi_escape = re.compile(r"\x1B[@-_][0-?]*[ -/]*[@-~]")
125
+ return ansi_escape.sub("", text)
126
+
127
+
121
128
  def stylize(
122
129
  text: str,
123
130
  color: int | None = None,
zrb/util/cmd/command.py CHANGED
@@ -1,4 +1,10 @@
1
+ import asyncio
2
+ import os
1
3
  import re
4
+ import sys
5
+ from collections.abc import Callable
6
+
7
+ from zrb.cmd.cmd_result import CmdResult
2
8
 
3
9
 
4
10
  def check_unrecommended_commands(cmd_script: str) -> dict[str, str]:
@@ -31,3 +37,57 @@ def check_unrecommended_commands(cmd_script: str) -> dict[str, str]:
31
37
  if re.search(pattern, cmd_script):
32
38
  violations[pattern] = reason
33
39
  return violations
40
+
41
+
42
+ async def run_command(
43
+ cmd: list[str],
44
+ cwd: str | None = None,
45
+ env_map: dict[str, str] | None = None,
46
+ log_method: Callable[..., None] = print,
47
+ max_output_line: int = 1000,
48
+ max_error_line: int = 1000,
49
+ ) -> tuple[CmdResult, int]:
50
+
51
+ async def __read_stream(
52
+ stream, log_method: Callable[..., None], max_lines: int
53
+ ) -> str:
54
+ lines = []
55
+ while True:
56
+ line = await stream.readline()
57
+ if not line:
58
+ break
59
+ line = line.decode("utf-8").rstrip()
60
+ lines.append(line)
61
+ if len(lines) > max_lines:
62
+ lines.pop(0) # Keep only the last max_lines
63
+ log_method(line)
64
+ return "\n".join(lines)
65
+
66
+ try:
67
+ if cwd is None:
68
+ cwd = os.getcwd()
69
+ if env_map is None:
70
+ env_map = os.environ
71
+ cmd_process = await asyncio.create_subprocess_exec(
72
+ *cmd,
73
+ cwd=cwd,
74
+ stdin=sys.stdin if sys.stdin.isatty() else None,
75
+ stdout=asyncio.subprocess.PIPE,
76
+ stderr=asyncio.subprocess.PIPE,
77
+ env=env_map,
78
+ bufsize=0,
79
+ )
80
+ stdout_task = asyncio.create_task(
81
+ __read_stream(cmd_process.stdout, log_method, max_output_line)
82
+ )
83
+ stderr_task = asyncio.create_task(
84
+ __read_stream(cmd_process.stderr, log_method, max_error_line)
85
+ )
86
+ # Wait for process to complete and gather stdout/stderr
87
+ return_code = await cmd_process.wait()
88
+ stdout = await stdout_task
89
+ stderr = await stderr_task
90
+ return CmdResult(stdout, stderr), return_code
91
+ finally:
92
+ if cmd_process is not None and cmd_process.returncode is None:
93
+ cmd_process.terminate()
@@ -0,0 +1,12 @@
1
+ def add_code_to_module(source_code: str, new_code: str) -> str:
2
+ lines = source_code.splitlines()
3
+ last_import_index = -1
4
+ for i, line in enumerate(lines):
5
+ stripped_line = line.strip()
6
+ if stripped_line.startswith("import") or stripped_line.startswith("from"):
7
+ last_import_index = i
8
+ elif stripped_line and not stripped_line.startswith("#"):
9
+ break
10
+ if last_import_index != -1:
11
+ lines.insert(last_import_index + 1, new_code)
12
+ return "\n".join(lines)
zrb/util/git.py CHANGED
@@ -1,8 +1,11 @@
1
1
  import os
2
- import subprocess
2
+ from collections.abc import Callable
3
+ from typing import Any
3
4
 
4
5
  from pydantic import BaseModel
5
6
 
7
+ from zrb.util.cmd.command import run_command
8
+
6
9
 
7
10
  class DiffResult(BaseModel):
8
11
  created: list[str]
@@ -10,19 +13,20 @@ class DiffResult(BaseModel):
10
13
  updated: list[str]
11
14
 
12
15
 
13
- def get_diff(repo_dir: str, source_commit: str, current_commit: str) -> DiffResult:
14
- try:
15
- result = subprocess.run(
16
- ["git", "diff", source_commit, current_commit],
17
- stdout=subprocess.PIPE,
18
- stderr=subprocess.PIPE,
19
- cwd=repo_dir,
20
- text=True,
21
- check=True,
22
- )
23
- except subprocess.CalledProcessError as e:
24
- raise Exception(e.stderr or e.stdout)
25
- lines = result.stdout.strip().split("\n")
16
+ async def get_diff(
17
+ repo_dir: str,
18
+ source_commit: str,
19
+ current_commit: str,
20
+ log_method: Callable[..., Any] = print,
21
+ ) -> DiffResult:
22
+ cmd_result, exit_code = await run_command(
23
+ cmd=["git", "diff", source_commit, current_commit],
24
+ cwd=repo_dir,
25
+ log_method=log_method,
26
+ )
27
+ if exit_code != 0:
28
+ raise Exception(f"Non zero exit code: {exit_code}")
29
+ lines = cmd_result.output.strip().split("\n")
26
30
  diff: dict[str, dict[str, bool]] = {}
27
31
  for line in lines:
28
32
  if not line.startswith("---") and not line.startswith("+++"):
@@ -50,125 +54,103 @@ def get_diff(repo_dir: str, source_commit: str, current_commit: str) -> DiffResu
50
54
  )
51
55
 
52
56
 
53
- def get_repo_dir() -> str:
54
- try:
55
- # Run the Git command to get the repository's top-level directory
56
- result = subprocess.run(
57
- ["git", "rev-parse", "--show-toplevel"],
58
- stdout=subprocess.PIPE,
59
- stderr=subprocess.PIPE,
60
- text=True,
61
- check=True,
62
- )
63
- # Return the directory path
64
- return os.path.abspath(result.stdout.strip())
65
- except subprocess.CalledProcessError as e:
66
- raise Exception(e.stderr or e.stdout)
67
-
68
-
69
- def get_current_branch(repo_dir: str) -> str:
70
- try:
71
- result = subprocess.run(
72
- ["git", "rev-parse", "--abbrev-ref", "HEAD"],
73
- stdout=subprocess.PIPE,
74
- stderr=subprocess.PIPE,
75
- cwd=repo_dir,
76
- text=True,
77
- check=True,
78
- )
79
- return result.stdout.strip()
80
- except subprocess.CalledProcessError as e:
81
- raise Exception(e.stderr or e.stdout)
82
-
83
-
84
- def get_branches(repo_dir: str) -> list[str]:
85
- try:
86
- result = subprocess.run(
87
- ["git", "branch"],
88
- stdout=subprocess.PIPE,
89
- stderr=subprocess.PIPE,
90
- cwd=repo_dir,
91
- text=True,
92
- check=True,
93
- )
94
- return [
95
- branch.lstrip("*").strip() for branch in result.stdout.strip().split("\n")
96
- ]
97
- except subprocess.CalledProcessError as e:
98
- raise Exception(e.stderr or e.stdout)
99
-
100
-
101
- def delete_branch(repo_dir: str, branch_name: str) -> str:
102
- try:
103
- result = subprocess.run(
104
- ["git", "branch", "-D", branch_name],
105
- stdout=subprocess.PIPE,
106
- stderr=subprocess.PIPE,
107
- cwd=repo_dir,
108
- text=True,
109
- check=True,
110
- )
111
- return result.stdout.strip()
112
- except subprocess.CalledProcessError as e:
113
- raise Exception(e.stderr or e.stdout)
114
-
115
-
116
- def add(repo_dir: str) -> str:
117
- try:
118
- subprocess.run(
119
- ["git", "add", ".", "-A"],
120
- stdout=subprocess.PIPE,
121
- stderr=subprocess.PIPE,
122
- cwd=repo_dir,
123
- text=True,
124
- check=True,
125
- )
126
- except subprocess.CalledProcessError as e:
127
- raise Exception(e.stderr or e.stdout)
128
-
129
-
130
- def commit(repo_dir: str, message: str) -> str:
131
- try:
132
- subprocess.run(
133
- ["git", "commit", "-m", message],
134
- stdout=subprocess.PIPE,
135
- stderr=subprocess.PIPE,
136
- cwd=repo_dir,
137
- text=True,
138
- check=True,
139
- )
140
- except subprocess.CalledProcessError as e:
57
+ async def get_repo_dir(log_method: Callable[..., Any] = print) -> str:
58
+ cmd_result, exit_code = await run_command(
59
+ cmd=["git", "rev-parse", "--show-toplevel"],
60
+ log_method=log_method,
61
+ )
62
+ if exit_code != 0:
63
+ raise Exception(f"Non zero exit code: {exit_code}")
64
+ return os.path.abspath(cmd_result.output.strip())
65
+
66
+
67
+ async def get_current_branch(
68
+ repo_dir: str, log_method: Callable[..., Any] = print
69
+ ) -> str:
70
+ cmd_result, exit_code = await run_command(
71
+ cmd=["git", "rev-parse", "--abbrev-ref", "HEAD"],
72
+ cwd=repo_dir,
73
+ log_method=log_method,
74
+ )
75
+ if exit_code != 0:
76
+ raise Exception(f"Non zero exit code: {exit_code}")
77
+ return cmd_result.output.strip()
78
+
79
+
80
+ async def get_branches(
81
+ repo_dir: str, log_method: Callable[..., Any] = print
82
+ ) -> list[str]:
83
+ cmd_result, exit_code = await run_command(
84
+ cmd=["git", "rev-parse", "--abbrev-ref", "HEAD"],
85
+ cwd=repo_dir,
86
+ log_method=log_method,
87
+ )
88
+ if exit_code != 0:
89
+ raise Exception(f"Non zero exit code: {exit_code}")
90
+ return [
91
+ branch.lstrip("*").strip() for branch in cmd_result.output.strip().split("\n")
92
+ ]
93
+
94
+
95
+ async def delete_branch(
96
+ repo_dir: str, branch_name: str, log_method: Callable[..., Any] = print
97
+ ) -> str:
98
+ cmd_result, exit_code = await run_command(
99
+ cmd=["git", "branch", "-D", branch_name],
100
+ cwd=repo_dir,
101
+ log_method=log_method,
102
+ )
103
+ if exit_code != 0:
104
+ raise Exception(f"Non zero exit code: {exit_code}")
105
+ return cmd_result.output.strip()
106
+
107
+
108
+ async def add(repo_dir: str, log_method: Callable[..., Any] = print):
109
+ _, exit_code = await run_command(
110
+ cmd=["git", "add", ".", "-A"],
111
+ cwd=repo_dir,
112
+ log_method=log_method,
113
+ )
114
+ if exit_code != 0:
115
+ raise Exception(f"Non zero exit code: {exit_code}")
116
+
117
+
118
+ async def commit(
119
+ repo_dir: str, message: str, log_method: Callable[..., Any] = print
120
+ ) -> str:
121
+ cmd_result, exit_code = await run_command(
122
+ cmd=["git", "commit", "-m", message],
123
+ cwd=repo_dir,
124
+ log_method=log_method,
125
+ )
126
+ if exit_code != 0:
141
127
  ignored_error_message = "nothing to commit, working tree clean"
142
128
  if (
143
- ignored_error_message not in e.stderr
144
- and ignored_error_message not in e.stdout
129
+ ignored_error_message not in cmd_result.error
130
+ and ignored_error_message not in cmd_result.output
145
131
  ):
146
- raise Exception(e.stderr or e.stdout)
147
-
148
-
149
- def pull(repo_dir: str, remote: str, branch: str) -> str:
150
- try:
151
- subprocess.run(
152
- ["git", "pull", remote, branch],
153
- stdout=subprocess.PIPE,
154
- stderr=subprocess.PIPE,
155
- cwd=repo_dir,
156
- text=True,
157
- check=True,
158
- )
159
- except subprocess.CalledProcessError as e:
160
- raise Exception(e.stderr or e.stdout)
161
-
162
-
163
- def push(repo_dir: str, remote: str, branch: str) -> str:
164
- try:
165
- subprocess.run(
166
- ["git", "push", "-u", remote, branch],
167
- stdout=subprocess.PIPE,
168
- stderr=subprocess.PIPE,
169
- cwd=repo_dir,
170
- text=True,
171
- check=True,
172
- )
173
- except subprocess.CalledProcessError as e:
174
- raise Exception(e.stderr or e.stdout)
132
+ raise Exception(f"Non zero exit code: {exit_code}")
133
+
134
+
135
+ async def pull(
136
+ repo_dir: str, remote: str, branch: str, log_method: Callable[..., Any] = print
137
+ ) -> str:
138
+ _, exit_code = await run_command(
139
+ cmd=["git", "pull", remote, branch],
140
+ cwd=repo_dir,
141
+ log_method=log_method,
142
+ )
143
+ if exit_code != 0:
144
+ raise Exception(f"Non zero exit code: {exit_code}")
145
+
146
+
147
+ async def push(
148
+ repo_dir: str, remote: str, branch: str, log_method: Callable[..., Any] = print
149
+ ) -> str:
150
+ _, exit_code = await run_command(
151
+ cmd=["git", "push", "-u", remote, branch],
152
+ cwd=repo_dir,
153
+ log_method=log_method,
154
+ )
155
+ if exit_code != 0:
156
+ raise Exception(f"Non zero exit code: {exit_code}")