cornflow 2.0.0a13__tar.gz → 2.0.0a14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. {cornflow-2.0.0a13/cornflow.egg-info → cornflow-2.0.0a14}/PKG-INFO +2 -2
  2. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/app.py +3 -1
  3. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/__init__.py +4 -0
  4. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/actions.py +4 -0
  5. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/config.py +4 -0
  6. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/migrations.py +13 -8
  7. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/permissions.py +4 -0
  8. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/roles.py +4 -0
  9. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/schemas.py +5 -0
  10. cornflow-2.0.0a14/cornflow/cli/service.py +397 -0
  11. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/tools/api_generator.py +13 -10
  12. cornflow-2.0.0a14/cornflow/cli/tools/endpoint_tools.py +283 -0
  13. cornflow-2.0.0a14/cornflow/cli/tools/models_tools.py +161 -0
  14. cornflow-2.0.0a14/cornflow/cli/tools/schema_generator.py +281 -0
  15. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/tools/schemas_tools.py +4 -5
  16. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/users.py +8 -0
  17. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/views.py +4 -0
  18. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/dag.py +3 -2
  19. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/schemas.py +6 -4
  20. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/users.py +12 -17
  21. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/config.py +3 -2
  22. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/dag.py +27 -25
  23. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/data_check.py +102 -164
  24. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/example_data.py +9 -3
  25. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/execution.py +27 -23
  26. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/health.py +4 -5
  27. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/instance.py +39 -12
  28. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/meta_resource.py +4 -5
  29. cornflow-2.0.0a14/cornflow/shared/airflow.py +157 -0
  30. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/authentication/auth.py +73 -42
  31. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/const.py +9 -0
  32. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/databricks.py +10 -10
  33. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/exceptions.py +3 -1
  34. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/utils_tables.py +36 -8
  35. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/validators.py +1 -1
  36. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/custom_test_case.py +4 -4
  37. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_alarms.py +1 -2
  38. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_cases.py +4 -7
  39. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_executions.py +29 -20
  40. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_log_in.py +46 -9
  41. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_tables.py +3 -3
  42. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/tools.py +31 -13
  43. {cornflow-2.0.0a13 → cornflow-2.0.0a14/cornflow.egg-info}/PKG-INFO +2 -2
  44. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow.egg-info/SOURCES.txt +1 -0
  45. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow.egg-info/requires.txt +1 -1
  46. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/requirements.txt +1 -1
  47. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/setup.py +1 -1
  48. cornflow-2.0.0a13/cornflow/cli/service.py +0 -284
  49. cornflow-2.0.0a13/cornflow/cli/tools/endpoint_tools.py +0 -288
  50. cornflow-2.0.0a13/cornflow/cli/tools/models_tools.py +0 -134
  51. cornflow-2.0.0a13/cornflow/cli/tools/schema_generator.py +0 -187
  52. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/MANIFEST.in +0 -0
  53. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/README.rst +0 -0
  54. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/__init__.py +0 -0
  55. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/airflow_local_settings.py +0 -0
  56. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/plugins/XCom/__init__.py +0 -0
  57. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/plugins/XCom/gce_xcom_backend.py +0 -0
  58. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/plugins/__init__.py +0 -0
  59. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/airflow_config/webserver_ldap.py +0 -0
  60. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/__init__.py +0 -0
  61. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/arguments.py +0 -0
  62. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/tools/__init__.py +0 -0
  63. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/tools/tools.py +0 -0
  64. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/cli/utils.py +0 -0
  65. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/__init__.py +0 -0
  66. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/access.py +0 -0
  67. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/actions.py +0 -0
  68. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/cleanup.py +0 -0
  69. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/permissions.py +0 -0
  70. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/roles.py +0 -0
  71. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/commands/views.py +0 -0
  72. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/__init__.py +0 -0
  73. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/action.py +0 -0
  74. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/alarms.py +0 -0
  75. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/apiview.py +0 -0
  76. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/case.py +0 -0
  77. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/licenses.py +0 -0
  78. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/login.py +0 -0
  79. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/main_alarms.py +0 -0
  80. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/permission.py +0 -0
  81. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/roles.py +0 -0
  82. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/schemas.py +0 -0
  83. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/signup.py +0 -0
  84. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/tables.py +0 -0
  85. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/token.py +0 -0
  86. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/user.py +0 -0
  87. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/endpoints/user_role.py +0 -0
  88. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/gunicorn.py +0 -0
  89. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/README +0 -0
  90. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/alembic.ini +0 -0
  91. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/env.py +0 -0
  92. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/script.py.mako +0 -0
  93. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/00757b557b02_.py +0 -0
  94. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/1af47a419bbd_.py +0 -0
  95. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/4aac5e0c6e66_.py +0 -0
  96. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/7c3ea5ab5501_.py +0 -0
  97. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/991b98e24225_.py +0 -0
  98. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/999b98e24225.py +0 -0
  99. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/a472b5ad50b7_.py +0 -0
  100. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/c2db9409cb5f_.py +0 -0
  101. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/c8a6c762e818_.py +0 -0
  102. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/ca449af8034c_.py +0 -0
  103. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/d0e0700dcd8e_.py +0 -0
  104. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/d1b5be1f0549_.py +0 -0
  105. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/e1a50dae1ac9_.py +0 -0
  106. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/e937a5234ce4_.py +0 -0
  107. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/ebdd955fcc5e_.py +0 -0
  108. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/migrations/versions/f3bee20314a2_.py +0 -0
  109. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/__init__.py +0 -0
  110. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/action.py +0 -0
  111. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/alarms.py +0 -0
  112. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/base_data_model.py +0 -0
  113. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/case.py +0 -0
  114. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/dag.py +0 -0
  115. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/dag_permissions.py +0 -0
  116. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/execution.py +0 -0
  117. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/instance.py +0 -0
  118. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/main_alarms.py +0 -0
  119. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/meta_models.py +0 -0
  120. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/permissions.py +0 -0
  121. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/role.py +0 -0
  122. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/user.py +0 -0
  123. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/user_role.py +0 -0
  124. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/models/view.py +0 -0
  125. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/orchestrator_constants.py +0 -0
  126. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/__init__.py +0 -0
  127. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/action.py +0 -0
  128. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/alarms.py +0 -0
  129. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/case.py +0 -0
  130. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/common.py +0 -0
  131. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/dag.py +0 -0
  132. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/example_data.py +0 -0
  133. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/execution.py +0 -0
  134. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/health.py +0 -0
  135. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/instance.py +0 -0
  136. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/main_alarms.py +0 -0
  137. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/model_json.py +0 -0
  138. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/patch.py +0 -0
  139. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/permissions.py +0 -0
  140. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/query.py +0 -0
  141. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/role.py +0 -0
  142. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/schemas.py +0 -0
  143. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/solution_log.py +0 -0
  144. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/tables.py +0 -0
  145. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/user.py +0 -0
  146. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/user_role.py +0 -0
  147. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/schemas/view.py +0 -0
  148. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/__init__.py +0 -0
  149. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/authentication/__init__.py +0 -0
  150. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/authentication/decorators.py +0 -0
  151. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/authentication/ldap.py +0 -0
  152. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/compress.py +0 -0
  153. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/email.py +0 -0
  154. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/licenses.py +0 -0
  155. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/log_config.py +0 -0
  156. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/query_tools.py +0 -0
  157. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/shared/utils.py +0 -0
  158. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/__init__.py +0 -0
  159. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/const.py +0 -0
  160. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/custom_liveServer.py +0 -0
  161. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/integration/__init__.py +0 -0
  162. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/integration/test_commands.py +0 -0
  163. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/integration/test_cornflowclient.py +0 -0
  164. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/ldap/__init__.py +0 -0
  165. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/ldap/test_ldap_authentication.py +0 -0
  166. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/__init__.py +0 -0
  167. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_actions.py +0 -0
  168. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_apiview.py +0 -0
  169. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_application.py +0 -0
  170. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_cli.py +0 -0
  171. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_commands.py +0 -0
  172. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_dags.py +0 -0
  173. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_data_checks.py +0 -0
  174. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_example_data.py +0 -0
  175. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_generate_from_schema.py +0 -0
  176. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_health.py +0 -0
  177. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_instances.py +0 -0
  178. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_instances_file.py +0 -0
  179. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_licenses.py +0 -0
  180. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_main_alarms.py +0 -0
  181. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_permissions.py +0 -0
  182. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_roles.py +0 -0
  183. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_schema_from_models.py +0 -0
  184. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_schemas.py +0 -0
  185. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_sign_up.py +0 -0
  186. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_token.py +0 -0
  187. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow/tests/unit/test_users.py +0 -0
  188. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow.egg-info/dependency_links.txt +0 -0
  189. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow.egg-info/entry_points.txt +0 -0
  190. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/cornflow.egg-info/top_level.txt +0 -0
  191. {cornflow-2.0.0a13 → cornflow-2.0.0a14}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cornflow
