From 5dddd72f42b2d0edd65b312ff72ea29776bf54ca Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:20:36 -0600 Subject: [PATCH 1/7] Removed `source` from justfile (Doesn't work on Ubuntu) --- .justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.justfile b/.justfile index 18a95eb..578e0db 100644 --- a/.justfile +++ b/.justfile @@ -1,5 +1,5 @@ test: - source .venv/bin/activate + .venv/bin/activate #pip3 install -e . uv pip install -e ".[test]" @@ -7,6 +7,6 @@ test: PATH=$(echo $PATH | tr ':' '\n' | grep -v "\.jbang/bin" | tr '\n' ':' | sed 's/:$//') .venv/bin/python -m pytest -o log_cli_level=DEBUG -o log_cli=true release: - source .venv/bin/activate + .venv/bin/activate uv pip install setuptools gh release create `python3 setup.py --version` --generate-notes From e4e2500868b7e5cf9191d76fb7bd359488c98626 Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:21:28 -0600 Subject: [PATCH 2/7] Added `.venv` to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 446fe4d..3e87e4b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ jbang.egg-info jbang/__pycache__ __pycache__ .coverage +.venv From 3be07b02520711d0fee5a00e3a00c5b1e37a45ff Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:32:10 -0600 Subject: [PATCH 3/7] Added popen function to jbang.py --- jbang/jbang.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/jbang/jbang.py b/jbang/jbang.py index c2b7245..d2b2678 100644 --- a/jbang/jbang.py +++ b/jbang/jbang.py @@ -199,6 +199,27 @@ def spawnSync(args: Union[str, List[str]]) -> Any: 2 ) +def popen(args: Union[str, List[str]]) -> subprocess.Popen: + """Returns a reference to subprocess.Popen for streaming stdout.""" + log.debug(f"trying to execute popen command: {args}") + + cmdLine = _getCommandLine(args) + + if not cmdLine: + print("Could not locate a way to run jbang. Try installing jbang manually and try again.") + raise Exception("Could not locate a way to run jbang. Try installing jbang manually and try again.", 2) + + return subprocess.Popen( + cmdLine, + shell=True, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + bufsize=1, + universal_newlines=True, + ) + def main(): """Command-line entry point for jbang-python.""" log.debug("Starting jbang-python CLI") From 3489fe4883bb07d5ab921da275f1e47b46b30c4d Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 18:54:52 -0600 Subject: [PATCH 4/7] Added popen to init --- jbang/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jbang/__init__.py b/jbang/__init__.py index b08f380..70d5795 100644 --- a/jbang/__init__.py +++ b/jbang/__init__.py @@ -1,6 +1,6 @@ -from .jbang import exec, spawnSync, main, quote +from .jbang import exec, spawnSync, main, quote, popen -__all__ = ['exec', 'spawnSync', 'main', 'quote'] +__all__ = ['exec', 'spawnSync', 'main', 'quote', 'popen'] if __name__ == "__main__": main() \ No newline at end of file From 33e522bd95975602b78b662e740d891cb5d6eb9f Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:55:58 -0600 Subject: [PATCH 5/7] Added fixtures for testable java files --- tests/test_jbang.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_jbang.py b/tests/test_jbang.py index 8629bf1..f5c0429 100644 --- a/tests/test_jbang.py +++ b/tests/test_jbang.py @@ -1,10 +1,48 @@ import sys +from pathlib import Path import pytest import jbang from jbang.jbang import CommandResult +@pytest.fixture +def java_hello(tmp_path: Path): + code = """ + public class HelloWorld { + public static void main(String[] args) { + System.out.print("Hello, world!"); + } + } + """ + + file_path = tmp_path / "HelloWorld.java" + file_path.write_text(code.strip()) + return file_path + +@pytest.fixture +def streamable_java_hello(tmp_path: Path): + code = """ + import java.io.*; + import java.util.Random; + + public class HelloStreamable { + static final BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out), 1 << 20); + public static void main(String[] args) throws Exception { + String message = \"Hello, world!\"; + Random rand = new Random(); + for (int i = 0; i < message.length(); i++){ + out.write(message.charAt(i)); + out.newLine(); + out.flush(); + Thread.sleep(rand.nextInt(3)); + } + } + } + """ + file_path = tmp_path / "HelloStreamable.java" + file_path.write_text(code.strip()) + return file_path def test_version_command(): """Test version command.""" From 80a9b08997b18bf318189d8a3f50fa9c2a913e80 Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:58:32 -0600 Subject: [PATCH 6/7] Added tests for popen --- tests/test_jbang.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_jbang.py b/tests/test_jbang.py index f5c0429..2bf0592 100644 --- a/tests/test_jbang.py +++ b/tests/test_jbang.py @@ -98,6 +98,23 @@ def test_invalid_java_version(): out = jbang.exec('--java invalid properties@jbangdev java.version') assert 'Invalid version' in out.stderr +def test_popen_single_write(java_hello): + process = jbang.popen(str(java_hello)) + process.wait() + + assert process.returncode == 0 + assert process.stdout.readlines()[0] == "Hello, world!" + +def test_popen_streamable_java_hello(streamable_java_hello): + process = jbang.popen(str(streamable_java_hello)) + rows = [] + message = "Hello, world!" + for i, line in enumerate(process.stdout): + assert line.rstrip("\n") == message[i] + + return_code = process.wait() + assert return_code == 0 + @pytest.mark.skipif(sys.platform == 'win32', reason="Quote tests behave differently on Windows") class TestQuoting: def test_quote_empty_string(self): From 68f0d95b216e721bcae874d33f55aa3c604315f9 Mon Sep 17 00:00:00 2001 From: KotaBlip <71233489+Kotablip@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:00:49 -0600 Subject: [PATCH 7/7] Small changes to docstring / formatting on popen function --- jbang/jbang.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jbang/jbang.py b/jbang/jbang.py index d2b2678..6367d32 100644 --- a/jbang/jbang.py +++ b/jbang/jbang.py @@ -200,14 +200,17 @@ def spawnSync(args: Union[str, List[str]]) -> Any: ) def popen(args: Union[str, List[str]]) -> subprocess.Popen: - """Returns a reference to subprocess.Popen for streaming stdout.""" + """Returns a reference to a subprocess.Popen instance for streaming stdout.""" log.debug(f"trying to execute popen command: {args}") cmdLine = _getCommandLine(args) if not cmdLine: print("Could not locate a way to run jbang. Try installing jbang manually and try again.") - raise Exception("Could not locate a way to run jbang. Try installing jbang manually and try again.", 2) + raise Exception( + "Could not locate a way to run jbang. Try installing jbang manually and try again.", + 2 + ) return subprocess.Popen( cmdLine,