1from .draft06 import CodeGeneratorDraft06
2
3
4class CodeGeneratorDraft07(CodeGeneratorDraft06):
5 FORMAT_REGEXS = dict(CodeGeneratorDraft06.FORMAT_REGEXS, **{
6 'date': r'^(?P<year>\d{4})-(?P<month>(0[1-9]|1[0-2]))-(?P<day>(0[1-9]|[12]\d|3[01]))\Z',
7 'iri': r'^\w+:(\/?\/?)[^\s]+\Z',
8 'iri-reference': r'^(\w+:(\/?\/?))?[^#\\\s]*(#[^\\\s]*)?\Z',
9 'idn-email': r'^[^@]+@[^@]+\.[^@]+\Z',
10 # pylint: disable=line-too-long
11 'idn-hostname': r'^(?!-)(xn--)?[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.(?!-)(xn--)?([a-zA-Z0-9\-]{1,50}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,})$',
12 'relative-json-pointer': r'^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)\Z',
13 #'regex': r'',
14 'time': (
15 r'^(?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
16 r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6}))?'
17 r'([zZ]|[+-]\d\d:\d\d)?)?\Z'
18 ),
19 })
20
21 def __init__(
22 self,
23 definition,
24 resolver=None,
25 formats={},
26 use_default=True,
27 use_formats=True,
28 detailed_exceptions=True,
29 fast_fail=True
30 ):
31 super().__init__(definition, resolver, formats, use_default, use_formats, detailed_exceptions, fast_fail)
32 # pylint: disable=duplicate-code
33 self._json_keywords_to_function.update((
34 ('if', self.generate_if_then_else),
35 ('contentEncoding', self.generate_content_encoding),
36 ('contentMediaType', self.generate_content_media_type),
37 ))
38
39 def generate_if_then_else(self):
40 """
41 Implementation of if-then-else.
42
43 .. code-block:: python
44
45 {
46 'if': {
47 'exclusiveMaximum': 0,
48 },
49 'then': {
50 'minimum': -10,
51 },
52 'else': {
53 'multipleOf': 2,
54 },
55 }
56
57 Valid values are any between -10 and 0 or any multiplication of two.
58 """
59 with self.l('try:', optimize=False):
60 code_len = len(self._code)
61 self.generate_func_code_block(
62 self._definition['if'],
63 self._variable,
64 self._variable_name,
65 clear_variables=True
66 )
67 if len(self._code) == code_len:
68 self.l('pass')
69 with self.l('except JsonSchemaValueException:'):
70 if 'else' in self._definition:
71 code_len = len(self._code)
72 self.generate_func_code_block(
73 self._definition['else'],
74 self._variable,
75 self._variable_name,
76 clear_variables=True
77 )
78 if len(self._code) == code_len:
79 self.l('pass')
80 else:
81 self.l('pass')
82 if 'then' in self._definition:
83 with self.l('else:'):
84 code_len = len(self._code)
85 self.generate_func_code_block(
86 self._definition['then'],
87 self._variable,
88 self._variable_name,
89 clear_variables=True
90 )
91 if len(self._code) == code_len:
92 self.l('pass')
93
94 def generate_content_encoding(self):
95 """
96 Means decoding value when it's encoded by base64.
97
98 .. code-block:: python
99
100 {
101 'contentEncoding': 'base64',
102 }
103 """
104 if self._definition['contentEncoding'] == 'base64':
105 with self.l('if isinstance({variable}, str):'):
106 with self.l('try:'):
107 self.l('import base64')
108 self.l('{variable} = base64.b64decode({variable})')
109 with self.l('except Exception:'):
110 self.exc('{name} must be encoded by base64')
111 with self.l('if {variable} == "":'):
112 self.exc('contentEncoding must be base64')
113
114 def generate_content_media_type(self):
115 """
116 Means loading value when it's specified as JSON.
117
118 .. code-block:: python
119
120 {
121 'contentMediaType': 'application/json',
122 }
123 """
124 if self._definition['contentMediaType'] == 'application/json':
125 with self.l('if isinstance({variable}, bytes):'):
126 with self.l('try:'):
127 self.l('{variable} = {variable}.decode("utf-8")')
128 with self.l('except Exception:'):
129 self.exc('{name} must encoded by utf8')
130 with self.l('if isinstance({variable}, str):'):
131 with self.l('try:'):
132 self.l('import json')
133 self.l('{variable} = json.loads({variable})')
134 with self.l('except Exception:'):
135 self.exc('{name} must be valid JSON')