bounded_subprocess 2.4.0__tar.gz → 2.5.0__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 (39) hide show
  1. bounded_subprocess-2.5.0/AGENTS.md +10 -0
  2. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/PKG-INFO +1 -1
  3. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/pyproject.toml +1 -1
  4. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/bounded_subprocess_async.py +25 -2
  5. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/test_async.py +45 -0
  6. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/uv.lock +1 -1
  7. bounded_subprocess-2.4.0/AGENTS.md +0 -5
  8. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/.git +0 -0
  9. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/.github/workflows/docs.yaml +0 -0
  10. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/.github/workflows/test.yml +0 -0
  11. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/.gitignore +0 -0
  12. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/LICENSE.txt +0 -0
  13. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/Makefile +0 -0
  14. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/README.md +0 -0
  15. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/cspell.config.yaml +0 -0
  16. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/docs/index.md +0 -0
  17. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/mkdocs.yaml +0 -0
  18. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/__init__.py +0 -0
  19. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/bounded_subprocess.py +0 -0
  20. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/interactive.py +0 -0
  21. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/interactive_async.py +0 -0
  22. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/src/bounded_subprocess/util.py +0 -0
  23. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/__init__.py +0 -0
  24. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/block_on_inputs.py +0 -0
  25. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/close_outputs.py +0 -0
  26. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/dies_shortly_after_launch.py +0 -0
  27. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/dies_while_writing.py +0 -0
  28. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/does_not_read.py +0 -0
  29. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/echo_stdin.py +0 -0
  30. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/fork_bomb.py +0 -0
  31. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/fork_once.py +0 -0
  32. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/long_stdout.py +0 -0
  33. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/read_one_line.py +0 -0
  34. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/sleep_forever.py +0 -0
  35. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/unbounded_output.py +0 -0
  36. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/evil_programs/write_forever_but_no_newline.py +0 -0
  37. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/module_test.py +0 -0
  38. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/test_interactive.py +0 -0
  39. {bounded_subprocess-2.4.0 → bounded_subprocess-2.5.0}/test/test_interactive_async.py +0 -0
@@ -0,0 +1,10 @@
1
+ Use `uv run`to run and not `python`.
2
+
3
+ ## Publishing Process
4
+
5
+ Increment the version number as appropriate in pyproject.toml. Delete old
6
+ builds from dist/. Run uv sync to update the lock file. Commit the changes,
7
+ which should have just changes to pyproject.taml and uv.lock. Run `uv build`
8
+ and then `uv publish`. In the interactive prompt, you MUST enter __token__
9
+ for the username. I know it says that, but I don't read what's on the screen.
10
+ The password is in the keychain.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bounded_subprocess
3
- Version: 2.4.0
3
+ Version: 2.5.0
4
4
  Summary: A library to facilitate running subprocesses that may misbehave.
5
5
  Project-URL: Homepage, https://github.com/arjunguha/bounded_subprocess