3
- Version: 2.0.0a13
3
+ Version: 2.0.0a14
4
4
  Summary: cornflow is an open source multi-solver optimization server with a REST API built using flask.
5
5
  Home-page: https://github.com/baobabsoluciones/cornflow
6
6
  Author: baobab soluciones
@@ -14,7 +14,7 @@ Requires-Dist: alembic==1.9.2
14
14
  Requires-Dist: apispec<=6.3.0
15
15
  Requires-Dist: cachetools==5.3.3
16
16
  Requires-Dist: click<=8.1.7
17
- Requires-Dist: cornflow-client==2.0.0a13
17
+ Requires-Dist: cornflow-client==2.0.0a14
18
18
  Requires-Dist: cryptography<=44.0.1
19
19
  Requires-Dist: databricks-sdk==0.29.0
20
20
  Requires-Dist: disposable-email-domains>=0.0.86
@@ -51,6 +51,8 @@ def create_app(env_name="development", dataconn=None):
51
51
  """
52
52
  dictConfig(log_config(app_config[env_name].LOG_LEVEL))
53
53
 
54
+ # Note: Explicit CSRF protection is not configured as the application uses
55
+ # JWT for authentication via headers, mitigating standard CSRF vulnerabilities.
54
56
  app = Flask(__name__)
55
57
  app.json.sort_keys = False
56
58
  app.logger.setLevel(app_config[env_name].LOG_LEVEL)
@@ -103,7 +105,7 @@ def create_app(env_name="development", dataconn=None):
103
105
  else:
104
106
  raise ConfigurationError(
105
107
  error="Invalid authentication type",
106
- log_txt="Error while configuring authentication. The authentication type is not valid."
108
+ log_txt="Error while configuring authentication. The authentication type is not valid.",
107
109
  )
108
110
 
109
111
  initialize_errorhandlers(app)
@@ -17,6 +17,10 @@ from cornflow.cli.views import views
17
17
 
18
18
  @click.group(name="cornflow", help="Commands in the cornflow cli")
19
19
  def cli():
20
+ """
21
+ This method is empty but it serves as the building block
22
+ for the rest of the commands
23
+ """
20
24
  pass
21
25
 
22
26
 
@@ -7,6 +7,10 @@ from .arguments import verbose
7
7
 
8
8
  @click.group(name="actions", help="Commands to manage the actions")
9
9
  def actions():
10
+ """
11
+ This method is empty but it serves as the building block
12
+ for the rest of the commands
13
+ """
10
14
  pass
11
15
 
12
16
 
@@ -7,6 +7,10 @@ from .arguments import path
7
7
 
8
8
  @click.group(name="config", help="Commands to manage the configuration variables")
9
9
  def config():
10
+ """
11
+ This method is empty but it serves as the building block
12
+ for the rest of the commands
13
+ """
10
14
  pass
11
15
 
12
16
 
@@ -3,6 +3,7 @@ import os.path
3
3
 
4
4
  import click
5
5
  from cornflow.shared import db
6
+ from cornflow.shared.const import MIGRATIONS_DEFAULT_PATH
6
7
  from flask_migrate import Migrate, migrate, upgrade, downgrade, init
7
8
 
8
9
  from .utils import get_app
@@ -10,6 +11,10 @@ from .utils import get_app
10
11
 
11
12
  @click.group(name="migrations", help="Commands to manage the migrations")
12
13
  def migrations():
14
+ """
15
+ This method is empty but it serves as the building block
16
+ for the rest of the commands
17
+ """
13
18
  pass
14
19
 
15
20
 
@@ -18,12 +23,12 @@ def migrate_migrations():
18
23
  app = get_app()
19
24
  external = int(os.getenv("EXTERNAL_APP", 0))
20
25
  if external == 0:
21
- path = "./cornflow/migrations"
26
+ path = MIGRATIONS_DEFAULT_PATH
22
27
  else:
23
28
  path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
24
29
 
25
30
  with app.app_context():
26
- migration_client = Migrate(app=app, db=db, directory=path)
31
+ Migrate(app=app, db=db, directory=path)
27
32
  migrate()
28
33
 
29
34
 
@@ -35,12 +40,12 @@ def upgrade_migrations(revision="head"):
35
40
  app = get_app()
36
41
  external = int(os.getenv("EXTERNAL_APP", 0))
37
42
  if external == 0:
38
- path = "./cornflow/migrations"
43
+ path = MIGRATIONS_DEFAULT_PATH
39
44
  else:
40
45
  path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
41
46
 
42
47
  with app.app_context():
43
- migration_client = Migrate(app=app, db=db, directory=path)
48
+ Migrate(app=app, db=db, directory=path)
44
49
  upgrade(revision=revision)
45
50
 
46
51
 
@@ -52,12 +57,12 @@ def downgrade_migrations(revision="-1"):
52
57
  app = get_app()
53
58
  external = int(os.getenv("EXTERNAL_APP", 0))
54
59
  if external == 0:
55
- path = "./cornflow/migrations"
60
+ path = MIGRATIONS_DEFAULT_PATH
56
61
  else:
57
62
  path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
58
63
 
59
64
  with app.app_context():
60
- migration_client = Migrate(app=app, db=db, directory=path)
65
+ Migrate(app=app, db=db, directory=path)
61
66
  downgrade(revision=revision)
62
67
 
63
68
 
@@ -69,10 +74,10 @@ def init_migrations():
69
74
  app = get_app()
70
75
  external = int(os.getenv("EXTERNAL_APP", 0))
71
76
  if external == 0:
72
- path = "./cornflow/migrations"
77
+ path = MIGRATIONS_DEFAULT_PATH
73
78
  else:
74
79
  path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
75
80
 
76
81
  with app.app_context():
77
- migration_client = Migrate(app=app, db=db, directory=path)
82
+ Migrate(app=app, db=db, directory=path)
78
83
  init()
@@ -11,6 +11,10 @@ from .utils import get_app
11
11
 
12
12
  @click.group(name="permissions", help="Commands to manage the permissions")
13
13
  def permissions():
14
+ """
15
+ This method is empty but it serves as the building block
16
+ for the rest of the commands
17
+ """
14
18
  pass
15
19
 
16
20
 
@@ -6,6 +6,10 @@ from .utils import get_app
6
6
 
7
7
  @click.group(name="roles", help="Commands to manage the roles")
8
8
  def roles():
9
+ """
10
+ This method is empty but it serves as the building block
11
+ for the rest of the commands
12
+ """
9
13
  pass
10
14
 
11
15
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  File that implements the generate from schema cli command
3
3
  """
