@@ -130,9 +130,10 @@ def generate_library(spec, version_number):
130130 tags = spec ['tags' ]
131131 paths = spec ['paths' ]
132132 scopes = {tag ['name' ]: {} for tag in tags [:10 ]}
133+ batchable_action_summaries = [action ['summary' ] for action in spec ['x-batchable-actions' ]]
133134
134135 # Check paths and create sub-directories if needed
135- subdirs = ['meraki' , 'meraki/api' , 'meraki/aio' , 'meraki/aio/api' ]
136+ subdirs = ['meraki' , 'meraki/api' , 'meraki/api/batch' , 'meraki/ aio' , 'meraki/aio/api' , 'meraki/api/batch ' ]
136137 for dir in subdirs :
137138 if not os .path .isdir (dir ):
138139 os .mkdir (dir )
@@ -182,6 +183,7 @@ def generate_library(spec, version_number):
182183 )
183184 )
184185
186+ # Generate Asyncio API libraries
185187 async_output = open (f'meraki/aio/api/{ scope } .py' , 'w' , encoding = 'utf-8' )
186188 with open ('async_class_template.jinja2' , encoding = 'utf-8' ) as fp :
187189 class_template = fp .read ()
@@ -192,6 +194,18 @@ def generate_library(spec, version_number):
192194 )
193195 )
194196
197+ # Generate Action Batch API libraries
198+ batch_output = open (f'meraki/api/batch/{ scope } .py' , 'w' , encoding = 'utf-8' )
199+ with open ('batch_class_template.jinja2' , encoding = 'utf-8' ) as fp :
200+ class_template = fp .read ()
201+ template = jinja_env .from_string (class_template )
202+ batch_output .write (
203+ template .render (
204+ class_name = scope [0 ].upper () + scope [1 :],
205+ )
206+ )
207+
208+ # Generate API & Asyncio API functions
195209 for path , methods in section .items ():
196210 for method , endpoint in methods .items ():
197211 # Get metadata
@@ -299,7 +313,7 @@ def generate_library(spec, version_number):
299313 query_params = query_params ,
300314 array_params = array_params ,
301315 body_params = body_params ,
302- call_line = call_line ,
316+ call_line = call_line
303317 )
304318 )
305319 async_output .write (
@@ -318,10 +332,113 @@ def generate_library(spec, version_number):
318332 query_params = query_params ,
319333 array_params = array_params ,
320334 body_params = body_params ,
321- call_line = call_line ,
335+ call_line = call_line
322336 )
323337 )
324338
339+ # Generate API action batch functions
340+ for path , methods in section .items ():
341+ for method , endpoint in methods .items ():
342+ if endpoint ['description' ] in batchable_action_summaries :
343+ # Get metadata
344+ tags = endpoint ['tags' ]
345+ operation = endpoint ['operationId' ]
346+ description = endpoint ['summary' ]
347+ parameters = endpoint ['parameters' ] if 'parameters' in endpoint else None
348+ responses = endpoint ['responses' ] # not actually used here for library generation
349+
350+ # Function definition
351+ definition = ''
352+ if parameters :
353+ for p , values in parse_params (operation , parameters , 'required' ).items ():
354+ if values ['type' ] == 'array' :
355+ definition += f', { p } : list'
356+ elif values ['type' ] == 'number' :
357+ definition += f', { p } : float'
358+ elif values ['type' ] == 'integer' :
359+ definition += f', { p } : int'
360+ elif values ['type' ] == 'boolean' :
361+ definition += f', { p } : bool'
362+ elif values ['type' ] == 'object' :
363+ definition += f', { p } : dict'
364+ elif values ['type' ] == 'string' :
365+ definition += f', { p } : str'
366+
367+ if 'perPage' in parse_params (operation , parameters ):
368+ if operation in REVERSE_PAGINATION :
369+ definition += ", total_pages=1, direction='prev'"
370+ else :
371+ definition += ", total_pages=1, direction='next'"
372+ if operation == 'getNetworkEvents' :
373+ definition += ', event_log_end_time=None'
374+
375+ if parse_params (operation , parameters , ['optional' ]):
376+ definition += f', **kwargs'
377+
378+ # Docstring
379+ param_descriptions = []
380+ all_params = parse_params (operation , parameters , ['required' , 'pagination' , 'optional' ])
381+ if all_params :
382+ for p , values in all_params .items ():
383+ param_descriptions .append (f'{ p } ({ values ["type" ]} ): { values ["description" ]} ' )
384+
385+ # Combine keyword args with locals
386+ kwarg_line = ''
387+ if parse_params (operation , parameters , ['optional' ]):
388+ kwarg_line = 'kwargs.update(locals())'
389+ elif parse_params (operation , parameters , ['query' , 'array' , 'body' ]):
390+ kwarg_line = 'kwargs = locals()'
391+
392+ # Assert valid values for enum
393+ enum_params = parse_params (operation , parameters , ['enum' ])
394+ assert_blocks = []
395+ if enum_params :
396+ for p , values in enum_params .items ():
397+ assert_blocks .append ((p , values ['enum' ]))
398+
399+ # Function body for GET endpoints
400+ query_params = array_params = body_params = {}
401+
402+ # Function body for POST/PUT endpoints
403+ if method == 'post' or method == 'put' :
404+ body_params = parse_params (operation , parameters , 'body' )
405+ if method == 'post' :
406+ batch_operation = 'create'
407+ else :
408+ batch_operation = 'update'
409+
410+ # Function body for DELETE endpoints
411+ elif method == 'delete' :
412+ batch_operation = 'destroy'
413+
414+ # Function return statement
415+ call_line = 'return action'
416+
417+ # Add function to files
418+ with open ('batch_function_template.jinja2' , encoding = 'utf-8' ) as fp :
419+ function_template = fp .read ()
420+ template = jinja_env .from_string (function_template )
421+ batch_output .write (
422+ '\n \n ' +
423+ template .render (
424+ operation = operation ,
425+ function_definition = definition ,
426+ description = description ,
427+ doc_url = docs_url (operation ),
428+ descriptions = param_descriptions ,
429+ kwarg_line = kwarg_line ,
430+ all_params = list (all_params .keys ()),
431+ assert_blocks = assert_blocks ,
432+ tags = tags ,
433+ resource = path ,
434+ query_params = query_params ,
435+ array_params = array_params ,
436+ body_params = body_params ,
437+ call_line = call_line ,
438+ batch_operation = batch_operation
439+ )
440+ )
441+
325442
326443# Prints READ_ME help message for user to read
327444def print_help ():
0 commit comments