37 if 'robot' not in sys.modules
and __name__ ==
'__main__':
38 import pythonpathsetter
42 disable_curdir_processing)
46 USAGE =
"""robot.tidy -- Robot Framework test data clean-up tool
50 Usage: python -m robot.tidy [options] inputfile
51 or: python -m robot.tidy [options] inputfile [outputfile]
52 or: python -m robot.tidy --inplace [options] inputfile [more input files]
53 or: python -m robot.tidy --recursive [options] directory
55 Tidy tool can be used to clean up and change format of Robot Framework test
56 data files. The output is written into the standard output stream by default,
57 but an optional output file can be given as well. Files can also be modified
58 in-place using --inplace or --recursive options.
63 -i --inplace Tidy given file(s) so that original file(s) are overwritten
64 (or removed, if the format is changed). When this option is
65 used, it is possible to give multiple input files.
67 python -m robot.tidy --inplace tests.robot
68 python -m robot.tidy --inplace --format robot *.html
69 -r --recursive Process given directory recursively. Files in the directory
70 are processed in-place similarly as when --inplace option
72 -f --format txt|html|tsv|robot
73 Output file format. If omitted, the format of the input
75 -p --usepipes Use pipe ('|') as a cell separator in the plain text format.
76 -s --spacecount number
77 The number of spaces between cells in the plain text format.
79 -l --lineseparator native|windows|unix
80 Line separator to use in outputs. The default is 'native'.
81 native: use operating system's native line separators
82 windows: use Windows line separators (CRLF)
83 unix: use Unix line separators (LF)
84 -h -? --help Show this help.
86 Cleaning up the test data
87 =========================
89 Test case files can be normalized using Tidy. Tidy always writes consistent
90 headers, consistent order for settings, and consistent amount of whitespace
91 between sections and cells.
94 python -m robot.tidy messed_up_tests.robot cleaned_up_tests.robot
95 python -m robot.tidy --inplace tests.robot
96 python -m robot.tidy --recursive path/to/tests
98 Changing the test data format
99 =============================
101 Robot Framework supports test data in various formats, but nowadays the
102 plain text format with the '.robot' extension is the most commonly used.
103 Tidy makes it easy to convert data from one format to another. This is
104 especially useful if there is a need to convert tests in deprecated HTML
105 format to other formats.
107 Input format is always determined based on the extension of the input file.
108 If output file is given, the output format is got from its extension, and
109 when using --inplace or --recursive, it is possible to specify the desired
110 format using the --format option.
113 python -m robot.tidy tests.html tests.robot
114 python -m robot.tidy --format robot --inplace tests.html
115 python -m robot.tidy --format robot --recursive path/to/tests
120 All output files are written using UTF-8 encoding. Outputs written to the
121 console use the current console encoding.
123 Alternative execution
124 =====================
126 In the above examples Tidy is used only with Python, but it works also with
127 Jython and IronPython. Above it is executed as an installed module, but it
128 can also be run as a script like `python path/robot/tidy.py`.
130 For more information about Tidy and other built-in tools, see
131 http://robotframework.org/robotframework/#built-in-tools.
143 space_count=4, line_separator=os.linesep):
145 pipe_separated=use_pipes,
146 txt_separating_spaces=space_count,
147 line_separator=line_separator)
157 def file(self, path, output=None):
159 with self.
_get_writer_get_writer(path, output)
as writer:
162 return writer.getvalue().replace(
'\r\n',
'\n')
165 if PY2
and self.
_is_tsv_is_tsv(inpath):
170 format = self.
_options_options[
'format']
or os.path.splitext(path)[1][1:]
171 return format.upper() ==
'TSV'
190 @disable_curdir_processing
192 if os.path.isdir(path):
195 path = os.path.dirname(path)
203 raise DataError(
"Invalid data source '%s'." % path)
206 return os.path.splitext(os.path.basename(path))[0].
lower() ==
'__init__'
209 source = data.initfile
if self.
_is_directory_is_directory(data)
else data.source
210 if source
and not output:
212 data.save(output=output, **self.
_options_options)
220 for child
in data.children:
224 return hasattr(data,
'initfile')
235 Application.__init__(self, USAGE, arg_limits=(1,))
237 def main(self, arguments, recursive=False, inplace=False, format='txt',
238 usepipes=False, spacecount=4, lineseparator=os.linesep):
239 tidy =
Tidy(format=format, use_pipes=usepipes,
240 space_count=spacecount, line_separator=lineseparator)
242 tidy.directory(arguments[0])
244 tidy.inplace(*arguments)
246 output = tidy.file(*arguments)
251 opts[
'recursive'], opts[
'inplace'] \
252 = validator.mode_and_arguments(args, **opts)
253 opts[
'format'] = validator.format(args, **opts)
254 opts[
'lineseparator'] = validator.line_sep(**opts)
255 if not opts[
'spacecount']:
256 opts.pop(
'spacecount')
258 opts[
'spacecount'] = validator.spacecount(opts[
'spacecount'])
265 recursive, inplace = bool(recursive), bool(inplace)
270 validator = validators[(recursive, inplace)]
272 return recursive, inplace
275 raise DataError(
'--recursive and --inplace can not be used together.')
279 raise DataError(
'--recursive requires exactly one argument.')
280 if not os.path.isdir(args[0]):
281 raise DataError(
'--recursive requires input to be a directory.')
284 if not all(os.path.isfile(path)
for path
in args):
285 raise DataError(
'--inplace requires inputs to be files.')
288 if len(args)
not in (1, 2):
289 raise DataError(
'Default mode requires 1 or 2 arguments.')
290 if not os.path.isfile(args[0]):
291 raise DataError(
'Default mode requires input to be a file.')
293 def format(self, args, format, inplace, recursive, **others):
295 if inplace
or recursive
or len(args) < 2:
297 format = os.path.splitext(args[1])[1][1:]
298 format = format.upper()
299 if format
not in (
'TXT',
'TSV',
'HTML',
'ROBOT'):
300 raise DataError(
"Invalid format '%s'." % format)
304 values = {
'native': os.linesep,
'windows':
'\r\n',
'unix':
'\n'}
306 return values[(lineseparator
or 'native').
lower()]
308 raise DataError(
"Invalid line separator '%s'." % lineseparator)
312 spacecount =
int(spacecount)
316 raise DataError(
'--spacecount must be an integer greater than 1.')
334 if __name__ ==
'__main__':
Used when variable does not exist.
The parsed resource file object.
The parsed test case file object.
The parsed test data directory object.
def _recursive_mode_arguments(self, args)
def spacecount(self, spacecount)
def _default_mode_arguments(self, args)
def mode_and_arguments(self, args, recursive, inplace, **others)
def _recursive_and_inplace_together(self, args)
def line_sep(self, lineseparator, **others)
def format(self, args, format, inplace, recursive, **others)
def _inplace_mode_arguments(self, args)
Command line interface for the Tidy tool.
def main(self, arguments, recursive=False, inplace=False, format='txt', usepipes=False, spacecount=4, lineseparator=os.linesep)
def validate(self, opts, args)
Programmatic API for the Tidy tool.
def directory(self, path)
Tidy a directory.
def _save_directory(self, data)
def inplace(self, *paths)
Tidy file(s) in-place.
def _is_init_file(self, path)
def __init__(self, format='txt', use_pipes=False, space_count=4, line_separator=os.linesep)
def _get_writer(self, inpath, outpath)
def _parse_data(self, path)
def _save_file(self, data, output=None)
def _is_directory(self, data)
def file(self, path, output=None)
Tidy a file.
def tidy_cli(arguments)
Executes Tidy similarly as from the command line.
def file_writer(path=None, encoding='UTF-8', newline=None)
def binary_file_writer(path=None)