UncountablePythonSDK 0.0.69__tar.gz → 0.0.71__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.

Potentially problematic release.


This version of UncountablePythonSDK might be problematic. Click here for more details.

Files changed (295) hide show
  1. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/PKG-INFO +3 -1
  2. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/UncountablePythonSDK.egg-info/PKG-INFO +3 -1
  3. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/UncountablePythonSDK.egg-info/SOURCES.txt +21 -1
  4. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/UncountablePythonSDK.egg-info/requires.txt +2 -0
  5. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/integration-server/jobs/materials_auto/example_cron.py +2 -2
  6. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pyproject.toml +3 -1
  7. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/environment.py +5 -1
  8. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/cli.py +1 -0
  9. uncountablepythonsdk-0.0.71/uncountable/integration/cron.py +29 -0
  10. uncountablepythonsdk-0.0.71/uncountable/integration/db/connect.py +18 -0
  11. uncountablepythonsdk-0.0.71/uncountable/integration/db/session.py +25 -0
  12. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/entrypoint.py +6 -6
  13. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/executors/generic_upload_executor.py +5 -1
  14. uncountablepythonsdk-0.0.71/uncountable/integration/job.py +87 -0
  15. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/__init__.py +24 -0
  16. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/command_client.py +68 -0
  17. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/command_server.py +64 -0
  18. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
  19. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/protocol/command_server.proto +22 -0
  20. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +40 -0
  21. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +38 -0
  22. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +129 -0
  23. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/command_server/types.py +52 -0
  24. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/datastore/__init__.py +3 -0
  25. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/datastore/datastore_sqlite.py +93 -0
  26. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/datastore/interface.py +19 -0
  27. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/datastore/model.py +17 -0
  28. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/job_scheduler.py +128 -0
  29. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/queue_runner.py +26 -0
  30. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/types.py +7 -0
  31. uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/worker.py +109 -0
  32. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/scan_profiles.py +2 -0
  33. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/scheduler.py +40 -3
  34. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/webhook_server/entrypoint.py +27 -31
  35. uncountablepythonsdk-0.0.71/uncountable/py.typed +0 -0
  36. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/__init__.py +2 -0
  37. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_recipes_data.py +1 -0
  38. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_outputs.py +2 -0
  39. uncountablepythonsdk-0.0.71/uncountable/types/queued_job.py +16 -0
  40. uncountablepythonsdk-0.0.71/uncountable/types/queued_job_t.py +107 -0
  41. uncountablepythonsdk-0.0.69/Dockerfile.testing +0 -19
  42. uncountablepythonsdk-0.0.69/uncountable/integration/cron.py +0 -45
  43. uncountablepythonsdk-0.0.69/uncountable/integration/db/connect.py +0 -8
  44. uncountablepythonsdk-0.0.69/uncountable/integration/job.py +0 -60
  45. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/.github/workflows/documentation.yml +0 -0
  46. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/.github/workflows/publish.yml +0 -0
  47. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/.gitignore +0 -0
  48. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/README.md +0 -0
  49. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
  50. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
  51. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/.gitignore +0 -0
  52. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/conf.py +0 -0
  53. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/index.md +0 -0
  54. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/justfile +0 -0
  55. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/quickstart.md +0 -0
  56. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/requirements.txt +0 -0
  57. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/android-chrome-192x192.png +0 -0
  58. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/android-chrome-512x512.png +0 -0
  59. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/apple-touch-icon.png +0 -0
  60. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/browserconfig.xml +0 -0
  61. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/favicon-16x16.png +0 -0
  62. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/favicon-32x32.png +0 -0
  63. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/manifest.json +0 -0
  64. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/mstile-150x150.png +0 -0
  65. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/favicons/safari-pinned-tab.svg +0 -0
  66. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/docs/static/logo_blue.png +0 -0
  67. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/async_batch.py +0 -0
  68. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/create_entity.py +0 -0
  69. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/edit_recipe_inputs.py +0 -0
  70. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/integration-server/jobs/materials_auto/profile.yaml +0 -0
  71. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/integration-server/pyproject.toml +0 -0
  72. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/invoke_uploader.py +0 -0
  73. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/set_recipe_metadata_file.py +0 -0
  74. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/set_recipe_output_file_sdk.py +0 -0
  75. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/examples/upload_files.py +0 -0
  76. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/__init__.py +0 -0
  77. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/argument_parser/__init__.py +0 -0
  78. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/argument_parser/_is_enum.py +0 -0
  79. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/argument_parser/_is_namedtuple.py +0 -0
  80. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/argument_parser/argument_parser.py +0 -0
  81. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/argument_parser/case_convert.py +0 -0
  82. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/__init__.py +0 -0
  83. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/_gdrive_session.py +0 -0
  84. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/_local_session.py +0 -0
  85. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/_s3_session.py +0 -0
  86. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/_sftp_session.py +0 -0
  87. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/file_type_utils.py +0 -0
  88. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/filesystem_utils/filesystem_session.py +0 -0
  89. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/py.typed +0 -0
  90. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/__init__.py +0 -0
  91. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/missing_sentry.py +0 -0
  92. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/opaque_key.py +0 -0
  93. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/serial_class.py +0 -0
  94. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/serial_union.py +0 -0
  95. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization/yaml.py +0 -0
  96. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization_util/__init__.py +0 -0
  97. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
  98. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization_util/convert_to_snakecase.py +0 -0
  99. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/serialization_util/serialization_helpers.py +0 -0
  100. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/strenum_compat/__init__.py +0 -0
  101. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/strenum_compat/strenum_compat.py +0 -0
  102. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/__init__.py +0 -0
  103. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/__main__.py +0 -0
  104. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/actions_registry/__init__.py +0 -0
  105. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/actions_registry/__main__.py +0 -0
  106. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/actions_registry/emit_typescript.py +0 -0
  107. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/builder.py +0 -0
  108. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/config.py +0 -0
  109. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_io_ts.py +0 -0
  110. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_open_api.py +0 -0
  111. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_open_api_util.py +0 -0
  112. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_python.py +0 -0
  113. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_typescript.py +0 -0
  114. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/emit_typescript_util.py +0 -0
  115. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/load_types.py +0 -0
  116. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/open_api_util.py +0 -0
  117. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/parts/base.py.prepart +0 -0
  118. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/parts/base.ts.prepart +0 -0
  119. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/test.py +0 -0
  120. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/type_info/__main__.py +0 -0
  121. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/type_info/emit_type_info.py +0 -0
  122. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/util.py +0 -0
  123. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/value_spec/__init__.py +0 -0
  124. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/value_spec/__main__.py +0 -0
  125. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/value_spec/convert_type.py +0 -0
  126. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/value_spec/emit_python.py +0 -0
  127. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/pkgs/type_spec/value_spec/types.py +0 -0
  128. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/setup.cfg +0 -0
  129. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/__init__.py +0 -0
  130. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/__init__.py +0 -0
  131. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/async_batch.py +0 -0
  132. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/client.py +0 -0
  133. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/file_upload.py +0 -0
  134. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/core/types.py +0 -0
  135. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/__init__.py +0 -0
  136. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/construct_client.py +0 -0
  137. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/db/__init__.py +0 -0
  138. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/executors/__init__.py +0 -0
  139. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/executors/executors.py +0 -0
  140. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/executors/script_executor.py +0 -0
  141. /uncountablepythonsdk-0.0.69/uncountable/py.typed → /uncountablepythonsdk-0.0.71/uncountable/integration/queue_runner/__init__.py +0 -0
  142. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/secret_retrieval/__init__.py +0 -0
  143. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/secret_retrieval/retrieve_secret.py +0 -0
  144. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/server.py +0 -0
  145. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/integration/telemetry.py +0 -0
  146. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/__init__.py +0 -0
  147. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/batch/__init__.py +0 -0
  148. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/batch/execute_batch.py +0 -0
  149. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/batch/execute_batch_load_async.py +0 -0
  150. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/chemical/__init__.py +0 -0
  151. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/chemical/convert_chemical_formats.py +0 -0
  152. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/__init__.py +0 -0
  153. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/create_entities.py +0 -0
  154. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/create_entity.py +0 -0
  155. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/get_entities_data.py +0 -0
  156. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/list_entities.py +0 -0
  157. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/lock_entity.py +0 -0
  158. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
  159. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/set_values.py +0 -0
  160. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/transition_entity_phase.py +0 -0
  161. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/entity/unlock_entity.py +0 -0
  162. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/equipment/__init__.py +0 -0
  163. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/equipment/associate_equipment_input.py +0 -0
  164. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/field_options/__init__.py +0 -0
  165. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/field_options/upsert_field_options.py +0 -0
  166. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/id_source/__init__.py +0 -0
  167. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/id_source/list_id_source.py +0 -0
  168. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/id_source/match_id_source.py +0 -0
  169. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/input_groups/__init__.py +0 -0
  170. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
  171. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/__init__.py +0 -0
  172. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/create_inputs.py +0 -0
  173. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/get_input_data.py +0 -0
  174. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/get_input_names.py +0 -0
  175. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
  176. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
  177. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/set_input_category.py +0 -0
  178. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/set_input_subcategories.py +0 -0
  179. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/inputs/set_intermediate_type.py +0 -0
  180. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/material_families/__init__.py +0 -0
  181. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/material_families/update_entity_material_families.py +0 -0
  182. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/outputs/__init__.py +0 -0
  183. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/outputs/get_output_data.py +0 -0
  184. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/outputs/get_output_names.py +0 -0
  185. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
  186. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/permissions/__init__.py +0 -0
  187. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/permissions/set_core_permissions.py +0 -0
  188. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/project/__init__.py +0 -0
  189. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/project/get_projects.py +0 -0
  190. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/project/get_projects_data.py +0 -0
  191. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipe_links/__init__.py +0 -0
  192. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipe_links/create_recipe_link.py +0 -0
  193. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipe_links/remove_recipe_link.py +0 -0
  194. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
  195. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
  196. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/__init__.py +0 -0
  197. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/add_recipe_to_project.py +0 -0
  198. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/archive_recipes.py +0 -0
  199. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/associate_recipe_as_input.py +0 -0
  200. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/associate_recipe_as_lot.py +0 -0
  201. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/clear_recipe_outputs.py +0 -0
  202. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/create_recipe.py +0 -0
  203. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/create_recipes.py +0 -0
  204. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/disassociate_recipe_as_input.py +0 -0
  205. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/edit_recipe_inputs.py +0 -0
  206. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_curve.py +0 -0
  207. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
  208. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
  209. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
  210. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
  211. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/lock_recipes.py +0 -0
  212. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/remove_recipe_from_project.py +0 -0
  213. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
  214. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_metadata.py +0 -0
  215. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_output_annotations.py +0 -0
  216. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_output_file.py +0 -0
  217. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/set_recipe_tags.py +0 -0
  218. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/unarchive_recipes.py +0 -0
  219. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/recipes/unlock_recipes.py +0 -0
  220. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/triggers/__init__.py +0 -0
  221. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/triggers/run_trigger.py +0 -0
  222. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/uploader/__init__.py +0 -0
  223. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/api/uploader/invoke_uploader.py +0 -0
  224. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/async_batch.py +0 -0
  225. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/async_batch_processor.py +0 -0
  226. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/async_batch_t.py +0 -0
  227. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/base.py +0 -0
  228. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/base_t.py +0 -0
  229. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/calculations.py +0 -0
  230. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/calculations_t.py +0 -0
  231. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/chemical_structure.py +0 -0
  232. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/chemical_structure_t.py +0 -0
  233. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/client_base.py +0 -0
  234. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/client_config.py +0 -0
  235. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/client_config_t.py +0 -0
  236. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/curves.py +0 -0
  237. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/curves_t.py +0 -0
  238. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/entity.py +0 -0
  239. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/entity_t.py +0 -0
  240. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/experiment_groups.py +0 -0
  241. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/experiment_groups_t.py +0 -0
  242. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/field_values.py +0 -0
  243. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/field_values_t.py +0 -0
  244. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/fields.py +0 -0
  245. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/fields_t.py +0 -0
  246. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/generic_upload.py +0 -0
  247. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/generic_upload_t.py +0 -0
  248. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/id_source.py +0 -0
  249. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/id_source_t.py +0 -0
  250. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/identifier.py +0 -0
  251. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/identifier_t.py +0 -0
  252. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/input_attributes.py +0 -0
  253. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/input_attributes_t.py +0 -0
  254. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/inputs.py +0 -0
  255. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/inputs_t.py +0 -0
  256. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/job_definition.py +0 -0
  257. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/job_definition_t.py +0 -0
  258. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/outputs.py +0 -0
  259. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/outputs_t.py +0 -0
  260. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/overrides.py +0 -0
  261. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/overrides_t.py +0 -0
  262. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/permissions.py +0 -0
  263. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/permissions_t.py +0 -0
  264. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/phases.py +0 -0
  265. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/phases_t.py +0 -0
  266. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/post_base.py +0 -0
  267. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/post_base_t.py +0 -0
  268. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_identifiers.py +0 -0
  269. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_identifiers_t.py +0 -0
  270. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_inputs.py +0 -0
  271. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_inputs_t.py +0 -0
  272. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_links.py +0 -0
  273. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_links_t.py +0 -0
  274. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_metadata.py +0 -0
  275. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_metadata_t.py +0 -0
  276. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_output_metadata.py +0 -0
  277. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_output_metadata_t.py +0 -0
  278. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_tags.py +0 -0
  279. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_tags_t.py +0 -0
  280. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_workflow_steps.py +0 -0
  281. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipe_workflow_steps_t.py +0 -0
  282. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipes.py +0 -0
  283. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/recipes_t.py +0 -0
  284. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/response.py +0 -0
  285. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/response_t.py +0 -0
  286. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/secret_retrieval.py +0 -0
  287. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/secret_retrieval_t.py +0 -0
  288. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/units.py +0 -0
  289. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/units_t.py +0 -0
  290. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/users.py +0 -0
  291. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/users_t.py +0 -0
  292. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/webhook_job.py +0 -0
  293. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/webhook_job_t.py +0 -0
  294. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/workflows.py +0 -0
  295. {uncountablepythonsdk-0.0.69 → uncountablepythonsdk-0.0.71}/uncountable/types/workflows_t.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.69
