gitbolt 0.0.0.dev16__tar.gz → 0.0.0.dev17__tar.gz

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 (36) hide show
  1. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/PKG-INFO +2 -2
  2. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/pyproject.toml +2 -2
  3. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/base.py +87 -0
  4. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/impl/simple.py +13 -1
  5. gitbolt-0.0.0.dev17/src/gitbolt/subprocess/session.py +33 -0
  6. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/PKG-INFO +2 -2
  7. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/SOURCES.txt +1 -0
  8. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/requires.txt +1 -1
  9. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/LICENSE +0 -0
  10. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/README.md +0 -0
  11. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/setup.cfg +0 -0
  12. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/__init__.py +0 -0
  13. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/_internal_init.py +0 -0
  14. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/add.py +0 -0
  15. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/base.py +0 -0
  16. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/constants.py +0 -0
  17. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/exceptions.py +0 -0
  18. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/ls_tree.py +0 -0
  19. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/models.py +0 -0
  20. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/py.typed +0 -0
  21. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/pytest_plugin.py +0 -0
  22. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/__init__.py +0 -0
  23. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/_internal_init.py +0 -0
  24. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/add.py +0 -0
  25. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/constants.py +0 -0
  26. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/exceptions.py +0 -0
  27. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/impl/__init__.py +0 -0
  28. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/ls_tree.py +0 -0
  29. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/__init__.py +0 -0
  30. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/base.py +0 -0
  31. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/simple.py +0 -0
  32. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/utils.py +0 -0
  33. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/utils.py +0 -0
  34. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/dependency_links.txt +0 -0
  35. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/entry_points.txt +0 -0
  36. {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitbolt
3
- Version: 0.0.0.dev16
3
+ Version: 0.0.0.dev17
4
4
  Summary: Fast, flexible and type-safe Git commands in Python.
5
5
  Author-email: Suhas Krishna Srivastava <suhas.srivastava@vaastav.tech>
6
6
  Maintainer-email: Suhas Krishna Srivastava <suhas.srivastava@vaastav.tech>
@@ -27,7 +27,7 @@ Requires-Python: >=3.12
27
27
  Description-Content-Type: text/markdown
28
28
  License-File: LICENSE
29
29
  Requires-Dist: vt-err-hndlr>=0.0.0dev6
30
- Requires-Dist: vt-commons>=0.0.1.dev9
30
+ Requires-Dist: vt-commons>=0.0.1.dev11
31
31
  Provides-Extra: pygit2
32
32
  Requires-Dist: pygit2; extra == "pygit2"
33
33
  Provides-Extra: test
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gitbolt"
3
- version = "0.0.0.dev16"
3
+ version = "0.0.0.dev17"
4
4
  description = "Fast, flexible and type-safe Git commands in Python."
5
5
  requires-python = ">=3.12"
6
6
  readme = "README.md"
@@ -37,7 +37,7 @@ classifiers = [
37
37
  ]
38
38
  dependencies = [
39
39
  "vt-err-hndlr >= 0.0.0dev6",
40
- "vt-commons >= 0.0.1.dev9",
40
+ "vt-commons >= 0.0.1.dev11",
41
41
  ]
42
42
 
43
43
  [project.optional-dependencies]
@@ -9,8 +9,10 @@ from __future__ import annotations
9
9
 
10
10
  from abc import abstractmethod, ABC
11
11
  from collections.abc import Callable
12
+ from contextlib import AbstractContextManager
12
13
  from pathlib import Path
13
14
  from subprocess import CompletedProcess, Popen, PIPE
15
+ from types import SimpleNamespace
14
16
  from typing import override, Protocol, Unpack, Self, overload, Literal, Any
15
17
 
16
18
  from vt.utils.commons.commons.core_py import is_unset, not_none_not_unset
@@ -295,10 +297,95 @@ class GitCommand(Git, ABC):
295
297
  def subcmd_unchecked(self) -> UncheckedSubcmd:
296
298
  """
297
299
  Run an unchecked git subcommand using subprocess.
300
+
301
+ :returns: An unchecked subcommand instance that simply runs the asked command in a ``subprocess.run()`` with
302
+ optional ``subprocess.Popen()``.
303
+ """
304
+ ...
305
+
306
+ @abstractmethod
307
+ def session(self, **commands: list[str] | Callable[[], Popen[bytes]]) -> GitSession:
308
+ """
309
+ Run long-running git session with multiple unchecked subcommands using ``subprocess.Popen`` and
310
+ communicate with them.
311
+
312
+ Client/Caller can communicate with ``GitSession``'s processes with their stdin and stdout.
313
+
314
+ Examples:
315
+
316
+ Obtain a session:
317
+
318
+ >>> import gitbolt
319
+ >>> _git = gitbolt.get_git_command()
320
+ >>> ses = _git.session(ls_tree=["ls-tree", "HEAD"], cat_file=["cat-file", "--batch"])
321
+ >>> with ses: # start the session by ctx mgr
322
+ ... pass # any communication can be done by Popen semantics.
323
+
324
+ Start the session in one go:
325
+
326
+ >>> with _git.session(cat_file=["cat-file", "--batch"]) as ses: # obtain, start and ctx manage the session.
327
+ ... pass # any communication can be done by Popen semantics.
328
+
329
+ :param commands: list of string git commands suppliable to ``subprocess.Popen`` or ``subprocess.Popen`` lambdas.
330
+ :returns: A (not yet started) long-running ``GitSession`` context manager.
298
331
  """
299
332
  ...
300
333
 
301
334
 
335
+ class GitSession(HasGitUnderneath[GitCommand], AbstractContextManager):
336
+
337
+ def __init__(self, git: GitCommand, **commands: Callable[[], Popen[bytes]]):
338
+ """
339
+ Context Manager to start a git long-running session. Useful when a command is to be held in open state and be
340
+ communicated with its stdin and stdout. This is way faster that spawning multiple processes each time.
341
+
342
+ Examples:
343
+
344
+ Obtain a session:
345
+
346
+ >>> import gitbolt
347
+ >>> _git = gitbolt.get_git_command()
348
+ >>> ses = _git.session(ls_tree=["ls-tree", "HEAD"], cat_file=["cat-file", "--batch"])
349
+ >>> with ses: # start the session by ctx mgr
350
+ ... pass # any communication can be done by Popen semantics.
351
+
352
+ Start the session in one go:
353
+
354
+ >>> with _git.session(cat_file=["cat-file", "--batch"]) as ses: # obtain, start and ctx manage the session.
355
+ ... pass # any communication can be done by Popen semantics.
356
+
357
+ :param git: ``gitbolt.subprocess.GitCommand`` instance.
358
+ :param commands: commands in kwargs fashion.
359
+ """
360
+ self._git = git
361
+ self.unstarted_commands: dict[str, Callable[[], Popen[bytes]]] = commands
362
+ self.started_commands: dict[str, Popen[bytes]] = dict()
363
+ self.commands: SimpleNamespace | None = None
364
+
365
+ def __enter__(self) -> Self:
366
+ processes_started_keys: list[str] = []
367
+ for unstarted_command_key, unstarted_command in self.unstarted_commands.items():
368
+ self.started_commands[unstarted_command_key] = unstarted_command().__enter__()
369
+ processes_started_keys.append(unstarted_command_key)
370
+ self.commands = SimpleNamespace(**self.started_commands)
371
+ for pk in processes_started_keys:
372
+ del self.unstarted_commands[pk]
373
+
374
+ @property
375
+ def git(self) -> GitCommand:
376
+ return self._git
377
+
378
+ def __exit__(self, exc_type, exc_value, traceback, /):
379
+ process_done_keys: list[str] = []
380
+ for started_popen_key, started_popen in self.started_commands.items():
381
+ started_popen.__exit__(exc_type, exc_value, traceback)
382
+ process_done_keys.append(started_popen_key)
383
+ self.commands = None
384
+ for pk in process_done_keys:
385
+ del self.started_commands[pk]
386
+ return False
387
+
388
+
302
389
  class GitSubcmdCommand(GitSubCommand, HasGitUnderneath["GitCommand"], Protocol):
303
390
  """
304
391
  A ``GitSubCommand`` that holds a reference to ``git`` and provides ``git_opts_override`` by default.
@@ -9,7 +9,8 @@ from __future__ import annotations
9
9
 
10
10
  from abc import ABC
11
11
  from pathlib import Path
12
- from typing import override, Literal, overload
12
+ from subprocess import Popen
13
+ from typing import override, Literal, overload, Callable
13
14
 
14
15
  from vt.utils.commons.commons.op import RootDirOp
15
16
 
@@ -24,6 +25,7 @@ from gitbolt.subprocess import (
24
25
  UncheckedSubcmd,
25
26
  )
26
27
  from gitbolt.subprocess.add import AddCLIArgsBuilder
28
+ from gitbolt.subprocess.base import GitSession
27
29
  from gitbolt.subprocess.constants import VERSION_CMD
28
30
  from gitbolt.subprocess.ls_tree import LsTreeCLIArgsBuilder
29
31
  from gitbolt.subprocess.runner import GitCommandRunner
@@ -168,6 +170,7 @@ class UncheckedSubcmdImpl(UncheckedSubcmd, GitSubcmdCommandImpl):
168
170
 
169
171
 
170
172
  class SimpleGitCommand(GitCommand, RootDirOp):
173
+
171
174
  def __init__(
172
175
  self,
173
176
  git_root_dir: Path = Path.cwd(),
@@ -245,6 +248,15 @@ class SimpleGitCommand(GitCommand, RootDirOp):
245
248
  subcmd_unchecked._set_underlying_git(self)
246
249
  return subcmd_unchecked
247
250
 
251
+ def session(self, **commands: list[str] | Callable[[], Popen[bytes]]) -> GitSession:
252
+ cmds: dict[str, Callable[[], Popen[bytes]]] = {}
253
+ for cmd_name, runnable_cmd in commands.items():
254
+ if callable(runnable_cmd):
255
+ cmds[cmd_name] = runnable_cmd
256
+ else:
257
+ cmds[cmd_name] = lambda : self.subcmd_unchecked.popen(runnable_cmd, text=False)
258
+ return GitSession(self, **cmds)
259
+
248
260
 
249
261
  class CLISimpleGitCommand(SimpleGitCommand):
250
262
  """
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ """
5
+ Git command sessions utilities for long-running commands.
6
+
7
+ Create sessions for long-running commands and communicate with them using their stdin/stdout.
8
+
9
+ Much faster that subprocess creation for each input/output pair.
10
+ """
11
+ import subprocess
12
+
13
+ from vt.utils.commons.commons.core_py import read_exact
14
+
15
+
16
+ def cat_file_blob_content(cat_file_popen: subprocess.Popen[bytes], blob_hash: bytes) -> bytes:
17
+ """
18
+ Read git blob contents using a long-running batched cat-file process.
19
+
20
+ Spawning new ``git show`` processes can be slower and resource consuming.
21
+
22
+ :param cat_file_popen: long-running ``git cat-file --batch`` process in bytes mode.
23
+ :param blob_hash: hash to be read from cat-file.
24
+ :return: contents of blob hash in bytes.
25
+ """
26
+ write_obj = blob_hash + b"\n"
27
+ cat_file_popen.stdin.write(write_obj)
28
+ cat_file_popen.stdin.flush()
29
+ header = cat_file_popen.stdout.readline()
30
+ obj, typ, size = header.split()
31
+ blob_content: bytes = read_exact(cat_file_popen.stdout, int(size))
32
+ cat_file_popen.stdout.readline()
33
+ return blob_content
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitbolt
3
- Version: 0.0.0.dev16
3
+ Version: 0.0.0.dev17
4
4
  Summary: Fast, flexible and type-safe Git commands in Python.
5
5
  Author-email: Suhas Krishna Srivastava <suhas.srivastava@vaastav.tech>
6
6
  Maintainer-email: Suhas Krishna Srivastava <suhas.srivastava@vaastav.tech>
@@ -27,7 +27,7 @@ Requires-Python: >=3.12
27
27
  Description-Content-Type: text/markdown
28
28
  License-File: LICENSE
29
29
  Requires-Dist: vt-err-hndlr>=0.0.0dev6
30
- Requires-Dist: vt-commons>=0.0.1.dev9
30
+ Requires-Dist: vt-commons>=0.0.1.dev11
31
31
  Provides-Extra: pygit2
32
32
  Requires-Dist: pygit2; extra == "pygit2"
33
33
  Provides-Extra: test
@@ -25,6 +25,7 @@ src/gitbolt/subprocess/base.py
25
25
  src/gitbolt/subprocess/constants.py
26
26
  src/gitbolt/subprocess/exceptions.py
27
27
  src/gitbolt/subprocess/ls_tree.py
28
+ src/gitbolt/subprocess/session.py
28
29
  src/gitbolt/subprocess/utils.py
29
30
  src/gitbolt/subprocess/impl/__init__.py
30
31
  src/gitbolt/subprocess/impl/simple.py
@@ -1,5 +1,5 @@
1
1
  vt-err-hndlr>=0.0.0dev6
2
- vt-commons>=0.0.1.dev9
2
+ vt-commons>=0.0.1.dev11
3
3
 
4
4
  [pygit2]
5
5
  pygit2
File without changes
File without changes
File without changes