ApiLogicServer 15.2.0__py3-none-any.whl → 15.2.3__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.
Files changed (24) hide show
  1. api_logic_server_cli/api_logic_server.py +2 -2
  2. api_logic_server_cli/prototypes/base/.github/.copilot-instructions.md +22 -0
  3. api_logic_server_cli/prototypes/base/docs/training/testing.md +21 -9
  4. api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_logic_report.py +55 -29
  5. api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_logic_report.py.bak +285 -0
  6. api_logic_server_cli/prototypes/basic_demo/customizations/test/api_logic_server_behave/reports/Behave Logic Report Intro micro.md +35 -0
  7. api_logic_server_cli/prototypes/basic_demo/customizations/test/api_logic_server_behave/reports/Behave Logic Report Intro.md +35 -0
  8. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/docs/training/testing.md +210 -12
  9. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/test/api_logic_server_behave/behave_logic_report.py +13 -84
  10. api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/test/api_logic_server_behave/behave_logic_report.py.bak +282 -0
  11. api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/copilot-dev-context.md +39 -4
  12. api_logic_server_cli/prototypes/manager/system/app_model_editor/test/api_logic_server_behave/behave_logic_report.py +13 -75
  13. api_logic_server_cli/prototypes/manager/system/app_model_editor/test/api_logic_server_behave/behave_logic_report.py.bak +256 -0
  14. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/behave_logic_report.py +13 -75
  15. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/behave_logic_report.py.bak +256 -0
  16. api_logic_server_cli/prototypes/nw/test/api_logic_server_behave/reports/Behave Logic Report Intro micro.md +17 -0
  17. api_logic_server_cli/prototypes/nw/test/api_logic_server_behave/reports/Behave Logic Report Intro.md +17 -0
  18. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/METADATA +79 -8
  19. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/RECORD +23 -16
  20. api_logic_server_cli/prototypes/base/.github/.copilot-instructionsZ.mdx +0 -661
  21. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/WHEEL +0 -0
  22. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/entry_points.txt +0 -0
  23. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/licenses/LICENSE +0 -0
  24. {apilogicserver-15.2.0.dist-info → apilogicserver-15.2.3.dist-info}/top_level.txt +0 -0
@@ -12,10 +12,10 @@ ApiLogicServer CLI: given a database url, create [and run] customizable ApiLogic
12
12
  Called from api_logic_server_cli.py, by instantiating the ProjectRun object.
