diff --git a/az b/az
old mode 100755
new mode 100644
diff --git a/azure-cli.pyproj b/azure-cli.pyproj
index 10e839a95da..f029358170c 100644
--- a/azure-cli.pyproj
+++ b/azure-cli.pyproj
@@ -12,11 +12,8 @@
.
{888888a0-9f3d-457c-b088-3a5042f75d52}
Standard Python launcher
- {1dd9c42b-5980-42ce-a2c3-46d3bf0eede4}
+ {4ae3497d-f45c-4ec2-9e26-57476ef276a0}
3.5
-
-
- False
@@ -28,34 +25,19 @@
-
-
-
-
Code
-
- Code
-
-
- Code
-
+
+
+
-
- Code
-
-
- Code
-
-
-
Code
@@ -72,6 +54,28 @@
+
+ {83c20e12-84e3-4c10-a1ba-466d2b57483d}
+ {2af0f10d-7135-4994-9156-5d01c9c11b7e}
+ 2.7
+ env27b (Python 2.7)
+ Scripts\python.exe
+ Scripts\pythonw.exe
+ Lib\
+ PYTHONPATH
+ X86
+
+
+ {4ae3497d-f45c-4ec2-9e26-57476ef276a0}
+ {2af0f10d-7135-4994-9156-5d01c9c11b7e}
+ 3.5
+ env35d (Python 3.5)
+ Scripts\python.exe
+ Scripts\pythonw.exe
+ Lib\
+ PYTHONPATH
+ X86
+
{1dd9c42b-5980-42ce-a2c3-46d3bf0eede4}
{2af0f10d-7135-4994-9156-5d01c9c11b7e}
diff --git a/src/azure/cli/_argparse.py b/src/azure/cli/_argparse.py
index 70abf3e3b56..bbd22236541 100644
--- a/src/azure/cli/_argparse.py
+++ b/src/azure/cli/_argparse.py
@@ -107,10 +107,10 @@ def add_command(self,
m['$args'] = []
m['$kwargs'] = kw = {}
m['$argdoc'] = ad = []
- for spec, desc in args or []:
+ for spec, desc, req in args or []:
if not any(spec.startswith(p) for p in ARG_PREFIXES):
m['$args'].append(spec.strip('<> '))
- ad.append((spec, desc))
+ ad.append((spec, desc, req))
continue
aliases = spec.split()
@@ -119,10 +119,12 @@ def add_command(self,
else:
v = aliases.pop().strip('<> ')
target, _ = _read_arg(aliases[0])
- kw.update({_read_arg(a)[0]: (target, v) for a in aliases})
- ad.append(('/'.join(aliases), desc))
-
+ kw.update({_read_arg(a)[0]: (target, v, req) for a in aliases})
+ ad.append(('/'.join(aliases), desc, req))
+ #pylint: disable=too-many-branches
+ #pylint: disable=too-many-statements
+ #pylint: disable=too-many-locals
def execute(self,
args,
show_usage=False,
@@ -209,6 +211,14 @@ def not_global(a):
parsed.positional.append(n)
n = next_n
+ required_args = [x for x, _, req in expected_kwargs.values() if req]
+ for a in required_args:
+ try:
+ parsed[a]
+ except KeyError:
+ print(L("Missing required argument {}".format(a)))
+ return self._display_usage(nouns, m, out)
+
old_stdout = sys.stdout
try:
sys.stdout = out
@@ -236,9 +246,10 @@ def _display_usage(self, nouns, noun_map, out=sys.stdout):
argdoc = noun_map.get('$argdoc')
if argdoc:
print('Arguments', file=out)
- maxlen = max(len(a) for a, d in argdoc)
- for a, d in argdoc:
- print(' {0:<{1}} - {2}'.format(a, maxlen, d), file=out)
+ maxlen = max(len(a) for a, d, r in argdoc)
+ for a, d, r in argdoc:
+ print(' {0:<{1}} - {2} {3}'.format(a, maxlen, d, L("[Required]") if r else ""),
+ file=out)
print(file=out)
out.flush()
diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py
index d27ce5d1570..23a6a8c9057 100644
--- a/src/azure/cli/commands/__init__.py
+++ b/src/azure/cli/commands/__init__.py
@@ -28,9 +28,10 @@ def add_description(handler):
return handler
return add_description
-def option(spec, description_text=None):
+def option(spec, description_text=None, required=False):
def add_option(handler):
- _COMMANDS.setdefault(handler, {}).setdefault('args', []).append((spec, description_text))
+ _COMMANDS.setdefault(handler, {}).setdefault('args', []) \
+ .append((spec, description_text, required))
logger.debug('Added option "%s" to %s', spec, handler)
return handler
return add_option
diff --git a/src/azure/cli/tests/test_argparse.py b/src/azure/cli/tests/test_argparse.py
index 99f6b7fa0e3..1ba3540800a 100644
--- a/src/azure/cli/tests/test_argparse.py
+++ b/src/azure/cli/tests/test_argparse.py
@@ -36,7 +36,7 @@ def set_n3(a, b): res[2] = True
def test_args(self):
p = ArgumentParser('test')
- p.add_command(lambda a, b: (a, b), 'n1', args=[('--arg -a', ''), ('-b ', '')])
+ p.add_command(lambda a, b: (a, b), 'n1', args=[('--arg -a', '', False), ('-b ', '', False)])
res, other = p.execute('n1 -a x'.split())
self.assertTrue(res.arg)
@@ -69,7 +69,7 @@ def test_args(self):
def test_unexpected_args(self):
p = ArgumentParser('test')
- p.add_command(lambda a, b: (a, b), 'n1', args=[('-a', '')])
+ p.add_command(lambda a, b: (a, b), 'n1', args=[('-a', '', False)])
res, other = p.execute('n1 -b=2'.split())
self.assertFalse(res)
@@ -84,5 +84,16 @@ def test_unexpected_args(self):
self.assertEqual('2', other.b.c.d)
self.assertEqual('3', other.b.c.e)
+ def test_required_args(self):
+ p = ArgumentParser('test')
+ p.add_command(lambda a, b: (a, b), 'n1', args=[('--arg -a', '', True), ('-b ', '', False)])
+
+ res, other = p.execute('n1 -a x'.split())
+ self.assertTrue(res.arg)
+ self.assertSequenceEqual(res.positional, ['x'])
+
+ self.assertIsNone(p.execute('n1 -b x'.split()))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/src/azure/cli/tests/test_autocommand.py b/src/azure/cli/tests/test_autocommand.py
index ee403cae0f0..7cc8fddabe2 100644
--- a/src/azure/cli/tests/test_autocommand.py
+++ b/src/azure/cli/tests/test_autocommand.py
@@ -47,7 +47,7 @@ def testfunc():
self.assertIsNotNone(registered_command)
self.assertEqual(registered_command['name'], command_name)
self.assertEqual(len(registered_command['args']), 1)
- self.assertEqual(registered_command['args'][0], (spec, desc))
+ self.assertEqual(registered_command['args'][0], (spec, desc, False))
def test_load_test_commands(self):
import sys