Exemplo n.º 1
0
    def normalise(self, meta, val):
        if type(val) not in (tuple, list):
            raise BadSpecValue("Expected a list", got=type(val), meta=meta)

        if len(val) != len(self.specs):
            raise BadSpecValue("Expected a value with certain number of items",
                               wanted=len(self.specs),
                               got=len(val),
                               meta=meta)

        res = []
        for i, v in enumerate(val):
            res.append(self.specs[i].normalise(meta.indexed_at(i), v))

        return res
Exemplo n.º 2
0
    def normalise_either(self, meta, val):
        """Format the value"""
        options_opts = {}
        if hasattr(meta.everything, "converters"):
            options_opts['converters'] = meta.everything.converters
        if hasattr(meta.everything, "dont_prefix"):
            options_opts["dont_prefix"] = meta.everything.dont_prefix
        options = meta.everything.__class__(**options_opts)
        options.update(meta.key_names())
        options.update(meta.everything)

        af = self.after_format
        if af != NotSpecified:
            af = self.after_format
            if callable(af):
                af = af()

        specd = self.spec.normalise(meta, val)
        if not isinstance(specd, six.string_types) and af != NotSpecified:
            return af.normalise(meta, specd)

        formatted = self.formatter(options, meta.path, value=specd).format()
        if af != NotSpecified:
            formatted = af.normalise(meta, formatted)

        if self.has_expected_type:
            if not isinstance(formatted, self.expected_type):
                raise BadSpecValue("Expected a different type",
                                   got=type(formatted),
                                   expected=self.expected_type)

        return formatted
Exemplo n.º 3
0
 def normalise_filled(self, meta, val):
     if not isinstance(val, self.kls):
         raise BadSpecValue("Got the wrong type of value",
                            expected=self.kls,
                            got=type(val),
                            meta=meta)
     return val
Exemplo n.º 4
0
 def normalise_filled(self, meta, val):
     val = sb.integer_spec().normalise(meta, val)
     if val % self.divider != 0:
         raise BadSpecValue("Value should be divisible by {0}".format(
             self.divider),
                            meta=meta)
     return val
Exemplo n.º 5
0
def apply_validators(meta, val, validators, chain_value=True):
    """
    Apply a number of validators to a value.

    chain_value
        Sets whether to pass the validated value into the next
        validator or whether to use the original value each time

    All validators are tried and errors are collected.

    If any fails, an error is raised, otherwise the value is returned.

    Where value is the original value, or the result of the last validator
    depending on ``chain_value``.
    """
    errors = []
    for validator in validators:
        try:
            nxt = validator.normalise(meta, val)
            if chain_value:
                val = nxt
        except BadSpecValue as e:
            errors.append(e)

    if errors:
        raise BadSpecValue("Failed to validate", meta=meta, _errors=errors)

    return val
Exemplo n.º 6
0
    def normalise_filled(self, meta, val):
        """Make sure all the names match the spec and normalise the values"""
        val = super(dictof, self).normalise_filled(meta, val)

        result = {}
        errors = []
        for key, value in val.items():
            try:
                name = self.name_spec.normalise(meta.at(key), key)
            except BadSpec as error:
                errors.append(error)
            else:
                try:
                    if self.nested and (isinstance(value, dict)
                                        or getattr(value, "is_dict", False)):
                        normalised = self.__class__(
                            self.name_spec,
                            self.value_spec,
                            nested=self.nested).normalise(meta.at(key), value)
                    else:
                        normalised = self.value_spec.normalise(
                            meta.at(key), value)
                except BadSpec as error:
                    errors.append(error)
                else:
                    result[name] = normalised

        if errors:
            raise BadSpecValue(meta=meta, _errors=errors)

        return result
