From 3c1f6bc8867ea3a72ff18904857de475d2425307 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Mon, 1 Sep 2025 23:20:13 +0530 Subject: [PATCH 1/9] setup cli.py --- src/osdag/cli.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/osdag/cli.py diff --git a/src/osdag/cli.py b/src/osdag/cli.py new file mode 100644 index 000000000..6d4e3b510 --- /dev/null +++ b/src/osdag/cli.py @@ -0,0 +1,63 @@ +from osdag.design_type.connection.fin_plate_connection import FinPlateConnection +from osdag.design_type.connection.cleat_angle_connection import CleatAngleConnection +from osdag.design_type.connection.seated_angle_connection import SeatedAngleConnection +from osdag.design_type.connection.end_plate_connection import EndPlateConnection +from osdag.design_type.connection.base_plate_connection import BasePlateConnection +from osdag.design_type.connection.beam_cover_plate import BeamCoverPlate +from osdag.design_type.connection.beam_cover_plate_weld import BeamCoverPlateWeld +from osdag.design_type.connection.column_cover_plate_weld import ColumnCoverPlateWeld +from osdag.design_type.tension_member.tension_bolted import Tension_bolted +from osdag.design_type.tension_member.tension_welded import Tension_welded +from osdag.design_type.connection.beam_beam_end_plate_splice import BeamBeamEndPlateSplice +from osdag.design_type.connection.beam_column_end_plate import BeamColumnEndPlate +from osdag.design_type.connection.column_cover_plate import ColumnCoverPlate +from osdag.design_type.connection.column_end_plate import ColumnEndPlate +from osdag.design_type.compression_member.compression import Compression +from osdag.design_type.main import Main +from osdag.Common import TYPE_TEXTBOX, TYPE_OUT_BUTTON +from osdag.Common import ( + # Shear Connection + KEY_DISP_FINPLATE, + KEY_DISP_ENDPLATE, + KEY_DISP_CLEATANGLE, + KEY_DISP_SEATED_ANGLE, + + # Base Plate Connection + KEY_DISP_BASE_PLATE, + + # Moment Connection + KEY_DISP_BEAMCOVERPLATE, + KEY_DISP_COLUMNCOVERPLATE, + KEY_DISP_BEAMCOVERPLATEWELD, + KEY_DISP_COLUMNCOVERPLATEWELD, + KEY_DISP_BB_EP_SPLICE, + KEY_DISP_COLUMNENDPLATE, + KEY_DISP_BCENDPLATE, + + # Tension Member + KEY_DISP_TENSION_BOLTED, + KEY_DISP_TENSION_WELDED, + + # Compression Member + KEY_DISP_COMPRESSION + +) + + +available_modules = { + KEY_DISP_BASE_PLATE:BasePlateConnection, + KEY_DISP_BEAMCOVERPLATE:BeamCoverPlate, + KEY_DISP_CLEATANGLE:CleatAngleConnection, + KEY_DISP_COLUMNCOVERPLATE:ColumnCoverPlate, + KEY_DISP_COLUMNENDPLATE:ColumnEndPlate, + KEY_DISP_ENDPLATE:EndPlateConnection, + KEY_DISP_FINPLATE:FinPlateConnection, + KEY_DISP_SEATED_ANGLE:SeatedAngleConnection, + KEY_DISP_TENSION_BOLTED:Tension_bolted, + KEY_DISP_TENSION_WELDED:Tension_welded, + KEY_DISP_COMPRESSION:Compression, + KEY_DISP_BEAMCOVERPLATEWELD:BeamCoverPlateWeld, + KEY_DISP_COLUMNCOVERPLATEWELD:ColumnCoverPlateWeld, + KEY_DISP_BB_EP_SPLICE:BeamBeamEndPlateSplice, + KEY_DISP_BCENDPLATE:BeamColumnEndPlate, +} From 2ce42202ff66f7013dacf0a546484f4991856082 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Mon, 1 Sep 2025 23:21:08 +0530 Subject: [PATCH 2/9] add method to generate design_dictionary from osi file --- src/osdag/cli.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 6d4e3b510..7f1c68ac3 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -61,3 +61,15 @@ KEY_DISP_BB_EP_SPLICE:BeamBeamEndPlateSplice, KEY_DISP_BCENDPLATE:BeamColumnEndPlate, } + +from pathlib import Path +import yaml +import pandas as pd + +def _get_design_dictionary(osi_path:Path) -> dict | None: + """return the design dictionary from an OSI file.""" + if not osi_path.exists(): + return None + with open(osi_path, 'r') as file: + return yaml.safe_load(file) + \ No newline at end of file From 8f300dace4ea7e189a3560060d0e9c371b26bd59 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Mon, 1 Sep 2025 23:21:57 +0530 Subject: [PATCH 3/9] add method to generate output_dictinory --- src/osdag/cli.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 7f1c68ac3..44aa1d057 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -72,4 +72,20 @@ def _get_design_dictionary(osi_path:Path) -> dict | None: return None with open(osi_path, 'r') as file: return yaml.safe_load(file) - \ No newline at end of file + +def _get_output_dictionary(module_class:Main) -> dict: + status = module_class.design_status + out_list = module_class.output_values(module_class, status) + out_dict = {} + for option in out_list: + if option[0] is not None and option[2] == TYPE_TEXTBOX: + out_dict[option[0]] = option[3] + if option[2] == TYPE_OUT_BUTTON: + tup = option[3] + fn = tup[1] + for item in fn(module_class, status): + lable = item[0] + value = item[3] + if lable!=None and value!=None: + out_dict[lable] = value + return out_dict From 96d6a4c94e64e322c39cd95ed369cbe02e922f5d Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Mon, 1 Sep 2025 23:22:44 +0530 Subject: [PATCH 4/9] add method to save output as csv or complete pdf report --- src/osdag/cli.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 44aa1d057..aee1d8473 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -89,3 +89,27 @@ def _get_output_dictionary(module_class:Main) -> dict: if lable!=None and value!=None: out_dict[lable] = value return out_dict + + +def _save_to_csv(output_dictionary:dict, output_file:str): + df = pd.DataFrame(output_dictionary.items()) + df.to_csv(output_file, index=False, header=None) + +def _save_to_pdf(module_class:Main, output_file:Path): + popup_summary = { + 'ProfileSummary': { + 'CompanyName': 'LoremIpsum', + 'CompanyLogo': '', + 'Group/TeamName': 'LoremIpsum', + 'Designer': 'LoremIpsum' + }, + 'ProjectTitle': 'Fossee', + 'Subtitle': '', + 'JobNumber': '123', + 'AdditionalComments': 'No comments', + 'Client': 'LoremIpsum', + 'filename': f'{output_file}', + 'does_design_exist': True, + 'logger_messages': '' + } + module_class.save_design(module_class, popup_summary) From 5dc6c7515fd169a51e131603a155bc4b3755d6b9 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Mon, 1 Sep 2025 23:23:25 +0530 Subject: [PATCH 5/9] add run_module method for cli --- src/osdag/cli.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index aee1d8473..00403b6d4 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -113,3 +113,56 @@ def _save_to_pdf(module_class:Main, output_file:Path): 'logger_messages': '' } module_class.save_design(module_class, popup_summary) + + + +def run_module(osi_path:Path | str, op_type:str): + """Run the module specified in the OSI file located at osi_path.""" + if isinstance(osi_path, str): + osi_path = Path(osi_path) + + filename = osi_path.stem + output_folder_path = osi_path.parent / "Outputs" + output_folder_path.mkdir(exist_ok=True) + design_dict = _get_design_dictionary(osi_path) + if design_dict is None: + print("File not found.") + return None + + module_name = design_dict.get("Module") + if module_name is None: + print("Module not specified.") + return None + + module_class = available_modules.get(module_name) + if module_class is None: + print("Not a valid module class.") + return None + + module_class.set_osdaglogger(None) + val_errors = module_class.func_for_validation(module_class, design_dict) + + if (val_errors is None): + output_file = output_folder_path / f"{module_class.__name__}/{filename}" + output_file.parent.mkdir(parents=True, exist_ok=True) + + if op_type == "save to csv": + _save_to_csv(_get_output_dictionary(module_class),str(output_file)+".csv") + return True + + elif op_type == "save to pdf": + _save_to_pdf(module_class, output_file) + return True + + elif op_type == "output dictionary": + return _get_output_dictionary(module_class) + + else: + for error in val_errors: + print(f"Error: {error}") + return None + + +# run_module(r"C:\Users\1hasa\Osdag\TensionBoltedTest4.osi",op_type="save to csv") +# run_module(r"C:\Users\1hasa\Osdag\TensionBoltedTest4.osi",op_type="save to pdf") +# print(run_module(r"C:\Users\1hasa\Osdag\TensionBoltedTest4.osi",op_type="output dictionary")) \ No newline at end of file From 5e092fc64ac20e1750ff216bf363d54ddc898db6 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Tue, 2 Sep 2025 13:41:27 +0530 Subject: [PATCH 6/9] Add cli osi file feature --- src/osdag/cli.py | 48 ++++++++++++++++++++++++-------------- src/osdag/osdagMainPage.py | 31 ++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 00403b6d4..4ab992586 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -66,14 +66,13 @@ import yaml import pandas as pd -def _get_design_dictionary(osi_path:Path) -> dict | None: +def _get_design_dictionary(osi_path:Path) -> dict: """return the design dictionary from an OSI file.""" - if not osi_path.exists(): - return None with open(osi_path, 'r') as file: return yaml.safe_load(file) def _get_output_dictionary(module_class:Main) -> dict: + """return the output dictionary for the design""" status = module_class.design_status out_list = module_class.output_values(module_class, status) out_dict = {} @@ -92,10 +91,12 @@ def _get_output_dictionary(module_class:Main) -> dict: def _save_to_csv(output_dictionary:dict, output_file:str): + """save the output dictionary to a csv file""" df = pd.DataFrame(output_dictionary.items()) df.to_csv(output_file, index=False, header=None) def _save_to_pdf(module_class:Main, output_file:Path): + """save the output dictionary to a pdf file""" popup_summary = { 'ProfileSummary': { 'CompanyName': 'LoremIpsum', @@ -116,19 +117,28 @@ def _save_to_pdf(module_class:Main, output_file:Path): -def run_module(osi_path:Path | str, op_type:str): +def run_module(osi_path:Path | str, op_type:str = "print_result", output_path:str | Path = None) -> bool | dict | None: """Run the module specified in the OSI file located at osi_path.""" if isinstance(osi_path, str): osi_path = Path(osi_path) + if not osi_path.exists(): + print("File not found.") + return None filename = osi_path.stem - output_folder_path = osi_path.parent / "Outputs" - output_folder_path.mkdir(exist_ok=True) + output_file = None + if not output_path: + output_folder_path = osi_path.parent / "Outputs" + else: + if isinstance(output_path, str): + output_path = Path(output_path) + output_file = output_path.stem + output_folder_path = output_path.parent + output_folder_path.mkdir(parents=True, exist_ok=True) + output_file = output_folder_path / f"{output_file if output_file else filename}" + print(output_folder_path) + print(output_file) design_dict = _get_design_dictionary(osi_path) - if design_dict is None: - print("File not found.") - return None - module_name = design_dict.get("Module") if module_name is None: print("Module not specified.") @@ -143,19 +153,23 @@ def run_module(osi_path:Path | str, op_type:str): val_errors = module_class.func_for_validation(module_class, design_dict) if (val_errors is None): - output_file = output_folder_path / f"{module_class.__name__}/{filename}" - output_file.parent.mkdir(parents=True, exist_ok=True) - - if op_type == "save to csv": + # if output_file is None: + # output_file = output_folder_path / f"{module_class.__name__}/{filename}" + # else : + # output_file = output_folder_path / f"{module_class.__name__}/{output_file}" + # output_folder_path.parent.mkdir(parents=True, exist_ok=True) + if op_type == "save_csv": _save_to_csv(_get_output_dictionary(module_class),str(output_file)+".csv") return True - elif op_type == "save to pdf": + elif op_type == "save_pdf": _save_to_pdf(module_class, output_file) return True - elif op_type == "output dictionary": - return _get_output_dictionary(module_class) + elif op_type == "print_result": + out_dict = _get_output_dictionary(module_class) + print(out_dict) + return out_dict else: for error in val_errors: diff --git a/src/osdag/osdagMainPage.py b/src/osdag/osdagMainPage.py index 0cfc08b51..85f8afc4a 100644 --- a/src/osdag/osdagMainPage.py +++ b/src/osdag/osdagMainPage.py @@ -80,7 +80,7 @@ 7) Any further Levels will result in an error . ''' -import os +import os, argparse from pathlib import Path import re import io @@ -131,6 +131,7 @@ from PyQt5 import QtWidgets, QtCore, QtGui import math import sys +from osdag.cli import run_module from .gui.ui_tutorial import Ui_Tutorial from .gui.ui_aboutosdag import Ui_AboutOsdag from .gui.ui_ask_question import Ui_AskQuestion @@ -975,5 +976,31 @@ def do_stuff(): except BaseException as e: print("ERROR", e) +def main(): + parser = argparse.ArgumentParser(description="Osdag") + parser.add_argument("--input", type=str, default=None, help="Path to input file") + parser.add_argument( + "--op_type", + type=str, + choices=["save_csv", "save_pdf", "print_result"], + default=None, + help="Type of operation: save_csv | save_pdf | print_result" + ) + parser.add_argument("--output", type=str, default=None, help="Path to output file") + args = parser.parse_args() + + if args.input: + if args.op_type: + if args.output: + run_module(args.input, args.op_type, args.output) + else: + run_module(args.input, args.op_type) + else: + + run_module(args.input) + else: + do_stuff() + if __name__ == '__main__': - do_stuff() + main() + # do_stuff() From b18ec9b11948140b13e3c0a881681fd209cbed29 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Wed, 3 Sep 2025 06:37:52 +0530 Subject: [PATCH 7/9] Add cli utility for osi files --- src/osdag/cli.py | 139 ++++++++++++++++++++++++------------- src/osdag/osdagMainPage.py | 48 ++++++++----- 2 files changed, 122 insertions(+), 65 deletions(-) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 4ab992586..84d9a46b9 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -66,6 +66,12 @@ import yaml import pandas as pd +def _print_result(out_dict:dict): + print("="*100) + for key, value in out_dict.items(): + print(f"|| {key}: {value}") + print("="*100) + def _get_design_dictionary(osi_path:Path) -> dict: """return the design dictionary from an OSI file.""" with open(osi_path, 'r') as file: @@ -75,7 +81,7 @@ def _get_output_dictionary(module_class:Main) -> dict: """return the output dictionary for the design""" status = module_class.design_status out_list = module_class.output_values(module_class, status) - out_dict = {} + out_dict = {"Parameter": "Value"} for option in out_list: if option[0] is not None and option[2] == TYPE_TEXTBOX: out_dict[option[0]] = option[3] @@ -109,7 +115,7 @@ def _save_to_pdf(module_class:Main, output_file:Path): 'JobNumber': '123', 'AdditionalComments': 'No comments', 'Client': 'LoremIpsum', - 'filename': f'{output_file}', + 'input_filename': f'{output_file}', 'does_design_exist': True, 'logger_messages': '' } @@ -117,64 +123,99 @@ def _save_to_pdf(module_class:Main, output_file:Path): -def run_module(osi_path:Path | str, op_type:str = "print_result", output_path:str | Path = None) -> bool | dict | None: +def run_module(*args, **kargs) -> dict: """Run the module specified in the OSI file located at osi_path.""" - if isinstance(osi_path, str): - osi_path = Path(osi_path) - if not osi_path.exists(): - print("File not found.") - return None - - filename = osi_path.stem - output_file = None - if not output_path: - output_folder_path = osi_path.parent / "Outputs" - else: - if isinstance(output_path, str): - output_path = Path(output_path) - output_file = output_path.stem - output_folder_path = output_path.parent - output_folder_path.mkdir(parents=True, exist_ok=True) - output_file = output_folder_path / f"{output_file if output_file else filename}" - print(output_folder_path) - print(output_file) + osi_path = kargs["input_path"] if len(kargs) > 0 else None + op_type = kargs["op_type"] if len(kargs) > 1 else "print_result" + output_path = kargs["output_path"] if len(kargs) > 2 else None + + result = { + "success": False, + "operation": op_type, + "input": str(osi_path) if osi_path else None, + "output": None, + "data": None, + "errors": [], + } + + if osi_path is None: + result["errors"].append("No input file provided.") + print(result) + return result + + osi_path = Path(osi_path) if osi_path else None + output_path = Path(output_path) if output_path else None + if not osi_path.exists(): + result["errors"].append(f"File not found: {osi_path}") + print(result) + return result + design_dict = _get_design_dictionary(osi_path) module_name = design_dict.get("Module") - if module_name is None: - print("Module not specified.") - return None + if not module_name: + result["errors"].append("Module not specified.") + print(result) + return result module_class = available_modules.get(module_name) - if module_class is None: - print("Not a valid module class.") - return None + if not module_class: + result["errors"].append(f"Not a valid module class: {module_name}") + print(result) + return result + input_filename = osi_path.stem + output_filename = output_path.stem if output_path else None + if not output_path: + output_folder_path = osi_path.parent / "Outputs" / f"{module_class.__name__}" + else: + output_folder_path = output_path.parent / f"{module_class.__name__}" + output_folder_path.mkdir(parents=True, exist_ok=True) + output_file = output_folder_path / f"{output_filename if output_filename else input_filename}" + module_class.set_osdaglogger(None) val_errors = module_class.func_for_validation(module_class, design_dict) - - if (val_errors is None): - # if output_file is None: - # output_file = output_folder_path / f"{module_class.__name__}/{filename}" - # else : - # output_file = output_folder_path / f"{module_class.__name__}/{output_file}" - # output_folder_path.parent.mkdir(parents=True, exist_ok=True) - if op_type == "save_csv": - _save_to_csv(_get_output_dictionary(module_class),str(output_file)+".csv") - return True - - elif op_type == "save_pdf": - _save_to_pdf(module_class, output_file) - return True - elif op_type == "print_result": - out_dict = _get_output_dictionary(module_class) - print(out_dict) - return out_dict + if val_errors: + result["errors"].extend(val_errors) + print(result) + return result + + out_dict = _get_output_dictionary(module_class) + result["data"] = out_dict + if op_type == "save_csv": + try: + _save_to_csv(out_dict, str(output_file) + ".csv") + result["success"] = True + result["output"] = str(output_file) + except Exception as e: + result["success"] = False + result["errors"].append(f"Failed to save CSV: {e}") + + elif op_type == "save_pdf": + try: + _save_to_pdf(module_class, output_file) + result["success"] = True + result["output"] = str(output_file) + except Exception as e: + result["success"] = False + result["errors"].append(f"Failed to save PDF: {e}") + + elif op_type == "print_result": + try: + result["success"] = True + _print_result(out_dict=out_dict) + except Exception as e: + result["success"] = False + result["errors"].append(f"Failed to get result: {e}") else: - for error in val_errors: - print(f"Error: {error}") - return None + result["errors"].append(f"Unsupported op_type: {op_type}") + + if len(result["errors"]) > 0: + print(result) + + return result + # run_module(r"C:\Users\1hasa\Osdag\TensionBoltedTest4.osi",op_type="save to csv") diff --git a/src/osdag/osdagMainPage.py b/src/osdag/osdagMainPage.py index 85f8afc4a..8e7d6bad4 100644 --- a/src/osdag/osdagMainPage.py +++ b/src/osdag/osdagMainPage.py @@ -80,6 +80,7 @@ 7) Any further Levels will result in an error . ''' +from html import parser import os, argparse from pathlib import Path import re @@ -977,29 +978,44 @@ def do_stuff(): print("ERROR", e) def main(): - parser = argparse.ArgumentParser(description="Osdag") - parser.add_argument("--input", type=str, default=None, help="Path to input file") + parser = argparse.ArgumentParser( + description=( + "========================================================================================================" + "\n\nOsdag Steel Design and Graphics Application\n\n" + "By default, running 'osdag' launches the GUI.\n" + "You can also run in CLI mode by providing --input, optional --op_type, and --output.\n" + "\nExamples:\n" + " osdag # Launch GUI\n" + " osdag -i TensionBolted.osi # Run design from input file and print design output\n" + " osdag -i TensionBolted.osi -op save_csv -o result.csv # Save output to CSV\n" + " osdag -i TensionBolted.osi -op save_pdf -o result.pdf # Save design report to PDF\n" + " osdag -i TensionBolted.osi -op print_result # Print design result\n\n" + "========================================================================================================" + ), + formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument("-i", "--input", type=str, help="Path to input file (.osi)") parser.add_argument( + "-op", "--op_type", type=str, choices=["save_csv", "save_pdf", "print_result"], - default=None, - help="Type of operation: save_csv | save_pdf | print_result" + default="print_result", + help="Type of operation: save_csv | save_pdf | print_result (default: print_result)" ) - parser.add_argument("--output", type=str, default=None, help="Path to output file") + parser.add_argument("-o", "--output", type=str, help="Path for output file") + args = parser.parse_args() - if args.input: - if args.op_type: - if args.output: - run_module(args.input, args.op_type, args.output) - else: - run_module(args.input, args.op_type) - else: - - run_module(args.input) - else: - do_stuff() + if not args.input: + return do_stuff() + input_path = args.input + output_path = args.output if args.output else None + + + result = run_module(input_path=input_path, op_type=args.op_type, output_path=output_path) + return result if __name__ == '__main__': main() From 1406d55a3201e99bd41a991ac9bee3cf0eea6381 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Thu, 4 Sep 2025 16:22:08 +0530 Subject: [PATCH 8/9] migrate from argparser to click --- src/osdag/cli.py | 4 +- src/osdag/osdagMainPage.py | 117 ++++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 44 deletions(-) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index 84d9a46b9..db92a2d09 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -63,7 +63,7 @@ } from pathlib import Path -import yaml +import yaml, click import pandas as pd def _print_result(out_dict:dict): @@ -203,7 +203,7 @@ def run_module(*args, **kargs) -> dict: elif op_type == "print_result": try: result["success"] = True - _print_result(out_dict=out_dict) + click.echo(_print_result(out_dict=out_dict)) except Exception as e: result["success"] = False result["errors"].append(f"Failed to get result: {e}") diff --git a/src/osdag/osdagMainPage.py b/src/osdag/osdagMainPage.py index 8e7d6bad4..30c6be51e 100644 --- a/src/osdag/osdagMainPage.py +++ b/src/osdag/osdagMainPage.py @@ -81,7 +81,7 @@ ''' from html import parser -import os, argparse +import os, click from pathlib import Path import re import io @@ -977,46 +977,79 @@ def do_stuff(): except BaseException as e: print("ERROR", e) -def main(): - parser = argparse.ArgumentParser( - description=( - "========================================================================================================" - "\n\nOsdag Steel Design and Graphics Application\n\n" - "By default, running 'osdag' launches the GUI.\n" - "You can also run in CLI mode by providing --input, optional --op_type, and --output.\n" - "\nExamples:\n" - " osdag # Launch GUI\n" - " osdag -i TensionBolted.osi # Run design from input file and print design output\n" - " osdag -i TensionBolted.osi -op save_csv -o result.csv # Save output to CSV\n" - " osdag -i TensionBolted.osi -op save_pdf -o result.pdf # Save design report to PDF\n" - " osdag -i TensionBolted.osi -op print_result # Print design result\n\n" - "========================================================================================================" - ), - formatter_class=argparse.RawTextHelpFormatter - ) - - parser.add_argument("-i", "--input", type=str, help="Path to input file (.osi)") - parser.add_argument( - "-op", - "--op_type", - type=str, - choices=["save_csv", "save_pdf", "print_result"], - default="print_result", - help="Type of operation: save_csv | save_pdf | print_result (default: print_result)" - ) - parser.add_argument("-o", "--output", type=str, help="Path for output file") - - args = parser.parse_args() - - if not args.input: - return do_stuff() - input_path = args.input - output_path = args.output if args.output else None +# --- Main CLI group --- +help_msg = """\n\b +================================================== +Osdag Steel Design and Graphics Application + +Usage:\n + osdag # Launch GUI (default)\n + osdag cli run # Use CLI tools (see below) + +By default, running 'osdag' launches the GUI. +You can also run in CLI mode using 'osdag cli run'. + +Examples:\n + osdag\n + osdag cli run -i TensionBolted.osi\n + osdag cli run -i TensionBolted.osi -op save_csv -o result.csv\n + osdag cli run -i TensionBolted.osi -op save_pdf -o result.pdf\n + osdag cli run -i TensionBolted.osi -op print_result\n +==================================================\n +""" + +@click.group(invoke_without_command=True, + help="\nOsdag Application. Run osdag to launch GUI, or use 'osdag cli run' for command-line tools.\n", + epilog=help_msg, + context_settings=dict(help_option_names=['-h', '--help']), + ) + +@click.pass_context +def osdag(ctx): + if ctx.invoked_subcommand is None: + do_stuff() + + +# --- CLI group --- +@osdag.group(help="\nRun in CLI mode (use subcommands like 'run').\n", + epilog=help_msg, + context_settings=dict(help_option_names=['-h', '--help']), + ) +def cli(): + pass + + +# --- Subcommand: run --- +@cli.command(help="\nOsdag Application. Run osdag to launch GUI, or use 'osdag cli run' for command-line tools.\n", + epilog=help_msg, + context_settings=dict(help_option_names=['-h', '--help']), + ) +@click.option("-i", "--input", "input_path", + type=click.Path(exists=True, dir_okay=False), + required=True, + help="Path to input file (.osi)") +@click.option("-op", "--op_type", + type=click.Choice(["save_csv", "save_pdf", "print_result"]), + default="print_result", + show_default=True, + help="Type of operation") +@click.option("-o", "--output", "output_path", + type=click.Path(dir_okay=False, writable=True), + help="Path for output file") +def run(input_path, op_type, output_path): + result = run_module(input_path=input_path, + op_type=op_type, + output_path=output_path) + + if not result["success"]: + click.echo("Errors encountered:") + for err in result["errors"]: + click.echo(f" - {err}") + else: + click.echo("Operation completed successfully") + if result.get("output"): + click.echo(f"Output saved at: {result['output']}") - - result = run_module(input_path=input_path, op_type=args.op_type, output_path=output_path) - return result -if __name__ == '__main__': - main() - # do_stuff() +if __name__ == "__main__": + osdag() \ No newline at end of file From 0e95140359ad5f6b0d198e674be653896c709f49 Mon Sep 17 00:00:00 2001 From: Zehen-249 <1hasanmehendi123@gmail.com> Date: Wed, 10 Sep 2025 12:28:30 +0530 Subject: [PATCH 9/9] Add _get_module_class method --- src/osdag/cli.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/osdag/cli.py b/src/osdag/cli.py index db92a2d09..a2a035584 100644 --- a/src/osdag/cli.py +++ b/src/osdag/cli.py @@ -66,7 +66,8 @@ import yaml, click import pandas as pd -def _print_result(out_dict:dict): +def _print_result(out_dict:dict) -> None: + """print the output dictionary to the console""" print("="*100) for key, value in out_dict.items(): print(f"|| {key}: {value}") @@ -77,14 +78,27 @@ def _get_design_dictionary(osi_path:Path) -> dict: with open(osi_path, 'r') as file: return yaml.safe_load(file) +def _get_module_class(design_dict:dict) -> Main: + """return the module class from the design dictionary.""" + module_name = design_dict.get("Module") + if not module_name: + raise ValueError("Module not specified.") + module_class = available_modules.get(module_name) + if not module_class: + raise ValueError(f"Not a valid module class: {module_name}") + return module_class + def _get_output_dictionary(module_class:Main) -> dict: """return the output dictionary for the design""" status = module_class.design_status out_list = module_class.output_values(module_class, status) out_dict = {"Parameter": "Value"} for option in out_list: + # ('Member.tension_blockshear', 'Block Shear Capacity (kN)', 'TextBox', 83.86, True) if option[0] is not None and option[2] == TYPE_TEXTBOX: out_dict[option[0]] = option[3] + + # ('pattern1', 'Pattern', 'Output_dock_Button', ['Shear Pattern ', ], True) if option[2] == TYPE_OUT_BUTTON: tup = option[3] fn = tup[1] @@ -101,7 +115,7 @@ def _save_to_csv(output_dictionary:dict, output_file:str): df = pd.DataFrame(output_dictionary.items()) df.to_csv(output_file, index=False, header=None) -def _save_to_pdf(module_class:Main, output_file:Path): +def _save_to_pdf(module_class:Main, output_file:Path) -> None: """save the output dictionary to a pdf file""" popup_summary = { 'ProfileSummary': { @@ -125,6 +139,7 @@ def _save_to_pdf(module_class:Main, output_file:Path): def run_module(*args, **kargs) -> dict: """Run the module specified in the OSI file located at osi_path.""" + osi_path = kargs["input_path"] if len(kargs) > 0 else None op_type = kargs["op_type"] if len(kargs) > 1 else "print_result" output_path = kargs["output_path"] if len(kargs) > 2 else None