def test_key_dict_multiple_items(self): schema = KeyDict({"one": Int(), "two": List(Float())}) input = {"one": 32, "two": [1.5, 2.3]} self.assertEquals(schema.coerce(input, PATH), { "one": 32, "two": [1.5, 2.3] })
def test_key_dict_unknown_key(self): """ Unknown key/value pairs processed by a KeyDict are left untouched. This is an attempt at not eating values by mistake due to something like different application versions operating on the same data. """ schema = KeyDict({"foo": Int()}) self.assertEquals(schema.coerce({"foo": 1, "bar": "hi"}, PATH), {"foo": 1, "bar": "hi"})
def test_key_dict_path_without_dots(self): """ The first path entry shouldn't have a dot as prefix. """ schema = KeyDict({1: KeyDict({2: Int()})}) error = self.assertRaises(SchemaError, schema.coerce, {1: { 2: "hi" }}, []) self.assertEquals(str(error), "1.2: expected int, got 'hi'")
def test_select_dict_errors(self): schema = SelectDict("name", { "foo": KeyDict({"foo_": Int()}), "bar": KeyDict({"bar_": Int()}) }) error = self.assertRaises(SchemaError, schema.coerce, {"name": "foo"}, PATH) self.assertEquals(str(error), "<path>.foo_: required value not found") error = self.assertRaises(SchemaError, schema.coerce, {"name": "bar"}, PATH) self.assertEquals(str(error), "<path>.bar_: required value not found")
def test_key_dict_unknown_key(self): """ Unknown key/value pairs processed by a KeyDict are left untouched. This is an attempt at not eating values by mistake due to something like different application versions operating on the same data. """ schema = KeyDict({"foo": Int()}) self.assertEquals(schema.coerce({ "foo": 1, "bar": "hi" }, PATH), { "foo": 1, "bar": "hi" })
def test_key_dict_must_have_all_keys(self): """ dicts which are applied to a KeyDict must have all the keys specified in the KeyDict. """ schema = KeyDict({"foo": Int()}) error = self.assertRaises(SchemaError, schema.coerce, {}, PATH) self.assertEquals(str(error), "<path>.foo: required value not found")
def test_key_dict_arbitrary_keys(self): """ KeyDict doesn't actually need to have strings as keys, just any object which hashes the same. """ key = object() self.assertEquals( KeyDict({ key: Int() }).coerce({key: 32}, PATH), {key: 32})
def test_select_dict(self): schema = SelectDict("name", { "foo": KeyDict({"value": Int()}), "bar": KeyDict({"value": String()}) }) self.assertEquals(schema.coerce({ "name": "foo", "value": 1 }, PATH), { "name": "foo", "value": 1 }) self.assertEquals(schema.coerce({ "name": "bar", "value": "one" }, PATH), { "name": "bar", "value": "one" })
def test_key_dict_bad_value_unstringifiable(self): """ If the path can't be stringified, it's repr()ed. """ a = u"\N{HIRAGANA LETTER A}" error = self.assertRaises(SchemaError, KeyDict({ a: Int() }).coerce, {a: "hi"}, PATH) self.assertEquals(str(error), "<path>.u'\\u3042': expected int, got 'hi'")
def test_best_error(self): """ OneOf attempts to select a relevant error to report to user when no branch of its schema can be satisitifed. """ schema = OneOf(Unicode(), KeyDict({"flavor": String()})) # an error related to flavor is more specific and useful # than one related to the 1st branch error = self.assertRaises(SchemaExpectationError, schema.coerce, {"flavor": None}, PATH) # the correct error is returned self.assertEquals(str(error), "<path>.flavor: expected string, got None") # here the error related to Unicode is better error = self.assertRaises(SchemaExpectationError, schema.coerce, "a string", PATH) self.assertEquals(str(error), "<path>: expected unicode, got 'a string'") # and the success case still functions self.assertEqual(schema.coerce(u"some unicode", PATH), u"some unicode")
import sys import yaml from juju.lib.schema import (SchemaError, KeyDict, Dict, String, Constant, OneOf, Int, Float) from juju.charm.errors import (ServiceConfigError, ServiceConfigValueError) OPTION_SCHEMA = KeyDict( { "type": OneOf( Constant("string"), Constant("str"), # Obsolete Constant("int"), Constant("float")), "default": OneOf(String(), Int(), Float()), "description": String(), }, optional=["default", "description"], ) # Schema used to validate ConfigOptions specifications CONFIG_SCHEMA = KeyDict({ "options": Dict(String(), OPTION_SCHEMA), }) WARNED_STR_IS_OBSOLETE = False
def test_key_dict(self): self.assertEquals( KeyDict({ "foo": Int() }).coerce({"foo": 1}, PATH), {"foo": 1})
def test_key_dict_coerces(self): self.assertEquals( KeyDict({ "foo": DummySchema() }).coerce({"foo": 3}, PATH), {"foo": "hello!"})
def test_key_dict_pass_optional_key(self): """Regression test. It should be possible to pass an optional key. """ schema = KeyDict({"foo": Int()}, optional=["foo"]) self.assertEquals(schema.coerce({"foo": 32}, PATH), {"foo": 32})
import os import yaml from juju.charm.errors import MetaDataError from juju.errors import FileNotFound from juju.lib.schema import (SchemaError, Bool, Constant, Dict, Int, KeyDict, OneOf, UnicodeOrString) log = logging.getLogger("juju.charm") UTF8_SCHEMA = UnicodeOrString("utf-8") INTERFACE_SCHEMA = KeyDict({ "interface": UTF8_SCHEMA, "limit": OneOf(Constant(None), Int()), "optional": Bool() }) class InterfaceExpander(object): """Schema coercer that expands the interface shorthand notation. We need this class because our charm shorthand is difficult to work with (unfortunately). So we coerce shorthand and then store the desired format in ZK. Supports the following variants:: provides: server: riak
def test_key_dict_optional_keys(self): """KeyDict allows certain keys to be optional. """ schema = KeyDict({"foo": Int(), "bar": Int()}, optional=["bar"]) self.assertEquals(schema.coerce({"foo": 32}, PATH), {"foo": 32})
def test_key_dict_bad(self): error = self.assertRaises(SchemaError, KeyDict({}).coerce, "1", PATH) self.assertEquals(str(error), "<path>: expected dict, got '1'")
def test_key_dict_bad_value(self): schema = KeyDict({"foo": Int()}) error = self.assertRaises(SchemaError, schema.coerce, {"foo": "hi"}, PATH) self.assertEquals(str(error), "<path>.foo: expected int, got 'hi'")
def test_key_dict_multiple_items(self): schema = KeyDict({"one": Int(), "two": List(Float())}) input = {"one": 32, "two": [1.5, 2.3]} self.assertEquals(schema.coerce(input, PATH), {"one": 32, "two": [1.5, 2.3]})
SCHEMA = KeyDict({ "default": String(), "environments": Dict(String(), SelectDict("type", { "ec2": KeyDict({"control-bucket": String(), "admin-secret": String(), "access-key": String(), "secret-key": String(), "region": OneOf( Constant("us-east-1"), Constant("us-west-1"), Constant("us-west-2"), Constant("eu-west-1"), Constant("sa-east-1"), Constant("ap-northeast-1"), Constant("ap-southeast-1")), "default-instance-type": String(), "default-ami": String(), "ec2-uri": String(), "s3-uri": String(), "placement": OneOf( Constant("unassigned"), Constant("local")), "default-series": String()}, optional=["access-key", "secret-key", "default-instance-type", "default-ami", "region", "ec2-uri", "s3-uri", "placement"]), "orchestra": KeyDict({"orchestra-server": String(), "orchestra-user": String(), "orchestra-pass": String(), "admin-secret": String(), "acquired-mgmt-class": String(), "available-mgmt-class": String(), "storage-url": String(), "storage-user": String(), "storage-pass": String(), "placement": String(), "default-series": String()}, optional=["storage-url", "storage-user", "storage-pass", "placement"]), "local": KeyDict({"admin-secret": String(), "data-dir": String(), "placement": Constant("local"), "default-series": String()}, optional=["placement"]), "dummy": KeyDict({})}))}, optional=["default"])