3
+ Version: 0.0.71
4
4
  Summary: Uncountable SDK
5
5
  Project-URL: Homepage, https://github.com/uncountableinc/uncountable-python-sdk
6
6
  Project-URL: Repository, https://github.com/uncountableinc/uncountable-python-sdk.git
@@ -35,6 +35,8 @@ Requires-Dist: paramiko==3.*
35
35
  Requires-Dist: boto3==1.*
36
36
  Requires-Dist: flask==3.*
37
37
  Requires-Dist: simplejson==3.*
38
+ Requires-Dist: grpcio==1.*
39
+ Requires-Dist: protobuf==4.*
38
40
  Provides-Extra: test
39
41
  Requires-Dist: mypy==1.*; extra == "test"
40
42
  Requires-Dist: ruff==0.*; extra == "test"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.69
3
+ Version: 0.0.71
4
4
  Summary: Uncountable SDK
5
5
  Project-URL: Homepage, https://github.com/uncountableinc/uncountable-python-sdk
6
6
  Project-URL: Repository, https://github.com/uncountableinc/uncountable-python-sdk.git
@@ -35,6 +35,8 @@ Requires-Dist: paramiko==3.*
35
35
  Requires-Dist: boto3==1.*
36
36
  Requires-Dist: flask==3.*