4
+
4
5
  import click
5
6
  from .tools.api_generator import APIGenerator
6
7
  from .tools.schema_generator import SchemaGenerator
@@ -20,6 +21,10 @@ METHOD_OPTIONS = [
20
21
 
21
22
  @click.group(name="schemas", help="Commands to manage the schemas")
22
23
  def schemas():
24
+ """
25
+ This method is empty but it serves as the building block
26
+ for the rest of the commands
27
+ """
23
28
  pass
24
29
 
25
30
 
@@ -0,0 +1,397 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ import time
5
+ from logging import error
6
+
7
+
8
+ import click
9
+ from .utils import get_db_conn
10
+ import cornflow
11
+ from cornflow.app import create_app
12
+ from cornflow.commands import (
13
+ access_init_command,
14
+ create_user_with_role,
15
+ register_deployed_dags_command,
16
+ register_dag_permissions_command,
17
+ update_schemas_command,
18
+ update_dag_registry_command,
19
+ )
20
+ from cornflow.shared.const import (
21
+ AUTH_DB,
22
+ AUTH_LDAP,
23
+ AUTH_OID,
24
+ ADMIN_ROLE,
25
+ SERVICE_ROLE,
26
+ PLANNER_ROLE,
27
+ DATABRICKS_BACKEND,
28
+ AIRFLOW_BACKEND,
29
+ )
30
+ from cornflow.shared import db
31
+ from cryptography.fernet import Fernet
32
+ from flask_migrate import Migrate, upgrade
33
+
34
+ MAIN_WD = "/usr/src/app"
35
+
36
+
37
+ @click.group(name="service", help="Commands to run the cornflow service")
38
+ def service():
39
+ """
40
+ This method is empty but it serves as the building block
41
+ for the rest of the commands
42
+ """
43
+ pass
44
+
45
+
46
+ @service.command(name="init", help="Initialize the service")
47
+ def init_cornflow_service():
48
+ click.echo("Starting the service")
49
+ os.chdir(MAIN_WD)
50
+
51
+ config = _setup_environment_variables()
52
+ _configure_logging(config["cornflow_logging"])
53
+
54
+ external_application = config["external_application"]
55
+ environment = config["environment"]
56
+ cornflow_db_conn = config["cornflow_db_conn"]
57
+ external_app_module = config["external_app_module"]
58
+
59
+ app = None # Initialize app to None
60
+
61
+ if external_application == 0:
62
+ click.echo("Initializing standard Cornflow application")
63
+ app = create_app(environment, cornflow_db_conn)
64
+ with app.app_context():
65
+ _initialize_database(app)
66
+ _create_initial_users(
67
+ config["auth"],
68
+ config["cornflow_admin_user"],
69
+ config["cornflow_admin_email"],
70
+ config["cornflow_admin_pwd"],
71
+ config["cornflow_service_user"],
72
+ config["cornflow_service_email"],
73
+ config["cornflow_service_pwd"],
74
+ )
75
+ _sync_with_airflow(
76
+ config["airflow_url"],
77
+ config["airflow_user"],
78
+ config["airflow_pwd"],
79
+ config["open_deployment"],
80
+ external_app=False,
81
+ )
82
+ _start_application(external_application, environment)
83
+
84
+ elif external_application == 1:
85
+ click.echo(f"Initializing Cornflow with external app: {external_app_module}")
86
+ if not external_app_module:
87
+ sys.exit("FATAL: EXTERNAL_APP is 1 but EXTERNAL_APP_MODULE is not set.")
88
+
89
+ _setup_external_app()
90
+ from importlib import import_module
91
+
92
+ external_app_lib = import_module(external_app_module)
93
+ app = external_app_lib.create_wsgi_app(environment, cornflow_db_conn)
94
+
95
+ with app.app_context():
96
+ _initialize_database(app, external_app_module)
97
+ _create_initial_users(
98
+ config["auth"],
99
+ config["cornflow_admin_user"],
100
+ config["cornflow_admin_email"],
101
+ config["cornflow_admin_pwd"],
102
+ config["cornflow_service_user"],
103
+ config["cornflow_service_email"],
104
+ config["cornflow_service_pwd"],
105
+ )
106
+ _sync_with_airflow(
107
+ config["airflow_url"],
108
+ config["airflow_user"],
109
+ config["airflow_pwd"],
110
+ config["open_deployment"],
111
+ external_app=True,
112
+ )
113
+ _start_application(external_application, environment, external_app_module)
114
+
115
+ else:
116
+ # This case should ideally be caught earlier or handled differently
117
+ sys.exit(f"FATAL: Invalid EXTERNAL_APP value: {external_application}")
118
+
119
+
120
+ def _setup_environment_variables():
121
+ """Reads environment variables, sets defaults, and returns config values."""
122
+ environment = os.getenv("FLASK_ENV", "development")
123
+ os.environ["FLASK_ENV"] = environment
124
+
125
+ ###################################
126
+ # Global defaults and back-compat #
127
+ ###################################
128
+ # cornflow backend selection
129
+ cornflow_backend = os.getenv("CORNFLOW_BACKEND", str(AIRFLOW_BACKEND))
130
+ os.environ["CORNFLOW_BACKEND"] = cornflow_backend
131
+ cornflow_backend = int(cornflow_backend)
132
+ # Airflow global default conn
133
+ if cornflow_backend == AIRFLOW_BACKEND:
134
+ airflow_user = os.getenv("AIRFLOW_USER", "admin")
135
+ airflow_pwd = os.getenv("AIRFLOW_PWD", "admin")
136
+ airflow_url = os.getenv("AIRFLOW_URL", "http://webserver:8080")
137
+ os.environ["AIRFLOW_USER"] = airflow_user
138
+ os.environ["AIRFLOW_PWD"] = airflow_pwd
139
+ os.environ["AIRFLOW_URL"] = airflow_url
140
+ elif cornflow_backend == DATABRICKS_BACKEND:
141
+ databricks_url = os.getenv("DATABRICKS_HOST")
142
+ databricks_auth_secret = os.getenv("DATABRICKS_CLIENT_SECRET")
143
+ databricks_token_endpoint = os.getenv("DATABRICKS_TOKEN_ENDPOINT")
144
+ databricks_ep_clusters = os.getenv("DATABRICKS_EP_CLUSTERS")
145
+ databricks_client_id = os.getenv("DATABRICKS_CLIENT_ID")
146
+ os.environ["DATABRICKS_HOST"] = databricks_url
147
+ os.environ["DATABRICKS_CLIENT_SECRET"] = databricks_auth_secret
148
+ os.environ["DATABRICKS_TOKEN_ENDPOINT"] = databricks_token_endpoint
149
+ os.environ["DATABRICKS_EP_CLUSTERS"] = databricks_ep_clusters
150
+ os.environ["DATABRICKS_CLIENT_ID"] = databricks_client_id
151
+ else:
152
+ raise Exception("Selected backend not among valid options")
153
+ # Cornflow app config
154
+ os.environ.setdefault("cornflow_url", "http://cornflow:5000")
155
+ os.environ["FLASK_APP"] = "cornflow.app"
156
+ os.environ["SECRET_KEY"] = os.getenv("FERNET_KEY", Fernet.generate_key().decode())
157
+
158
+ # Cornflow db defaults
159
+ os.environ["DEFAULT_POSTGRES"] = "1"
160
+ cornflow_db_conn = get_db_conn()
161
+ os.environ["DATABASE_URL"] = cornflow_db_conn
162
+
163
+ # Platform auth config and service users
164
+ auth = int(os.getenv("AUTH_TYPE", AUTH_DB))
165
+ cornflow_admin_user = os.getenv("CORNFLOW_ADMIN_USER", "cornflow_admin")
166
+ cornflow_admin_email = os.getenv(
167
+ "CORNFLOW_ADMIN_EMAIL", "cornflow_admin@cornflow.com"
168
+ )
169
+ cornflow_admin_pwd = os.getenv("CORNFLOW_ADMIN_PWD", "Cornflow_admin1234")
170
+ cornflow_service_user = os.getenv("CORNFLOW_SERVICE_USER", "service_user")
171
+ cornflow_service_email = os.getenv(
172
+ "CORNFLOW_SERVICE_EMAIL", "service_user@cornflow.com"
173
+ )
174
+ cornflow_service_pwd = os.getenv("CORNFLOW_SERVICE_PWD", "Service_user1234")
175
+
176
+ # Cornflow logging and deployment config
177
+ cornflow_logging = os.getenv("CORNFLOW_LOGGING", "console")
178
+ os.environ["CORNFLOW_LOGGING"] = cornflow_logging
179
+ open_deployment = os.getenv("OPEN_DEPLOYMENT", 1)
180
+ os.environ["OPEN_DEPLOYMENT"] = str(open_deployment)
181
+ signup_activated = os.getenv("SIGNUP_ACTIVATED", 1)
182
+ os.environ["SIGNUP_ACTIVATED"] = str(signup_activated)
183
+ user_access_all_objects = os.getenv("USER_ACCESS_ALL_OBJECTS", 0)
184
+ os.environ["USER_ACCESS_ALL_OBJECTS"] = str(user_access_all_objects)
185
+ default_role = int(os.getenv("DEFAULT_ROLE", PLANNER_ROLE))
186
+ os.environ["DEFAULT_ROLE"] = str(default_role)
187
+
188
+ # Check LDAP parameters for active directory and show message
189
+ if auth == AUTH_LDAP:
190
+ click.echo(
191
+ "WARNING: Cornflow will be deployed with LDAP Authorization. "
192
+ "Please review your ldap auth configuration."
193
+ )
194
+
195
+ # check database param from docker env
196
+ if cornflow_db_conn is None:
197
+ sys.exit("FATAL: you need to provide a postgres database for Cornflow")
198
+
199
+ external_application = int(os.getenv("EXTERNAL_APP", 0))
200
+ external_app_module = os.getenv("EXTERNAL_APP_MODULE")
201
+ if cornflow_backend == AIRFLOW_BACKEND:
202
+ return {
203
+ "environment": environment,
204
+ "auth": auth,
205
+ "airflow_user": airflow_user,
206
+ "airflow_pwd": airflow_pwd,
207
+ "airflow_url": airflow_url,
208
+ "cornflow_db_conn": cornflow_db_conn,
209
+ "cornflow_admin_user": cornflow_admin_user,
210
+ "cornflow_admin_email": cornflow_admin_email,
211
+ "cornflow_admin_pwd": cornflow_admin_pwd,
212
+ "cornflow_service_user": cornflow_service_user,
213
+ "cornflow_service_email": cornflow_service_email,
214
+ "cornflow_service_pwd": cornflow_service_pwd,
215
+ "cornflow_logging": cornflow_logging,
216
+ "open_deployment": open_deployment,
217
+ "external_application": external_application,
218
+ "external_app_module": external_app_module,
219
+ }
220
+ elif cornflow_backend == DATABRICKS_BACKEND:
221
+ return {
222
+ "environment": environment,
223
+ "auth": auth,
224
+ "databricks_url": databricks_url,
225
+ "databricks_auth_secret": databricks_auth_secret,
226
+ "databricks_token_endpoint": databricks_token_endpoint,
227
+ "databricks_ep_clusters": databricks_ep_clusters,
228
+ "databricks_client_id": databricks_client_id,
229
+ "cornflow_db_conn": cornflow_db_conn,
230
+ "cornflow_admin_user": cornflow_admin_user,
231
+ "cornflow_admin_email": cornflow_admin_email,
232
+ "cornflow_admin_pwd": cornflow_admin_pwd,
233
+ "cornflow_service_user": cornflow_service_user,
234
+ "cornflow_service_email": cornflow_service_email,
235
+ "cornflow_service_pwd": cornflow_service_pwd,
236
+ "cornflow_logging": cornflow_logging,
237
+ "open_deployment": open_deployment,
238
+ "external_application": external_application,
239
+ "external_app_module": external_app_module,
240
+ }
241
+ else:
242
+ raise Exception("Selected backend not among valid options")
243
+
244
+
245
+ def _configure_logging(cornflow_logging):
246
+ """Configures log rotation if logging to file."""
247
+ if cornflow_logging == "file":
248
+ try:
249
+ conf = f"""/usr/src/app/log/*.log {{
250
+ rotate 30
251
+ daily
252
+ compress
253
+ size 20M
254
+ postrotate
255
+ kill -HUP $(cat {MAIN_WD}/gunicorn.pid)
256
+ endscript}}"""
257
+ logrotate = subprocess.run(
258
+ f"cat > /etc/logrotate.d/cornflow <<EOF\n {conf} \nEOF",
259
+ shell=True,
260
+ capture_output=True,
261
+ text=True,
262
+ )
263
+ if logrotate.returncode != 0:
264
+ error(f"Error configuring logrotate: {logrotate.stderr}")
265
+ else:
266
+ print(logrotate.stdout)
267
+ except Exception as e:
268
+ error(f"Exception during logrotate configuration: {e}")
269
+
270
+
271
+ def _initialize_database(app, external_app_module=None):
272
+ """Initializes the database and runs migrations."""
273
+ with app.app_context():
274
+ if external_app_module:
275
+ from importlib import import_module
276
+
277
+ external_app_lib = import_module(external_app_module)
278
+ migrations_path = f"{os.path.dirname(external_app_lib.__file__)}/migrations"
279
+ else:
280
+ migrations_path = f"{os.path.dirname(cornflow.__file__)}/migrations"
281
+
282
+ Migrate(app=app, db=db, directory=migrations_path)
283
+ upgrade()
284
+ access_init_command(verbose=False)
285
+
286
+
287
+ def _create_initial_users(
288
+ auth,
289
+ admin_user,
290
+ admin_email,
291
+ admin_pwd,
292
+ service_user,
293
+ service_email,
294
+ service_pwd,
295
+ ):
296
+ """Creates the initial admin and service users if using DB or OID auth."""
297
+ if auth == AUTH_DB or auth == AUTH_OID:
298
+ # create cornflow admin user
299
+ create_user_with_role(
300
+ admin_user,
301
+ admin_email,
302
+ admin_pwd,
303
+ "admin",
304
+ ADMIN_ROLE,
305
+ verbose=True,
306
+ )
307
+ # create cornflow service user
308
+ create_user_with_role(
309
+ service_user,
310
+ service_email,
311
+ service_pwd,
312
+ "serviceuser",
313
+ SERVICE_ROLE,
314
+ verbose=True,
315
+ )
316
+
317
+
318
+ def _sync_with_airflow(
319
+ airflow_url, airflow_user, airflow_pwd, open_deployment, external_app=False
320
+ ):
321
+ """Syncs DAGs, permissions, and schemas with Airflow."""
322
+ register_deployed_dags_command(airflow_url, airflow_user, airflow_pwd, verbose=True)
323
+ register_dag_permissions_command(open_deployment, verbose=True)
324
+ update_schemas_command(airflow_url, airflow_user, airflow_pwd, verbose=True)
325
+ if external_app:
326
+ update_dag_registry_command(
327
+ airflow_url, airflow_user, airflow_pwd, verbose=True
328
+ )
329
+
330
+
331
+ def _setup_external_app():
332
+ """Performs setup steps specific to external applications."""
333
+ os.chdir(MAIN_WD)
334
+ if _register_key():
335
+ prefix = "CUSTOM_SSH_"
336
+ env_variables = {
337
+ key: value for key, value in os.environ.items() if key.startswith(prefix)
338
+ }
339
+ for _, value in env_variables.items():
340
+ _register_ssh_host(value)
341
+
342
+ # Install requirements for the external app
343
+ pip_install_cmd = "$(command -v pip) install --user -r requirements.txt"
344
+ click.echo(f"Running: {pip_install_cmd}")
345
+ result = subprocess.run(pip_install_cmd, shell=True, capture_output=True, text=True)
346
+ if result.returncode != 0:
347
+ error(f"Error installing requirements: {result.stderr}")
348
+ else:
349
+ print(result.stdout)
350
+ time.sleep(5) # Consider if this sleep is truly necessary
351
+ sys.path.append(MAIN_WD)
352
+
353
+
354
+ def _start_application(external_application, environment, external_app_module=None):
355
+ """Starts the Gunicorn server."""
356
+ if external_application == 0:
357
+ os.environ["GUNICORN_WORKING_DIR"] = MAIN_WD
358
+ gunicorn_cmd = (
359
+ "/usr/local/bin/gunicorn -c python:cornflow.gunicorn "
360
+ f"\"cornflow.app:create_app('{environment}')\""
361
+ )
362
+ elif external_application == 1:
363
+ os.environ["GUNICORN_WORKING_DIR"] = MAIN_WD
364
+ if not external_app_module:
365
+ raise ValueError(
366
+ "EXTERNAL_APP_MODULE must be set for external applications"
367
+ )
368
+ gunicorn_cmd = (
369
+ "/usr/local/bin/gunicorn -c python:cornflow.gunicorn "
370
+ f"\"{external_app_module}:create_wsgi_app('{environment}')\""
371
+ )
372
+ else:
373
+ raise ValueError(f"Invalid EXTERNAL_APP value: {external_application}")
374
+
375
+ click.echo(f"Starting application with Gunicorn: {gunicorn_cmd}")
376
+ os.system(gunicorn_cmd)
377
+
378
+
379
+ def _register_ssh_host(host):
380
+ if host is not None:
381
+ add_host = f"ssh-keyscan {host} >> {MAIN_WD}/.ssh/known_hosts"
382
+ config_ssh_host = f"echo Host {host} >> {MAIN_WD}/.ssh/config"
383
+ config_ssh_key = (
384
+ 'echo " IdentityFile {MAIN_WD}/.ssh/id_rsa" >> {MAIN_WD}/.ssh/config'
385
+ )
386
+ os.system(add_host)
387
+ os.system(config_ssh_host)
388
+ os.system(config_ssh_key)
389
+
390
+
391
+ def _register_key():
392
+ if os.path.isfile(f"{MAIN_WD}/.ssh/id_rsa"):
393
+ add_key = f"chmod 0600 {MAIN_WD}/.ssh/id_rsa && ssh-add {MAIN_WD}/.ssh/id_rsa"
394
+ os.system(add_key)
395
+ return True
396
+ else:
397
+ return False
@@ -1,6 +1,7 @@
1
1
  """
2
2
  This file has the class that creates the new API
3
3
  """
4
+
4
5
  import json
5
6
  import os
6
7
  import re
@@ -10,6 +11,8 @@ from .models_tools import ModelGenerator, model_shared_imports
10
11
  from .schemas_tools import SchemaGenerator, schemas_imports
11
12
  from .tools import generate_class_def
12
13
 
14
+ INIT_FILE = "__init__.py"
15
+
13
16
 
14
17
  class APIGenerator:
15
18
  """
@@ -52,7 +55,7 @@ class APIGenerator:
52
55
  self.endpoint_path = os.path.join(self.output_path, "endpoints")
53
56
  self.schema_path = os.path.join(self.output_path, "schemas")
54
57
  self.init_resources = []
55
- self.init_file = os.path.join(self.endpoint_path, "__init__.py")
58
+ self.init_file = os.path.join(self.endpoint_path, INIT_FILE)
56
59
 
57
60
  def import_schema(self) -> dict:
58
61
  """
@@ -77,23 +80,23 @@ class APIGenerator:
77
80
  if not os.path.isdir(self.model_path):
78
81
  os.mkdir(self.model_path)
79
82
 
80
- init_path = os.path.join(self.model_path, "__init__.py")
83
+ init_path = os.path.join(self.model_path, INIT_FILE)
81
84
  with open(init_path, "w") as file:
82
- file.write(f'"""\nThis file exposes the models\n"""\n')
85
+ file.write("\nThis file exposes the models\n\n")
83
86
 
84
87
  if not os.path.isdir(self.endpoint_path):
85
88
  os.mkdir(self.endpoint_path)
86
89
 
87
- init_path = os.path.join(self.endpoint_path, "__init__.py")
90
+ init_path = os.path.join(self.endpoint_path, INIT_FILE)
88
91
  with open(init_path, "w") as file:
89
- file.write(f'"""\nThis file exposes the endpoints\n"""\n')
92
+ file.write("\nThis file exposes the endpoints\n\n")
90
93
 
91
94
  if not os.path.isdir(self.schema_path):
92
95
  os.mkdir(self.schema_path)
93
96
 
94
- init_path = os.path.join(self.schema_path, "__init__.py")
97
+ init_path = os.path.join(self.schema_path, INIT_FILE)
95
98
  with open(init_path, "w") as file:
96
- file.write(f'"""\nThis file exposes the schemas\n"""\n')
99
+ file.write("\nThis file exposes the schemas\n\n")
97
100
 
98
101
  def main(self):
99
102
  """
@@ -151,7 +154,7 @@ class APIGenerator:
151
154
  fd.write(mg.generate_model_repr_str())
152
155
  fd.write("\n")
153
156
 
154
- init_file = os.path.join(self.model_path, "__init__.py")
157
+ init_file = os.path.join(self.model_path, INIT_FILE)
155
158
 
156
159
  with open(init_file, "a") as file:
157
160
  file.write(f"from .{self.prefix}{table_name} import {class_name}\n")
@@ -207,7 +210,7 @@ class APIGenerator:
207
210
  fd.write(generate_class_def(class_name_one, parents_class))
208
211
  fd.write(sg.generate_schema())
209
212
 
210
- init_file = os.path.join(self.schema_path, "__init__.py")
213
+ init_file = os.path.join(self.schema_path, INIT_FILE)
211
214
  with open(init_file, "a") as file:
212
215
  file.write(
213
216
  f"from .{self.prefix}{table_name} import {class_name_one}, "
@@ -432,7 +435,7 @@ class APIGenerator:
432
435
  :return: str: the type in format "<type:idx>"
433
436
  """
434
437
  schema_table = self.schema["properties"][table_name]["items"]["properties"]
435
- id_type=None
438
+ id_type = None
436
439
  if "id" in schema_table.keys():
437
440
  id_type = schema_table["id"]["type"]
438
441
  if id_type == "string" or isinstance(id_type, list):