| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| |
| class Context: |
| |
| def __init__(self): |
| self.containers = [] |
| |
| def push(self, o): |
| self.containers.append(o) |
| |
| def pop(self): |
| return self.containers.pop() |
| |
| class Values: |
| |
| def __init__(self, *values): |
| self.values = values |
| |
| def validate(self, o, ctx): |
| if not o in self.values: |
| return "%s not in %s" % (o, self.values) |
| |
| def __str__(self): |
| return self.value |
| |
| class Types: |
| |
| def __init__(self, *types): |
| self.types = types |
| |
| def validate(self, o, ctx): |
| for t in self.types: |
| if isinstance(o, t): |
| return |
| if len(self.types) == 1: |
| return "%s is not a %s" % (o, self.types[0].__name__) |
| else: |
| return "%s is not one of: %s" % (o, ", ".join([t.__name__ for t in self.types])) |
| |
| class List: |
| |
| def __init__(self, condition): |
| self.condition = condition |
| |
| def validate(self, o, ctx): |
| if not isinstance(o, list): |
| return "%s is not a list" % o |
| |
| ctx.push(o) |
| for v in o: |
| err = self.condition.validate(v, ctx) |
| if err: return err |
| |
| class Map: |
| |
| def __init__(self, map, restricted=True): |
| self.map = map |
| self.restricted = restricted |
| |
| def validate(self, o, ctx): |
| errors = [] |
| |
| if not hasattr(o, "get"): |
| return "%s is not a map" % o |
| |
| ctx.push(o) |
| for k, t in self.map.items(): |
| v = o.get(k) |
| if v is not None: |
| err = t.validate(v, ctx) |
| if err: errors.append("%s: %s" % (k, err)) |
| if self.restricted: |
| for k in o: |
| if not k in self.map: |
| errors.append("%s: illegal key" % k) |
| ctx.pop() |
| |
| if errors: |
| return ", ".join(errors) |
| |
| class And: |
| |
| def __init__(self, *conditions): |
| self.conditions = conditions |
| |
| def validate(self, o, ctx): |
| for c in self.conditions: |
| err = c.validate(o, ctx) |
| if err: |
| return err |