Exemplo n.º 7
0
    def normalise_either(self, meta, val):
        """Format the formatted spec"""
        val = self.spec.normalise(meta, val)
        done = []

        while True:
            fm = formatted(string_spec(),
                           formatter=self.formatter,
                           expected_type=six.string_types)
            normalised = fm.normalise(meta, val)
            if normalised == val:
                break

            if normalised in done:
                done.append(normalised)
                raise BadSpecValue("Recursive formatting",
                                   done=done,
                                   meta=meta)
            else:
                done.append(normalised)
                val = normalised

        return formatted(string_spec(),
                         formatter=self.formatter,
                         expected_type=self.expected_type).normalise(
                             meta, "{{{0}}}".format(val))
Exemplo n.º 8
0
    def normalise(self, meta, val):
        result = sb.create_spec(
            LambdaMethod,
            http_method=sb.overridden(self.method),
            resource_name=sb.overridden(self.resource_name),
            function=formatted_string(),
            location=formatted_string(),
            account=sb.optional_spec(formatted_string()),
            require_api_key=sb.defaulted(sb.boolean(), False),
            request_mapping=sb.defaulted(mapping_spec(),
                                         Mapping("application/json", "")),
            mapping=sb.defaulted(
                mapping_spec(), Mapping("application/json",
                                        "$input.json('$')")),
            sample_event=sb.or_spec(formatted_dictionary(), sb.string_spec()),
            desired_output_for_test=sb.or_spec(formatted_dictionary(),
                                               sb.string_spec())).normalise(
                                                   meta, val)

        for key in ('sample_event', 'desired_output_for_test'):
            if isinstance(result[key], six.string_types):
                v = result[key]
                if v.startswith("{") and v.endswith("}"):
                    v = sb.formatted(
                        sb.string_spec(),
                        formatter=MergedOptionStringFormatter).normalise(
                            meta.at(key), v)
                    result[key] = v

        function = result.function
        location = None

        if result.location is not NotSpecified and location is not None:
            raise BadSpecValue(
                "Please don't specify a defined lambda function and location at the same time",
                meta=meta)

        if not isinstance(function, six.string_types):
            location = function.location
            function = function.name

        if location is None and result.location is NotSpecified:
            raise BadSpecValue("Location is a required key!", meta=meta)

        result.function = function
        result.location = location
        return result
Exemplo n.º 9
0
 def validate(self, meta, val):
     """Complain about dots"""
     if '.' in val:
         reason = self.reason
         if not reason:
             reason = "Expected no dots"
         raise BadSpecValue(reason, meta=meta, val=val)
     return val
Exemplo n.º 10
0
    def normalise_filled(self, meta, val):
        """Make sure it's a dictionary"""
        if not isinstance(val, dict) and not getattr(val, "is_dict", False):
            raise BadSpecValue("Expected a dictionary",
                               meta=meta,
                               got=type(val))

        return val
Exemplo n.º 11
0
    def normalise(self, meta, val):
        val = self.spec.normalise(meta, val)
        if type(val) is not list:
            return val

        if len(val) != 1:
            raise BadSpecValue("Please only specify one value", meta=meta)

        return val[0]
Exemplo n.º 12
0
 def validate(self, meta, val):
     """Complain if the value doesn't match the regex"""
     for spec, regex in self.regexes:
         if not regex.match(val):
             raise BadSpecValue("Expected value to match regex, it didn't",
                                spec=spec,
                                meta=meta,
                                val=val)
     return val
Exemplo n.º 13
0
 def normalise_filled(self, meta, val):
     """Make sure it's a string or integer"""
     if isinstance(val,
                   bool) or (not isinstance(val, six.string_types)
                             and not isinstance(val, six.integer_types)):
         raise BadSpecValue("Expected a string or integer",
                            meta=meta,
                            got=type(val))
     return str(val)
