codeplain 0.2.16__py3-none-any.whl → 0.2.18__py3-none-any.whl

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.
_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.16"
1
+ __version__ = "0.2.18"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeplain
3
- Version: 0.2.16
3
+ Version: 0.2.18
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
@@ -1,4 +1,4 @@
1
- _version.py,sha256=nS1Qf8CA6pxMzqGCeAMZHTKK2igCSNakZ3o7kDK0JIQ,23
1
+ _version.py,sha256=3RGPra41WobAbWeoPRqR_JXeysqFvK3H3AP1g9gjj3g,23
2
2
  codeplain_REST_api.py,sha256=KIY0buZ2oStlHN2YyoCWxen8JLFaqWUFuE7zQoJU5e8,19558
3
3
  concept_utils.py,sha256=vwSY4-FmxyqaDBxhntYzqG8t9pXvAWwiULP0DYQI32o,7905
4
4
  diff_utils.py,sha256=AjiQlqo5pRos_8hVXZo5yBurl5BzSrTMGrQv4dCtRCg,1198
@@ -33,7 +33,7 @@ render_machine/conformance_tests.py,sha256=SHDGMDw--fO4mglEEG5sGecc-uFbG-XNZl017
33
33
  render_machine/implementation_code_helpers.py,sha256=LdHNLoKgVtrDaGH2APX8C9vjNjLBUhu2V7OAaJvm4rM,2009
34
34
  render_machine/render_context.py,sha256=sJY4hDc5OXLZuqgNNuD9oryJynYEctDQIUdoAOh04Vk,21752
35
35
  render_machine/render_types.py,sha256=-Mt5i-XYjtBnKHXj9j9aUST5TbVnzpOwngeBwOl24TE,7430
36
- render_machine/render_utils.py,sha256=7YWaKoI0ceDuThkhzb5FjtB7UvLUV7bYVU94yHnbdOQ,8391
36
+ render_machine/render_utils.py,sha256=uTZkThRQXHd9zZ3um2LA1bzlNKES0QUC4vDSJCYTIKk,9371
37
37
  render_machine/state_machine_config.py,sha256=sd-P9kdvBYlj0R6aT1RZLFquIwAcbEBNL3aZG-Wo4hw,27988
38
38
  render_machine/states.py,sha256=niFXqayyA_rezCrlzo0hYeHAruErcPzQVF-BeIBGnL8,1968
39
39
  render_machine/triggers.py,sha256=GarwIYPY6ZZzVdRF7yXLB54tofr08NpFZfp5DH6AOuI,1331
@@ -76,8 +76,8 @@ tui/spinner.py,sha256=Ro6Gd9Przf-whuHqPRY6HwI0T57yJjyNPbhDbigZKZE,2471
76
76
  tui/state_handlers.py,sha256=NCAu-Pv2Bc8HG5GHaV47kwZHtbCOh_mBYQAW7DbN0jg,15927
77
77
  tui/styles.css,sha256=XrGdtAjyscJL3Rey2gT0rbuRnMnXgePGiAqySKlcezs,6133
78
78
  tui/widget_helpers.py,sha256=hQKlURgdSC8RT6QgKPzRhSRAIO1bMoLuM3lz_sCc3FU,5819
79
- codeplain-0.2.16.dist-info/METADATA,sha256=V4gPfjNM5HWSavw_xQw3NbPnZBsRQmdlL2sEjdQxPZw,4210
80
- codeplain-0.2.16.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
81
- codeplain-0.2.16.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
82
- codeplain-0.2.16.dist-info/licenses/LICENSE,sha256=pCeKgQ1mXE5OmNUuKOfOZh1T1vqkeCUxghE7N8qgnzc,11345
83
- codeplain-0.2.16.dist-info/RECORD,,
79
+ codeplain-0.2.18.dist-info/METADATA,sha256=Dg9wzAE17DhsyisARFBIgjCFqkqbs5TVkhBJuYpHNWE,4210
80
+ codeplain-0.2.18.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
81
+ codeplain-0.2.18.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
82
+ codeplain-0.2.18.dist-info/licenses/LICENSE,sha256=pCeKgQ1mXE5OmNUuKOfOZh1T1vqkeCUxghE7N8qgnzc,11345
83
+ codeplain-0.2.18.dist-info/RECORD,,
@@ -19,7 +19,7 @@ SCRIPT_EXECUTION_TIMEOUT = 120
19
19
  TIMEOUT_ERROR_EXIT_CODE = 124
