codeplain 0.3.10.dev4__py3-none-any.whl → 0.3.11.dev6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codeplain
3
- Version: 0.3.10.dev4
3
+ Version: 0.3.11.dev6
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
@@ -11,7 +11,7 @@ metadata_utils.py,sha256=YO17o7IAma5TT1ZN0pTwrLVr_KxFQ8APv02KqKPpI5k,1641
11
11
  module_renderer.py,sha256=IJBle8mbBARn_xrekjSpsVID7719yy2rNPkM15-ONoI,6982
12
12
  partial_rendering.py,sha256=uzZc2j4d3pAXzfiHw_y1TK4yLRsLOb1Mm21570AGxJ8,13837
13
13
  path_resolution.py,sha256=0tMqU0a1g4DYhTOp7QjLVSEkv_cgasb4NI1mK809dUM,2233
14
- plain2code.py,sha256=NsZf7JS2bGmOQ6HsbiTqNA3EMXXY5YQW6nBBXCG7m-U,17392
14
+ plain2code.py,sha256=v8xBTv3mQjntpBTBJUvl5naGnSPFAzhEQTqpeRr40ow,18072
15
15
  plain2code_arguments.py,sha256=xMK-R13Vu005bHz3MUDY8F0Cf3ED9hCPqNsC6jGZmkk,17620
16
16
  plain2code_console.py,sha256=5N4_GIV8qE-2zvFh6qoOHhhsuwCF_3r7jG19S-YWtfk,5906
17
17
  plain2code_events.py,sha256=rgDF5PDtNr_lEPvJmd1tIQXZrzwgzZW5b-_pykugqe4,1587
@@ -75,6 +75,7 @@ tests/test_cli_output.py,sha256=ZV2F1NNW4EiZvMNkhF9XUZH6bFJbddfkZof5qAFxe3Y,1888
75
75
  tests/test_conformance_fix_journal.py,sha256=olTeAuxXgFwQ8LSQyt0FqtBy9_XY_gK-Ei_pUuJ0C3M,10389
76
76
  tests/test_console_log_styles.py,sha256=63DQWiwWNhe_rMP70bW9DAB6-EPaqU3Wpwyh8eR09pc,4080
77
77
  tests/test_distill_conformance_test_memory.py,sha256=Tftw9l-gLVwIU6QttY03h2VedvuFxpIsCmZIzvWfxMA,5481
78
+ tests/test_dry_run_link_validation.py,sha256=ivvYXQPqUkQ8glbFyUrdCninCxF2mg-rAsDcfjcB7MM,2140
78
79
  tests/test_file_utils.py,sha256=R_ZIhrTtwlhHxgmbBtA8PFEU5-QB4Fi5skJ7PS2KzdU,3614
79
80
  tests/test_folder_path_resolution.py,sha256=K9v684xkPE0HOAsovg8uDixpZmaIk7ho-Wd3rTjKLF0,6560
80
81
  tests/test_git_utils.py,sha256=h3rWhhs4XVRYqzVzdmj51siF_AYD-GkbZiefK2iGfWo,15614
@@ -111,8 +112,8 @@ tui/spinner.py,sha256=Ro6Gd9Przf-whuHqPRY6HwI0T57yJjyNPbhDbigZKZE,2471
111
112
  tui/state_handlers.py,sha256=zbUS_D9eU8qIwVpaxPEp9zL9bpg8gXsWNoUaqg9TLrQ,16664
112
113
  tui/styles.css,sha256=kiC7Og_2G1E7owoiZgV95-3_dSeQnsNj3qzaY04xkDg,6727
113
114
  tui/widget_helpers.py,sha256=ToO9MV2bF2Rp-XMNcjIYclnB_qmgO5sLw4UtQ2CyTMg,6652
114
- codeplain-0.3.10.dev4.dist-info/METADATA,sha256=AHNwzkViIw83FQTt9C5UKXgVVALnEwJ3li-gXTzaUxU,7256
115
- codeplain-0.3.10.dev4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
116
- codeplain-0.3.10.dev4.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
117
- codeplain-0.3.10.dev4.dist-info/licenses/LICENSE,sha256=pCeKgQ1mXE5OmNUuKOfOZh1T1vqkeCUxghE7N8qgnzc,11345
118
- codeplain-0.3.10.dev4.dist-info/RECORD,,
115
+ codeplain-0.3.11.dev6.dist-info/METADATA,sha256=R_gO4pJAF6hs5De_MsOrekkrm9Eax1Wgfuf6aNNvLpw,7256
116
+ codeplain-0.3.11.dev6.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
117
+ codeplain-0.3.11.dev6.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
118
+ codeplain-0.3.11.dev6.dist-info/licenses/LICENSE,sha256=pCeKgQ1mXE5OmNUuKOfOZh1T1vqkeCUxghE7N8qgnzc,11345
119
+ codeplain-0.3.11.dev6.dist-info/RECORD,,
plain2code.py CHANGED
@@ -203,6 +203,15 @@ def warn_if_acceptance_tests_without_conformance_script(plain_module, args) -> N
203
203
  )