Exemplo n.º 14
0
    def normalise(self, meta, val):
        if 'use' in val:
            template = val['use']
            if template not in meta.everything['templates']:
                available = list(meta.everything['templates'].keys())
                raise BadTemplate("Template doesn't exist!",
                                  wanted=template,
                                  available=available,
                                  meta=meta)

            val = MergedOptions.using(meta.everything['templates'][template],
                                      val)

        formatted_string = sb.formatted(sb.string_spec(),
                                        MergedOptionStringFormatter,
                                        expected_type=six.string_types)
        role_name = meta.key_names()['_key_name_0']

        original_permission = sb.listof(permission_dict()).normalise(
            meta.at("permission"),
            NotSpecified if "permission" not in val else val["permission"])
        deny_permission = sb.listof(permission_dict(effect='Deny')).normalise(
            meta.at("deny_permission"), NotSpecified
            if "deny_permission" not in val else val["deny_permission"])
        allow_permission = sb.listof(
            permission_dict(effect='Allow')).normalise(
                meta.at("allow_permission"), NotSpecified
                if "allow_permission" not in val else val["allow_permission"])

        allow_to_assume_me = sb.listof(trust_dict("principal")).normalise(
            meta.at("allow_to_assume_me"),
            val.get("allow_to_assume_me", NotSpecified))
        disallow_to_assume_me = sb.listof(
            trust_dict("notprincipal")).normalise(
                meta.at("disallow_to_assume_me"),
                val.get("disallow_to_assume_me", NotSpecified))

        if not allow_to_assume_me and not disallow_to_assume_me:
            raise BadSpecValue(
                "Roles must have either allow_to_assume_me or disallow_to_assume_me specified",
                meta=meta)

        val = val.wrapped()
        val['trust'] = allow_to_assume_me + disallow_to_assume_me
        val['permission'] = original_permission + deny_permission + allow_permission
        return sb.create_spec(
            Role,
            name=sb.overridden(role_name),
            description=formatted_string,
            attached_policies=sb.listof(formatted_string),
            trust=sb.container_spec(
                Document, sb.listof(trust_statement_spec('role', role_name))),
            permission=sb.container_spec(
                Document,
                sb.listof(permission_statement_spec('role', role_name))),
            make_instance_profile=sb.defaulted(sb.boolean(),
                                               False)).normalise(meta, val)
Exemplo n.º 15
0
 def validate(self, meta, val):
     """Complain if the key is not one of the correct choices"""
     if val not in self.choices:
         raise BadSpecValue(
             "Expected the value to be one of the valid choices",
             got=val,
             choices=self.choices,
             meta=meta)
     return val
Exemplo n.º 16
0
    def normalise_empty(self, meta):
        path = [p for p, _ in meta._path]
        path.pop()
        runtime = meta.everything['.'.join(path)].get("runtime", "python")
        runtime = sb.formatted(
            sb.string_spec(), formatter=MergedOptionStringFormatter).normalise(
                meta.at("runtime"), runtime)

        if runtime == 'java8':
            raise BadSpecValue("No default function handler for java",
                               meta=meta)
        elif runtime == 'nodejs':
            return "index.handler"
        elif runtime == 'python2.7':
            return "lambda_function.lambda_handler"
        else:
            raise BadSpecValue(
                "No default function handler for {0}".format(runtime),
                meta=meta)
Exemplo n.º 17
0
 def validate(self, meta, val):
     """Complain if we have none of the choices"""
     if all(
             val.get(key, NotSpecified) is NotSpecified
             for key in self.choices):
         raise BadSpecValue(
             "Need to specify atleast one of the required keys",
             choices=self.choices,
             meta=meta)
     return val