37
37
  Requires-Dist: simplejson==3.*
38
+ Requires-Dist: grpcio==1.*
39
+ Requires-Dist: protobuf==4.*
38
40
  Provides-Extra: test
39
41
  Requires-Dist: mypy==1.*; extra == "test"
40
42
  Requires-Dist: ruff==0.*; extra == "test"
@@ -1,5 +1,4 @@
1
1
  .gitignore
2
- Dockerfile.testing
3
2
  README.md
4
3
  pyproject.toml
5
4
  .github/workflows/documentation.yml
@@ -107,10 +106,29 @@ uncountable/integration/server.py
107
106
  uncountable/integration/telemetry.py
108
107
  uncountable/integration/db/__init__.py
109
108
  uncountable/integration/db/connect.py
109
+ uncountable/integration/db/session.py
110
110
  uncountable/integration/executors/__init__.py
111
111
  uncountable/integration/executors/executors.py
112
112
  uncountable/integration/executors/generic_upload_executor.py
113
113
  uncountable/integration/executors/script_executor.py
114
+ uncountable/integration/queue_runner/__init__.py
115
+ uncountable/integration/queue_runner/job_scheduler.py
116
+ uncountable/integration/queue_runner/queue_runner.py
117
+ uncountable/integration/queue_runner/types.py
118
+ uncountable/integration/queue_runner/worker.py
119
+ uncountable/integration/queue_runner/command_server/__init__.py
120
+ uncountable/integration/queue_runner/command_server/command_client.py
121
+ uncountable/integration/queue_runner/command_server/command_server.py
122
+ uncountable/integration/queue_runner/command_server/types.py
123
+ uncountable/integration/queue_runner/command_server/protocol/__init__.py
124
+ uncountable/integration/queue_runner/command_server/protocol/command_server.proto
125
+ uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py
126
+ uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi
127
+ uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py
128
+ uncountable/integration/queue_runner/datastore/__init__.py
129
+ uncountable/integration/queue_runner/datastore/datastore_sqlite.py
130
+ uncountable/integration/queue_runner/datastore/interface.py
131
+ uncountable/integration/queue_runner/datastore/model.py
114
132
  uncountable/integration/secret_retrieval/__init__.py
