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.
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/PKG-INFO +2 -2
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/pyproject.toml +2 -2
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/base.py +87 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/impl/simple.py +13 -1
- gitbolt-0.0.0.dev17/src/gitbolt/subprocess/session.py +33 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/PKG-INFO +2 -2
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/SOURCES.txt +1 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/requires.txt +1 -1
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/LICENSE +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/README.md +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/setup.cfg +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/__init__.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/_internal_init.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/add.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/base.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/constants.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/exceptions.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/ls_tree.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/models.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/py.typed +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/pytest_plugin.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/__init__.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/_internal_init.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/add.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/constants.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/exceptions.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/impl/__init__.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/ls_tree.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/__init__.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/base.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/runner/simple.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/subprocess/utils.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt/utils.py +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/dependency_links.txt +0 -0
- {gitbolt-0.0.0.dev16 → gitbolt-0.0.0.dev17}/src/gitbolt.egg-info/entry_points.txt +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|