summaryrefslogtreecommitdiff
path: root/lib/thandy/checkJson.py
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-11-30 06:19:04 +0000
committerNick Mathewson <nickm@torproject.org>2008-11-30 06:19:04 +0000
commit3bef6462fa8117dde2f55a3ff06dbf1b1a8e02a8 (patch)
tree4dd9ef4282482e81422b28624fd1dbfb442e4f61 /lib/thandy/checkJson.py
parentbd2a8dad04994c28086c7c30636273a40be01243 (diff)
Big thandy installation refactoring. Things should be saner now: we recognize that checking an item is sometimes orthogonal to installing it; we do not carry around big bits of unimplemented machinery; we actually document what stuff does in thandy-spec.txt; we do more OO in the places that make sense and less in the places that do not; and almost as an afterthought, we support the command installer type internally. Now all we need is a frontend to make command installers.
git-svn-id: file:///home/or/svnrepo/updater/trunk@17414 55e972cd-5a19-0410-ae62-a4d7a52db4cd
Diffstat (limited to 'lib/thandy/checkJson.py')
-rw-r--r--lib/thandy/checkJson.py106
1 files changed, 103 insertions, 3 deletions
diff --git a/lib/thandy/checkJson.py b/lib/thandy/checkJson.py
index 84ea9f2..e63a1fc 100644
--- a/lib/thandy/checkJson.py
+++ b/lib/thandy/checkJson.py
@@ -137,6 +137,16 @@ class OneOf(Schema):
raise thandy.FormatException("Object matched no recognized alternative")
+class AllOf(Schema):
+ """Matches the intersection of a list of schemas.
+ """
+ def __init__(self, required):
+ self._subschemas = required[:]
+
+ def checkMatche(self, obj):
+ for s in self._subschemas:
+ s.checkMatch(obj)
+
class ListOf(Schema):
"""
Matches a homogenous list of some subschema.
@@ -211,16 +221,34 @@ class Struct(Schema):
True
>>> s.matches([["X"]])
False
+
+ >>> s = Struct([Str("X"), Int()], [Int()])
+ >>> s.matches([])
+ False
+ >>> s.matches({})
+ False
+ >>> s.matches(["X"])
+ False
+ >>> s.matches(["X", 3])
+ True
+ >>> s.matches(["X", 3, 9])
+ True
+ >>> s.matches(["X", 3, 9, 11])
+ False
+ >>> s.matches(["X", 3, "A"])
+ False
"""
- def __init__(self, subschemas, allowMore=False, structName="list"):
- self._subschemas = subschemas[:]
+ def __init__(self, subschemas, optschemas=[], allowMore=False,
+ structName="list"):
+ self._subschemas = subschemas + optschemas
+ self._min = len(subschemas)
self._allowMore = allowMore
self._structName = structName
def checkMatch(self, obj):
if not isinstance(obj, (list, tuple)):
raise thandy.FormatException("Expected %s; got %r"
%(self._structName,obj))
- elif len(obj) < len(self._subschemas):
+ elif len(obj) < self._min:
raise thandy.FormatException(
"Too few fields in %s"%self._structName)
elif len(obj) > len(self._subschemas) and not self._allowMore:
@@ -298,6 +326,10 @@ class Obj(Schema):
def checkMatch(self, obj):
+ if not isinstance(obj, dict):
+ raise thandy.FormatException("Wanted a %s; did not get a dict"%
+ self._objname)
+
for k,schema in self._required:
try:
item = obj[k]
@@ -313,6 +345,63 @@ class Obj(Schema):
raise thandy.FormatException("%s in %s.%s"
%(e,self._objname,k))
+class TaggedObj(Schema):
+ """
+ Matches an object based on the value of a particular 'tag' field.
+ If tagIsOptional, matches any object when the tag is missing.
+ If ignoreUnrecognized, matches any object when the tag is present
+ but the value is not one we know.
+
+ >>> s = TaggedObj('tp', a=Obj(int1=Int()), b=Obj(s=AnyStr()))
+ >>> s.matches(3)
+ False
+ >>> s.matches([])
+ False
+ >>> s.matches({})
+ False
+ >>> s.matches({'tp' : 'fred'})
+ True
+ >>> s.matches({'tp' : 'a'})
+ False
+ >>> s.matches({'tp' : 'a', 'int1': 3})
+ True
+ >>> s.matches({'tp' : 'a', 'int1': []})
+ False
+ >>> s.matches({'tp' : 'b', 'int1': 3, 's': 'tt'})
+ True
+ """
+ def __init__(self, tagName, tagIsOptional=False, ignoreUnrecognized=True,
+ **tagvals):
+ self._tagName = tagName
+ self._tagOpt = tagIsOptional
+ self._ignoreOthers = ignoreUnrecognized
+ self._tagvals = tagvals
+
+ def checkMatch(self, obj):
+ try:
+ tag = obj[self._tagName]
+ except KeyError:
+ if self._tagOpt:
+ return
+ else:
+ raise thandy.FormatException("Missing tag %s on object"%
+ self._tagName)
+ except TypeError:
+ raise thandy.FormatException("Got a %s, not a tagged object"%
+ type(obj))
+ if not isinstance(tag, basestring):
+ raise thandy.FormatException("Expected a string for %s; got a %s"%(
+ self._tagName, type(tag)))
+ try:
+ subschema = self._tagvals[tag]
+ except KeyError:
+ if self._ignoreOthers:
+ return
+ else:
+ raise thandy.FormatException("Unrecognized value %s for %s"%(
+ tag, self._tagName))
+
+ subschema.checkMatch(obj)
class Int(Schema):
"""
@@ -359,3 +448,14 @@ class Bool(Schema):
def checkMatch(self, obj):
if not isinstance(obj, bool):
raise thandy.FormatException("Got %r instead of a boolean"%obj)
+
+class Func(Schema):
+ def __init__(self, fn, baseSchema=None):
+ self._fn = fn
+ self._base = baseSchema
+ def checkMatch(self, obj):
+ if self._base:
+ self._base.checkMatch(obj)
+ r = self._fn(obj)
+ if r is False:
+ raise thandy.FormatException("%s returned False"%self._fn)