1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
|
"""
The tests should be run as standalone script
"""
import os
import sys
import argparse
import datetime
import doctest
import subprocess
import plac
import plac_core
import difflib
version = sys.version_info[:2]
# The name of the directory that will store version specific outputs.
dirname = "3.13"
sys_argv0 = sys.argv[0]
docdir = os.path.dirname(os.path.abspath(__file__))
os.chdir(docdir)
PLAC_RUNNER = os.path.join(os.path.dirname(docdir), 'plac_runner.py')
# ####################### helpers ###################### #
def fix_today(text):
text = text.replace('YYYY-MM-DD', str(datetime.date.today()))
text = text.replace('2024-02-20', str(datetime.date.today()))
return text
def expect(errclass, func, *args, **kw):
try:
func(*args, **kw)
except errclass:
pass
else:
raise RuntimeError('%s expected, got none!' % errclass.__name__)
def parser_from(f, **kw):
f.__annotations__ = kw
return plac.parser_from(f)
# FIXME: Remove this when removing support for Python 3.8
class PlacTestFormatter(argparse.RawDescriptionHelpFormatter):
if version < (3, 9):
def _format_args(self, action, default_metavar):
get_metavar = self._metavar_formatter(action, default_metavar)
if action.nargs == argparse.ZERO_OR_MORE:
metavar = get_metavar(1)
if len(metavar) == 2:
result = '[%s [%s ...]]' % metavar
else:
result = '[%s ...]' % metavar
else:
result = super(PlacTestFormatter, self)._format_args(
action, default_metavar)
return result
def check_help(name):
sys.argv[0] = name + '.py' # avoid issue with pytest
plac_core._parser_registry.clear() # makes different imports independent
try:
try:
main = plac.import_main(name + '.py')
except SyntaxError:
if sys.version < '3': # expected for Python 2.X
return
else: # not expected for Python 3.X
raise
p = plac.parser_from(main, formatter_class=PlacTestFormatter)
# Different format for Python > 3.13
hname = name
if version >= (3, 13):
hname = dirname + '/' + hname
#print (hname)
expected = fix_today(open(hname + '.help').read()).strip()
got = p.format_help().strip()
#print (got)
diff = list(difflib.unified_diff(expected.splitlines(),
got.splitlines()))
diff = '\n'.join(diff)
assert got == expected, diff
finally:
sys.argv[0] = sys_argv0
# ###################### tests ########################### #
def test_expected_help():
for fname in os.listdir('.'):
if fname.endswith('.help'):
name = fname[:-5]
if name not in ('vcs', 'ishelve'):
check_help(fname[:-5])
p1 = parser_from(lambda delete, *args: None,
delete=('delete a file', 'option'))
def test_p1():
arg = p1.parse_args(['-d', 'foo', 'arg1', 'arg2'])
assert arg.delete == 'foo'
assert arg.args == ['arg1', 'arg2']
arg = p1.parse_args([])
assert arg.delete is None, arg.delete
assert arg.args == [], arg.args
p2 = parser_from(lambda arg1, delete, *args: None,
delete=('delete a file', 'option', 'd'))
def test_p2():
arg = p2.parse_args(['-d', 'foo', 'arg1', 'arg2'])
assert arg.delete == 'foo', arg.delete
assert arg.arg1 == 'arg1', arg.arg1
assert arg.args == ['arg2'], arg.args
arg = p2.parse_args(['arg1'])
assert arg.delete is None, arg.delete
assert arg.args == [], arg.args
assert arg, arg
expect(SystemExit, p2.parse_args, [])
p3 = parser_from(lambda arg1, delete: None,
delete=('delete a file', 'option', 'd'))
def test_p3():
arg = p3.parse_args(['arg1'])
assert arg.delete is None, arg.delete
assert arg.arg1 == 'arg1', arg.args
expect(SystemExit, p3.parse_args, ['arg1', 'arg2'])
expect(SystemExit, p3.parse_args, [])
p4 = parser_from(lambda delete, delete_all, color="black": None,
delete=('delete a file', 'option', 'd'),
delete_all=('delete all files', 'flag', 'a'),
color=('color', 'option', 'c'))
def test_p4():
arg = p4.parse_args(['-a'])
assert arg.delete_all is True, arg.delete_all
arg = p4.parse_args([])
arg = p4.parse_args(['--color=black'])
assert arg.color == 'black'
arg = p4.parse_args(['--color=red'])
assert arg.color == 'red'
p5 = parser_from(lambda dry_run=False: None, dry_run=('Dry run', 'flag', 'x'))
def test_p5():
arg = p5.parse_args(['--dry-run'])
assert arg.dry_run is True, arg.dry_run
p_global = parser_from(lambda reserved_=False: None, reserved_=('Reserved word', 'flag', 'g'))
def test_global():
arg = p_global.parse_args(['--reserved'])
assert arg.reserved is True, arg.reserved
def test_flag_with_default():
expect(TypeError, parser_from, lambda yes_or_no='no': None,
yes_or_no=('A yes/no flag', 'flag', 'f'))
def assert_usage(parser, expected):
usage = parser.format_usage()
assert usage == expected, usage
def test_metavar_no_defaults():
sys.argv[0] = 'test_plac.py'
# positional
p = parser_from(lambda x: None,
x=('first argument', 'positional', None, str,
[], 'METAVAR'))
assert_usage(p, 'usage: test_plac.py [-h] METAVAR\n')
# option
p = parser_from(lambda x: None,
x=('first argument', 'option', None, str, [], 'METAVAR'))
assert_usage(p, 'usage: test_plac.py [-h] [-x METAVAR]\n')
sys.argv[0] = sys_argv0
def test_metavar_with_defaults():
sys.argv[0] = 'test_plac.py'
# positional
p = parser_from(lambda x='a': None,
x=('first argument', 'positional', None, str,
[], 'METAVAR'))
assert_usage(p, 'usage: test_plac.py [-h] [METAVAR]\n')
# option
p = parser_from(lambda x='a': None,
x=('first argument', 'option', None, str,
[], 'METAVAR'))
assert_usage(p, 'usage: test_plac.py [-h] [-x METAVAR]\n')
p = parser_from(lambda x='a': None,
x=('first argument', 'option', None, str, []))
assert_usage(p, 'usage: test_plac.py [-h] [-x a]\n')
sys.argv[0] = sys_argv0
def test_metavar_empty_string():
# see https://github.com/ialbert/plac/issues/36
def main(arg=''):
pass
sys.argv[0] = 'test_plac.py'
p = parser_from(main)
assert_usage(p, "usage: test_plac.py [-h] ['']\n")
sys.argv[0] = sys_argv0
def test_kwargs():
def main(opt, arg1, *args, **kw):
print(opt, arg1)
return args, kw
main.__annotations__ = dict(opt=('Option', 'option'))
argskw = plac.call(main, ['arg1', 'arg2', 'a=1', 'b=2'])
assert argskw == [('arg2',), {'a': '1', 'b': '2'}], argskw
argskw = plac.call(main, ['arg1', 'arg2', 'a=1', '-o', '2'])
assert argskw == [('arg2',), {'a': '1'}], argskw
expect(SystemExit, plac.call, main, ['arg1', 'arg2', 'a=1', 'opt=2'])
def test_kwargs2():
# see https://github.com/ialbert/plac/issues/39
def main(**kw):
return kw.items()
assert plac.call(main, ['a=1']) == [('a', '1')]
expect(SystemExit, plac.call, main, ['foo'])
expect(SystemExit, plac.call, main, ['foo', 'a=1'])
def test_kwargs3():
# see https://github.com/ialbert/plac/issues/38
def main(opt='foo', **kw):
return opt, kw
main.__annotations__ = dict(opt=('Option', 'option'))
assert plac.call(main, ['-o', 'abc=']) == ['abc=', {}]
assert plac.call(main, ['-o', 'abc=', 'z=1']) == ['abc=', {'z': '1'}]
assert plac.call(main, ['z=1']) == ['foo', {'z': '1'}]
def test_date_default():
p = parser_from(lambda day=datetime.date.today(): day)
arg = p.parse_args(['2019-11-19'])
assert arg.day == datetime.date(2019, 11, 19)
def test_int_default():
p = parser_from(lambda number=42: number)
arg = p.parse_args([])
assert arg.number == 42
arg = p.parse_args(['424242'])
assert arg.number == 424242
def test_none_default():
p = parser_from(lambda nonable=None: arg)
arg = p.parse_args([])
assert arg.nonable is None
arg = p.parse_args(['somestring'])
assert arg.nonable == 'somestring'
class Cmds(object):
add_help = False
commands = 'help', 'commit'
def help(self, name):
return 'help', name
def commit(self):
return 'commit'
cmds = Cmds()
def test_cmds():
assert 'commit' == plac.call(cmds, ['commit'])
assert ['help', 'foo'] == plac.call(cmds, ['help', 'foo'])
expect(SystemExit, plac.call, cmds, [])
def test_cmd_abbrevs():
assert 'commit' == plac.call(cmds, ['comm'])
assert ['help', 'foo'] == plac.call(cmds, ['h', 'foo'])
expect(SystemExit, plac.call, cmds, ['foo'])
def test_sub_help():
c = Cmds()
c.add_help = True
expect(SystemExit, plac.call, c, ['commit', '-h'])
def test_yield():
def main():
for i in (1, 2, 3):
yield i
assert plac.call(main, []) == [1, 2, 3]
def test_doctest():
failure, tot = doctest.testfile('index.rst', module_relative=False)
assert not failure, failure
failing_scripts = set(['ishelve2.plac'])
def check_script(args):
if failing_scripts.intersection(args):
assert subprocess.call(args) > 0, ( # expected failure
'Unexpected success for %s' % ' '.join(args))
else:
assert subprocess.call(args) == 0, 'Failed %s' % ' '.join(args)
'''
# Disabling unused functionality
def test_batch():
for batch in os.listdir('.'):
if batch.endswith('.plac'):
check_script([sys.executable, PLAC_RUNNER, '-b', batch])
def test_placet():
for placet in os.listdir('.'):
if placet.endswith('.placet'):
check_script([sys.executable, PLAC_RUNNER, '-t', placet])
'''
if __name__ == '__main__':
n = 0
for name, test in sorted(globals().items()):
if name.startswith('test_'):
print('Running ' + name)
maybegen = test()
if hasattr(maybegen, '__iter__'):
for func, arg in maybegen:
func(arg)
n += 1
else:
n += 1
print('Executed %d tests OK' % n)
|