115
133
  uncountable/integration/secret_retrieval/retrieve_secret.py
116
134
  uncountable/integration/webhook_server/entrypoint.py
@@ -159,6 +177,8 @@ uncountable/types/phases.py
159
177
  uncountable/types/phases_t.py
160
178
  uncountable/types/post_base.py
161
179
  uncountable/types/post_base_t.py
180
+ uncountable/types/queued_job.py
181
+ uncountable/types/queued_job_t.py
162
182
  uncountable/types/recipe_identifiers.py
163
183
  uncountable/types/recipe_identifiers_t.py
164
184
  uncountable/types/recipe_inputs.py
@@ -17,6 +17,8 @@ paramiko==3.*
17
17
  boto3==1.*
18
18
  flask==3.*
19
19
  simplejson==3.*
20
+ grpcio==1.*
21
+ protobuf==4.*
20
22
 
21
23
  [test]
22
24
  mypy==1.*
@@ -1,11 +1,11 @@
1
- from uncountable.integration.job import CronJob, CronJobArguments, register_job
1
+ from uncountable.integration.job import CronJob, JobArguments, register_job
2
2
  from uncountable.types import entity_t
3
3
  from uncountable.types.job_definition_t import JobResult
4
4
 
5
5
 
6
6
  @register_job
7
7
  class MyCronJob(CronJob):
8
- def run(self, args: CronJobArguments) -> JobResult:
8
+ def run(self, args: JobArguments) -> JobResult:
9
9
  matfam = args.client.get_entities_data(
10
10
  entity_ids=[1],
11
11
  entity_type=entity_t.EntityType.MATERIAL_FAMILY,
@@ -67,7 +67,9 @@ dependencies = [
67
67
  "paramiko == 3.*",
68
68
  "boto3 == 1.*",
69
69
  "flask == 3.*",
70
- "simplejson == 3.*"
70
+ "simplejson == 3.*",
71
+ "grpcio == 1.*",
72
+ "protobuf == 4.*"
71
73
  ]
72
74
  dynamic = ["version"]
73
75
 
@@ -17,7 +17,11 @@ def get_integration_env() -> str | None:
17
17
 
18
18
 
19
19
  def get_webhook_server_port() -> int:
20
- return int(os.environ.get("UNC_WEBHOOK_SERVER_PORT") or 5001)
20
+ return int(os.environ.get("UNC_WEBHOOK_SERVER_PORT", 5001))
21
+
22
+
23
+ def get_local_admin_server_port() -> int:
24
+ return int(os.environ.get("UNC_ADMIN_SERVER_PORT", 50051))
21
25
 
22
26
 
23
27
  def get_otel_enabled() -> bool:
@@ -58,6 +58,7 @@ def main() -> None:
58
58
  client=client,
59
59
  batch_processor=batch_processor,
60
60
  logger=job_logger,
61
+ payload=None,
61
62
  )