Exemplo n.º 18
0
    def normalise_filled(self, meta, val):
        if val == "rainbow":
            return HueRange(0, 360)

        was_list = False
        if type(val) is list:
            was_list = True
            if len(val) not in (1, 2):
                raise BadSpecValue("A hue range must be 2 or 1 items",
                                   got=val,
                                   meta=meta)
            if len(val) == 1:
                val = [val[0], val[0]]

        try:
            val = int(val)
            if val < 0 or val > 360:
                raise BadSpecValue("A hue number must be between 0 and 360",
                                   got=val,
                                   meta=meta)
            val = [val, val]
        except (ValueError, TypeError):
            pass

        if type(val) is str:
            val = val.split("-", 1)

        for part in val:
            if type(part) is str and (not part or not part.isdigit()):
                msg = "Hue range must be the string 'rainbow' or a string of '<min>-<max>'"
                if was_list:
                    msg = f"{msg} or a list of [<min>, <max>]"
                raise BadSpecValue(msg, got=val, meta=meta)

        rnge = [int(p) for p in val]
        for i, number in enumerate(rnge):
            if number < 0 or number > 360:
                raise BadSpecValue("A hue number must be between 0 and 360",
                                   got=number,
                                   meta=meta.indexed_at(i))

        return HueRange(*rnge)
Exemplo n.º 19
0
 def validate(self, meta, val):
     """Complain if we don't have one of the choices"""
     if [
             val.get(key, NotSpecified) is NotSpecified
             for key in self.choices
     ].count(True) != 1:
         raise BadSpecValue(
             "Can only specify exactly one of the available choices",
             choices=self.choices,
             meta=meta)
     return val
Exemplo n.º 20
0
    def validate(self, meta, val):
        val = sb.dictionary_spec().normalise(meta, val)
        if 'plain' in val and 'kms' in val:
            raise BadSpecValue("Please only specify plain or kms",
                               got=list(val.keys()),
                               meta=meta)

        if 'plain' not in val and 'kms' not in val:
            raise BadSpecValue("Please specify plain or kms",
                               got=list(val.keys()),
                               meta=meta)

        if 'kms' in val and ('location' not in val
                             or 'kms_data_key' not in val):
            raise BadSpecValue(
                "Please specify location and kms_data_key if you specify kms",
                got=list(val.keys()),
                meta=meta)

        return val
Exemplo n.º 21
0
    def normalise_filled(self, meta, val):
        """Complain if val isn't one of the available"""
        val = super(string_choice_spec, self).normalise_filled(meta, val)

        if val not in self.choices:
            raise BadSpecValue(self.reason,
                               available=self.choices,
                               got=val,
                               meta=meta)

        return val
Exemplo n.º 22
0
 def validate_split(self, vals, dividers, meta, val):
     """Validate the vals against our list of specs"""
     if len(vals) < len(self.specs) or len(vals) > len(self.specs) + len(
             self.optional_specs):
         raise BadSpecValue(
             "The value is a list with the wrong number of items",
             got=val,
             meta=meta,
             got_length=len(vals),
             min_length=len(self.specs),
             max_length=len(self.specs) + len(self.optional_specs),
             looking_at=self.value_name)
Exemplo n.º 23
0
    def normalise_filled(self, meta, val):
        missing = []
        for prop in self.properties:
            if not hasattr(val, prop):
                missing.append(prop)

        if missing:
            raise BadSpecValue("Value is missing required properties",
                               required=self.properties,
                               missing=missing,
                               meta=meta)

        return val
Exemplo n.º 24
0
    def normalise_filled(self, meta, val):
        val = sb.dictof(sb.string_choice_spec(["s3", "inline", "directory"]), sb.any_spec()).normalise(meta, val)
        if not val:
            raise BadSpecValue("Please specify s3, inline or directory for your code", meta=meta)

        if len(val) > 1:
            raise BadSpecValue("Please only specify one of s3, inline or directory for your code", got=list(val.keys()), meta=meta)

        formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter)
        if "s3" in val:
            return sb.create_spec(S3Code
                , key = formatted_string
                , bucket = formatted_string
                , version = sb.defaulted(sb.string_spec(), NotSpecified)
                ).normalise(meta, val['s3'])
        elif "inline" in val:
            path = [p for p, _ in meta._path]
            path.pop()
            runtime = meta.everything['.'.join(path)].get("runtime", "python")
            runtime = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter).normalise(meta.at("runtime"), runtime)

            return sb.create_spec(InlineCode
                , code = sb.string_spec()
                , runtime = sb.overridden(runtime)
                ).normalise(meta, {"code": val['inline']})
        else:
            directory = val['directory']
            if isinstance(val['directory'], six.string_types):
                directory = {"directory": val['directory']}

            if 'directory' in directory:
                formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter)
                directory['directory'] = formatted_string.normalise(meta.at("directory").at("directory"), directory['directory'])

            return sb.create_spec(DirectoryCode
                , directory = sb.directory_spec()
                , exclude = sb.listof(sb.string_spec())
                ).normalise(meta, directory)