6
6
  Project-URL: Bug Tracker, https://github.com/arjunguha/bounded_subprocess
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bounded_subprocess"
3
- version = "2.4.0"
3
+ version = "2.5.0"
4
4
  authors = [
5
5
  { name="Arjun Guha" },
6
6
  { name="Ming-Ho Yee" },
@@ -163,6 +163,8 @@ async def podman_run(
163
163
  env=None,
164
164
  stdin_data: Optional[str] = None,
165
165
  stdin_write_timeout: Optional[int] = None,
166
+ volumes: List[str] = [],
167
+ cwd: Optional[str] = None,
166
168
  ) -> Result:
167
169
  """
168
170
  Run a subprocess in a podman container asynchronously with bounded stdout/stderr capture.
@@ -172,19 +174,32 @@ async def podman_run(
172
174
  the same as `run`, except for an additional `image` parameter to specify the
173
175
  container image to use.
174
176
 
177
+ Args:
178
+ args: Command arguments to run in the container.
179
+ image: Container image to use.
180
+ timeout_seconds: Maximum time to wait for the process to complete.
181
+ max_output_size: Maximum size in bytes for stdout/stderr capture.
182
+ env: Optional dictionary of environment variables.
183
+ stdin_data: Optional string data to write to stdin.
184
+ stdin_write_timeout: Optional timeout for writing stdin data.
185
+ volumes: Optional list of volume mount specifications (e.g., ["/host/path:/container/path"]).
186
+ cwd: Optional working directory path inside the container.
187
+
175
188
  Example:
176
189
 
177
190
  ```python
178
191
  import asyncio
179
- from bounded_subprocess.bounded_subprocess_async import run_container
192
+ from bounded_subprocess.bounded_subprocess_async import podman_run
180
193
 
181
194
  async def main():
182
- result = await run_container(
195
+ result = await podman_run(
183
196
  ["cat"],
184
197
  image="alpine:latest",
185
198
  timeout_seconds=5,
186
199
  max_output_size=1024,
187
200
  stdin_data="hello\n",
201
+ volumes=["/host/data:/container/data"],
202
+ cwd="/container/data",
188
203
  )
189
204
  print(result.exit_code)
190
205
  print(result.stdout.strip())
@@ -209,6 +224,14 @@ async def podman_run(
209
224
  for key, value in env.items():
210
225
  podman_args.extend(["-e", f"{key}={value}"])
211
226
 
227
+ # Handle volume mounts
228
+ for volume in volumes:
229
+ podman_args.extend(["-v", volume])
230
+
231
+ # Handle working directory
232
+ if cwd is not None:
233
+ podman_args.extend(["-w", cwd])
234
+
212
235
  podman_args.append(image)
213
236
  podman_args.extend(args)
214
237
 
@@ -171,3 +171,48 @@ async def test_podman_run_unbounded_output():
171
171
  assert result.timeout is True
172
172
  # stderr may contain podman pull messages, which is fine
173
173
  assert len(result.stdout) == 1024
174
+
175
+
176
+ @pytest.mark.asyncio
177
+ async def test_podman_run_volumes():
178
+ """Test podman_run with volume mounts."""
179
+ import tempfile
180
+
181
+ # Create a temporary file with test content
182
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as tmp_file:
183
+ tmp_file.write("test content\n")
184
+ tmp_path = tmp_file.name
185
+
186
+ try:
187
+ # Mount the file and read it from the container
188
+ result = await podman_run(
189
+ ["cat", "/mnt/test.txt"],
190
+ image="alpine:latest",
191
+ timeout_seconds=5,
192
+ max_output_size=1024,
193
+ volumes=[f"{tmp_path}:/mnt/test.txt:ro"],
194
+ )
195
+ assert result.exit_code == 0
196
+ assert result.timeout is False
197
+ assert result.stdout == "test content\n"
198
+ finally:
199
+ # Clean up
200
+ try:
201
+ os.unlink(tmp_path)
202
+ except OSError:
203
+ pass
204
+
205
+
206
+ @pytest.mark.asyncio
207
+ async def test_podman_run_cwd():
208
+ """Test podman_run with working directory."""
209
+ result = await podman_run(
210
+ ["pwd"],
211
+ image="alpine:latest",
212
+ timeout_seconds=5,
213
+ max_output_size=1024,
214
+ cwd="/tmp",
215
+ )
216
+ assert result.exit_code == 0
217
+ assert result.timeout is False
218
+ assert result.stdout.strip() == "/tmp"
@@ -31,7 +31,7 @@ wheels = [
31
31
 
32
32
  [[package]]
33
33
  name = "bounded-subprocess"
34
- version = "2.4.0"
34
+ version = "2.5.0"
35
35
  source = { editable = "." }
36
36
  dependencies = [
37
37
  { name = "typeguard" },
@@ -1,5 +0,0 @@
1
- ## Publishing Process
2
-
3
- Increment the version number as appropriate in pyproject.toml. Delete old
4
- builds from dist/. Run uv sync to update the lock file. Commit the changes,
5
- which should have just changes to pyproject.taml and uv.lock.