13
13
  '''
14
14
 
15
- __version__ = "15.02.00" # last public release: 15.01.03
15
+ __version__ = "15.02.03" # last public release: 15.02.00
16
16
  recent_changes = \
17
17
  f'\n\nRecent Changes:\n' +\
18
- "\t10/21/2025 - 15.02.00: Copilot test creation from rules and custom APIs \n"\
18
+ "\t10/22/2025 - 15.02.03: Copilot test creation from rules and custom APIs with issues [103, 104] \n"\
19
19
  "\t10/06/2025 - 15.01.06: Incorrect dbml reln arrows [102] \n"\
20
20
  "\t09/27/2025 - 15.01.05: Error reporting for bad test data rebuild [101], Minor fix to ensure react-app cards have links \n"\
21
21
  "\t08/17/2025 - 15.01.03: LogicBan 01.30, with fix for copy_children[19] \n"\
@@ -44,6 +44,28 @@ If the user asks "what do I do now?", these subsections are good suggestions.
44
44
 
45
45
  List these as choices, do not just do all of them at once - that would be overwhelming.
46
46
 
47
+ ### 📚 Main Services Available in This Project
48
+
49
+ This GenAI-Logic project provides 13 main customization services:
50
+
51
+ 1. **Run Project** - F5 debug or `python api_logic_server_run.py`
52
+ 2. **Adding Business Logic** - Declarative rules in `logic/declare_logic.py`
53
+ 3. **Discovery Systems** - Auto-load logic and APIs from discovery folders
54
+ 4. **Automated Testing** - Behave tests with BLT (Business Logic Traceability) reports
55
+ 5. **Adding MCP** - Model Context Protocol client integration
56
+ 6. **Configuring Admin UI** - Edit `ui/admin/admin.yaml`
57
+ 7. **Create React Apps** - Custom UIs with `genai-logic genai-add-app`
58
+ 8. **Security - RBAC** - Role-based access control with `als add-auth`
59
+ 9. **Custom API Endpoints** - Add routes in `api/customize_api.py`
60
+ 10. **B2B Integration APIs** - Complex endpoints with Row Dict Mappers
61
+ 11. **Customize Models** - Add tables, attributes, derived fields
62
+ 12. **Adding Events** - Row events for Kafka, webhooks, integrations
63
+ 13. **Critical Patterns** - React components, null-safe constraints, test repeatability
64
+
65
+ Each service is detailed below with examples and best practices.
66
+
67
+ ---
68
+
47
69
  ### Set Up Virtual Environment
48
70
  If it is not already set, you can often find a `venv` in the GenAI-Logic Manager - a parent or grandparent directory.
49
71
 
@@ -25,6 +25,9 @@ Step 5. SUGGEST how to run tests (DO NOT run automatically)
25
25
 
26
26
  **CRITICAL PRE-TEST CHECKLIST:**
27
27
  - [ ] Step 1c completed? (Custom APIs discovered)
28
+ - [ ] **Database values verified?** (Rule #10: Run SQL to check actual prices/flags)
29
+ - [ ] `sqlite3 db.sqlite "SELECT name, unit_price, carbon_neutral FROM product;"`
30
+ - [ ] Don't assume product attributes - verify BEFORE writing expectations!
28
31
  - [ ] **Step ordering verified?** (Most specific → Most general)
29
32
  - [ ] @when patterns: carbon neutral > multi-item > single-item
30
33
  - [ ] @given patterns: multi-item > single-item
@@ -470,19 +473,28 @@ Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total,
470
473
  ```python
471
474
  # ALWAYS check actual product prices/flags before writing test expectations!
472
475
 
473
- # Check prices:
474
- # sqlite3 db.sqlite "SELECT name, unit_price, carbon_neutral FROM Product;"
476
+ # Check prices AND flags:
477
+ # sqlite3 db.sqlite "SELECT name, unit_price, carbon_neutral FROM product;"
475
478
 
476
- # Widget=90, Gadget=150, Green=109
479
+ # Results:
480
+ # 1|Gadget|150|1 ← carbon_neutral = 1 (TRUE)
481
+ # 2|Widget|90| ← carbon_neutral = NULL (not carbon neutral!)
482
+ # 3|Thingamajig|5075|
483
+ # 4|Doodad|110|
484
+ # 5|Green|109|1 ← carbon_neutral = 1 (TRUE)
477
485
 
478
- # ❌ WRONG - Assumed Widget=$100
479
- # Expected: 10 * 100 = 1000
486
+ # ❌ WRONG - Assumed Widget is carbon neutral
487
+ # Scenario: Carbon Neutral Discount
488
+ # When B2B order placed with 10 carbon neutral Widget
489
+ # Then balance should be 810 # Expected 10 * 90 * 0.9 = 810
490
+ # FAILS: Widget is NOT carbon neutral → no discount → balance = 900
480
491
 
481
- # ✅ CORRECT - Verified Widget=$90
482
- # Expected: 10 * 90 = 900
492
+ # ✅ CORRECT - Verified Gadget IS carbon neutral (flag = 1)
493
+ # Scenario: Carbon Neutral Discount
494
+ # When B2B order placed with 10 carbon neutral Gadget
495
+ # Then balance should be 1350 # Correct: 10 * 150 * 0.9 = 1350
483
496
 
484
- # For carbon neutral discount (10% off when qty >= 10):
485
- # Expected: 10 * 90 * 0.9 = 810
497
+ # CRITICAL: Don't assume product attributes - VERIFY with SQL first!
486
498
  ```
487
499
 
488
500
  ### Rule #11: Step Definitions Must Match Feature Files ⚠️ NEW
@@ -95,14 +95,43 @@ def show_logic(scenario: str, logic_logs_dir: str):
95
95
  last_rules_start = -1
96
96
  last_rules_end = -1
97
97
 
98
- # First, find the LAST "These Rules Fired" section
99
- for i, each_logic_line in enumerate(logic_lines):
100
- if "These Rules Fired" in each_logic_line:
101
- last_rules_start = i + 1 # Start collecting from next line
102
- last_rules_end = -1 # Reset end marker to find the next COMPLETE
103
- elif last_rules_start > 0 and last_rules_end == -1:
104
- if 'Logic Phase:' in each_logic_line and 'COMPLETE' in each_logic_line:
105
- last_rules_end = i
98
+ # Find ALL "These Rules Fired" sections and choose the one with the most rules
99
+ rules_sections = []
100
+ i = 0
101
+ while i < len(logic_lines):
102
+ if "These Rules Fired" in logic_lines[i]:
103
+ start_pos = i + 1
104
+ # Find the end of this rules section
105
+ end_pos = start_pos
106
+ while end_pos < len(logic_lines):
107
+ if 'Logic Phase:' in logic_lines[end_pos] and 'COMPLETE' in logic_lines[end_pos]:
108
+ break
109
+ end_pos += 1
110
+
111
+ # Count non-empty rule lines in this section (after removing trailers)
112
+ rule_count = 0
113
+ for j in range(start_pos, end_pos):
114
+ line = remove_trailer(logic_lines[j]).strip()
115
+ if line and not line.startswith('Logic Phase:'):
116
+ rule_count += 1
117
+
118
+ rules_sections.append({
119
+ 'start': start_pos,
120
+ 'end': end_pos,
121
+ 'rule_count': rule_count
122
+ })
123
+ i = end_pos
124
+ else:
125
+ i += 1
126
+
127
+ # Choose the section with the most rules
128
+ if rules_sections:
129
+ best_section = max(rules_sections, key=lambda x: x['rule_count'])
130
+ last_rules_start = best_section['start']
131
+ last_rules_end = best_section['end']
132
+ else:
133
+ last_rules_start = -1
134
+ last_rules_end = -1
106
135
 
107
136
  # Now process the file, collecting logic log and extracting the last rules section
108
137
  for i, each_logic_line in enumerate(logic_lines):
@@ -182,36 +211,27 @@ def main(behave_log: str, scenario_logs: str, wiki: str, prepend_wiki: str):
182
211
 
183
212
  just_saw_then = False
184
213
  current_scenario = ""
214
+ previous_scenario = ""
185
215
  for each_line in contents:
186
- # Show logic when we hit a blank line after assertions OR when starting a new scenario
187
- if just_saw_then and (each_line == "\n" or each_line.startswith(" Scenario")):
216
+ if just_saw_then and each_line == "\n":
188
217
  show_logic(scenario=current_scenario, logic_logs_dir=scenario_logs)
189
218
  just_saw_then = False
190
-
219
+ previous_scenario = ""
191
220
  if each_line.startswith("Feature"):
192
221
  wiki_data.append("&nbsp;")
193
222
  wiki_data.append("&nbsp;")
194
223
  each_line = "## " + each_line
195
-
196
224
  if each_line.startswith(" Scenario"):
197
- # Extract scenario name for logic lookup
198
- current_scenario = each_line.strip().replace("Scenario: ", "").replace(" ", " ").strip()
199
- wiki_data.append("&nbsp;")
200
- wiki_data.append("&nbsp;")
201
- wiki_data.append("### " + each_line[2:]) # Add scenario header
225
+ # Before starting new scenario, show logic for previous one if we saw Then
226
+ if just_saw_then and previous_scenario:
227
+ show_logic(scenario=previous_scenario, logic_logs_dir=scenario_logs)
228
+ just_saw_then = False
202
229
  each_line = tab + each_line
203
-
204
230
  if each_line.startswith(" Given") or \
205
231
  each_line.startswith(" When") or \
206
- each_line.startswith(" Then") or \
207
- each_line.startswith(" And"):
208
- if each_line.startswith(" Then") or each_line.startswith(" And"):
232
+ each_line.startswith(" Then"):
233
+ if each_line.startswith(" Then"):
209
234
  just_saw_then = True
210
- # Add subtle formatting to keywords
211
- for keyword in ["Given", "When", "Then", "And"]:
212
- if f" {keyword} " in each_line:
213
- each_line = each_line.replace(f" {keyword} ", f" **{keyword}** ")
214
- break
215
235
  each_line = tab + tab + each_line
216
236
 
217
237
  each_line = each_line[:-1]
@@ -219,13 +239,19 @@ def main(behave_log: str, scenario_logs: str, wiki: str, prepend_wiki: str):
219
239
  if debug_loc > 0:
220
240
  each_line = each_line[0 : debug_loc]
221
241
  each_line = each_line.rstrip()
242
+ if "Scenario" in each_line:
243
+ current_scenario = each_line[18:]
244
+ previous_scenario = current_scenario
245
+ wiki_data.append("&nbsp;")
246
+ wiki_data.append("&nbsp;")
247
+ wiki_data.append("### " + each_line[8:])
222
248
 
223
249
  each_line = each_line + " " # wiki for "new line"
224
250
 
225
251
  wiki_data.append(each_line)
226
-
227
- # Show logic for the last scenario
228
- if current_scenario and just_saw_then:
252
+
253
+ # Show logic for the last scenario if we saw Then
254
+ if just_saw_then and current_scenario:
229
255
  show_logic(scenario=current_scenario, logic_logs_dir=scenario_logs)
230
256
 
231
257
  with open(wiki, 'w') as rpt:
@@ -0,0 +1,285 @@
1
+ import requests
2
+ from pathlib import Path
3
+ import os
4
+ import ast
5
+ import sys
6
+ import click
7
+
8
+ """
9
+ Creates wiki file from test/behave/behave.log, with rule use.
10
+
11
+ Tips
12
+ * use 2 spaces (at end) for newline
13
+ * for tab: & emsp;
14
+
15
+ """
16
+
17
+ tab = "&emsp;"
18
+ behave_debug_info = " # "
19
+ wiki_data = []
20
+ debug_scenario = "XXGood Order Custom Service"
21
+
22
+ scenario_doc_strings = {}
23
+ """ dict of scenario_name, array of strings """
24
+
25
+
26
+ def remove_trailer(line: str) -> str:
27
+ """ remove everything after the ## """
28
+ end_here = line.find("\t\t##")
29
+ result = line[0:end_here]
30
+ return result
31
+
32
+ def line_spacer():
33
+ wiki_data.append("\n")
34
+ wiki_data.append("&nbsp;")
35
+ wiki_data.append("&nbsp;")
36
+ wiki_data.append("\n")
37
+
38
+
39
+ def get_current_readme(prepend_wiki: str):
40
+ """ initialize wiki_data with readme up to {report_name} """
41
+ report_name = "Behave Logic Report"
42
+ with open(prepend_wiki) as readme:
43
+ readme_lines = readme.readlines()
44
+ need_spacer = True
45
+ for each_readme_line in readme_lines:
46
+ if '# ' + report_name in each_readme_line:
47
+ need_spacer = False
48
+ break
49
+ wiki_data.append(each_readme_line[0:-1])
50
+ if need_spacer:
51
+ line_spacer()
52
+ wiki_data.append(f'# {report_name}')
53
+
54
+ def get_truncated_scenario_name(scenario_name: str) -> str:
55
+ """ address max file length (chop at 26), illegal characters """
56
+ scenario_trunc = scenario_name
57
+ if scenario_trunc is not None and len(scenario_trunc) >= 26:
58
+ scenario_trunc = scenario_name[0:25]
59
+ scenario_trunc = f'{str(scenario_trunc).replace(" ", "_")}'
60
+ return scenario_trunc
61
+
62
+
63
+ def show_logic(scenario: str, logic_logs_dir: str):
64
+ """ insert s{logic_logs_dir}/scenario.log into wiki_data as disclosure area """
65
+ scenario_trunc = get_truncated_scenario_name(scenario)
66
+ logic_file_name = f'{logic_logs_dir}/{scenario_trunc}.log'
67
+ logic_file_name_path = Path(logic_file_name)
68
+ if not logic_file_name_path.is_file(): # debug code
69
+ # wiki_data.append(f'unable to find Logic Log file: {logic_file_name}')
70
+ if scenario == debug_scenario:
71
+ print(f'RELATIVE: {logic_file_name} in {os.getcwd()}')
72
+ full_name = f'{os.getcwd()}/{logic_file_name}'
73
+ print(f'..FULL: {os.getcwd()}/{logic_file_name}')
74
+ logic_file_name = '{logic_logs_dir}/test.log'
75
+ with open(logic_file_name) as logic:
76
+ logic_lines = logic.readlines()
77
+ else:
78
+ logic_log = []
79
+ rules_used = []
80
+ wiki_data.append("<details markdown>")
81
+ wiki_data.append("<summary>Tests - and their logic - are transparent.. click to see Logic</summary>")
82
+ line_spacer()
83
+ scenario_trunc = get_truncated_scenario_name(scenario)
84
+ if scenario_trunc in scenario_doc_strings:
85
+ wiki_data.append(f'**Logic Doc** for scenario: {scenario}')
86
+ wiki_data.append(" ")
87
+ for each_doc_string_line in scenario_doc_strings[scenario_trunc]:
88
+ wiki_data.append(each_doc_string_line[0: -1])
89
+ line_spacer()
90
+ wiki_data.append(f'**Rules Used** in Scenario: {scenario}')
91
+ wiki_data.append("```")
92
+ with open(logic_file_name) as logic:
93
+ logic_lines = logic.readlines()
94
+ is_logic_log = True
95
+ last_rules_start = -1
96
+ last_rules_end = -1
97
+
98
+ # First, find the LAST "These Rules Fired" section
99
+ for i, each_logic_line in enumerate(logic_lines):
100
+ if "These Rules Fired" in each_logic_line:
101
+ last_rules_start = i + 1 # Start collecting from next line
102
+ last_rules_end = -1 # Reset end marker to find the next COMPLETE
103
+ elif last_rules_start > 0 and last_rules_end == -1:
104
+ if 'Logic Phase:' in each_logic_line and 'COMPLETE' in each_logic_line:
105
+ last_rules_end = i
106
+
107
+ # Now process the file, collecting logic log and extracting the last rules section
108
+ for i, each_logic_line in enumerate(logic_lines):
109
+ each_logic_line = remove_trailer(each_logic_line)
110
+
111
+ if is_logic_log:
112
+ if "These Rules Fired" in each_logic_line:
113
+ is_logic_log = False
114
+ else:
115
+ logic_log.append(each_logic_line)
116
+
117
+ # Extract rules from the last "These Rules Fired" section
118
+ if last_rules_start <= i < last_rules_end:
119
+ # Skip empty lines
120
+ if each_logic_line.strip():
121
+ wiki_data.append(each_logic_line + " ")
122
+
123
+ wiki_data.append("```")
124
+ wiki_data.append(f'**Logic Log** in Scenario: {scenario}')
125
+ wiki_data.append("```")
126
+ for each_logic_log in logic_log:
127
+ each_line = remove_trailer(each_logic_log)
128
+ wiki_data.append(each_line)
129
+ wiki_data.append("```")
130
+ wiki_data.append("</details>")
131
+
132
+
133
+ def get_docStrings(steps_dir: str):
134
+ steps_dir_files = os.listdir(steps_dir)
135
+ indent = 4 # skip leading blanks
136
+ for each_steps_dir_file in steps_dir_files:
137
+ each_steps_dir_file_path = Path(steps_dir).joinpath(each_steps_dir_file)
138
+ if each_steps_dir_file_path.is_file():
139
+ with open(each_steps_dir_file_path) as f:
140
+ step_code = f.readlines()
141
+ # print(f'Found File: {str(each_steps_dir_file_path)}')
142
+ for index, each_step_code_line in enumerate(step_code):
143
+ if each_step_code_line.startswith('@when'):
144
+ comment_start = index + 2
145
+ if '"""' in step_code[comment_start]:
146
+ # print(".. found doc string")
147
+ doc_string_line = comment_start+1
148
+ doc_string = []
149
+ while (True):
150
+ if '"""' in step_code[doc_string_line]:
151
+ break
152
+ doc_string.append(step_code[doc_string_line][indent:])
153
+ doc_string_line += 1
154
+ scenario_line = doc_string_line+1
155
+ if 'scenario_name' not in step_code[scenario_line]:
156
+ print(f'\n** Warning - scenario_name not found '\
157
+ f'in file {str(each_steps_dir_file_path)}, '\
158
+ f'after line {scenario_line} -- skipped')
159
+ else:
160
+ scenario_code_line = step_code[scenario_line]
161
+ scenario_name_start = scenario_code_line.find("'") + 1
162
+ scenario_name_end = scenario_code_line[scenario_name_start+1:].find("'")
163
+ scenario_name = scenario_code_line[scenario_name_start:
164
+ scenario_name_end + scenario_name_start+1]
165
+ if scenario_name == debug_scenario:
166
+ print(f'got {debug_scenario}')
167
+ scenario_trunc = get_truncated_scenario_name(scenario_name)
168
+ # print(f'.... truncated scenario_name: {scenario_trunc} in {scenario_code_line}')
169
+ scenario_doc_strings[scenario_trunc] = doc_string
170
+ # print("that's all, folks")
171
+
172
+
173
+ def main(behave_log: str, scenario_logs: str, wiki: str, prepend_wiki: str):
174
+ """ main driver """
175
+ get_docStrings(steps_dir="features/steps")
176
+
177
+ get_current_readme(prepend_wiki=prepend_wiki)
178
+
179
+ contents = None
180
+ with open(behave_log) as f:
181
+ contents = f.readlines()
182
+
183
+ just_saw_then = False
184
+ current_scenario = ""
185
+ for each_line in contents:
186
+ # Show logic when we hit a blank line after assertions OR when starting a new scenario
187
+ if just_saw_then and (each_line == "\n" or each_line.startswith(" Scenario")):
188
+ show_logic(scenario=current_scenario, logic_logs_dir=scenario_logs)
189
+ just_saw_then = False
190
+
191
+ if each_line.startswith("Feature"):
192
+ wiki_data.append("&nbsp;")
193
+ wiki_data.append("&nbsp;")
194
+ each_line = "## " + each_line
195
+
196
+ if each_line.startswith(" Scenario"):
197
+ # Extract scenario name for logic lookup
198
+ current_scenario = each_line.strip().replace("Scenario: ", "").replace(" ", " ").strip()
199
+ wiki_data.append("&nbsp;")
200
+ wiki_data.append("&nbsp;")
201
+ wiki_data.append("### " + each_line[2:]) # Add scenario header
202
+ each_line = tab + each_line
203
+
204
+ if each_line.startswith(" Given") or \
205
+ each_line.startswith(" When") or \
206
+ each_line.startswith(" Then") or \
207
+ each_line.startswith(" And"):
208
+ if each_line.startswith(" Then") or each_line.startswith(" And"):
209
+ just_saw_then = True
210
+ # Add subtle formatting to keywords
211
+ for keyword in ["Given", "When", "Then", "And"]:
212
+ if f" {keyword} " in each_line:
213
+ each_line = each_line.replace(f" {keyword} ", f" **{keyword}** ")
214
+ break
215
+ each_line = tab + tab + each_line
216
+
217
+ each_line = each_line[:-1]
218
+ debug_loc = each_line.find(behave_debug_info)
219
+ if debug_loc > 0:
220
+ each_line = each_line[0 : debug_loc]
221
+ each_line = each_line.rstrip()
222
+
223
+ each_line = each_line + " " # wiki for "new line"
224
+
225
+ wiki_data.append(each_line)
226
+
227
+ # Show logic for the last scenario
228
+ if current_scenario and just_saw_then:
229
+ show_logic(scenario=current_scenario, logic_logs_dir=scenario_logs)
230
+
231
+ with open(wiki, 'w') as rpt:
232
+ rpt.write('\n'.join(wiki_data))
233
+ wiki_full_path = Path(wiki).absolute()
234
+ print(f'Wiki Output: {wiki_full_path}\n\n')
235
+
236
+
237
+
238
+ def print_args(args, msg):
239
+ print(msg)
240
+ for each_arg in args:
241
+ print(f' {each_arg}')
242
+ print(" ")
243
+
244
+
245
+ @click.group()
246
+ @click.pass_context
247
+ def cli(ctx):
248
+ """
249
+ Combine behave.log and scenario_logic_logs to create Behave Logic Report
250
+
251
+ """
252
+ pass
253
+
254
+
255
+ @cli.command("run")
256
+ @click.pass_context
257
+ @click.option('--behave_log',
258
+ default=f'logs/behave.log', # cwd set to test/api_logic_server_behave
259
+ # prompt="Log from behave test suite run [behave.log]",
260
+ help="Help")
261
+ @click.option('--scenario_logs',
262
+ default=f'logs/scenario_logic_logs',
263
+ # prompt="Logic Log directory from ",
264
+ help="Help")
265
+ @click.option('--wiki',
266
+ default=f'reports/Behave Logic Report.md',
267
+ # prompt="Log from behave test suite run [api_logic_server_behave]",
268
+ help="Help")
269
+ @click.option('--prepend_wiki',
270
+ default=f'reports/Behave Logic Report Intro micro.md',
271
+ # prompt="Log from behave test suite run [Behave Logic Report Intro]",
272
+ help="Help")
273
+ def run(ctx, behave_log: str, scenario_logs: str, wiki: str, prepend_wiki: str):
274
+ main(behave_log = behave_log, scenario_logs = scenario_logs, wiki = wiki, prepend_wiki = prepend_wiki)
275
+
276
+
277
+ if __name__ == '__main__': # debugger & python command line start here
278
+ # eg: python api_logic_server_cli/cli.py create --project_name=~/Desktop/test_project
279
+ # unix: python api_logic_server_cli/cli.py create --project_name=/home/ApiLogicProject
280
+
281
+ print(f'\nBehave Logic Report 1.1, started at {os.getcwd()}')
282
+ commands = sys.argv
283
+ if len(sys.argv) > 1:
284
+ print_args(commands, f'\n\nCommand Line Arguments:')
285
+ cli()
@@ -0,0 +1,35 @@
1
+ ## Basic Demo Sample
2
+
3
+ This is a basic demonstration project created from a simple natural language prompt using API Logic Server's GenAI capabilities.
4
+
5
+ ### Data Model
6
+
7
+ ![Basic Demo Data Model](https://apilogicserver.github.io/Docs/images/basic_demo/basic_demo_data_model.jpeg)
8
+
9
+ ### Creation Prompt
10
+
11
+ This project was created from the following natural language prompt:
12
+
13
+ ```
14
+ Create a system with customers, orders, items and products.
15
+
16
+ Include a notes field for orders.
17
+
18
+ Use case: Check Credit
19
+ 1. The Customer's balance is less than the credit limit
20
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
21
+ 3. The Order's amount_total is the sum of the Item amount
22
+ 4. The Item amount is the quantity * unit_price
23
+ 5. The Item unit_price is copied from the Product unit_price
24
+
25
+ Use case: App Integration
26
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
27
+ ```
28
+
29
+ The sample Scenarios below were chosen to illustrate the basic patterns of using rules. Open the disclosure box ("Tests - and their logic...") to see the implementation and notes.
30
+
31
+ The following report was created during test suite execution.
32
+
33
+ &nbsp;
34
+
35
+ # Behave Logic Report
@@ -0,0 +1,35 @@
1
+ ## Basic Demo Sample
2
+
3
+ This is a basic demonstration project created from a simple natural language prompt using API Logic Server's GenAI capabilities (with a custom Behave Report Intro).
4
+
5
+ ### Data Model
6
+
7
+ ![Basic Demo Data Model](https://apilogicserver.github.io/Docs/images/basic_demo/basic_demo_data_model.jpeg)
8
+
9
+ ### Creation Prompt
10
+
11
+ This project was created from the following natural language prompt:
12
+
13
+ ```
14
+ Create a system with customers, orders, items and products.
15
+
16
+ Include a notes field for orders.
17
+
18
+ Use case: Check Credit
19
+ 1. The Customer's balance is less than the credit limit
20
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
21
+ 3. The Order's amount_total is the sum of the Item amount
22
+ 4. The Item amount is the quantity * unit_price
23
+ 5. The Item unit_price is copied from the Product unit_price
24
+
25
+ Use case: App Integration
26
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
27
+ ```
28
+
29
+ The sample Scenarios below were chosen to illustrate the basic patterns of using rules. Open the disclosure box ("Tests - and their logic...") to see the implementation and notes.
30
+
31
+ The following report was created during test suite execution.
32
+
33
+ &nbsp;
34
+
35
+ # Behave Logic Report