bashrun 0.5.0.dev37378802238__tar.gz → 0.5.0.dev37693327146__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 (24) hide show
  1. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/PKG-INFO +1 -1
  2. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/pyproject.toml +1 -1
  3. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/src/bashrun/bash.py +15 -5
  4. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.gitattributes +0 -0
  5. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.github/actions/setup-release-devkit/action.yml +0 -0
  6. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.github/workflows/integrate.yml +0 -0
  7. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.github/workflows/merge-gate.yml +0 -0
  8. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.github/workflows/release.yml +0 -0
  9. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.gitignore +0 -0
  10. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/.python-version +0 -0
  11. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/AGENTS.md +0 -0
  12. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/CLAUDE.md +0 -0
  13. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/LICENSE +0 -0
  14. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/NOTICE +0 -0
  15. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/README.md +0 -0
  16. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/release-devkit.yaml +0 -0
  17. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/ruff.base.toml +0 -0
  18. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/ruff.toml +0 -0
  19. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/src/bashrun/__init__.py +0 -0
  20. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/src/bashrun/py.typed +0 -0
  21. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/tests/test_bash.py +0 -0
  22. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/tools/devkit/pyproject.toml +0 -0
  23. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/tools/devkit/uv.lock +0 -0
  24. {bashrun-0.5.0.dev37378802238 → bashrun-0.5.0.dev37693327146}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: bashrun
3
- Version: 0.5.0.dev37378802238
3
+ Version: 0.5.0.dev37693327146
4
4
  Summary: Guardrailed shell-exec helpers for Python
5
5
  License-File: LICENSE
6
6
  License-File: NOTICE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bashrun"
3
- version = "0.5.0.dev37378802238"
3
+ version = "0.5.0.dev37693327146"
4
4
  description = "Guardrailed shell-exec helpers for Python"
5
5
  requires-python = ">=3.13"
6
6
  dependencies = []
@@ -43,6 +43,15 @@ def _merge_env(env: dict[str, str] | None) -> dict[str, str] | None:
43
43
  return {**os.environ, **env} if env else None
44
44
 
45
45
 
46
+ def _encode_stdin(stdin_text: str | None) -> bytes | None:
47
+ # Not text=True: that wraps stdin in a TextIOWrapper with newline=None, which rewrites every
48
+ # \n to os.linesep on write. On Windows the child then reads \r\n, and anything parsing
49
+ # line-oriented input sees a trailing \r on every record -- `git update-index --index-info`
50
+ # rejects all of them as invalid paths, for instance. Writing bytes sends exactly what the
51
+ # caller composed, on every platform.
52
+ return stdin_text.encode() if stdin_text is not None else None
53
+
54
+
46
55
  def bash_output(
47
56
  command: str, *, cwd: Path | None = None, stdin_text: str | None = None, env: dict[str, str] | None = None
48
57
  ) -> str:
@@ -56,10 +65,9 @@ def bash_output(
56
65
  stdout=subprocess.PIPE,
57
66
  stderr=subprocess.PIPE,
58
67
  stdin=subprocess.PIPE if stdin_text else None,
59
- text=True,
60
68
  ) as process:
61
69
  try:
62
- stdout, stderr = process.communicate(input=stdin_text)
70
+ raw_stdout, raw_stderr = process.communicate(input=_encode_stdin(stdin_text))
63
71
  except KeyboardInterrupt:
64
72
  try:
65
73
  process.wait(timeout=5)
@@ -67,12 +75,15 @@ def bash_output(
67
75
  process.kill()
68
76
  raise
69
77
 
78
+ stdout = raw_stdout.decode(errors="replace") if raw_stdout else ""
79
+ stderr = raw_stderr.decode(errors="replace") if raw_stderr else ""
80
+
70
81
  if process.returncode != 0:
71
82
  if stderr:
72
83
  print(stderr, file=sys.stderr, end="")
73
84
  raise CalledProcessError(process.returncode, command, output=stdout, stderr=stderr)
74
85
 
75
- return stdout or ""
86
+ return stdout
76
87
 
77
88
 
78
89
  def bash(
@@ -102,12 +113,11 @@ def bash(
102
113
  stdout=stdout,
103
114
  stderr=stderr,
104
115
  stdin=subprocess.PIPE if stdin_text else None,
105
- text=True,
106
116
  )
107
117
  )
108
118
 
109
119
  try:
110
- process.communicate(input=stdin_text)
120
+ process.communicate(input=_encode_stdin(stdin_text))
111
121
  except KeyboardInterrupt:
112
122
  try:
113
123
  process.wait(timeout=5)