204
204
 
205
205
 
206
+ def validate_linked_resources(plain_module) -> None:
207
+ """Load every linked resource exactly the way rendering does, so dry-run
208
+ surfaces the same errors (binary file, missing file, oversized base64 blob)."""
209
+ for module in plain_module.all_required_modules + [plain_module]:
210
+ resources_list: list[dict] = []
211
+ plain_spec.collect_linked_resources(module.plain_source, resources_list, None, True)
212
+ file_utils.load_linked_resources(module.template_dirs, resources_list, module.module_name)
213
+
214
+
206
215
  def render( # noqa: C901
207
216
  plain_module: plain_modules.PlainModule,
208
217
  args,
@@ -393,6 +402,12 @@ def main(): # noqa: C901
393
402
  return
394
403
 
395
404
  if args.dry_run:
405
+ try:
406
+ validate_linked_resources(plain_module)
407
+ except Exception as e:
408
+ console.error(f"Error: {str(e)}")
409
+ return
410
+
396
411
  console.info("Printing dry run output...\n")
397
412
  render_range = plain_spec.compute_render_range(args, plain_module.plain_source)
398
413
  print_dry_run_output(plain_module.plain_source, render_range)
@@ -0,0 +1,60 @@
1
+ """Regression tests for linked-resource validation during --dry-run.
2
+
3
+ A linked resource must be a single text-based file. Rendering rejects binary
4
+ targets in ``file_utils.load_linked_resources`` (a failed UTF-8 decode raises
5
+ ``UnsupportedResourceType``); dry-run must surface the same errors through
6
+ ``plain2code.validate_linked_resources``, which reuses that exact mechanism.
7
+ """
8
+
9
+ import pytest
10
+
11
+ from plain2code import validate_linked_resources
12
+ from plain2code_exceptions import UnsupportedResourceType
13
+ from plain_modules import PlainModule
14
+
15
+ PLAIN_TEMPLATE = """***definitions***
16
+
17
+ - :Widget: is an item managed by the application.
18
+ - Its icon is [the widget resource](resources/{resource_name}).
19
+
20
+ ***implementation reqs***
21
+
22
+ - Implementation should be in Python.
23
+
24
+ ***functional specs***
25
+
26
+ - A :Widget: can be created.
27
+ """
28
+
29
+
30
+ def _make_module(tmp_path, monkeypatch, resource_name, resource_bytes):
31
+ resources_dir = tmp_path / "resources"
32
+ resources_dir.mkdir()
33
+ (resources_dir / resource_name).write_bytes(resource_bytes)
34
+ (tmp_path / "binlink.plain").write_text(PLAIN_TEMPLATE.format(resource_name=resource_name))
35
+
36
+ # Link targets are resolved relative to the current working directory at parse time.
37
+ monkeypatch.chdir(tmp_path)
38
+ return PlainModule("binlink.plain", str(tmp_path / "build"), [str(tmp_path)])
39
+
40
+
41
+ def test_dry_run_validation_rejects_binary_linked_resource(tmp_path, monkeypatch):
42
+ module = _make_module(tmp_path, monkeypatch, "image.png", b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\xff\xfe\xfd")
43
+
44
+ with pytest.raises(UnsupportedResourceType) as exc_info:
45
+ validate_linked_resources(module)
46
+
47
+ assert "resources/image.png" in str(exc_info.value)
48
+ assert "binary file" in str(exc_info.value)
49
+
50
+
51
+ def test_dry_run_validation_accepts_text_file_with_unusual_extension(tmp_path, monkeypatch):
52
+ module = _make_module(tmp_path, monkeypatch, "notes.xyz123", b"plain text content\n")
53
+
54
+ validate_linked_resources(module)
55
+
56
+
57
+ def test_dry_run_validation_accepts_empty_file(tmp_path, monkeypatch):
58
+ module = _make_module(tmp_path, monkeypatch, "empty.txt", b"")
59
+
60
+ validate_linked_resources(module)