Exemplo n.º 25
0
    def normalise_filled(self, meta, val):
        """Try all the specs till one doesn't raise a BadSpec"""
        errors = []
        for spec in self.specs:
            try:
                return spec.normalise(meta, val)
            except BadSpec as error:
                errors.append(error)

        # If made it this far, none of the specs passed :(
        raise BadSpecValue("Value doesn't match any of the options",
                           meta=meta,
                           val=val,
                           _errors=errors)
Exemplo n.º 26
0
    def normalise_filled(self, meta, val):
        """Complain if not a file object"""
        bad = False
        if six.PY2:
            if not isinstance(val, file):
                bad = True
        else:
            import io
            if not isinstance(val, io.TextIOBase):
                bad = True

        if bad:
            raise BadSpecValue("Didn't get a file object", meta=meta, got=val)
        return val
Exemplo n.º 27
0
    def normalise_filled(self, meta, val):
        """Turn this into a tuple of it's not and normalise all the items in the tuple"""
        if not isinstance(val, list) and not isinstance(val, tuple):
            val = [val]

        result = []
        errors = []
        for index, item in enumerate(val):
            try:
                result.append(self.spec.normalise(meta.indexed_at(index),
                                                  item))
            except BadSpec as error:
                errors.append(error)

        if errors:
            raise BadSpecValue(meta=meta, _errors=errors)

        return tuple(result)
Exemplo n.º 28
0
    def normalise_filled(self, meta, val):
        """Try all the specs"""
        errors = []
        transformations = [val]
        for spec in self.specs:
            try:
                val = spec.normalise(meta, val)
                transformations.append(val)
            except BadSpec as error:
                errors.append(error)
                break

        if errors:
            raise BadSpecValue("Value didn't match one of the options",
                               meta=meta,
                               transformations=transformations,
                               _errors=errors)
        else:
            return val
Exemplo n.º 29
0
    def normalise_filled(self, meta, val):
        """Try the specs given the type of val"""
        for expected_typ, spec in self.specs:
            if isinstance(val, expected_typ):
                if callable(spec):
                    spec = spec()
                return spec.normalise(meta, val)

        if self.fallback is not None:
            fallback = self.fallback
            if callable(self.fallback):
                fallback = self.fallback()
            return fallback.normalise(meta, val)

        # If made it this far, none of the specs matched
        raise BadSpecValue(
            "Value doesn't match any of the options",
            meta=meta,
            got=type(val),
            expected=[expected_typ for expected_typ, _ in self.specs])
Exemplo n.º 30
0
    def normalise_filled(self, meta, val):
        """Fill out a dictionary with what we want as well as the remaining extra"""
        # Make sure val is a dictionary!
        val = dictionary_spec().normalise(meta, val)

        result = {}
        errors = []

        for key, spec in self.options.items():
            nxt = val.get(key, NotSpecified)

            try:
                normalised = spec.normalise(meta.at(key), nxt)
                result[key] = normalised
            except (BadSpec, BadSpecValue) as error:
                errors.append(error)

        if errors:
            raise BadSpecValue(meta=meta, _errors=errors)

        return result