Skip to content

Commit 654295a

Browse files
committed
allow for nullable type definitions
to maintain definition reusability
1 parent 5d4b19c commit 654295a

3 files changed

Lines changed: 68 additions & 35 deletions

File tree

schema/common.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -220,45 +220,72 @@ def property_definition(property_id, ref=""):
220220
return prop, definition
221221

222222

223-
def load_definitions(*args):
223+
def load_definitions(*args, allow_null=False):
224224
"""
225225
Load the common.json definitions file, with some generated additions.
226226
227227
If args are provided, filter to a dictionary of definitions using the args as keys.
228228
229-
With only a single arg, return just the definition with that key directly.
229+
With only a single arg, return the definition with that key directly.
230+
231+
If allow_null is True, override definition types to allow null.
230232
"""
231233
global COMMON_DEFINITIONS
232234

233235
if COMMON_DEFINITIONS == {}:
234236
common = load_json("./templates/common.json")
235-
definitions = common["definitions"]
237+
common_definitions = common["definitions"]
236238

237239
# MDS specific geography definition
238240
mds_feature = mds_feature_point_definition()
239-
definitions.update(mds_feature)
241+
common_definitions.update(mds_feature)
240242

241243
# vehicle_type -> count definition
242-
veh_type_counts = vehicle_type_counts_definition(definitions)
243-
definitions.update(veh_type_counts)
244+
veh_type_counts = vehicle_type_counts_definition(common_definitions)
245+
common_definitions.update(veh_type_counts)
246+
247+
COMMON_DEFINITIONS = common_definitions
244248

245-
COMMON_DEFINITIONS = definitions
249+
definitions = copy.deepcopy(COMMON_DEFINITIONS)
246250

247251
if args and len(args) > 0:
248-
if len(args) == 1:
249-
return COMMON_DEFINITIONS.get(args[0])
250-
else:
251-
return { key: COMMON_DEFINITIONS.get(key) for key in args }
252-
else:
253-
return COMMON_DEFINITIONS
252+
definitions = { typekey: definitions.get(typekey) for typekey in args }
253+
254+
# modify definitions to allow null
255+
if allow_null:
256+
typekey = "type"
257+
typedefs = { k: v for k, v in definitions.items() if typekey in v }
258+
for key, defn in typedefs.items():
259+
nullkey = f"null_{key}"
260+
261+
if "$ref" in defn:
262+
refid = defn["$ref"].split("/")
263+
refid[-1] = f"null_{refid[-1]}"
264+
265+
defn["$ref"] = "/".join(refid)
266+
else:
267+
defnid = defn["$id"].split("/")
268+
defnid[-1] = f"null_{defnid[-1]}"
269+
270+
nulldefn = copy.deepcopy(defn)
271+
nulldefn["$id"] = "/".join(defnid)
272+
273+
if isinstance(nulldefn[typekey], str):
274+
nulldefn[typekey] = [nulldefn[typekey]]
275+
if "null" not in nulldefn[typekey]:
276+
nulldefn[typekey].append("null")
277+
278+
definitions[nullkey] = nulldefn
279+
280+
return definitions.get(args[0]) if len(args) == 1 else definitions
254281

255282

256283
def check_schema(schema):
257284
"""
258-
Check the validity of the given schema document under Draft 6 of the JSON Schema spec.
285+
Check the validity of the given schema document under Draft 7 of the JSON Schema spec.
259286
260287
Returns the (valid) schema instance.
261288
"""
262-
jsonschema.Draft6Validator.check_schema(schema)
289+
jsonschema.Draft7Validator.check_schema(schema)
263290

264291
return schema

schema/policy.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,25 @@ def policy_schema():
1616
definitions = common.load_definitions(
1717
"currency",
1818
"day",
19-
"days",
20-
"iso_time",
2119
"propulsion_type",
22-
"propulsion_types",
2320
"string",
2421
"timestamp",
2522
"uuid",
2623
"uuid_array",
2724
"vehicle_event",
25+
"vehicle_state",
2826
"vehicle_type",
29-
"vehicle_types",
3027
"version"
3128
)
29+
definitions.update(common.load_definitions(
30+
"days",
31+
"iso_time",
32+
"propulsion_types",
33+
"timestamp",
34+
"uuid_array",
35+
"vehicle_types",
36+
allow_null=True
37+
))
3238
schema["definitions"].update(definitions)
3339

3440
# verify and return

