55 python generate_schemas.py [--agency] [--provider]
66"""
77
8+ import copy
89import json
910import jsonschema
1011import requests
@@ -20,6 +21,55 @@ def load_json(path):
2021 return data
2122
2223
24+ def vehicle_model (common_definitions , provider_name = True , provider_id = True ):
25+ """
26+ Extract a deep-copy of the common vehicle model definition to allow for customization.
27+ """
28+ vehicle = copy .deepcopy (common_definitions ["vehicle" ])
29+
30+ if not provider_name :
31+ vehicle ["required" ].remove ("provider_name" )
32+ del vehicle ["properties" ]["provider_name" ]
33+
34+ if not provider_id :
35+ vehicle ["required" ].remove ("provider_id" )
36+ del vehicle ["properties" ]["provider_id" ]
37+
38+ return vehicle
39+
40+
41+ def vehicle_state_machine (common_definitions , vehicle_state = None , vehicle_events = None ):
42+ """
43+ Return a tuple (definitions, transitions) with the common vehicle state schema.
44+ * defitions is the common definitions for vehicle state fields
45+ * transitions is the rule for valid state/event combinations
46+
47+ Optionally pass field names for the vehicle_state and vehicle_events schemas
48+ to override those in transitions.
49+ """
50+ state_machine_defs = {
51+ "vehicle_state" : common_definitions ["vehicle_state" ],
52+ "vehicle_event" : common_definitions ["vehicle_event" ],
53+ "vehicle_events" : common_definitions ["vehicle_events" ],
54+ }
55+
56+ transitions = copy .deepcopy (common_definitions ["vehicle_state_transitions" ])
57+
58+ if vehicle_state :
59+ for option in transitions ["oneOf" ]:
60+ state = option ["properties" ]["vehicle_state" ]
61+ del option ["properties" ]["vehicle_state" ]
62+ option ["properties" ][vehicle_state ] = state
63+
64+ if vehicle_events :
65+ for option in transitions ["oneOf" ]:
66+ events = option ["properties" ]["vehicle_events" ]
67+ del option ["properties" ]["vehicle_events" ]
68+ option ["properties" ][vehicle_events ] = events
69+
70+ return (state_machine_defs , transitions )
71+
72+
2373def agency_get_vehicle_schema (common_definitions ):
2474 """
2575 Create the schema for the Agency GET /vehicles endpoint.
@@ -29,18 +79,18 @@ def agency_get_vehicle_schema(common_definitions):
2979 schema ["definitions" ] = {
3080 "propulsion_types" : common_definitions ["propulsion_types" ],
3181 "string" : common_definitions ["string" ],
32- "vehicle_state" : common_definitions ["vehicle_state" ],
33- "vehicle_events" : common_definitions ["vehicle_events" ],
3482 "vehicle_type" : common_definitions ["vehicle_type" ],
3583 "timestamp" : common_definitions ["timestamp" ],
3684 "uuid" : common_definitions ["uuid" ]
3785 }
3886
39- # merge common vehicle information, with Agency tweaks
40- vehicle = dict (common_definitions [ "vehicle" ] )
41- vehicle [ "required " ].remove ( "provider_name" )
42- del vehicle [ "properties" ][ "provider_name" ]
87+ # merge the state machine definitions and transition combinations rule
88+ state_machine_defs , transitions = vehicle_state_machine (common_definitions , "state" , "prev_events" )
89+ schema [ "definitions " ].update ( state_machine_defs )
90+ schema [ "allOf" ]. append ( transitions )
4391
92+ # merge common vehicle information, with Agency tweaks
93+ vehicle = vehicle_model (common_definitions , provider_name = False )
4494 schema ["required" ] = vehicle ["required" ] + schema ["required" ]
4595 schema ["properties" ] = { ** vehicle ["properties" ], ** schema ["properties" ] }
4696
@@ -64,10 +114,8 @@ def agency_post_vehicle_schema(common_definitions):
64114 }
65115
66116 # merge common vehicle information, with Agency tweaks
67- vehicle = dict (common_definitions ["vehicle" ])
68- vehicle ["required" ].remove ("provider_name" )
117+ vehicle = vehicle_model (common_definitions , provider_name = False )
69118 vehicle ["required" ].remove ("provider_id" )
70- del vehicle ["properties" ]["provider_name" ]
71119
72120 schema ["required" ] = vehicle ["required" ] + schema ["required" ]
73121 schema ["properties" ] = { ** vehicle ["properties" ], ** schema ["properties" ] }
@@ -85,12 +133,15 @@ def agency_post_vehicle_event_schema(common_definitions):
85133 # load schema template and insert definitions
86134 schema = load_json ("./templates/agency/post_vehicle_event.json" )
87135 schema ["definitions" ] = {
88- "vehicle_state" : common_definitions ["vehicle_state" ],
89- "vehicle_events" : common_definitions ["vehicle_events" ],
90136 "telemetry" : common_definitions ["telemetry" ],
91137 "timestamp" : common_definitions ["timestamp" ],
92138 }
93139
140+ # merge the state machine definitions and transition combinations rule
141+ state_machine_defs , transitions = vehicle_state_machine (common_definitions , "vehicle_state" , "event_types" )
142+ schema ["definitions" ].update (state_machine_defs )
143+ schema ["allOf" ].append (transitions )
144+
94145 # add the conditionally-required trip_id rule
95146 trip_id_ref = common_definitions ["trip_id_reference" ]
96147 schema ["allOf" ].append (trip_id_ref )
@@ -298,9 +349,10 @@ def provider_schema(endpoint, common_definitions, extra_definitions={}):
298349 # merge endpoint-specific schema with standard vehicle info
299350 endpoint_schema = load_json (f"./templates/provider/{ endpoint } .json" )
300351 items = endpoint_schema [endpoint ]["items" ]
301- vehicle_schema = dict (common_definitions ["vehicle" ])
302- items ["required" ] = vehicle_schema ["required" ] + items ["required" ]
303- items ["properties" ] = { ** vehicle_schema ["properties" ], ** items ["properties" ] }
352+
353+ vehicle = vehicle_model (common_definitions )
354+ items ["required" ] = vehicle ["required" ] + items ["required" ]
355+ items ["properties" ] = { ** vehicle ["properties" ], ** items ["properties" ] }
304356
305357 # merge this endpoint-specific schema into the endpoint template
306358 data_schema = schema ["properties" ]["data" ]
@@ -340,6 +392,11 @@ def provider_status_changes_schema(common_definitions):
340392 schema = provider_schema ("status_changes" , common_definitions )
341393 items = schema ["properties" ]["data" ]["properties" ]["status_changes" ]["items" ]
342394
395+ # merge the state machine definitions and transition combinations rule
396+ state_machine_defs , transitions = vehicle_state_machine (common_definitions , "vehicle_state" , "event_types" )
397+ schema ["definitions" ].update (state_machine_defs )
398+ items ["allOf" ].append (transitions )
399+
343400 trip_id_ref = common_definitions ["trip_id_reference" ]
344401 items ["allOf" ].append (trip_id_ref )
345402
@@ -356,9 +413,10 @@ def provider_events_schema(common_definitions):
356413 links_prop , links_def = property_definition ("links" , common_definitions )
357414
358415 # events is the same as status_changes, but allows paging
359- schema = provider_schema ( "status_changes" , common_definitions , links_def )
416+ schema = provider_status_changes_schema ( common_definitions )
360417 schema ["$id" ] = schema ["$id" ].replace ("status_changes" , "events" )
361418 schema ["title" ] = schema ["title" ].replace ("status_changes" , "events" )
419+ schema ["definitions" ].update (links_def )
362420 schema ["properties" ].update (links_prop )
363421
364422 # verify schema validity
@@ -384,12 +442,18 @@ def provider_vehicles_schema(common_definitions):
384442 definitions .update (defn )
385443 properties .update (prop )
386444
445+ state_machine_defs , transitions = vehicle_state_machine (common_definitions , "last_vehicle_state" , "last_event_types" )
446+ definitions .update (state_machine_defs )
447+
387448 schema = provider_schema ("vehicles" , common_definitions , definitions )
388449
389450 # update list of required and properties object
390451 schema ["required" ].extend (["last_updated" , "ttl" ])
391452 schema ["properties" ].update (properties )
392453
454+ # add state machine transition rules
455+ schema ["properties" ]["data" ]["properties" ]["vehicles" ]["items" ]["allOf" ].append (transitions )
456+
393457 # verify schema validity
394458 jsonschema .Draft6Validator .check_schema (schema )
395459
0 commit comments