-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_python_arg_launcher.py
More file actions
93 lines (81 loc) · 2.85 KB
/
Copy pathtest_python_arg_launcher.py
File metadata and controls
93 lines (81 loc) · 2.85 KB
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
from __future__ import annotations
import importlib.util
import sys
import unittest
from pathlib import Path
MODULE_PATH = Path(__file__).with_name("python_arg_launcher.pyw")
SPEC = importlib.util.spec_from_file_location("python_arg_launcher", MODULE_PATH)
assert SPEC and SPEC.loader
launcher = importlib.util.module_from_spec(SPEC)
sys.modules[SPEC.name] = launcher
SPEC.loader.exec_module(launcher)
class InspectionTests(unittest.TestCase):
def test_required_positional_and_choice(self):
model = launcher.inspect_source(
"""
import argparse
p = argparse.ArgumentParser(description='demo')
p.add_argument('input_file', help='source')
p.add_argument('--mode', choices=['fast', 'safe'], required=True)
"""
)
self.assertEqual(model.description, "demo")
self.assertTrue(model.root[0].positional)
self.assertTrue(model.root[0].required)
self.assertEqual(model.root[1].choices, ("fast", "safe"))
self.assertTrue(model.root[1].required)
def test_boolean_and_types(self):
model = launcher.inspect_source(
"""
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('--dry-run', action='store_true')
parser.add_argument('--count', type=int, default=4)
"""
)
self.assertEqual(model.root[0].action, "store_true")
self.assertEqual(model.root[1].type_name, "int")
self.assertEqual(model.root[1].default, 4)
def test_subcommands(self):
model = launcher.inspect_source(
"""
import argparse
p = argparse.ArgumentParser()
subs = p.add_subparsers(required=True)
build = subs.add_parser('build')
build.add_argument('--jobs', type=int)
check = subs.add_parser('check')
check.add_argument('path')
"""
)
self.assertEqual(list(model.commands), ["build", "check"])
self.assertEqual(model.commands["build"][0].dest, "jobs")
self.assertEqual(model.commands["check"][0].dest, "path")
def test_optional_positionals(self):
model = launcher.inspect_source(
"""
import argparse
p = argparse.ArgumentParser()
p.add_argument('one', nargs='?')
p.add_argument('many', nargs='*')
"""
)
self.assertFalse(model.root[0].required)
self.assertFalse(model.root[1].required)
def test_dynamic_argument_is_reported_not_executed(self):
model = launcher.inspect_source(
"""
import argparse
p = argparse.ArgumentParser()
name = '--danger'
p.add_argument(name)
raise RuntimeError('must never execute')
"""
)
self.assertFalse(model.root)
self.assertTrue(any("dynamic" in note for note in model.dynamic_notes))
def test_syntax_error_falls_back(self):
model = launcher.inspect_source("def broken(:")
self.assertTrue(any("could not be parsed" in note for note in model.dynamic_notes))
if __name__ == "__main__":
unittest.main()