@@ -79,38 +79,56 @@ def _tweak_prefix(prefix):
7979 return prefix
8080
8181
82- def main ():
83- '''Main entry point for script: parse arguments and execute'''
84- parser = argparse .ArgumentParser (description = 'Convert robot test cases to reStructuredText with traceable items.' )
85- parser .add_argument ("-i" , "--robot" , dest = 'robot_file' , required = True ,
86- help = 'Input robot file' )
87- parser .add_argument ("-o" , "--rst" , dest = 'rst_file' , required = True ,
88- help = 'Output RST file, e.g. my_component_qtp.rst' )
89- parser .add_argument ("--only" , dest = "expression" , default = "" ,
90- help = "Expression of tags for Sphinx' `only` directive that surrounds all RST content. "
91- "By default, no `only` directive is generated." )
92- parser .add_argument ("-p" , "--prefix" , default = 'QTEST-' ,
93- help = "Overrides the default 'QTEST-' prefix." )
94- parser .add_argument ("-r" , "--relationships" , nargs = '*' ,
95- help = "Name(s) of the relationship(s) used to link to items in Tags section. The default value "
96- "is 'validates'." )
97- parser .add_argument ("-t" , "--tags" , nargs = '*' ,
98- help = "Zero or more Python regexes for matching tags to treat them as traceable targets via a "
99- "relationship. All tags get matched by default." )
100- parser .add_argument ("--include" , nargs = '*' , default = [],
101- help = "Zero or more Python regexes for matching tags to filter test cases. "
102- "If every regex matches at least one of a test case's tags, the test case is included." )
103- parser .add_argument ("-c" , "--coverage" , nargs = '*' ,
104- help = "Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags." )
105- parser .add_argument ("--type" , default = 'q' ,
106- help = "Give value that starts with 'q' or 'i' (case-insensitive) to explicitly define "
107- "the type of test: qualification/integration test. The default is 'qualification'." )
108- parser .add_argument ("--trim-suffix" , action = 'store_true' ,
109- help = "If the suffix of any prefix or --tags argument ends with '_-' it gets trimmed to '-'." )
82+ def get_robot_files (paths ):
83+ """Yields Path objects for all robot files found in the input paths.
84+
85+ Args:
86+ paths (list of str): List of file or directory paths.
87+
88+ Yields:
89+ Path: Path object for each robot file found.
90+ """
91+ for p in paths :
92+ path = Path (p )
93+ if path .is_file () and path .suffix == ".robot" :
94+ yield path
95+ elif path .is_dir ():
96+ yield from path .rglob ("*.robot" )
97+
98+
99+ def run_stylecheck (args ):
100+ """Runs the style checker and fixer."""
101+ try :
102+ from .style_checker import StyleChecker
103+ except ImportError :
104+ LOGGER .error ("Missing packages. Install with 'pip install mlx.robot2rst[stylecheck]'" )
105+ return 1
106+
107+ issues_found = False
108+ lint_issues_found = False
109+ files_checked = False
110+ for robot_file in get_robot_files (args .paths ):
111+ files_checked = True
112+ style_kwargs = {"line_length" : args .line_length }
113+ parser = StyleChecker (robot_file , fix = args .fix , ** style_kwargs )
114+ parser .run ()
115+
116+ if (parser .issues_found or parser .lint_issues_found ) and args .fix :
117+ parser .model .save (robot_file )
118+
119+ if not (parser .issues_found or parser .lint_issues_found ):
120+ LOGGER .info ("%s: No RST syntax/layout issues found" , robot_file )
121+ issues_found = issues_found or parser .issues_found
122+ lint_issues_found = lint_issues_found or parser .lint_issues_found
123+
124+ if not files_checked :
125+ LOGGER .warning ("No Robot Framework files found to check." )
126+
127+ return 1 if issues_found or (args .fail_on_layout and lint_issues_found ) else 0
110128
111- logging .basicConfig (level = logging .INFO )
112- args = parser .parse_args ()
113129
130+ def run_conversion (args ):
131+ """Runs the robot to rst conversion."""
114132 type_map = {
115133 'i' : 'integration' ,
116134 'q' : 'qualification' ,
@@ -142,6 +160,7 @@ def main():
142160
143161 parser = ParserApplication (Path (args .robot_file ), args .include )
144162 parser .run ()
163+
145164 if parser .tests :
146165 exit_code = generate_robot_2_rst (parser , Path (args .rst_file ), prefix , relationship_config ,
147166 gen_matrix , test_type = test_type , only = args .expression , coverages = coverages )
@@ -154,6 +173,87 @@ def main():
154173 return exit_code
155174
156175
176+ def main ():
177+ '''Main entry point for script: parse arguments and execute'''
178+ parser = argparse .ArgumentParser (
179+ description = 'Convert robot test cases to reStructuredText with traceable items.' ,
180+ formatter_class = argparse .RawTextHelpFormatter
181+ )
182+ parser .epilog = """
183+ examples:
184+ # Convert a file (default command)
185+ robot2rst -i input.robot -o output.rst
186+
187+ # Explicitly call convert
188+ robot2rst convert -i input.robot -o output.rst
189+
190+ # Check style of all .robot files in the current directory and subdirectories
191+ robot2rst stylecheck --fix
192+ """
193+ subparsers = parser .add_subparsers (dest = 'command' , help = 'Available commands' )
194+
195+ # Conversion command
196+ parser_convert = subparsers .add_parser ('convert' , help = 'Converts a Robot Framework file to a reStructuredText '
197+ '(.rst) file (default).' )
198+ parser_convert .add_argument ("-i" , "--robot" , dest = 'robot_file' , required = True ,
199+ help = 'Input robot file' )
200+ parser_convert .add_argument ("-o" , "--rst" , dest = 'rst_file' , required = True ,
201+ help = 'Output RST file, e.g. my_component_qtp.rst' )
202+ parser_convert .add_argument ("--only" , dest = "expression" , default = "" ,
203+ help = "Expression of tags for Sphinx' `only` directive that surrounds all RST content." )
204+ parser_convert .add_argument ("-p" , "--prefix" , default = 'QTEST-' ,
205+ help = "Overrides the default 'QTEST-' prefix." )
206+ parser_convert .add_argument ("-r" , "--relationships" , nargs = '*' ,
207+ help = "Name(s) of the relationship(s) used to link to items in Tags section. "
208+ "Default: 'validates'." )
209+ parser_convert .add_argument ("-t" , "--tags" , nargs = '*' ,
210+ help = "Python regexes for matching tags to treat as traceable targets. "
211+ "Matches all by default." )
212+ parser_convert .add_argument ("--include" , nargs = '*' , default = [],
213+ help = "Python regexes for matching tags to filter test cases." )
214+ parser_convert .add_argument ("-c" , "--coverage" , nargs = '*' ,
215+ help = "Minimum coverage percentages for the item-matrix(es); 1 value per tag in --tags." )
216+ parser_convert .add_argument ("--type" , default = 'q' ,
217+ help = "Type of test ('q' for qualification, 'i' for integration). "
218+ "Default: 'qualification'." )
219+ parser_convert .add_argument ("--trim-suffix" , action = 'store_true' ,
220+ help = "If the suffix of any prefix or --tags argument ends with '_-' it gets trimmed "
221+ "to '-'." )
222+ parser_convert .set_defaults (func = run_conversion )
223+
224+ # Stylecheck command
225+ parser_stylecheck = subparsers .add_parser ('stylecheck' ,
226+ help = 'Checks and fixes RST style in Robot documentation blocks.' )
227+ parser_stylecheck .add_argument ('paths' , nargs = '*' , default = ['.' ],
228+ help = 'One or more paths to files or folders to check. Default: current directory.' )
229+ parser_stylecheck .add_argument ("--fix" , action = "store_true" ,
230+ help = "Automatically fix RST formatting inside Robot documentation blocks." )
231+ parser_stylecheck .add_argument ("--fail-on-layout" , action = "store_true" ,
232+ help = "Fail on RST layout issues as well as syntax issues." )
233+ parser_stylecheck .add_argument ("--line-length" , type = int , default = 100 ,
234+ help = "Max line length for RST blocks (note: the line length does not include the "
235+ "length of the [Documentation] tag for example). Default: 100." )
236+ parser_stylecheck .set_defaults (func = run_stylecheck )
237+
238+ # Make 'convert' the default command if no other command is specified
239+ commands = ['convert' , 'stylecheck' ]
240+ help_flags = ['-h' , '--help' ]
241+ is_command_present = any (cmd in sys .argv [1 :2 ] for cmd in commands + help_flags )
242+
243+ if not is_command_present and len (sys .argv ) > 1 :
244+ sys .argv .insert (1 , 'convert' )
245+
246+ logging .basicConfig (level = logging .INFO )
247+ args = parser .parse_args ()
248+
249+ if hasattr (args , 'func' ):
250+ return args .func (args )
251+ else :
252+ # No command was given (e.g., `robot2rst` or `robot2rst --help`)
253+ parser .print_help ()
254+ return 0
255+
256+
157257def entrypoint ():
158258 sys .exit (main ())
159259
0 commit comments