-
Notifications
You must be signed in to change notification settings - Fork 129
Expand file tree
/
Copy pathconftest.py
More file actions
155 lines (118 loc) · 4.74 KB
/
conftest.py
File metadata and controls
155 lines (118 loc) · 4.74 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
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
"""Cmd2 unit/functional testing"""
import argparse
import sys
from contextlib import redirect_stderr
from unittest import (
mock,
)
import pytest
import cmd2
from cmd2 import rich_utils as ru
from cmd2.rl_utils import readline
from cmd2.utils import StdSim
def verify_help_text(cmd2_app: cmd2.Cmd, help_output: str | list[str], verbose_strings: list[str] | None = None) -> None:
"""This function verifies that all expected commands are present in the help text.
:param cmd2_app: instance of cmd2.Cmd
:param help_output: output of help, either as a string or list of strings
:param verbose_strings: optional list of verbose strings to search for
"""
help_text = help_output if isinstance(help_output, str) else ''.join(help_output)
commands = cmd2_app.get_visible_commands()
for command in commands:
assert command in help_text
if verbose_strings:
for verbose_string in verbose_strings:
assert verbose_string in help_text
# Output from the shortcuts command with default built-in shortcuts
SHORTCUTS_TXT = """Shortcuts for other commands:
!: shell
?: help
@: run_script
@@: _relative_run_script
"""
def normalize(block):
"""Normalize a block of text to perform comparison.
Strip newlines from the very beginning and very end Then split into separate lines and strip trailing whitespace
from each line.
"""
assert isinstance(block, str)
block = block.strip('\n')
return [line.rstrip() for line in block.splitlines()]
def run_cmd(app, cmd):
"""Clear out and err StdSim buffers, run the command, and return out and err"""
# Only capture sys.stdout if it's the same stream as self.stdout
stdouts_match = app.stdout == sys.stdout
# This will be used to capture app.stdout and sys.stdout
copy_cmd_stdout = StdSim(app.stdout)
# This will be used to capture sys.stderr
copy_stderr = StdSim(sys.stderr)
try:
app.stdout = copy_cmd_stdout
if stdouts_match:
sys.stdout = app.stdout
with redirect_stderr(copy_stderr):
app.onecmd_plus_hooks(cmd)
finally:
app.stdout = copy_cmd_stdout.inner_stream
if stdouts_match:
sys.stdout = app.stdout
out = copy_cmd_stdout.getvalue()
err = copy_stderr.getvalue()
return normalize(out), normalize(err)
@pytest.fixture
def base_app():
return cmd2.Cmd(include_py=True, include_ipy=True)
def with_ansi_style(style):
def arg_decorator(func):
import functools
@functools.wraps(func)
def cmd_wrapper(*args, **kwargs):
old = ru.ALLOW_STYLE
ru.ALLOW_STYLE = style
try:
retval = func(*args, **kwargs)
finally:
ru.ALLOW_STYLE = old
return retval
return cmd_wrapper
return arg_decorator
# These are odd file names for testing quoting of them
odd_file_names = ['nothingweird', 'has spaces', '"is_double_quoted"', "'is_single_quoted'"]
def complete_tester(text: str, line: str, begidx: int, endidx: int, app) -> str | None:
"""This is a convenience function to test cmd2.complete() since
in a unit test environment there is no actual console readline
is monitoring. Therefore we use mock to provide readline data
to complete().
:param text: the string prefix we are attempting to match
:param line: the current input line with leading whitespace removed
:param begidx: the beginning index of the prefix text
:param endidx: the ending index of the prefix text
:param app: the cmd2 app that will run completions
:return: The first matched string or None if there are no matches
Matches are stored in app.completion_matches
These matches also have been sorted by complete()
"""
def get_line():
return line
def get_begidx():
return begidx
def get_endidx():
return endidx
# Run the readline tab completion function with readline mocks in place
with (
mock.patch.object(readline, 'get_line_buffer', get_line),
mock.patch.object(readline, 'get_begidx', get_begidx),
mock.patch.object(readline, 'get_endidx', get_endidx),
):
return app.complete(text, 0)
def find_subcommand(action: argparse.ArgumentParser, subcmd_names: list[str]) -> argparse.ArgumentParser:
if not subcmd_names:
return action
cur_subcmd = subcmd_names.pop(0)
for sub_action in action._actions:
if isinstance(sub_action, argparse._SubParsersAction):
for choice_name, choice in sub_action.choices.items():
if choice_name == cur_subcmd:
return find_subcommand(choice, subcmd_names)
break
raise ValueError(f"Could not find subcommand '{subcmd_names}'")