1313# limitations under the License.
1414
1515import json
16+ import operator
1617import os .path
1718import sys
1819from collections import OrderedDict
1920
21+
22+ # these four constants are shown as part of this example in []:
23+ # "[watch]Pod[List]" is the deprecated version of "[list]Pod?[watch]=True"
24+ WATCH_OP_PREFIX = "watch"
25+ WATCH_OP_SUFFIX = "List"
26+ LIST_OP_PREFIX = "list"
27+ WATCH_QUERY_PARAM_NAME = "watch"
28+
29+
2030_ops = ['get' , 'put' , 'post' , 'delete' , 'options' , 'head' , 'patch' ]
2131
2232
33+ class PreprocessingException (Exception ):
34+ pass
35+
36+
2337def _title (s ):
2438 if len (s ) == 0 :
2539 return s
@@ -30,24 +44,72 @@ def _to_camel_case(s):
3044 return '' .join (_title (y ) for y in s .split ("_" ))
3145
3246
33- def iterate_through_operations (spec , func ):
47+ def apply_func_to_spec_operations (spec , func , * params ):
48+ """Apply func to each operation in the spec.
49+
50+ :param spec: The OpenAPI spec to apply func to.
51+ :param func: the function to apply to the spec's operations. It should be
52+ a func(operation, parent) where operation will be each
53+ operation of the spec and parent would be the parent object of
54+ the given operation.
55+ If the return value of the func is True, then the operation
56+ will be deleted from the spec.
57+ """
3458 for k , v in spec ['paths' ].iteritems ():
3559 for op in _ops :
36- if op in v :
37- func (v [op ])
60+ if op not in v :
61+ continue
62+ if func (v [op ], v , * params ):
63+ del v [op ]
64+
65+
66+ def _has_property (prop_list , property_name ):
67+ for prop in prop_list :
68+ if prop ["name" ] == property_name :
69+ return True
70+
71+
72+ def remove_watch_operations (op , parent , operation_ids ):
73+ op_id = op ['operationId' ]
74+ if not op_id .startswith (WATCH_OP_PREFIX ):
75+ return
76+ list_id = (LIST_OP_PREFIX +
77+ op_id .replace (WATCH_OP_SUFFIX , "" )[len (WATCH_OP_PREFIX ):])
78+ if list_id not in operation_ids :
79+ raise PreprocessingException ("Cannot find %s" % list_id )
80+ list_op = operation_ids [list_id ]
81+ params = []
82+ if 'parameters' in list_op :
83+ params += list_op ['parameters' ]
84+ if 'parameters' in parent :
85+ params += parent ['parameters' ]
86+ if not _has_property (params , WATCH_QUERY_PARAM_NAME ):
87+ raise PreprocessingException ("%s has no watch query param" % list_id )
88+ return True
89+
90+
91+ def strip_tags_from_operation_id (operation , _ ):
92+ operation_id = operation ['operationId' ]
93+ for t in operation ['tags' ]:
94+ operation_id = operation_id .replace (_to_camel_case (t ), '' )
95+ operation ['operationId' ] = operation_id
3896
3997
4098def process_swagger (infile , outfile ):
4199 with open (infile , 'r' ) as f :
42100 spec = json .load (f , object_pairs_hook = OrderedDict )
43101
44- def strip_tags_from_operation_id ( operation ):
45- operation_id = operation [ 'operationId' ]
46- for t in operation [ 'tags' ]:
47- operation_id = operation_id . replace ( _to_camel_case ( t ), '' )
48- operation ['operationId' ] = operation_id
102+ apply_func_to_spec_operations ( spec , strip_tags_from_operation_id )
103+
104+ operation_ids = {}
105+ apply_func_to_spec_operations ( spec , lambda op , _ : operator . setitem (
106+ operation_ids , op ['operationId' ], op ))
49107
50- iterate_through_operations (spec , strip_tags_from_operation_id )
108+ try :
109+ apply_func_to_spec_operations (
110+ spec , remove_watch_operations , operation_ids )
111+ except PreprocessingException as e :
112+ print (e .message )
51113
52114 with open (outfile , 'w' ) as out :
53115 json .dump (spec , out , sort_keys = False , indent = 2 ,
0 commit comments