La forma más limpia de pegar el código generado de la aplicación Flask (Swagger-Codegen) para la implementación del servidor.

Yo tengo:

  1. una biblioteca que hace [Stuff]
  2. una definición de API swagger, que es aproximadamente el # 1 con pequeñas diferencias para mapear limpiamente a un servicio REST
  3. una aplicación de matraz generada # 2 usando Swagger-Codegen – por ejemplo, da como resultado funciones de controlador Python aproximadamente una a una con # 1.

Mi intención es que la aplicación del matraz (todo el código generado) solo debe manejar la asignación de la API REST real y el análisis de parámetros para que coincida con la especificación de la API codificada en swagger. Después de cualquier análisis de parámetros (una vez más, el código generado) debe llamar directamente a mi backend (no generado).

Mi pregunta es, ¿cuál es la mejor manera de conectarlos sin editar manualmente el código generado en python / flask? (La retroalimentación sobre mi diseño, o los detalles de un patrón de diseño formal que logre esto también sería genial; soy nuevo en este espacio).

Recién llegado del generador, termino con funciones de python como:

def create_task(myTaskDefinition): """ comment as specified in swagger.json :param myTaskDefinition: json blah blah blah :type myTaskDefinition: dict | bytes :rtype: ApiResponse """ if connexion.request.is_json: myTaskDefinition = MyTaskTypeFromSwagger.from_dict(connexion.request.get_json()) return 'do some magic!' # swagger codegen inserts this string :) 

En el backend tengo mi lógica real:

 def create_task_backend(myTaskDefinition): # hand-coded, checked into git: do all the things return APIResponse(...) 

¿Cuál es la forma correcta de obtener create_task() para llamar a create_task_backend() ?

Por supuesto, si hago cambios de última hora en mi especificación de swagger, tendré que actualizar manualmente el código no generado independientemente; sin embargo, hay muchas razones por las que me gustaría volver a generar mi API (por ejemplo, agregar / refinar la clase MyTaskTypeFromSwagger , o saltear el código generado en git) y si tengo que editar manualmente el código API generado, entonces todo esas ediciones son arrastradas con cada re-generación.

Por supuesto que podría escribir esto con una gramática simple en, por ejemplo. pyparsing; pero si bien esta es mi primera vez con este problema, parece probable que ya se haya resuelto ampliamente.

Tuve la tentación de usar swagger-codegen antes y me encontré con el mismo enigma. Todo está bien hasta que actualice la especificación. A pesar de que puede usar plantillas personalizadas, esto parece una gran cantidad de gastos generales y de mantenimiento, cuando lo único que quiero es una API de diseño inicial.

Terminé usando connexion en su lugar, que usa la especificación swagger para manejar automáticamente el enrutamiento, cálculo de referencias, validación, etc. Connexion se basa en el matraz, por lo que no debería preocuparse por cambiar los marcos o nada, solo obtendrá el beneficio de las porciones de que su aplicación se maneje automáticamente desde swagger en lugar de tener que mantener el código generado automáticamente.

El siguiente enfoque funcionó para mí:

  • creado tres directorios:

    • src – para mi código,
    • src-gen para el código generado swagger,
    • codegen en el que he puesto un script que genera el servidor junto con algunos trucos.
  • Copié todas las plantillas (disponibles en la comstackción de codegen/templates ) a codegen/templates y codegen/templates el controller.mustache para referirme a src/server_impl , para que pueda usar mi propio código. La edición utiliza el lenguaje de la plantilla por lo que es genérico. Aún así no es perfecto (cambiaría algunas convenciones de nombres) pero hace el trabajo. Entonces, primero agregue a controller.mustache :

 from {packageName}}.server_impl.controllers_impl import {{classname}}_impl 

luego agrega en lugar de return 'do some magic!' el seguimiento:

 return {{classname}}_impl.{{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) 
  • Guión:
    • El src tiene un directorio server_impl .
    • Crea un enlace simbólico para que server_impl se pueda importar como un módulo python.
 cd ../src-gen/swagger_server/ ln -s ../../src/server_impl/ cd ../../codegen java -jar swagger-codegen-cli.jar generate \ -i /path_to_your_swagger definition.yaml \ -l python-flask \ -o ../src-gen \ -t ./templates cd ../src-gen/ python3 -m swagger_server 

Por ahora estoy trabajando alrededor de esto haciendo la comstackción en estos pasos

  1. corre el codegen
  2. sed-script el código generado para arreglar cosas triviales como los espacios de nombres
  3. edite los archivos a mano, de modo que en lugar de devolver 'do some magic' (esa es la cadena que devuelven todos los puntos finales del controlador generados) simplemente llaman a una función correspondiente en mi “backend”
  4. use git format-patch para hacer un parche de los cambios anteriores, para que cuando se vuelva a generar el código, la comstackción pueda aplicar los cambios automáticamente.

Por lo tanto, puedo agregar nuevos puntos finales y solo tengo que codificar manualmente las llamadas a mi backend ~ una vez. En lugar de usar archivos de parches, podría hacer esto directamente escribiendo una gramática de análisis de py para el código generado y usando el código generado analizado para crear las llamadas a mi backend … eso llevaría más tiempo, así que hice todo esto rápidamente. cortar.

Esto está lejos de ser óptimo, no voy a marcar esto como aceptado ya que espero que alguien ofrezca una solución real.