schema/templates/policy/policy.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"provider_ids":{
3232
"$id": "#/definitions/policy/properties/provider_ids",
33-
"$ref": "#/definitions/uuid_array",
33+
"$ref": "#/definitions/null_uuid_array",
3434
"description": "Providers for whom this policy is applicable; empty arrays and null/absent implies all Providers.",
3535
"uniqueItems": true
3636
},
@@ -50,7 +50,7 @@
5050
},
5151
"end_date": {
5252
"$id": "#/definitions/policy/properties/end_date",
53-
"$ref": "#/definitions/timestamp",
53+
"$ref": "#/definitions/null_timestamp",
5454
"description": "End date/time of policy enforcement"
5555
},
5656
"published_date": {
@@ -60,12 +60,12 @@
6060
},
6161
"prev_policies": {
6262
"$id": "#/definitions/policy/properties/prev_policies",
63-
"$ref": "#/definitions/uuid_array",
63+
"$ref": "#/definitions/null_uuid_array",
6464
"description": "Unique IDs of prior policies replaced by this one",
6565
"uniqueItems": true
6666
},
6767
"rules": {
68-
"$id": "#/definitions/rule",
68+
"$id": "#/definitions/rules",
6969
"type": "array",
7070
"description": "Array of applicable Rule objects",
7171
"items": {
@@ -154,32 +154,32 @@
154154
},
155155
"vehicle_types": {
156156
"$id": "#/definitions/rule/properties/vehicle_types",
157-
"$ref": "#/definitions/vehicle_types",
157+
"$ref": "#/definitions/null_vehicle_types",
158158
"description": "Applicable vehicle types, default \"all\""
159159
},
160160
"propulsion_types": {
161161
"$id": "#/definitions/rule/properties/propulsion_types",
162-
"$ref": "#/definitions/propulsion_types",
162+
"$ref": "#/definitions/null_propulsion_types",
163163
"description": "Applicable vehicle propulsion types, default \"all\""
164164
},
165165
"minimum": {
166166
"$id": "#/definitions/rule/properties/minimum",
167-
"type": "integer",
167+
"type": ["null", "integer"],
168168
"description": "Minimum value, if applicable (default 0)"
169169
},
170170
"maximum": {
171171
"$id": "#/definitions/rule/properties/maximum",
172-
"type": "integer",
172+
"type": ["null", "integer"],
173173
"description": "Maximum value, if applicable (default unlimited)"
174174
},
175175
"rate_amount": {
176176
"$id": "#/definitions/rule/properties/rate_amount",
177-
"type": "integer",
177+
"type": ["null", "integer"],
178178
"description": "The amount of a rate applied when this rule applies, if applicable (default zero). A positive integer rate amount represents a fee, while a negative integer represents a subsidy. Rate amounts are given in the currency defined in the Policy."
179179
},
180180
"rate_recurrence": {
181181
"$id": "#/definitions/rule/properties/rate_recurrence",
182-
"type": "string",
182+
"type": ["string", "null"],
183183
"description": "Specify when a rate is applied – either once, or periodically according to a time unit specified using rule_units",
184184
"enum": [
185185
"once",
@@ -189,30 +189,30 @@
189189
},
190190
"start_time": {
191191
"$id": "#/definitions/rule/properties/start_time",
192-
"$ref": "#/definitions/iso_time",
192+
"$ref": "#/definitions/null_iso_time",
193193
"description": "Beginning time-of-day when the rule is in effect (default 00:00:00)"
194194
},
195195
"end_time": {
196196
"$id": "#/definitions/rule/properties/end_time",
197-
"$ref": "#/definitions/iso_time",
197+
"$ref": "#/definitions/null_iso_time",
198198
"description": "Ending time-of-day when the rule is in effect (default 23:59:59)"
199199
},
200200
"days": {
201201
"$id": "#/definitions/rule/properties/days",
202-
"$ref": "#/definitions/days",
202+
"$ref": "#/definitions/null_days",
203203
"description": "Days when the rule is in effect (default all)"
204204
},
205205
"messages": {
206206
"$id": "#/definitions/rule/properties/messages",
207-
"type": "object",
207+
"type": ["null", "object"],
208208
"description": "Message to rider user, if desired, in various languages, keyed by BCP 47 language tag",
209209
"propertyNames": {
210210
"pattern": "([A-Za-z]{2,3})([-][A-Za-z]{3}){0,3}([-]([A-Za-z]{4}))?([-]([A-Za-z]{2}|[0-9]{3}))?"
211211
}
212212
},
213213
"value_url": {
214214
"$id": "#/definitions/rule/properties/value_url",
215-
"type": "string",
215+
"type": ["null", "string"],
216216
"description": "URL to an API endpoint that can provide dynamic information for the measured value",
217217
"format": "uri"
218218
}
@@ -247,7 +247,7 @@
247247
},
248248
"end_date": {
249249
"$id": "#/properties/end_date",
250-
"$ref": "#/definitions/timestamp",
250+
"$ref": "#/definitions/null_timestamp",
251251
"description": "The timestamp after which the Policy is no longer effective"
252252
},
253253
"updated": {

0 commit comments

Comments
 (0)