Skip to content

Commit fd7400d

Browse files
committed
Add .profile dot command
Closes awslabs#9.
1 parent 94b2cbf commit fd7400d

File tree

3 files changed

+88
-6
lines changed

3 files changed

+88
-6
lines changed

awsshell/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def main():
6666
completer = shellcomplete.AWSShellCompleter(model_completer)
6767
shell = app.create_aws_shell(completer, model_completer, doc_data)
6868
if args.profile:
69-
shell.on_profile_change(args.profile)
69+
shell.profile = args.profile
7070
shell.run()
7171

7272

awsshell/app.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,45 @@ def run(self, command, application):
8282
p.communicate()
8383

8484

85+
class ProfileHandler(object):
86+
USAGE = (
87+
'.profile # Print the current profile\n'
88+
'.profile <name> # Change the current profile\n'
89+
)
90+
91+
def __init__(self, output=sys.stdout, err=sys.stderr):
92+
self._output = output
93+
self._err = err
94+
95+
def run(self, command, application):
96+
"""Get or set the profile.
97+
98+
If .profile is called with no args, the current profile
99+
is displayed. If the .profile command is called with a
100+
single arg, then the current profile for the application
101+
will be set to the new value.
102+
"""
103+
if len(command) == 1:
104+
profile = application.profile
105+
if profile is None:
106+
self._output.write(
107+
"Current shell profile: no profile configured\n"
108+
"You can change profiles using: .profile profile-name\n")
109+
else:
110+
self._output.write("Current shell profile: %s\n" % profile)
111+
elif len(command) == 2:
112+
new_profile_name = command[1]
113+
application.profile = new_profile_name
114+
self._output.write("Current shell profile changed to: %s\n" %
115+
new_profile_name)
116+
else:
117+
self._err.write("Usage:\n%s\n" % self.USAGE)
118+
119+
85120
class DotCommandHandler(object):
86121
HANDLER_CLASSES = {
87122
'edit': EditHandler,
123+
'profile': ProfileHandler,
88124
}
89125

90126
def __init__(self, output=sys.stdout, err=sys.stderr):
@@ -163,6 +199,7 @@ def __init__(self, completer, model_completer, docs):
163199
self.key_manager = None
164200
self._dot_cmd = DotCommandHandler()
165201
self._env = os.environ.copy()
202+
self._profile = None
166203

167204
# These attrs come from the config file.
168205
self.config_obj = None
@@ -388,11 +425,12 @@ def create_cli_interface(self, display_completions_in_columns):
388425
cli = CommandLineInterface(application=app, eventloop=loop)
389426
return cli
390427

391-
def on_profile_change(self, new_profile_name):
392-
"""Handler invoked when the user requests to use a new profile.
428+
@property
429+
def profile(self):
430+
return self._profile
393431

394-
This will inform the necessary objects to use the new profile.
395-
"""
432+
@profile.setter
433+
def profile(self, new_profile_name):
396434
# There's only two things that need to know about new profile
397435
# changes.
398436
#
@@ -409,3 +447,4 @@ def on_profile_change(self, new_profile_name):
409447
# would be worth it.
410448
self._env['AWS_DEFAULT_PROFILE'] = new_profile_name
411449
self.completer.change_profile(new_profile_name)
450+
self._profile = new_profile_name

tests/unit/test_app.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,48 @@ def test_edit_handler():
3939
assert command_run[0] == 'my-editor'
4040

4141

42+
def test_profile_handler_prints_profile():
43+
shell = mock.Mock(spec=app.AWSShell)
44+
shell.profile = 'myprofile'
45+
stdout = compat.StringIO()
46+
handler = app.ProfileHandler(stdout)
47+
handler.run(['.profile'], shell)
48+
assert stdout.getvalue().strip() == 'Current shell profile: myprofile'
49+
50+
51+
def test_profile_handler_when_no_profile_configured():
52+
shell = mock.Mock(spec=app.AWSShell)
53+
shell.profile = None
54+
stdout = compat.StringIO()
55+
handler = app.ProfileHandler(stdout)
56+
handler.run(['.profile'], shell)
57+
assert stdout.getvalue() == (
58+
'Current shell profile: no profile configured\n'
59+
'You can change profiles using: .profile profile-name\n'
60+
)
61+
62+
63+
def test_profile_command_changes_profile():
64+
shell = mock.Mock(spec=app.AWSShell)
65+
shell.profile = 'myprofile'
66+
stdout = compat.StringIO()
67+
handler = app.ProfileHandler(stdout)
68+
69+
handler.run(['.profile', 'newprofile'], shell)
70+
71+
assert shell.profile == 'newprofile'
72+
73+
74+
def test_profile_prints_error_on_bad_syntax():
75+
stderr = compat.StringIO()
76+
handler = app.ProfileHandler(None, stderr)
77+
handler.run(['.profile', 'a', 'b', 'c'], None)
78+
79+
# We don't really care about the exact usage message here,
80+
# we just want to ensure usage was written to stderr.
81+
assert 'Usage' in stderr.getvalue()
82+
83+
4284
def test_prints_error_message_on_unknown_dot_command(errstream):
4385
handler = app.DotCommandHandler(err=errstream)
4486
handler.handle_cmd(".unknown foo bar", None)
@@ -48,5 +90,6 @@ def test_prints_error_message_on_unknown_dot_command(errstream):
4890
def test_delegates_to_complete_changing_profile():
4991
completer = mock.Mock(spec=shellcomplete.AWSShellCompleter)
5092
shell = app.AWSShell(completer, mock.Mock(), mock.Mock())
51-
shell.on_profile_change('mynewprofile')
93+
shell.profile = 'mynewprofile'
5294
assert completer.change_profile.call_args == mock.call('mynewprofile')
95+
assert shell.profile == 'mynewprofile'

0 commit comments

Comments
 (0)