62
63
  job_result = execute_job(
63
64
  job_definition=job,
@@ -0,0 +1,29 @@
1
+ from dataclasses import dataclass
2
+
3
+ from pkgs.argument_parser import CachedParser
4
+ from uncountable.core.environment import get_local_admin_server_port
5
+ from uncountable.integration.queue_runner.command_server.command_client import (
6
+ send_job_queue_message,
7
+ )
8
+ from uncountable.types import queued_job_t
9
+ from uncountable.types.job_definition_t import JobDefinition, ProfileMetadata
10
+
11
+
12
+ @dataclass
13
+ class CronJobArgs:
14
+ definition: JobDefinition
15
+ profile_metadata: ProfileMetadata
16
+
17
+
18
+ cron_args_parser = CachedParser(CronJobArgs)
19
+
20
+
21
+ def cron_job_executor(**kwargs: dict) -> None:
22
+ args_passed = cron_args_parser.parse_storage(kwargs)
23
+ send_job_queue_message(
24
+ job_ref_name=args_passed.definition.id,
25
+ payload=queued_job_t.QueuedJobPayload(
26
+ invocation_context=queued_job_t.InvocationContextCron()
27
+ ),
28
+ port=get_local_admin_server_port(),
29
+ )
@@ -0,0 +1,18 @@
1
+ import os
2
+ from enum import StrEnum
3
+
4
+ from sqlalchemy import create_engine
5
+ from sqlalchemy.engine.base import Engine
6
+
7
+
8
+ class IntegrationDBService(StrEnum):
9
+ CRON = "cron"
10
+ RUNNER = "runner"
11
+
12
+
13
+ def create_db_engine(service: IntegrationDBService) -> Engine:
14
+ match service:
15
+ case IntegrationDBService.CRON:
16
+ return create_engine(os.environ["UNC_CRON_SQLITE_URI"])
17
+ case IntegrationDBService.RUNNER:
18
+ return create_engine(os.environ["UNC_RUNNER_SQLITE_URI"])
@@ -0,0 +1,25 @@
1
+ from contextlib import _GeneratorContextManager, contextmanager
2
+ from typing import Callable, Generator
3
+
4
+ from sqlalchemy.engine import Engine
5
+ from sqlalchemy.orm import Session, sessionmaker
6
+
7
+ DBSessionMaker = Callable[[], _GeneratorContextManager[Session]]
8
+
9
+
10
+ def get_session_maker(engine: Engine) -> DBSessionMaker:
11
+ session_maker = sessionmaker(bind=engine)
12
+
13
+ @contextmanager
14
+ def session_manager() -> Generator[Session, None, None]:
15
+ session = session_maker()
16
+ try:
17
+ yield session
18
+ session.commit()
19
+ except Exception:
20
+ session.rollback()
21
+ raise
22
+ finally:
23
+ session.close()
24
+
25
+ return session_manager
@@ -1,10 +1,10 @@
1
- from uncountable.integration.db.connect import create_db_engine
1
+ from uncountable.integration.db.connect import IntegrationDBService, create_db_engine
2
2
  from uncountable.integration.scan_profiles import load_profiles
3
3
  from uncountable.integration.server import IntegrationServer
4
4
 
5
5
 
6
- def main(blocking: bool) -> None:
7
- with IntegrationServer(create_db_engine()) as server:
6
+ def main() -> None:
7
+ with IntegrationServer(create_db_engine(IntegrationDBService.CRON)) as server:
8
8
  for profile_details in load_profiles():
9
9
  server.register_profile(
10
10
  profile_name=profile_details.name,
@@ -14,8 +14,8 @@ def main(blocking: bool) -> None:
14
14
  client_options=profile_details.definition.client_options,
15
15
  )
16
16
 
17
- if blocking:
18
- server.serve_forever()
17
+ server.serve_forever()
19
18
 
20
19
 
21
- main(__name__ == "__main__")
20
+ if __name__ == "__main__":
21
+ main()
@@ -165,7 +165,7 @@ def _move_files_post_upload(
165
165
  filesystem_session.move_files([*success_file_transfers, *failed_file_transfers])
166
166
 
167
167
 
168
- class GenericUploadJob(Job):
168
+ class GenericUploadJob(Job[None]):
169
169
  def __init__(
170
170
  self,
171
171
  data_source: GenericUploadDataSource,
@@ -177,6 +177,10 @@ class GenericUploadJob(Job):
177
177
  self.upload_strategy = upload_strategy
178
178
  self.data_source = data_source
179
179
 
180
+ @property
181
+ def payload_type(self) -> type[None]:
182
+ return type(None)
183
+
180
184
  def _construct_filesystem_session(self, args: JobArguments) -> FileSystemSession:
181
185
  match self.data_source:
182
186
  case GenericUploadDataSourceSFTP():
@@ -0,0 +1,87 @@
1
+ import functools
2
+ import typing
3
+ from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass
5
+
6
+ from pkgs.argument_parser import CachedParser
7
+ from uncountable.core.async_batch import AsyncBatchProcessor
8
+ from uncountable.core.client import Client
9
+ from uncountable.integration.telemetry import JobLogger
10
+ from uncountable.types import base_t, webhook_job_t
11
+ from uncountable.types.job_definition_t import JobDefinition, JobResult, ProfileMetadata
12
+
13
+
14
+ @dataclass(kw_only=True)
15
+ class JobArguments:
16
+ job_definition: JobDefinition
17
+ profile_metadata: ProfileMetadata
18
+ client: Client
19
+ batch_processor: AsyncBatchProcessor
20
+ logger: JobLogger
21
+ payload: base_t.JsonValue
22
+
23
+
24
+ # only for compatibility:
25
+ CronJobArguments = JobArguments
26
+
27
+
28
+ PT = typing.TypeVar("PT")
29
+
30
+
31
+ class Job(ABC, typing.Generic[PT]):
32
+ _unc_job_registered: bool = False
33
+
34
+ @property
35
+ @abstractmethod
36
+ def payload_type(self) -> type[PT]: ...
37
+
38
+ @abstractmethod
39
+ def run_outer(self, args: JobArguments) -> JobResult: ...
40
+
41
+ @functools.cached_property
42
+ def _cached_payload_parser(self) -> CachedParser[PT]:
43
+ return CachedParser(self.payload_type)
44
+
45
+ def get_payload(self, payload: base_t.JsonValue) -> PT:
46
+ return self._cached_payload_parser.parse_storage(payload)
47
+
48
+
49
+ class CronJob(Job):
50
+ @property
51
+ def payload_type(self) -> type[None]:
52
+ return type(None)
53
+
54
+ def run_outer(self, args: JobArguments) -> JobResult:
55
+ assert isinstance(args, CronJobArguments)
56
+ return self.run(args)
57
+
58
+ @abstractmethod
59
+ def run(self, args: JobArguments) -> JobResult: ...
60
+
61
+
62
+ WPT = typing.TypeVar("WPT")
63
+
64
+
65
+ class WebhookJob(Job[webhook_job_t.WebhookEventPayload], typing.Generic[WPT]):
66
+ @property
67
+ def payload_type(self) -> type[webhook_job_t.WebhookEventPayload]:
68
+ return webhook_job_t.WebhookEventPayload
69
+
70
+ @property
71
+ @abstractmethod
72
+ def webhook_payload_type(self) -> type[WPT]: ...
73
+
74
+ def run_outer(self, args: JobArguments) -> JobResult:
75
+ webhook_body = self.get_payload(args.payload)
76
+ inner_payload = CachedParser(self.webhook_payload_type).parse_api(
77
+ webhook_body.data
78
+ )
79
+ return self.run(args, inner_payload)
80
+
81
+ @abstractmethod
82
+ def run(self, args: JobArguments, payload: WPT) -> JobResult: ...
83
+
84
+
85
+ def register_job(cls: type[Job]) -> type[Job]:
86
+ cls._unc_job_registered = True
87
+ return cls
@@ -0,0 +1,24 @@
1
+ from .command_client import check_health, send_job_queue_message
2
+ from .command_server import serve
3
+ from .types import (
4
+ CommandEnqueueJob,
5
+ CommandEnqueueJobResponse,
6
+ CommandQueue,
7
+ CommandServerBadResponse,
8
+ CommandServerException,
9
+ CommandServerTimeout,
10
+ CommandTask,
11
+ )
12
+
13
+ __all__: list[str] = [
14
+ "serve",
15
+ "check_health",
16
+ "send_job_queue_message",
17
+ "CommandEnqueueJob",
18
+ "CommandEnqueueJobResponse",
19
+ "CommandTask",
20
+ "CommandQueue",
21
+ "CommandServerTimeout",
22
+ "CommandServerException",
23
+ "CommandServerBadResponse",
24
+ ]
@@ -0,0 +1,68 @@
1
+ from contextlib import contextmanager
2
+ from typing import Generator
3
+
4
+ import grpc
5
+ import simplejson as json
6
+
7
+ from pkgs.serialization_util import serialize_for_api
8
+ from uncountable.integration.queue_runner.command_server.protocol.command_server_pb2 import (
9
+ CheckHealthRequest,
10
+ CheckHealthResult,
11
+ EnqueueJobRequest,
12
+ EnqueueJobResult,
13
+ )
14
+ from uncountable.integration.queue_runner.command_server.types import (
15
+ CommandServerBadResponse,
16
+ CommandServerTimeout,
17
+ )
18
+ from uncountable.types import queued_job_t
19
+
20
+ from .protocol.command_server_pb2_grpc import CommandServerStub
21
+
22
+ _LOCAL_RPC_HOST = "localhost"
23
+ _DEFAULT_MESSAGE_TIMEOUT_SECS = 2
24
+
25
+
26
+ @contextmanager
27
+ def command_server_connection(
28
+ host: str, port: int
29
+ ) -> Generator[CommandServerStub, None, None]:
30
+ try:
31
+ with grpc.insecure_channel(f"{host}:{port}") as channel:
32
+ stub = CommandServerStub(channel)
33
+ yield stub
34
+ except grpc._channel._InactiveRpcError as e:
35
+ raise CommandServerTimeout() from e
36
+
37
+
38
+ def send_job_queue_message(
39
+ *,
40
+ job_ref_name: str,
41
+ payload: queued_job_t.QueuedJobPayload,
42
+ host: str = "localhost",
43
+ port: int,
44
+ ) -> str:
45
+ with command_server_connection(host=host, port=port) as stub:
46
+ request = EnqueueJobRequest(
47
+ job_ref_name=job_ref_name,
48
+ serialized_payload=json.dumps(serialize_for_api(payload)),
49
+ )
50
+
51
+ response = stub.EnqueueJob(request, timeout=_DEFAULT_MESSAGE_TIMEOUT_SECS)
52
+
53
+ assert isinstance(response, EnqueueJobResult)
54
+ if not response.successfully_queued:
55
+ raise CommandServerBadResponse("queue operation was not successful")
56
+
57
+ return response.queued_job_uuid
58
+
59
+
60
+ def check_health(*, host: str = _LOCAL_RPC_HOST, port: int) -> bool:
61
+ with command_server_connection(host=host, port=port) as stub:
62
+ request = CheckHealthRequest()
63
+
64
+ response = stub.CheckHealth(request, timeout=_DEFAULT_MESSAGE_TIMEOUT_SECS)
65
+
66
+ assert isinstance(response, CheckHealthResult)
67
+
68
+ return response.success
@@ -0,0 +1,64 @@
1
+ import asyncio
2
+
3
+ import simplejson as json
4
+ from grpc import aio
5
+
6
+ from pkgs.argument_parser import CachedParser
7
+ from uncountable.core.environment import get_local_admin_server_port
8
+ from uncountable.integration.queue_runner.command_server.protocol.command_server_pb2 import (
9
+ CheckHealthRequest,
10
+ CheckHealthResult,
11
+ EnqueueJobRequest,
12
+ EnqueueJobResult,
13
+ )
14
+ from uncountable.integration.queue_runner.command_server.types import (
15
+ CommandEnqueueJob,
16
+ CommandEnqueueJobResponse,
17
+ CommandQueue,
18
+ )
19
+ from uncountable.types import queued_job_t
20
+
21
+ from .protocol.command_server_pb2_grpc import (
22
+ CommandServerServicer,
23
+ add_CommandServerServicer_to_server,
24
+ )
25
+
26
+ queued_job_payload_parser = CachedParser(queued_job_t.QueuedJobPayload)
27
+
28
+
29
+ async def serve(command_queue: CommandQueue) -> None:
30
+ server = aio.server()
31
+
32
+ class CommandServerHandler(CommandServerServicer):
33
+ async def EnqueueJob(
34
+ self, request: EnqueueJobRequest, context: aio.ServicerContext
35
+ ) -> EnqueueJobResult:
36
+ payload_json = json.loads(request.serialized_payload)
37
+ payload = queued_job_payload_parser.parse_api(payload_json)
38
+ response_queue: asyncio.Queue[CommandEnqueueJobResponse] = asyncio.Queue()
39
+ await command_queue.put(
40
+ CommandEnqueueJob(
41
+ job_ref_name=request.job_ref_name,
42
+ payload=payload,
43
+ response_queue=response_queue,
44
+ )
45
+ )
46
+ response = await response_queue.get()
47
+ result = EnqueueJobResult(
48
+ successfully_queued=True, queued_job_uuid=response.queued_job_uuid
49
+ )
50
+ return result
51
+
52
+ async def CheckHealth(
53
+ self, request: CheckHealthRequest, context: aio.ServicerContext
54
+ ) -> CheckHealthResult:
55
+ return CheckHealthResult(success=True)
56
+
57
+ add_CommandServerServicer_to_server(CommandServerHandler(), server)
58
+
59
+ listen_addr = f"[::]:{get_local_admin_server_port()}"
60
+
61
+ server.add_insecure_port(listen_addr)
62
+
63
+ await server.start()
64
+ await server.wait_for_termination()
@@ -0,0 +1,22 @@
1
+ syntax = "proto3";
2
+
3
+ service CommandServer {
4
+ rpc EnqueueJob(EnqueueJobRequest) returns (EnqueueJobResult) {}
5
+ rpc CheckHealth(CheckHealthRequest) returns (CheckHealthResult) {}
6
+ }
7
+
8
+ message EnqueueJobRequest {
9
+ string job_ref_name = 1;
10
+ string serialized_payload = 2;
11
+ }
12
+
13
+ message EnqueueJobResult {
14
+ bool successfully_queued = 1;
15
+ string queued_job_uuid = 2;
16
+ }
17
+
18
+ message CheckHealthRequest {}
19
+
20
+ message CheckHealthResult {
21
+ bool success = 1;
22
+ }
@@ -0,0 +1,40 @@
1
+ # ruff: noqa
2
+ # -*- coding: utf-8 -*-
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: uncountable/integration/queue_runner/command_server/protocol/command_server.proto
5
+ # Protobuf Python Version: 4.25.1
6
+ """Generated protocol buffer code."""
7
+
8
+ from google.protobuf import descriptor as _descriptor
9
+ from google.protobuf import descriptor_pool as _descriptor_pool
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ # @@protoc_insertion_point(imports)
13
+
14
+ _sym_db = _symbol_database.Default()
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
18
+ b'\nQuncountable/integration/queue_runner/command_server/protocol/command_server.proto"E\n\x11\x45nqueueJobRequest\x12\x14\n\x0cjob_ref_name\x18\x01 \x01(\t\x12\x1a\n\x12serialized_payload\x18\x02 \x01(\t"H\n\x10\x45nqueueJobResult\x12\x1b\n\x13successfully_queued\x18\x01 \x01(\x08\x12\x17\n\x0fqueued_job_uuid\x18\x02 \x01(\t"\x14\n\x12\x43heckHealthRequest"$\n\x11\x43heckHealthResult\x12\x0f\n\x07success\x18\x01 \x01(\x08\x32\x80\x01\n\rCommandServer\x12\x35\n\nEnqueueJob\x12\x12.EnqueueJobRequest\x1a\x11.EnqueueJobResult"\x00\x12\x38\n\x0b\x43heckHealth\x12\x13.CheckHealthRequest\x1a\x12.CheckHealthResult"\x00\x62\x06proto3'
19
+ )
20
+
21
+ _globals = globals()
22
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
23
+ _builder.BuildTopDescriptorsAndMessages(
24
+ DESCRIPTOR,
25
+ "uncountable.integration.queue_runner.command_server.protocol.command_server_pb2",
26
+ _globals,
27
+ )
28
+ if _descriptor._USE_C_DESCRIPTORS == False:
29
+ DESCRIPTOR._options = None
30
+ _globals["_ENQUEUEJOBREQUEST"]._serialized_start = 85
31
+ _globals["_ENQUEUEJOBREQUEST"]._serialized_end = 154
32
+ _globals["_ENQUEUEJOBRESULT"]._serialized_start = 156
33
+ _globals["_ENQUEUEJOBRESULT"]._serialized_end = 228
34
+ _globals["_CHECKHEALTHREQUEST"]._serialized_start = 230
35
+ _globals["_CHECKHEALTHREQUEST"]._serialized_end = 250
36
+ _globals["_CHECKHEALTHRESULT"]._serialized_start = 252
37
+ _globals["_CHECKHEALTHRESULT"]._serialized_end = 288
38
+ _globals["_COMMANDSERVER"]._serialized_start = 291
39
+ _globals["_COMMANDSERVER"]._serialized_end = 419
40
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,38 @@
1
+ # ruff: noqa
2
+ from google.protobuf import descriptor as _descriptor
3
+ from google.protobuf import message as _message
4
+ from typing import ClassVar as _ClassVar, Optional as _Optional
5
+
6
+ DESCRIPTOR: _descriptor.FileDescriptor
7
+
8
+ class EnqueueJobRequest(_message.Message):
9
+ __slots__ = ("job_ref_name", "serialized_payload")
10
+ JOB_REF_NAME_FIELD_NUMBER: _ClassVar[int]
11
+ SERIALIZED_PAYLOAD_FIELD_NUMBER: _ClassVar[int]
12
+ job_ref_name: str
13
+ serialized_payload: str
14
+ def __init__(
15
+ self,
16
+ job_ref_name: _Optional[str] = ...,
17
+ serialized_payload: _Optional[str] = ...,
18
+ ) -> None: ...
19
+
20
+ class EnqueueJobResult(_message.Message):
21
+ __slots__ = ("successfully_queued", "queued_job_uuid")
22
+ SUCCESSFULLY_QUEUED_FIELD_NUMBER: _ClassVar[int]
23
+ QUEUED_JOB_UUID_FIELD_NUMBER: _ClassVar[int]
24
+ successfully_queued: bool
25
+ queued_job_uuid: str
26
+ def __init__(
27
+ self, successfully_queued: bool = ..., queued_job_uuid: _Optional[str] = ...
28
+ ) -> None: ...
29
+
30
+ class CheckHealthRequest(_message.Message):
31
+ __slots__ = ()
32
+ def __init__(self) -> None: ...
33
+
34
+ class CheckHealthResult(_message.Message):
35
+ __slots__ = ("success",)
36
+ SUCCESS_FIELD_NUMBER: _ClassVar[int]
37
+ success: bool
38
+ def __init__(self, success: bool = ...) -> None: ...