20
20
  POLL_INTERVAL_SECONDS = 0.2
21
21
  SIGTERM_GRACE_PERIOD_SECONDS = 0.2
22
- STDOUT_READ_TIMEOUT_SECONDS = 5
22
+ STDOUT_READ_TIMEOUT_SECONDS = 2
23
23
  F_SETPIPE_SIZE = 1031 # Linux-only constant
24
24
  PIPE_SIZE_KB = 1024 # 1MB
25
25
 
@@ -120,11 +120,27 @@ def execute_script( # noqa: C901
120
120
  # Set the pipe size to 1MB to avoid buffer overflows
121
121
  fcntl.fcntl(proc.stdout.fileno(), F_SETPIPE_SIZE, PIPE_SIZE_KB * 1024) # 1MB
122
122
 
123
+ # Drain stdout in a background thread to prevent pipe buffer deadlock.
124
+ # macOS has a 64KB pipe buffer; without continuous draining, scripts that produce
125
+ # more output than that block on write and never exit, causing spurious timeouts.
126
+ output_chunks: list[str] = []
127
+
128
+ def _drain_stdout() -> None:
129
+ try:
130
+ for chunk in iter(lambda: proc.stdout.read(8192), ""):
131
+ output_chunks.append(chunk)
132
+ except (OSError, ValueError):
133
+ pass
134
+
135
+ reader = threading.Thread(target=_drain_stdout, daemon=True)
136
+ reader.start()
137
+
123
138
  try:
124
139
  while proc.poll() is None:
125
140
  if time.time() - start_time >= script_timeout:
126
141
  _kill_process(proc)
127
- partial_stdout = proc.stdout.read()
142
+ reader.join(timeout=2)
143
+ partial_stdout = "".join(output_chunks)
128
144
  exc = subprocess.TimeoutExpired(cmd, script_timeout)
129
145
  exc.stdout = partial_stdout
130
146
  raise exc
@@ -136,12 +152,13 @@ def execute_script( # noqa: C901
136
152
  else:
137
153
  time.sleep(POLL_INTERVAL_SECONDS)
138
154
 
139
- # Use communicate() with a timeout because child processes may hold the pipe open after the main process exits.
140
- try:
141
- stdout, _ = proc.communicate(timeout=STDOUT_READ_TIMEOUT_SECONDS)
142
- except subprocess.TimeoutExpired:
155
+ # Wait for the reader to finish draining remaining output.
156
+ # Close stdout if child processes keep the pipe open beyond the grace period.
157
+ reader.join(timeout=STDOUT_READ_TIMEOUT_SECONDS)
158
+ if reader.is_alive():
143
159
  proc.stdout.close()
144
- stdout = ""
160
+ reader.join(timeout=1)
161
+ stdout = "".join(output_chunks)
145
162
  elapsed_time = time.time() - start_time
146
163
 
147
164
  sanitized_script_output = _sanitize_script_output(stdout)
@@ -201,8 +218,14 @@ def execute_script( # noqa: C901
201
218
  f"The {script_type} script timed out after {script_timeout} seconds. {script_type} script output stored in: {temp_file_path}"
202
219
  )
203
220
 
221
+ partial_output = ""
222
+ if e.stdout:
223
+ decoded = e.stdout.decode("utf-8") if isinstance(e.stdout, bytes) else e.stdout
224
+ sanitized = _sanitize_script_output(decoded)
225
+ if sanitized:
226
+ partial_output = f"\nPartial test script output:\n{sanitized}"
204
227
  return (
205
228
  TIMEOUT_ERROR_EXIT_CODE,
206
- f"{script_type} script did not finish in {script_timeout} seconds.",
229
+ f"{script_type} script did not finish in {script_timeout} seconds.{partial_output}",
207
230
  temp_file_path,
208
231
  )