codeplain 0.3.6__py3-none-any.whl → 0.3.8__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.
- cli_output/render_summary.py +2 -2
- cli_output/status.py +2 -2
- {codeplain-0.3.6.dist-info → codeplain-0.3.8.dist-info}/METADATA +7 -7
- {codeplain-0.3.6.dist-info → codeplain-0.3.8.dist-info}/RECORD +44 -32
- codeplain_REST_api.py +6 -2
- file_utils.py +1 -1
- module_renderer.py +3 -2
- path_resolution.py +64 -0
- plain2code.py +6 -10
- plain2code_arguments.py +200 -99
- plain2code_console.py +34 -22
- plain2code_events.py +1 -0
- plain2code_logger.py +13 -22
- plain2code_state.py +17 -1
- plain2code_utils.py +17 -13
- plain_file.py +39 -28
- render_machine/actions/create_dist.py +2 -2
- render_machine/actions/exit_with_error.py +2 -1
- render_machine/actions/fix_conformance_test.py +4 -2
- render_machine/actions/render_functional_requirement.py +4 -3
- render_machine/render_context.py +5 -3
- render_machine/render_utils.py +14 -8
- system_config.py +35 -1
- tests/test_arg_provenance.py +89 -0
- tests/test_cli_output.py +2 -2
- tests/test_console_log_styles.py +112 -0
- tests/test_folder_path_resolution.py +165 -0
- tests/test_log_file_name_resolution.py +89 -0
- tests/test_logging_config_path_resolution.py +67 -0
- tests/test_path_resolution.py +65 -0
- tests/test_plain2code_state.py +36 -0
- tests/test_plain2code_utils.py +36 -0
- tests/test_plainfileparser.py +2 -2
- tests/test_script_path_resolution.py +107 -0
- tests/test_tui_usage.py +209 -0
- tests/test_usage_summary.py +28 -0
- tui/components.py +29 -20
- tui/plain2code_tui.py +71 -2
- tui/styles.css +4 -0
- tui/widget_helpers.py +20 -1
- usage_summary.py +30 -0
- _version.py +0 -1
- {codeplain-0.3.6.dist-info → codeplain-0.3.8.dist-info}/WHEEL +0 -0
- {codeplain-0.3.6.dist-info → codeplain-0.3.8.dist-info}/entry_points.txt +0 -0
- {codeplain-0.3.6.dist-info → codeplain-0.3.8.dist-info}/licenses/LICENSE +0 -0
cli_output/render_summary.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
from plain2code_console import console
|
|
6
6
|
from plain2code_state import RunState
|
|
7
|
-
from
|
|
7
|
+
from usage_summary import format_usage_summary
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def print_exit_summary(
|
|
@@ -24,7 +24,7 @@ def print_exit_summary(
|
|
|
24
24
|
msg += f" [#8E8F91]render id:\t\t\t[#FFFFFF]{run_state.render_id}\n"
|
|
25
25
|
msg += f" [#8E8F91]input file:\t\t\t[#FFFFFF]{spec_filename}\n"
|
|
26
26
|
msg += f" [#8E8F91]generated code folder:\t[#FFFFFF]{run_state.render_generated_code_path or '-'}\n\n"
|
|
27
|
-
msg +=
|
|
27
|
+
msg += format_usage_summary(run_state.rendered_functionalities, run_state.render_time_accumulated) + "\n"
|
|
28
28
|
console.print(msg)
|
|
29
29
|
|
|
30
30
|
if not run_state.render_succeeded and error_message:
|
cli_output/status.py
CHANGED
|
@@ -32,7 +32,7 @@ def _display_credit_line(plan_credits: dict) -> None:
|
|
|
32
32
|
# If naive datetime, assume UTC
|
|
33
33
|
if dt.tzinfo is None:
|
|
34
34
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
35
|
-
formatted_date = dt.strftime(
|
|
35
|
+
formatted_date = f"{dt.strftime('%b')} {dt.day}, {dt.year}"
|
|
36
36
|
|
|
37
37
|
# Check if expired
|
|
38
38
|
now = datetime.now(timezone.utc)
|
|
@@ -62,7 +62,7 @@ def _display_bucket_credit_line(bucket: dict, label: str) -> None:
|
|
|
62
62
|
# If naive datetime, assume UTC
|
|
63
63
|
if dt.tzinfo is None:
|
|
64
64
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
65
|
-
formatted_date = dt.strftime(
|
|
65
|
+
formatted_date = f"{dt.strftime('%b')} {dt.day}, {dt.year}"
|
|
66
66
|
|
|
67
67
|
# Check if expired
|
|
68
68
|
now = datetime.now(timezone.utc)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeplain
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Transform plain language specifications into working code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -8,23 +8,23 @@ Classifier: Intended Audience :: Developers
|
|
|
8
8
|
Classifier: Operating System :: OS Independent
|
|
9
9
|
Classifier: Topic :: Software Development :: Code Generators
|
|
10
10
|
Requires-Python: ==3.11.*
|
|
11
|
-
Requires-Dist: gitpython==3.1.
|
|
12
|
-
Requires-Dist: mistletoe==1.
|
|
11
|
+
Requires-Dist: gitpython==3.1.52
|
|
12
|
+
Requires-Dist: mistletoe==1.5.1
|
|
13
13
|
Requires-Dist: networkx==3.6.1
|
|
14
14
|
Requires-Dist: python-frontmatter==1.3.0
|
|
15
15
|
Requires-Dist: python-liquid2==0.4.0
|
|
16
16
|
Requires-Dist: pyyaml==6.0.3
|
|
17
17
|
Requires-Dist: requests==2.34.2
|
|
18
18
|
Requires-Dist: rich==15.0.0
|
|
19
|
-
Requires-Dist: sentry-sdk==2.
|
|
19
|
+
Requires-Dist: sentry-sdk==2.66.0
|
|
20
20
|
Requires-Dist: textual>=7.5.0
|
|
21
21
|
Requires-Dist: tiktoken==0.13.0
|
|
22
22
|
Requires-Dist: transitions==0.9.3
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: black==26.
|
|
24
|
+
Requires-Dist: black==26.5.1; extra == 'dev'
|
|
25
25
|
Requires-Dist: flake8==7.3.0; extra == 'dev'
|
|
26
|
-
Requires-Dist: isort==
|
|
27
|
-
Requires-Dist: mypy==2.
|
|
26
|
+
Requires-Dist: isort==8.0.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
28
28
|
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
|
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
_version.py,sha256=W_9dCm49nLvZulVAvvsafxLJjVBSKDBHz9K7szFZllo,22
|
|
2
1
|
change_detection.py,sha256=CazORZrezeZSw2I6VBvieN-c2SEjieZPo6pNrKwmMVA,6915
|
|
3
|
-
codeplain_REST_api.py,sha256=
|
|
2
|
+
codeplain_REST_api.py,sha256=x-sCbbBSswID4eKXDMvv84nzWynNSbBPoyAtq__6tas,21644
|
|
4
3
|
concept_utils.py,sha256=D4qVHFBRvfJZwiIq1AD_SV0Ev-RnOMg2yGWo6Cal7PM,7913
|
|
5
4
|
diff_utils.py,sha256=AjiQlqo5pRos_8hVXZo5yBurl5BzSrTMGrQv4dCtRCg,1198
|
|
6
5
|
event_bus.py,sha256=g5XLwRfjrvTIcB6urjREuCJzZj5TA93hy8lKXLGXuCE,650
|
|
7
|
-
file_utils.py,sha256=
|
|
6
|
+
file_utils.py,sha256=MNZ5li1ofIMOYB6FCrMa_UkX6nkGCgSZuaqzhqVc1Ok,11682
|
|
8
7
|
git_utils.py,sha256=LQQnL5DAFpH5fDBQgUZX2WfjWY4YC5OEGBPIXryTmnY,16896
|
|
9
8
|
memory_management.py,sha256=nHNudgaOqp5UGkIMi62TRCc2nUeFOM0w-I1FfxBFaQE,6120
|
|
10
|
-
module_renderer.py,sha256=
|
|
9
|
+
module_renderer.py,sha256=DZCIo_QzvhFw8EqQTKeF3HUbvfumrV2O1sz-gUhWpIA,6752
|
|
11
10
|
partial_rendering.py,sha256=0ChOaGytogBUEGISpbWkbjT9Hqy8pnOkJdJXcitJDgk,12219
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
path_resolution.py,sha256=0tMqU0a1g4DYhTOp7QjLVSEkv_cgasb4NI1mK809dUM,2233
|
|
12
|
+
plain2code.py,sha256=YLwwzAvE0EWz51V9p8b_kbTltkPvhA2Q8J4JrYyMrAM,15327
|
|
13
|
+
plain2code_arguments.py,sha256=3tAA9Haw-j97zztjXdhi6LxFtURP0Tfg9J_rvJDoXmw,17685
|
|
14
|
+
plain2code_console.py,sha256=Ifs8tmfNX31UujQ5_0sk9AJcajMG_6qhF-6QZcfbcEE,5773
|
|
15
|
+
plain2code_events.py,sha256=rgDF5PDtNr_lEPvJmd1tIQXZrzwgzZW5b-_pykugqe4,1587
|
|
16
16
|
plain2code_exceptions.py,sha256=wkkEXw2k4LCd09PIH3_Hu0HyZvtXYjFaA653Sfey4FA,2287
|
|
17
|
-
plain2code_logger.py,sha256=
|
|
17
|
+
plain2code_logger.py,sha256=NRPLVIMnCHNVl6dII9gFoIzMdr8xa7icnL0T_Fx2XLw,4839
|
|
18
18
|
plain2code_nodes.py,sha256=IwjQqJxRSJKgP6eEnkYGy3VQHIyoazgkFxAEkxkjfJ8,4426
|
|
19
19
|
plain2code_read_config.py,sha256=D5CxnmTRjddupecWvstcUm0kIJWWzq5-Zmk6sU0wbIg,2235
|
|
20
|
-
plain2code_state.py,sha256=
|
|
20
|
+
plain2code_state.py,sha256=uePQlC29Pbhm1yXfdCFebONYdy6jo13gTTmXSwC11cQ,3168
|
|
21
21
|
plain2code_telemetry.py,sha256=7yuTH7mQE_wGVW2H1oiVZ3UJg98ArB5HcUUm9isnv9g,4354
|
|
22
|
-
plain2code_utils.py,sha256=
|
|
23
|
-
plain_file.py,sha256=
|
|
22
|
+
plain2code_utils.py,sha256=unOxuqSQRpwG8YF6uoQhnZ3ZSTJRIUCPLdJ-1lRZR5M,1534
|
|
23
|
+
plain_file.py,sha256=k2rcq53q0kOf9_8egrZILpkrVkZdfJt7HU0gHBFskU4,35116
|
|
24
24
|
plain_modules.py,sha256=uvRPfxBJwstaWi5lgYKgtQdhhf0Naiy2mS41tLw_TjY,16186
|
|
25
25
|
plain_spec.py,sha256=7nb5lLJKHZ3uu9THkSXyJ5brIKkbGW0ooVfRclLdlzA,16062
|
|
26
|
-
system_config.py,sha256=
|
|
26
|
+
system_config.py,sha256=VyE6MhXfi6agZvE02p_G4K8yCHkLh3eu890cBzPyDvs,2196
|
|
27
|
+
usage_summary.py,sha256=MA4WcVaAwz6IWCN4k_rgxVcwO4I157wN7BZlFi3h0R4,1282
|
|
27
28
|
cli_output/__init__.py,sha256=MBKl0YbVpWE-tBa3V5_aVbB7vbaqlIK2NsHTjRUZqis,284
|
|
28
29
|
cli_output/dry_run.py,sha256=6NKhNWPtD0CBK_QHSsSqIKLTzibTwxS9d8ltP9d1bgU,1473
|
|
29
|
-
cli_output/render_summary.py,sha256
|
|
30
|
-
cli_output/status.py,sha256=
|
|
30
|
+
cli_output/render_summary.py,sha256=-yRoI7ZZTS9IHyp1vd-sFleGXTVbxlrCkvuM5TX0Mp4,1168
|
|
31
|
+
cli_output/status.py,sha256=MvdocFXL1aA73NMp92gQb0Nd-f7-iw66XVUiHK33sEM,6194
|
|
31
32
|
config/__init__.py,sha256=beYSsJWmBNHDP5rYmVDouqgEeP3t1lkkepbXJ-oq0F8,37
|
|
32
33
|
config/system_config.yaml,sha256=of5R9vukSohU9AlkGJOcAVQA1UJgxYmDy6islU6iFuE,508
|
|
33
34
|
docs/generate_cli.py,sha256=0FHVhICbM8g7ahdInTNih3hNKpty1wbV5rdGECMJj48,656
|
|
@@ -36,9 +37,9 @@ render_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
36
37
|
render_machine/code_renderer.py,sha256=-vp_ltU7e3ssX9hbS8IY4ETSp-39JAuoJ3ZltKpdt1M,3959
|
|
37
38
|
render_machine/conformance_tests.py,sha256=MeEveEGJTClLGxWw04P4TR6U9kX9Qgz9qtxNrB9a8QI,7085
|
|
38
39
|
render_machine/implementation_code_helpers.py,sha256=LdHNLoKgVtrDaGH2APX8C9vjNjLBUhu2V7OAaJvm4rM,2009
|
|
39
|
-
render_machine/render_context.py,sha256=
|
|
40
|
+
render_machine/render_context.py,sha256=eoaO807LntIRYjLSpc3x7bvwBnFfzLlHmKkyKlIRrxs,25697
|
|
40
41
|
render_machine/render_types.py,sha256=cT3D0lmxQ3enIo0jGp3LEGCY2t3X1Q1_tqwcadzSAv0,8761
|
|
41
|
-
render_machine/render_utils.py,sha256=
|
|
42
|
+
render_machine/render_utils.py,sha256=Jb9NJ73yV1qCfGy9S5A9zcnz0FGVt3MHG8Ofk-9A-aI,9355
|
|
42
43
|
render_machine/state_machine_config.py,sha256=NnX5sBGkc6cNG8OOQ4PrJeJBCADRGZKJYQXV7ndR4bs,26789
|
|
43
44
|
render_machine/states.py,sha256=niFXqayyA_rezCrlzo0hYeHAruErcPzQVF-BeIBGnL8,1968
|
|
44
45
|
render_machine/triggers.py,sha256=VekNhHGR-u5JXIboqc_Eyqf73LNH7wezLK7r3WWtodk,1269
|
|
@@ -46,16 +47,16 @@ render_machine/actions/analyze_specification_ambiguity.py,sha256=SykZAozGvr1jySx
|
|
|
46
47
|
render_machine/actions/base_action.py,sha256=vVzMp-LanrZyq-jamHyWaQxpRl-pLqtTdtiEzUBhfyE,534
|
|
47
48
|
render_machine/actions/commit_conformance_tests_changes.py,sha256=08yxCPCpf5TlrzLPsEh5SJXVVvnLfwdNKSr7BlzlYxo,2589
|
|
48
49
|
render_machine/actions/commit_implementation_code_changes.py,sha256=yi51oAArLCgWcmFbynes-BK2IGnZwA7wygrTJGoL8dY,826
|
|
49
|
-
render_machine/actions/create_dist.py,sha256=
|
|
50
|
-
render_machine/actions/exit_with_error.py,sha256
|
|
50
|
+
render_machine/actions/create_dist.py,sha256=ykER7i2OvWAXjrlAZnkQHpiNl00vSMF8WDxNhlWKfsA,1088
|
|
51
|
+
render_machine/actions/exit_with_error.py,sha256=W6TMULHJcHEaXE4WUnlELEu0_l7IZy9HWaPkXyqg7ck,1279
|
|
51
52
|
render_machine/actions/finish_functional_requirement.py,sha256=usQgPSg6PHpBOR1RhK7lPz9zjY-2VJJDqi3T0nlqdLw,841
|
|
52
|
-
render_machine/actions/fix_conformance_test.py,sha256=
|
|
53
|
+
render_machine/actions/fix_conformance_test.py,sha256=EZLVjF4A8zSTmyqdgcLoz-2pLpeieq4M_Rb71pY3IKA,10095
|
|
53
54
|
render_machine/actions/fix_unit_tests.py,sha256=hvwvCJDk_-8fHMpkNFyeBSG1IshIcufDpymF00ulPXY,2301
|
|
54
55
|
render_machine/actions/prepare_repositories.py,sha256=eE-uU6H_K5IQMraVWSRi4TKk_XPrnA878T_JwtI9cWo,3410
|
|
55
56
|
render_machine/actions/prepare_testing_environment.py,sha256=kIsXgV6-jOlqp-04cimPgTQoHPrVIu0zW-H_Jj-jowE,2106
|
|
56
57
|
render_machine/actions/refactor_code.py,sha256=gyPsnqgHseL2bkENu4WeGCRyV0R18_GH3JOrPdoxKvg,2609
|
|
57
58
|
render_machine/actions/render_conformance_tests.py,sha256=5gOQn-G1T9UWEI8sDfALcVdArk0ln9DgUprOPjccS-U,9268
|
|
58
|
-
render_machine/actions/render_functional_requirement.py,sha256=
|
|
59
|
+
render_machine/actions/render_functional_requirement.py,sha256=53KzMVlcefoag1x73roCEQvQ7FbmH8FzhXMQau-s8tg,4655
|
|
59
60
|
render_machine/actions/run_conformance_tests.py,sha256=4sJTORl6YLFXQIdLMBQHDeJd2hztGyt3tsVvrCviBko,4008
|
|
60
61
|
render_machine/actions/run_unit_tests.py,sha256=A4WXtSzpCLDHYR8fQAbfxUf_E19GYflZSHZaSreoFPk,2101
|
|
61
62
|
render_machine/actions/summarize_conformance_tests.py,sha256=Vy1kRK8vyazK_BbsKuz1MLDN_TQWVxxzkwEEm-50byc,1639
|
|
@@ -65,34 +66,45 @@ standard_template_library/typescript-react-app-boilerplate.plain,sha256=6LFxhEOz
|
|
|
65
66
|
standard_template_library/typescript-react-app-template.plain,sha256=DN5wEJcT8ZqQTf0vFKi9Z1isi9cin2UVNOZb3r28d3M,715
|
|
66
67
|
tests/__init__.py,sha256=Wk73Io62J15BtlLVIzxmASDWaaJkQLevS4BLK5LDAQg,16
|
|
67
68
|
tests/conftest.py,sha256=QZcp08htUlJGgmHDlRWFgsWXZ8o8IBWTD5QqJaUMlU8,790
|
|
69
|
+
tests/test_arg_provenance.py,sha256=Vp-ZtNbTlSNOE8iiHOin3YI9sobbN0tRPUIfrYjxttQ,3459
|
|
68
70
|
tests/test_change_detection.py,sha256=jH8SEhndX400DNqIKmcYLzxHqq9WFdgmuvY3XPq-ZFc,13534
|
|
69
|
-
tests/test_cli_output.py,sha256=
|
|
71
|
+
tests/test_cli_output.py,sha256=iKS1Li4yhoIL0ezJ58o4oEf9V8TiKcQkvQLVtJpdM4c,18420
|
|
72
|
+
tests/test_console_log_styles.py,sha256=63DQWiwWNhe_rMP70bW9DAB6-EPaqU3Wpwyh8eR09pc,4080
|
|
70
73
|
tests/test_file_utils.py,sha256=R_ZIhrTtwlhHxgmbBtA8PFEU5-QB4Fi5skJ7PS2KzdU,3614
|
|
74
|
+
tests/test_folder_path_resolution.py,sha256=_ZvVFu5m2-AH8iQNn0fCYkA0flVxVwdh1oQiWcPNIxw,6611
|
|
71
75
|
tests/test_git_utils.py,sha256=h3rWhhs4XVRYqzVzdmj51siF_AYD-GkbZiefK2iGfWo,15614
|
|
72
76
|
tests/test_imports.py,sha256=1ncbqQhtQW237kIjyV-Ufl7-R-PuduvoYFj2iS-DXW4,2608
|
|
77
|
+
tests/test_log_file_name_resolution.py,sha256=99g9NgPF-BZ98CvNyqDcltBAx4sLBE8gpQPAAieKiPc,3619
|
|
78
|
+
tests/test_logging_config_path_resolution.py,sha256=avz_ehRd18INwIXvAy1AwVzNNUz0vS8eu1nRe0bra8g,2650
|
|
73
79
|
tests/test_partial_rendering.py,sha256=r0RUUd1pI4-2ZkRrM1j8_kUqv-70hrOGjuKBhZoRmH0,22758
|
|
80
|
+
tests/test_path_resolution.py,sha256=yQpd-Unq1lwNv0wkRPwVs5pDT8JmyyDgbpiTQsyt--Y,2615
|
|
74
81
|
tests/test_plain2code.py,sha256=DQYFc0JVSkMI8LZCNaQ__2Nph-DcZZW17rprJA54eyw,3851
|
|
82
|
+
tests/test_plain2code_state.py,sha256=cowPZS9oRbv9J49CE4P3Rc47Q5oQOby4bTf2OlnRlBI,1217
|
|
83
|
+
tests/test_plain2code_utils.py,sha256=-W8a7FquMJQ_pTdBoBF1XprzNL2G555QhdtXCy6BDyQ,1237
|
|
75
84
|
tests/test_plain_modules.py,sha256=S7sd4ZYNotXOgCyZzmBd714QFLih69nlZ3tV8WNtVPo,13766
|
|
76
85
|
tests/test_plainfile.py,sha256=wZ_PN4GULPWIpl_AK_r_6jkgtX0Ch8EHmN5IhX7huOE,11027
|
|
77
|
-
tests/test_plainfileparser.py,sha256=
|
|
86
|
+
tests/test_plainfileparser.py,sha256=xd9P0KqZJlJPn3RKT510IQbfBotk6nQ9O8p9iLwJiQk,22815
|
|
78
87
|
tests/test_plainspec.py,sha256=ng55E8ajrH2-gPC1p_QDIe_zXplPvoqHJ-d57UWKFTw,3577
|
|
79
88
|
tests/test_requires.py,sha256=6tnHYaKudxN-RiQjSFoi9nHe_x0ze3QF-f-j67zAE74,1250
|
|
80
89
|
tests/test_resolve_config_file.py,sha256=b87tDOvyzbsnE-QRWbZ97ou7NuyaAgskv-dbYBum31c,2830
|
|
90
|
+
tests/test_script_path_resolution.py,sha256=tiEqMevQRXr9YpfHN0xldOOQpLAUgnSqTzeZWkKHaUY,4156
|
|
81
91
|
tests/test_telemetry.py,sha256=hjm81aRQQZcZ0RB6aVbS3WO46_nIAii_csmbbtnUh74,7110
|
|
92
|
+
tests/test_tui_usage.py,sha256=sfiAGTpRrT3MRr0-8DH3qjuECSxjODVgwzrK_K3iPXs,7959
|
|
93
|
+
tests/test_usage_summary.py,sha256=Ps0kVzvmdZYeXrBR-cqkn3szTV5neYKs1PmmURngeIc,1079
|
|
82
94
|
tests/e2e/conftest.py,sha256=5Dm67UTOE-M6hMb-mqZvwa6Ek_wmZgsR7fUv9ZEqCwY,4164
|
|
83
95
|
tests/e2e/test_hello_world_python.py,sha256=PQy4elzB7WvpiWLKa6_HFO0K8HA6_6hGLaAqRi0J3OU,1627
|
|
84
96
|
tests/e2e/test_hello_world_python_windows.py,sha256=kJQZIuzj8OEEtgBVxnzFvyQJ_wvP2oBu9L-E9geg8sE,2010
|
|
85
97
|
tui/__init__.py,sha256=_fy7FowY0RkWdn4kC7XV2jgvQPCj-2gE8fNUb-Mny0A,60
|
|
86
|
-
tui/components.py,sha256=
|
|
98
|
+
tui/components.py,sha256=XkC4Aq6VyTnFnBQs8PEHwVdAOczhm0ebKN92kiYMbq0,25791
|
|
87
99
|
tui/models.py,sha256=KMjlWubmPD41GA-BjgiqkaV9v7tLJ0fuWKBDPmZj4JA,1493
|
|
88
|
-
tui/plain2code_tui.py,sha256=
|
|
100
|
+
tui/plain2code_tui.py,sha256=8F7ZYRpmTiWRdTeQ63LPf2LGrreYjIYXvf_9XNSPyHs,17104
|
|
89
101
|
tui/plain_module_render_choice_tui.py,sha256=DRl_xhUbUJsyOaCYt_uNDSLUAA3Ty9NYI9zFrVDwp9Y,11270
|
|
90
102
|
tui/spinner.py,sha256=Ro6Gd9Przf-whuHqPRY6HwI0T57yJjyNPbhDbigZKZE,2471
|
|
91
103
|
tui/state_handlers.py,sha256=4r_6m5YMcprQtgiTP0De3XFfGAF8VzgaWXHxPweYPbQ,16325
|
|
92
|
-
tui/styles.css,sha256=
|
|
93
|
-
tui/widget_helpers.py,sha256=
|
|
94
|
-
codeplain-0.3.
|
|
95
|
-
codeplain-0.3.
|
|
96
|
-
codeplain-0.3.
|
|
97
|
-
codeplain-0.3.
|
|
98
|
-
codeplain-0.3.
|
|
104
|
+
tui/styles.css,sha256=kiC7Og_2G1E7owoiZgV95-3_dSeQnsNj3qzaY04xkDg,6727
|
|
105
|
+
tui/widget_helpers.py,sha256=ToO9MV2bF2Rp-XMNcjIYclnB_qmgO5sLw4UtQ2CyTMg,6652
|
|
106
|
+
codeplain-0.3.8.dist-info/METADATA,sha256=nfj-9PV0EN0MS1W9ILf1GyOnSfcB-YSyEXW04UY9vHQ,6351
|
|
107
|
+
codeplain-0.3.8.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
108
|
+
codeplain-0.3.8.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
|
|
109
|
+
codeplain-0.3.8.dist-info/licenses/LICENSE,sha256=pCeKgQ1mXE5OmNUuKOfOZh1T1vqkeCUxghE7N8qgnzc,11345
|
|
110
|
+
codeplain-0.3.8.dist-info/RECORD,,
|
codeplain_REST_api.py
CHANGED
|
@@ -5,6 +5,7 @@ import requests
|
|
|
5
5
|
from requests.exceptions import ConnectionError, RequestException, Timeout
|
|
6
6
|
|
|
7
7
|
import plain2code_exceptions
|
|
8
|
+
from plain2code_console import RETRY_COLOR
|
|
8
9
|
from plain2code_state import RunState
|
|
9
10
|
|
|
10
11
|
MAX_RETRIES = 4
|
|
@@ -67,8 +68,11 @@ class CodeplainAPI:
|
|
|
67
68
|
connection_error_type = "Network error" if is_connection_error else "Error"
|
|
68
69
|
if attempt < num_retries:
|
|
69
70
|
if not silent:
|
|
70
|
-
self.console.debug(
|
|
71
|
-
|
|
71
|
+
self.console.debug(
|
|
72
|
+
f"↻ {connection_error_type} on attempt {attempt + 1}/{num_retries + 1}: {error}. "
|
|
73
|
+
f"Retrying in {retry_delay} seconds...",
|
|
74
|
+
color=RETRY_COLOR,
|
|
75
|
+
)
|
|
72
76
|
time.sleep(retry_delay)
|
|
73
77
|
# Exponential backoff
|
|
74
78
|
return retry_delay * 2
|
file_utils.py
CHANGED
|
@@ -293,7 +293,7 @@ def get_template_directories(plain_file_path, custom_template_dir=None, default_
|
|
|
293
293
|
3. Default template directory - for standard/fallback templates
|
|
294
294
|
"""
|
|
295
295
|
template_dirs = [
|
|
296
|
-
os.path.dirname(plain_file_path), # Highest precedence - directory containing plain file
|
|
296
|
+
os.path.dirname(os.path.abspath(plain_file_path)), # Highest precedence - directory containing plain file
|
|
297
297
|
]
|
|
298
298
|
|
|
299
299
|
if custom_template_dir:
|
module_renderer.py
CHANGED
|
@@ -158,13 +158,14 @@ class ModuleRenderer:
|
|
|
158
158
|
module.wipe_module()
|
|
159
159
|
|
|
160
160
|
self.loaded_modules = list[PlainModule]()
|
|
161
|
+
|
|
161
162
|
_, rendering_failed = self._render_module(self.plain_module, self.render_range, True)
|
|
163
|
+
|
|
162
164
|
if not rendering_failed:
|
|
163
|
-
# Get the last module that completed rendering
|
|
164
165
|
if self.args.copy_build:
|
|
165
166
|
rendered_code_path = f"{self.args.build_dest}/"
|
|
166
167
|
else:
|
|
167
|
-
rendered_code_path =
|
|
168
|
+
rendered_code_path = self.args.build_folder
|
|
168
169
|
|
|
169
170
|
self.run_state.set_render_generated_code_path(rendered_code_path)
|
|
170
171
|
self.event_bus.publish(RenderCompleted(rendered_code_path=rendered_code_path))
|
path_resolution.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Path resolution for CLI / config / default path arguments.
|
|
2
|
+
|
|
3
|
+
The rule, in one sentence: the resolution base for a relative path is determined
|
|
4
|
+
by *where the value was written*, not by which option key it sets.
|
|
5
|
+
|
|
6
|
+
- Values supplied on the command line resolve against the current working
|
|
7
|
+
directory (so they match what shell tab completion just produced).
|
|
8
|
+
- Values read from ``config.yaml`` resolve against the directory containing
|
|
9
|
+
that config file.
|
|
10
|
+
- Values left at their default (not supplied anywhere) resolve against the
|
|
11
|
+
directory containing the spec file.
|
|
12
|
+
|
|
13
|
+
Paths are expanded for ``~`` and returned as absolute paths. Canonicalization
|
|
14
|
+
(symlink resolution) is left to the caller, to be done just before I/O that
|
|
15
|
+
needs it (writing output, executing scripts) so we don't accidentally
|
|
16
|
+
dereference links the user wanted preserved.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
from typing import Literal, Optional
|
|
21
|
+
|
|
22
|
+
PathSource = Literal["cli", "config", "default"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def resolve_path(
|
|
26
|
+
value: str,
|
|
27
|
+
source: PathSource,
|
|
28
|
+
*,
|
|
29
|
+
cwd: str,
|
|
30
|
+
config_dir: Optional[str] = None,
|
|
31
|
+
spec_dir: str,
|
|
32
|
+
) -> str:
|
|
33
|
+
"""Resolve *value* to an absolute path using the base anchor for *source*.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
value: The path string as written by the user. May be absolute, relative,
|
|
37
|
+
or contain a leading ``~``.
|
|
38
|
+
source: Where the value came from -- ``"cli"``, ``"config"``, or
|
|
39
|
+
``"default"``.
|
|
40
|
+
cwd: Base directory for ``"cli"`` values.
|
|
41
|
+
config_dir: Base directory for ``"config"`` values. Must be provided
|
|
42
|
+
whenever ``source == "config"``.
|
|
43
|
+
spec_dir: Base directory for ``"default"`` values.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Absolute path with ``~`` expanded. Symlinks are not resolved.
|
|
47
|
+
"""
|
|
48
|
+
expanded = os.path.expanduser(value)
|
|
49
|
+
|
|
50
|
+
if os.path.isabs(expanded):
|
|
51
|
+
return os.path.normpath(expanded)
|
|
52
|
+
|
|
53
|
+
if source == "cli":
|
|
54
|
+
base = cwd
|
|
55
|
+
elif source == "config":
|
|
56
|
+
if config_dir is None:
|
|
57
|
+
raise ValueError("config_dir must be provided when source == 'config'")
|
|
58
|
+
base = config_dir
|
|
59
|
+
elif source == "default":
|
|
60
|
+
base = spec_dir
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(f"Unknown path source: {source!r}")
|
|
63
|
+
|
|
64
|
+
return os.path.normpath(os.path.join(base, expanded))
|
plain2code.py
CHANGED
|
@@ -48,7 +48,6 @@ from plain2code_logger import (
|
|
|
48
48
|
IndentedFormatter,
|
|
49
49
|
LoggingHandler,
|
|
50
50
|
dump_crash_logs,
|
|
51
|
-
get_log_file_path,
|
|
52
51
|
)
|
|
53
52
|
from plain2code_state import RunState
|
|
54
53
|
from plain2code_telemetry import capture_crash, initialize_telemetry
|
|
@@ -89,8 +88,7 @@ def setup_logging(
|
|
|
89
88
|
event_bus: EventBus,
|
|
90
89
|
run_state: RunState,
|
|
91
90
|
log_to_file: bool,
|
|
92
|
-
|
|
93
|
-
plain_file_path: Optional[str],
|
|
91
|
+
log_file_path: str,
|
|
94
92
|
headless: bool = False,
|
|
95
93
|
):
|
|
96
94
|
default_level = logging.DEBUG if args.verbose else logging.INFO
|
|
@@ -101,10 +99,9 @@ def setup_logging(
|
|
|
101
99
|
logging.getLogger("transitions").setLevel(logging.ERROR)
|
|
102
100
|
logging.getLogger("transitions.extensions.diagrams").setLevel(logging.ERROR)
|
|
103
101
|
|
|
104
|
-
log_file_path = get_log_file_path(plain_file_path, log_file_name)
|
|
105
|
-
|
|
106
102
|
# Try to load logging configuration from YAML file (takes precedence over --verbose)
|
|
107
103
|
config_loaded = False
|
|
104
|
+
|
|
108
105
|
if args.logging_config_path and os.path.exists(args.logging_config_path):
|
|
109
106
|
try:
|
|
110
107
|
with open(args.logging_config_path, "r") as f:
|
|
@@ -127,7 +124,7 @@ def setup_logging(
|
|
|
127
124
|
handler.setFormatter(formatter)
|
|
128
125
|
root_logger.addHandler(handler)
|
|
129
126
|
|
|
130
|
-
if log_to_file
|
|
127
|
+
if log_to_file:
|
|
131
128
|
try:
|
|
132
129
|
file_handler = logging.FileHandler(log_file_path, mode="w", encoding="utf-8")
|
|
133
130
|
file_handler.setFormatter(file_formatter)
|
|
@@ -289,6 +286,7 @@ def render( # noqa: C901
|
|
|
289
286
|
render_thread = threading.Thread(target=run_render, daemon=True)
|
|
290
287
|
app = Plain2CodeTUI(
|
|
291
288
|
event_bus=event_bus,
|
|
289
|
+
run_state=run_state,
|
|
292
290
|
on_ready=render_thread.start,
|
|
293
291
|
render_id=run_state.render_id,
|
|
294
292
|
unittests_script=args.unittests_script,
|
|
@@ -356,7 +354,7 @@ def main(): # noqa: C901
|
|
|
356
354
|
# Parse the plain file (and its required modules) once; reused by dry-run and rendering.
|
|
357
355
|
try:
|
|
358
356
|
plain_module = plain_modules.PlainModule(
|
|
359
|
-
args.filename,
|
|
357
|
+
os.path.basename(args.filename),
|
|
360
358
|
args.build_folder,
|
|
361
359
|
args.conformance_tests_folder,
|
|
362
360
|
template_dirs,
|
|
@@ -383,9 +381,7 @@ def main(): # noqa: C901
|
|
|
383
381
|
# Suppress Rich console output.
|
|
384
382
|
console.quiet = True
|
|
385
383
|
|
|
386
|
-
default_log_level = setup_logging(
|
|
387
|
-
args, event_bus, run_state, args.log_to_file, args.log_file_name, args.filename, args.headless
|
|
388
|
-
)
|
|
384
|
+
default_log_level = setup_logging(args, event_bus, run_state, args.log_to_file, args.log_file_name, args.headless)
|
|
389
385
|
|
|
390
386
|
initialize_telemetry()
|
|
391
387
|
|