]>
Commit | Line | Data |
---|---|---|
e0edde6f | 1 | # Copyright (c) 2010, 2011 Nicira, Inc. |
99155935 BP |
2 | # |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at: | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | ||
15 | import re | |
16 | ||
17 | from ovs.db import error | |
18 | ||
26bb0f31 | 19 | |
99155935 BP |
20 | class Parser(object): |
21 | def __init__(self, json, name): | |
22 | self.name = name | |
23 | self.json = json | |
da2d45c6 | 24 | if not isinstance(json, dict): |
99155935 BP |
25 | self.__raise_error("Object expected.") |
26 | self.used = set() | |
27 | ||
28 | def __get(self, name, types, optional, default=None): | |
29 | if name in self.json: | |
30 | self.used.add(name) | |
31 | member = float_to_int(self.json[name]) | |
32 | if is_identifier(member) and "id" in types: | |
33 | return member | |
25f599fb RB |
34 | try: |
35 | if len(types) and not isinstance(member, tuple(types)): | |
36 | self.__raise_error("Type mismatch for member '%s'." % name) | |
37 | except TypeError: | |
99155935 BP |
38 | self.__raise_error("Type mismatch for member '%s'." % name) |
39 | return member | |
40 | else: | |
26bb0f31 | 41 | if not optional: |
99155935 BP |
42 | self.__raise_error("Required '%s' member is missing." % name) |
43 | return default | |
44 | ||
45 | def get(self, name, types): | |
46 | return self.__get(name, types, False) | |
47 | ||
48 | def get_optional(self, name, types, default=None): | |
49 | return self.__get(name, types, True, default) | |
50 | ||
51 | def __raise_error(self, message): | |
52 | raise error.Error("Parsing %s failed: %s" % (self.name, message), | |
53 | self.json) | |
54 | ||
55 | def finish(self): | |
56 | missing = set(self.json) - set(self.used) | |
57 | if missing: | |
58 | name = missing.pop() | |
59 | if len(missing) > 1: | |
c29e06be | 60 | present = "and %d other members are" % len(missing) |
99155935 | 61 | elif missing: |
c29e06be | 62 | present = "and 1 other member are" |
99155935 | 63 | else: |
c29e06be BP |
64 | present = "is" |
65 | self.__raise_error("Member '%s' %s present but not allowed here" % | |
66 | (name, present)) | |
26bb0f31 EJ |
67 | |
68 | ||
99155935 BP |
69 | def float_to_int(x): |
70 | # XXX still needed? | |
da2d45c6 | 71 | if isinstance(x, float): |
99155935 | 72 | integer = int(x) |
26bb0f31 | 73 | if integer == x and -2 ** 53 <= integer < 2 ** 53: |
99155935 BP |
74 | return integer |
75 | return x | |
76 | ||
26bb0f31 | 77 | |
99155935 | 78 | id_re = re.compile("[_a-zA-Z][_a-zA-Z0-9]*$") |
26bb0f31 EJ |
79 | |
80 | ||
99155935 | 81 | def is_identifier(s): |
0c4d144a | 82 | return isinstance(s, str) and id_re.match(s) |
99155935 | 83 | |
26bb0f31 | 84 | |
8758e8a3 | 85 | def json_type_to_string(type_): |
0c4d144a | 86 | number_types = [int] |
8f808842 RB |
87 | number_types.extend([float]) |
88 | number_types = tuple(number_types) | |
3c057118 | 89 | if type_ is None: |
99155935 | 90 | return "null" |
8f808842 | 91 | elif issubclass(type_, bool): |
99155935 | 92 | return "boolean" |
8f808842 | 93 | elif issubclass(type_, dict): |
99155935 | 94 | return "object" |
8f808842 | 95 | elif issubclass(type_, list): |
99155935 | 96 | return "array" |
8f808842 | 97 | elif issubclass(type_, number_types): |
99155935 | 98 | return "number" |
0c4d144a | 99 | elif issubclass(type_, str): |
99155935 BP |
100 | return "string" |
101 | else: | |
102 | return "<invalid>" | |
103 | ||
26bb0f31 | 104 | |
5c3a4660 | 105 | def unwrap_json(json, name, types, desc): |
25f599fb RB |
106 | if (not isinstance(json, (list, tuple)) |
107 | or len(json) != 2 or json[0] != name | |
108 | or not isinstance(json[1], tuple(types))): | |
5c3a4660 | 109 | raise error.Error('expected ["%s", <%s>]' % (name, desc), json) |
99155935 BP |
110 | return json[1] |
111 | ||
26bb0f31 | 112 | |
99155935 | 113 | def parse_json_pair(json): |
da2d45c6 | 114 | if not isinstance(json, list) or len(json) != 2: |
99155935 BP |
115 | raise error.Error("expected 2-element array", json) |
116 | return json |