def test_extract_structure_with_optional(self): """L{Schema.extract} can handle optional parameters.""" schema = Schema( Structure("struct", fields={"name": Unicode(optional=True, default="radix")})) arguments, _ = schema.extract({"struct": {}}) self.assertEqual("radix", arguments.struct.name)
def test_extract_with_numbered(self): """ L{Schema.extract} can handle parameters with numbered values. """ schema = Schema(Unicode("name.n")) arguments, _ = schema.extract({"name.0": "Joe", "name.1": "Tom"}) self.assertEqual("Joe", arguments.name[0]) self.assertEqual("Tom", arguments.name[1])
def test_bundle(self): """ L{Schema.bundle} returns a dictionary of raw parameters that can be used for an EC2-style query. """ schema = Schema(Unicode("name")) params = schema.bundle(name="foo") self.assertEqual({"name": "foo"}, params)
def test_extract(self): """ L{Schema.extract} returns an L{Argument} object whose attributes are the arguments extracted from the given C{request}, as specified. """ schema = Schema(Unicode("name")) arguments, _ = schema.extract({"name": "value"}) self.assertEqual("value", arguments.name)
def test_extract_with_non_numbered_template(self): """ L{Schema.extract} accepts a single numbered argument even if the associated template is not numbered. """ schema = Schema(Unicode("name")) arguments, _ = schema.extract({"name.1": "foo"}) self.assertEqual("foo", arguments.name)
def test_extract_with_mixed(self): """ L{Schema.extract} stores in the rest result all numbered parameters given without an index. """ schema = Schema(Unicode("name.n")) _, rest = schema.extract({"name": "foo", "name.1": "bar"}) self.assertEqual(rest, {"name": "foo"})
def test_bundle_with_arguments(self): """L{Schema.bundle} can bundle L{Arguments} too.""" schema = Schema(Unicode("name.n"), Integer("count")) arguments = Arguments({"name": Arguments({1: "Foo", 7: "Bar"}), "count": 123}) params = schema.bundle(arguments) self.assertEqual({"name.1": "Foo", "name.7": "Bar", "count": "123"}, params)
def test_extract_with_single_numbered(self): """ L{Schema.extract} can handle an un-numbered argument passed in to a numbered parameter. """ schema = Schema(Unicode("name.n")) arguments, _ = schema.extract({"name": "Joe"}) self.assertEqual("Joe", arguments.name[0])
def test_bundle_with_multiple(self): """ L{Schema.bundle} correctly handles multiple arguments. """ schema = Schema(Unicode("name.n"), Integer("count")) params = schema.bundle(name=["Foo", "Bar"], count=123) self.assertEqual({"name.1": "Foo", "name.2": "Bar", "count": "123"}, params)
def test_structure_of_structures(self): """L{Structure}s can be nested.""" sub_struct = Structure(fields={"a": Unicode(), "b": Unicode()}) schema = Schema( Structure("foo", fields={ "a": sub_struct, "b": sub_struct })) arguments, _ = schema.extract({ "foo.a.a": "a-a", "foo.a.b": "a-b", "foo.b.a": "b-a", "foo.b.b": "b-b" }) self.assertEqual("a-a", arguments.foo.a.a) self.assertEqual("a-b", arguments.foo.a.b) self.assertEqual("b-a", arguments.foo.b.a) self.assertEqual("b-b", arguments.foo.b.b)
def test_schema_conversion_list(self): """ Backwards-compatibility conversion maintains the name of lists. """ schema = Schema(Unicode("foos.N")) parameters = schema.get_parameters() self.assertEqual(1, len(parameters)) self.assertTrue(isinstance(parameters[0], List)) self.assertEqual("foos", parameters[0].name)
def test_extract_with_goofy_numbered(self): """ L{Schema.extract} only uses the relative values of indices to determine the index in the resultant list. """ schema = Schema(Unicode("name.n")) arguments, _ = schema.extract({"name.5": "Joe", "name.10": "Tom"}) self.assertEqual("Joe", arguments.name[0]) self.assertEqual("Tom", arguments.name[1])
def test_get_parameters_order_on_parameter_only_construction(self): """ L{Schema.get_parameters} returns the original list of L{Parameter}s even when they are passed as positional arguments to L{Schema}. """ schema = Schema(Unicode("name"), List("scores", Integer()), Integer("index", Integer())) self.assertEqual(["name", "scores", "index"], [p.name for p in schema.get_parameters()])
def test_invalid_unicode(self): """ The L{Unicode} parameter returns an error with invalid unicode data. """ parameter = Unicode("Test") error = self.assertRaises(APIError, parameter.coerce, "Test\x95Error") self.assertIn(u"Invalid unicode value", error.message) self.assertEqual(400, error.status) self.assertEqual("InvalidParameterValue", error.code)
def test_extract_with_mixed(self): """ L{Schema.extract} stores in the rest result all numbered parameters given without an index. """ schema = Schema(Unicode("name.n")) self.assertRaises(InconsistentParameterError, schema.extract, { "nameFOOO": "foo", "nameFOOO.1": "bar" })
def test_extract_with_optional_default(self): """ The value of C{default} on a parameter is used as the value when it is not provided as an argument and the parameter is C{optional}. """ schema = Schema(Unicode("name"), Integer("count", optional=True, default=5)) arguments, _ = schema.extract({"name": "value"}) self.assertEqual(u"value", arguments.name) self.assertEqual(5, arguments.count)
def test_get_parameters(self): """ L{Schema.get_parameters} returns the original list of parameters. """ schema = Schema( parameters=[Unicode("name"), List("scores", Integer())]) parameters = schema.get_parameters() self.assertEqual("name", parameters[0].name) self.assertEqual("scores", parameters[1].name)
def test_additional_schema_attributes(self): """ Additional data can be specified on the Schema class for specifying a more rich schema. """ result = {'id': Integer(), 'name': Unicode(), 'data': RawStr()} errors = [APIError] schema = Schema(name="GetStuff", doc="""Get the stuff.""", parameters=[Integer("id"), Unicode("scope")], result=result, errors=errors) self.assertEqual("GetStuff", schema.name) self.assertEqual("Get the stuff.", schema.doc) self.assertEqual(result, schema.result) self.assertEqual(set(errors), schema.errors)
def test_extract_with_negative_index(self): """ L{Schema.extract} raises an error when trying to pass a numbered parameter with a negative index. """ schema = Schema(Unicode("name.n")) params = {"name.-1": "foo"} error = self.assertRaises(APIError, schema.extract, params) self.assertEqual(400, error.status) self.assertEqual("UnknownParameter", error.code) self.assertEqual("The parameter -1 is not recognized", error.message)
def test_bundle_with_arguments_and_extra(self): """ L{Schema.bundle} can bundle L{Arguments} with keyword arguments too. Keyword arguments take precedence. """ schema = Schema(Unicode("name.n"), Integer("count")) arguments = Arguments({"name": {1: "Foo", 7: "Bar"}, "count": 321}) params = schema.bundle(arguments, count=123) self.assertEqual({"name.1": "Foo", "name.2": "Bar", "count": "123"}, params)
def test_list_of_list(self): """L{List}s can be nested.""" schema = Schema(List("foo", List(item=Unicode()))) arguments, _ = schema.extract({ "foo.1.1": "first-first", "foo.1.2": "first-second", "foo.2.1": "second-first", "foo.2.2": "second-second" }) self.assertEqual([["first-first", "first-second"], ["second-first", "second-second"]], arguments.foo)
def test_coerce_list(self): """ When a L{List} coerces the value of one of its item, it uses the the proper name in the C{MissingParameter} error raised. """ parameter = List("foo", Unicode()) error = self.assertRaises(APIError, parameter.item.coerce, "") self.assertEqual(400, error.status) self.assertEqual("MissingParameter", error.code) self.assertEqual("The request must contain the parameter foo " "(str)", error.message)
def test_extract_with_multiple_parameters_in_singular_schema(self): """ If multiple parameters are passed in to a Schema element that is not flagged as supporting multiple values then we should throw an C{APIError}. """ schema = Schema(Unicode("name")) params = {"name.1": "value", "name.2": "value2"} error = self.assertRaises(APIError, schema.extract, params) self.assertEqual(400, error.status) self.assertEqual("InvalidParameterCombination", error.code) self.assertEqual("The parameter 'name' may only be specified once.", error.message)
def test_min_and_max(self): """The L{Unicode} parameter properly supports ranges.""" parameter = Unicode("Test", min=2, max=4) error = self.assertRaises(APIError, parameter.coerce, "a") self.assertEqual(400, error.status) self.assertEqual("InvalidParameterValue", error.code) self.assertIn("Length must be at least 2.", error.message) error = self.assertRaises(APIError, parameter.coerce, "abcde") self.assertIn("Length exceeds maximum of 4.", error.message) self.assertEqual(400, error.status) self.assertEqual("InvalidParameterValue", error.code)
def test_extend_result(self): """ Result fields can also be extended with L{Schema.extend}. """ schema = Schema(result={'name': Unicode()}) schema2 = schema.extend(result={'id': Integer()}) result_structure = Structure(fields=schema2.result) self.assertEqual({ 'name': u'foo', 'id': 5 }, result_structure.coerce({ 'name': u'foo', 'id': '5' }))
def test_bundle_with_structure(self): """L{Schema.bundle} can bundle L{Structure}s.""" schema = Schema(parameters=[ Structure("struct", fields={ "field1": Unicode(), "field2": Integer() }) ]) params = schema.bundle(struct={"field1": "hi", "field2": 59}) self.assertEqual({ "struct.field1": "hi", "struct.field2": "59" }, params)
def test_extend_with_additional_schema_attributes(self): """ The additional schema attributes can be passed to L{Schema.extend}. """ result = {'id': Integer(), 'name': Unicode(), 'data': RawStr()} errors = [APIError] schema = Schema(name="GetStuff", parameters=[Integer("id")]) schema2 = schema.extend(name="GetStuff2", doc="Get stuff 2", parameters=[Unicode("scope")], result=result, errors=errors) self.assertEqual("GetStuff2", schema2.name) self.assertEqual("Get stuff 2", schema2.doc) self.assertEqual(result, schema2.result) self.assertEqual(set(errors), schema2.errors) arguments, _ = schema2.extract({'id': '5', 'scope': u'foo'}) self.assertEqual(5, arguments.id) self.assertEqual(u'foo', arguments.scope)
def test_extend_maintains_existing_attributes(self): """ If additional schema attributes aren't passed to L{Schema.extend}, they stay the same. """ result = {'id': Integer(), 'name': Unicode(), 'data': RawStr()} errors = [APIError] schema = Schema(name="GetStuff", doc="""Get the stuff.""", parameters=[Integer("id")], result=result, errors=errors) schema2 = schema.extend(parameters=[Unicode("scope")]) self.assertEqual("GetStuff", schema2.name) self.assertEqual("Get the stuff.", schema2.doc) self.assertEqual(result, schema2.result) self.assertEqual(set(errors), schema2.errors) arguments, _ = schema2.extract({'id': '5', 'scope': u'foo'}) self.assertEqual(5, arguments.id) self.assertEqual(u'foo', arguments.scope)
def test_parameter_doc(self): """ All L{Parameter} subclasses accept a 'doc' keyword argument. """ parameters = [ Unicode(doc="foo"), RawStr(doc="foo"), Integer(doc="foo"), Bool(doc="foo"), Enum(mapping={"hey": 1}, doc="foo"), Date(doc="foo"), List(item=Integer(), doc="foo"), Structure(fields={}, doc="foo") ] for parameter in parameters: self.assertEqual("foo", parameter.doc)
def test_parse(self): """L{Unicode.parse} converts the given raw C{value} to C{unicode}.""" parameter = Unicode("Test") self.assertEqual(u"foo", parameter.parse("foo"))
def test_parse_unicode(self): """L{Unicode.parse} works with unicode input.""" parameter = Unicode("Test") self.assertEqual(u"cittá", parameter.parse("citt\xc3\xa1"))
def test_format(self): """L{Unicode.format} encodes the given C{unicode} with utf-8.""" parameter = Unicode("Test") value = parameter.format(u"fo\N{TAGBANWA LETTER SA}") self.assertEqual("fo\xe1\x9d\xb0", value) self.assertTrue(isinstance(value, str))
def test_bundle_with_list_with_arguments(self): """L{Schema.bundle} can bundle L{List}s (specified as L{Arguments}).""" schema = Schema(parameters=[List("things", item=Unicode())]) params = schema.bundle(things=Arguments({1: "foo", 2: "bar"})) self.assertEqual({"things.1": "foo", "things.2": "bar"}, params)