def test_json_with_spaces(self): p = self.get_param_object("ec2.RunInstances.BlockDeviceMappings") # If a user specifies the json with spaces, it will show up as # a multi element list. For example: # --block-device-mappings [{ "DeviceName":"/dev/sdf", # "VirtualName":"ephemeral0"}, {"DeviceName":"/dev/sdg", # "VirtualName":"ephemeral1" }] # # Will show up as: block_device_mapping = [ "[{", "DeviceName:/dev/sdf,", "VirtualName:ephemeral0},", "{DeviceName:/dev/sdg,", "VirtualName:ephemeral1", "}]", ] # The shell has removed the double quotes so this is invalid # JSON, but we should still raise a better exception. with self.assertRaises(ParamError) as e: unpack_cli_arg(p, block_device_mapping) # Parameter name should be in error message. self.assertIn("--block-device-mappings", str(e.exception)) # The actual JSON itself should be in the error message. # Becaues this is a list, only the first element in the JSON # will show. This will at least let customers know what # we tried to parse. self.assertIn("[{", str(e.exception))
def test_list_structure_scalars(self): p = self.get_param_object('elb.CreateLoadBalancer.Listeners') expected = [ {"protocol": "protocol1", "load_balancer_port": 1, "instance_protocol": "instance_protocol1", "instance_port": 2, "ssl_certificate_id": "ssl_certificate_id1"}, {"protocol": "protocol2", "load_balancer_port": 3, "instance_protocol": "instance_protocol2", "instance_port": 4, "ssl_certificate_id": "ssl_certificate_id2"}, ] returned = unpack_cli_arg( p, ['{"protocol": "protocol1", "load_balancer_port": 1, ' '"instance_protocol": "instance_protocol1", ' '"instance_port": 2, "ssl_certificate_id": ' '"ssl_certificate_id1"}', '{"protocol": "protocol2", "load_balancer_port": 3, ' '"instance_protocol": "instance_protocol2", ' '"instance_port": 4, "ssl_certificate_id": ' '"ssl_certificate_id2"}', ]) self.assertEqual(returned, expected) simplified = self.simplify(p, [ 'protocol=protocol1,load_balancer_port=1,' 'instance_protocol=instance_protocol1,' 'instance_port=2,ssl_certificate_id=ssl_certificate_id1', 'protocol=protocol2,load_balancer_port=3,' 'instance_protocol=instance_protocol2,' 'instance_port=4,ssl_certificate_id=ssl_certificate_id2' ]) self.assertEqual(simplified, expected)
def test_simplify_structure_scalars(self): p = self.get_param_object("elasticbeanstalk.CreateConfigurationTemplate.SourceConfiguration") value = "ApplicationName=foo,TemplateName=bar" json_value = '{"ApplicationName": "foo", "TemplateName": "bar"}' returned = self.simplify(p, value) json_version = unpack_cli_arg(p, json_value) self.assertEqual(returned, json_version)
def test_list_structure_scalars_2(self): p = self.get_param_object('elb.CreateLoadBalancer.Listeners') expected = [ {"Protocol": "protocol1", "LoadBalancerPort": 1, "InstanceProtocol": "instance_protocol1", "InstancePort": 2, "SSLCertificateId": "ssl_certificate_id1"}, {"Protocol": "protocol2", "LoadBalancerPort": 3, "InstanceProtocol": "instance_protocol2", "InstancePort": 4, "SSLCertificateId": "ssl_certificate_id2"}, ] returned = unpack_cli_arg( p, ['{"Protocol": "protocol1", "LoadBalancerPort": 1, ' '"InstanceProtocol": "instance_protocol1", ' '"InstancePort": 2, "SSLCertificateId": ' '"ssl_certificate_id1"}', '{"Protocol": "protocol2", "LoadBalancerPort": 3, ' '"InstanceProtocol": "instance_protocol2", ' '"InstancePort": 4, "SSLCertificateId": ' '"ssl_certificate_id2"}', ]) self.maxDiff = None self.assertEqual(returned, expected) simplified = self.simplify(p, [ 'Protocol=protocol1,LoadBalancerPort=1,' 'InstanceProtocol=instance_protocol1,' 'InstancePort=2,SSLCertificateId=ssl_certificate_id1', 'Protocol=protocol2,LoadBalancerPort=3,' 'InstanceProtocol=instance_protocol2,' 'InstancePort=4,SSLCertificateId=ssl_certificate_id2' ]) self.assertEqual(simplified, expected)
def __call__(self, args, parsed_globals): # args is the remaining unparsed args. # We might be able to parse these args so we need to create # an arg parser and parse them. self._subcommand_table = self._build_subcommand_table() self._arg_table = self._build_arg_table() parser = ArgTableArgParser(self.arg_table, self.subcommand_table) parsed_args, remaining = parser.parse_known_args(args) # Unpack arguments for key, value in vars(parsed_args).items(): cli_argument = None # Convert the name to use dashes instead of underscore # as these are how the parameters are stored in the # `arg_table`. xformed = key.replace('_', '-') if xformed in self.arg_table: cli_argument = self.arg_table[xformed] value = unpack_argument( self._session, 'custom', self.name, cli_argument, value ) # If this parameter has a schema defined, then allow plugins # a chance to process and override its value. if self._should_allow_plugins_override(cli_argument, value): override = self._session\ .emit_first_non_none_response( 'process-cli-arg.%s.%s' % ('custom', self.name), cli_argument=cli_argument, value=value, operation=None) if override is not None: # A plugin supplied a conversion value = override else: # Unpack the argument, which is a string, into the # correct Python type (dict, list, etc) value = unpack_cli_arg(cli_argument, value) self._validate_value_against_schema( cli_argument.argument_model, value) setattr(parsed_args, key, value) if hasattr(parsed_args, 'help'): self._display_help(parsed_args, parsed_globals) elif getattr(parsed_args, 'subcommand', None) is None: # No subcommand was specified so call the main # function for this top level command. if remaining: raise ValueError("Unknown options: %s" % ','.join(remaining)) return self._run_main(parsed_args, parsed_globals) else: return self.subcommand_table[parsed_args.subcommand](remaining, parsed_globals)
def add_to_params(self, parameters, value): if value is None: return parsed = self._session.emit_first_non_none_response( 'process-cli-arg.codedeploy.%s' % self.name, param=self.argument_model, cli_argument=self, value=value, operation=None) if parsed is None: parsed = unpack_cli_arg(self, value) parameters['revision'] = self.build_revision_location(parsed)
def __call__(self, args, parsed_globals): # args is the remaining unparsed args. # We might be able to parse these args so we need to create # an arg parser and parse them. self._subcommand_table = self._build_subcommand_table() self._arg_table = self._build_arg_table() parser = ArgTableArgParser(self.arg_table, self.subcommand_table) parsed_args, remaining = parser.parse_known_args(args) # Unpack arguments for key, value in vars(parsed_args).items(): cli_argument = None # Convert the name to use dashes instead of underscore # as these are how the parameters are stored in the # `arg_table`. xformed = key.replace('_', '-') if xformed in self.arg_table: cli_argument = self.arg_table[xformed] value = unpack_argument(self._session, 'custom', self.name, cli_argument, value) # If this parameter has a schema defined, then allow plugins # a chance to process and override its value. if self._should_allow_plugins_override(cli_argument, value): override = self._session\ .emit_first_non_none_response( 'process-cli-arg.%s.%s' % ('custom', self.name), cli_argument=cli_argument, value=value, operation=None) if override is not None: # A plugin supplied a conversion value = override else: # Unpack the argument, which is a string, into the # correct Python type (dict, list, etc) value = unpack_cli_arg(cli_argument, value) self._validate_value_against_schema( cli_argument.argument_model, value) setattr(parsed_args, key, value) if hasattr(parsed_args, 'help'): self._display_help(parsed_args, parsed_globals) elif getattr(parsed_args, 'subcommand', None) is None: # No subcommand was specified so call the main # function for this top level command. if remaining: raise ValueError("Unknown options: %s" % ','.join(remaining)) return self._run_main(parsed_args, parsed_globals) else: return self.subcommand_table[parsed_args.subcommand]( remaining, parsed_globals)
def add_to_params(self, parameters, value): if value is None: return parsed = self._session.emit_first_non_none_response( 'process-cli-arg.codedeploy.%s' % self.name, param=self.argument_model, cli_argument=self, value=value, operation_name=self.name) if parsed is None: parsed = unpack_cli_arg(self, value) parameters['revision'] = self.build_revision_location(parsed)
def _unpack_argument(self, value): service_name = self._operation_model.service_model.service_name operation_name = xform_name(self._operation_model.name, '-') override = self._emit_first_response('process-cli-arg.%s.%s' % ( service_name, operation_name), param=self.argument_model, cli_argument=self, value=value) if override is not None: # A plugin supplied an alternate conversion, # use it instead. return override else: # Fall back to the default arg processing. return unpack_cli_arg(self, value)
def _unpack_argument(self, value): service_name = self.operation_object.service.endpoint_prefix operation_name = xform_name(self.operation_object.name, '-') override = self._emit_first_response('process-cli-arg.%s.%s' % ( service_name, operation_name), param=self.argument_model, cli_argument=self, value=value, operation=self.operation_object) if override is not None: # A plugin supplied an alternate conversion, # use it instead. return override else: # Fall back to the default arg processing. return unpack_cli_arg(self, value)
def test_json_with_spaces(self): p = self.get_param_object('ec2.RunInstances.BlockDeviceMappings') # If a user specifies the json with spaces, it will show up as # a multi element list. For example: # --block-device-mappings [{ "DeviceName":"/dev/sdf", # "VirtualName":"ephemeral0"}, {"DeviceName":"/dev/sdg", # "VirtualName":"ephemeral1" }] # # Will show up as: block_device_mapping = [ '[{', 'DeviceName:/dev/sdf,', 'VirtualName:ephemeral0},', '{DeviceName:/dev/sdg,', 'VirtualName:ephemeral1', '}]'] # The shell has removed the double quotes so this is invalid # JSON, but we should still raise a better exception. with self.assertRaises(ParamError) as e: unpack_cli_arg(p, block_device_mapping) # Parameter name should be in error message. self.assertIn('--block-device-mappings', str(e.exception)) # The actual JSON itself should be in the error message. # Becaues this is a list, only the first element in the JSON # will show. This will at least let customers know what # we tried to parse. self.assertIn('[{', str(e.exception))
def test_parse_boolean_shorthand(self): bool_param = mock.Mock() bool_param.type = 'boolean' self.assertTrue(unpack_cli_arg(bool_param, True)) self.assertTrue(unpack_cli_arg(bool_param, 'True')) self.assertTrue(unpack_cli_arg(bool_param, 'true')) self.assertFalse(unpack_cli_arg(bool_param, False)) self.assertFalse(unpack_cli_arg(bool_param, 'False')) self.assertFalse(unpack_cli_arg(bool_param, 'false'))
def test_parse_boolean_shorthand(self): bool_param = mock.Mock() bool_param.type = "boolean" self.assertTrue(unpack_cli_arg(bool_param, True)) self.assertTrue(unpack_cli_arg(bool_param, "True")) self.assertTrue(unpack_cli_arg(bool_param, "true")) self.assertFalse(unpack_cli_arg(bool_param, False)) self.assertFalse(unpack_cli_arg(bool_param, "False")) self.assertFalse(unpack_cli_arg(bool_param, "false"))
def _unpack_argument(self, value): if not hasattr(self.argument_object, 'no_paramfile'): value = self._handle_param_file(value) service_name = self.operation_object.service.endpoint_prefix operation_name = xform_name(self.operation_object.name, '-') responses = self._emit('process-cli-arg.%s.%s' % ( service_name, operation_name), param=self.argument_object, value=value, operation=self.operation_object) override = first_non_none_response(responses) if override is not None: # A plugin supplied an alternate conversion, # use it instead. return override else: # Fall back to the default arg processing. return unpack_cli_arg(self.argument_object, value)
def test_parse_boolean_shorthand(self): bool_param = mock.Mock() bool_param.cli_type_name = 'boolean' bool_param.argument_model.type_name = 'boolean' bool_param.argument_model.is_document_type = False self.assertTrue(unpack_cli_arg(bool_param, True)) self.assertTrue(unpack_cli_arg(bool_param, 'True')) self.assertTrue(unpack_cli_arg(bool_param, 'true')) self.assertFalse(unpack_cli_arg(bool_param, False)) self.assertFalse(unpack_cli_arg(bool_param, 'False')) self.assertFalse(unpack_cli_arg(bool_param, 'false'))
def _unpack_argument(self, value): service_name = self.operation_object.service.endpoint_prefix operation_name = xform_name(self.operation_object.name, '-') # This is a two step process. First we "load" the value. value_override = self._emit_first_response( 'load-cli-arg.%s.%s' % (service_name, operation_name), param=self.argument_object, value=value, operation=self.operation_object) if value_override is not None: value = value_override # Then we "process/parse" the argument. override = self._emit_first_response('process-cli-arg.%s.%s' % ( service_name, operation_name), param=self.argument_object, value=value, operation=self.operation_object) if override is not None: # A plugin supplied an alternate conversion, # use it instead. return override else: # Fall back to the default arg processing. return unpack_cli_arg(self.argument_object, value)
def test_list_structure_scalars_2(self): p = self.get_param_object('elb.CreateLoadBalancer.Listeners') expected = [ { "Protocol": "protocol1", "LoadBalancerPort": 1, "InstanceProtocol": "instance_protocol1", "InstancePort": 2, "SSLCertificateId": "ssl_certificate_id1" }, { "Protocol": "protocol2", "LoadBalancerPort": 3, "InstanceProtocol": "instance_protocol2", "InstancePort": 4, "SSLCertificateId": "ssl_certificate_id2" }, ] returned = unpack_cli_arg(p, [ '{"Protocol": "protocol1", "LoadBalancerPort": 1, ' '"InstanceProtocol": "instance_protocol1", ' '"InstancePort": 2, "SSLCertificateId": ' '"ssl_certificate_id1"}', '{"Protocol": "protocol2", "LoadBalancerPort": 3, ' '"InstanceProtocol": "instance_protocol2", ' '"InstancePort": 4, "SSLCertificateId": ' '"ssl_certificate_id2"}', ]) self.maxDiff = None self.assertEqual(returned, expected) simplified = self.simplify(p, [ 'Protocol=protocol1,LoadBalancerPort=1,' 'InstanceProtocol=instance_protocol1,' 'InstancePort=2,SSLCertificateId=ssl_certificate_id1', 'Protocol=protocol2,LoadBalancerPort=3,' 'InstanceProtocol=instance_protocol2,' 'InstancePort=4,SSLCertificateId=ssl_certificate_id2' ]) self.assertEqual(simplified, expected)
def test_list_structure_scalars(self): p = self.get_param_object('elb.CreateLoadBalancer.Listeners') expected = [ { "protocol": "protocol1", "load_balancer_port": 1, "instance_protocol": "instance_protocol1", "instance_port": 2, "ssl_certificate_id": "ssl_certificate_id1" }, { "protocol": "protocol2", "load_balancer_port": 3, "instance_protocol": "instance_protocol2", "instance_port": 4, "ssl_certificate_id": "ssl_certificate_id2" }, ] returned = unpack_cli_arg(p, [ '{"protocol": "protocol1", "load_balancer_port": 1, ' '"instance_protocol": "instance_protocol1", ' '"instance_port": 2, "ssl_certificate_id": ' '"ssl_certificate_id1"}', '{"protocol": "protocol2", "load_balancer_port": 3, ' '"instance_protocol": "instance_protocol2", ' '"instance_port": 4, "ssl_certificate_id": ' '"ssl_certificate_id2"}', ]) self.assertEqual(returned, expected) simplified = self.simplify(p, [ 'protocol=protocol1,load_balancer_port=1,' 'instance_protocol=instance_protocol1,' 'instance_port=2,ssl_certificate_id=ssl_certificate_id1', 'protocol=protocol2,load_balancer_port=3,' 'instance_protocol=instance_protocol2,' 'instance_port=4,ssl_certificate_id=ssl_certificate_id2' ]) self.assertEqual(simplified, expected)
def test_simplify_map_scalar(self): p = self.get_param_object('sqs.SetQueueAttributes.Attributes') returned = self.simplify(p, 'VisibilityTimeout=15') json_version = unpack_cli_arg(p, '{"VisibilityTimeout": "15"}') self.assertEqual(returned, {'VisibilityTimeout': '15'}) self.assertEqual(returned, json_version)
def test_json_value_int(self): value = "5" self.assertEqual(unpack_cli_arg(self.p, value), 5)
def test_json_value_float(self): value = "1.2" self.assertEqual(unpack_cli_arg(self.p, value), 1.2)
def test_json_value_string(self): value = '"5"' self.assertEqual(unpack_cli_arg(self.p, value), '5')
def test_json_value_dict(self): value = '{"foo": "bar"}' self.assertEqual(unpack_cli_arg(self.p, value), OrderedDict([('foo', 'bar')]))
def test_simplify_map_scalar(self): p = self.get_param_model('sqs.SetQueueAttributes.Attributes') returned = self.simplify(p, 'VisibilityTimeout=15') json_version = unpack_cli_arg(p, '{"VisibilityTimeout": "15"}') self.assertEqual(returned, {'VisibilityTimeout': '15'}) self.assertEqual(returned, json_version)
def test_json_value_decode_error(self): value = 'invalid string to be serialized' with self.assertRaises(ParamError): unpack_cli_arg(self.p, value)
def test_json_value_list(self): value = '["foo", "bar"]' self.assertEqual(unpack_cli_arg(self.p, value), ['foo', 'bar'])
def test_json_value_null(self): value = 'null' self.assertEqual(unpack_cli_arg(self.p, value), None)
def __call__(self, args, parsed_globals): # args is the remaining unparsed args. # We might be able to parse these args so we need to create # an arg parser and parse them. subcommand_table = self._build_subcommand_table() arg_table = self.arg_table parser = ArgTableArgParser(arg_table, subcommand_table) parsed_args, remaining = parser.parse_known_args(args) # Unpack arguments for key, value in vars(parsed_args).items(): param = None # Convert the name to use dashes instead of underscore # as these are how the parameters are stored in the # `arg_table`. xformed = key.replace('_', '-') if xformed in arg_table: param = arg_table[xformed] value = unpack_argument( self._session, 'custom', self.name, param, value ) # If this parameter has a schema defined, then allow plugins # a chance to process and override its value. if param and getattr(param, 'argument_object', None) is not None \ and value is not None: param_object = param.argument_object # Allow a single event handler to process the value override = self._session\ .emit_first_non_none_response( 'process-cli-arg.%s.%s' % ('custom', self.name), param=param_object, value=value, operation=None) if override is not None: # A plugin supplied a conversion value = override else: # Unpack the argument, which is a string, into the # correct Python type (dict, list, etc) value = unpack_cli_arg(param_object, value) # Validate param types, required keys, etc param_object.validate(value) setattr(parsed_args, key, value) if hasattr(parsed_args, 'help'): self._display_help(parsed_args, parsed_globals) elif getattr(parsed_args, 'subcommand', None) is None: # No subcommand was specified so call the main # function for this top level command. return self._run_main(parsed_args, parsed_globals) else: return subcommand_table[parsed_args.subcommand](remaining, parsed_globals)
def test_simplify_map_scalar(self): p = self.get_param_object("sqs.SetQueueAttributes.Attributes") returned = self.simplify(p, "VisibilityTimeout=15") json_version = unpack_cli_arg(p, '{"VisibilityTimeout": "15"}') self.assertEqual(returned, {"VisibilityTimeout": "15"}) self.assertEqual(returned, json_version)
def test_json_value_boolean(self): value = "true" self.assertEqual(unpack_cli_arg(self.p, value), True) value = "false" self.assertEqual(unpack_cli_arg(self.p, value), False)