UncountablePythonSDK 0.0.122__tar.gz → 0.0.124__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 (355) hide show
  1. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/PKG-INFO +2 -2
  2. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/UncountablePythonSDK.egg-info/PKG-INFO +2 -2
  3. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/UncountablePythonSDK.egg-info/SOURCES.txt +13 -1
  4. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/UncountablePythonSDK.egg-info/requires.txt +1 -1
  5. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/conf.py +23 -4
  6. uncountablepythonsdk-0.0.124/docs/index.md +116 -0
  7. uncountablepythonsdk-0.0.124/docs/integration_examples/create_ingredient.md +43 -0
  8. uncountablepythonsdk-0.0.124/docs/integration_examples/create_output.md +56 -0
  9. uncountablepythonsdk-0.0.124/docs/integration_examples/index.md +6 -0
  10. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/requirements.txt +1 -1
  11. uncountablepythonsdk-0.0.124/examples/basic_auth.py +7 -0
  12. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/pyproject.toml +1 -1
  13. uncountablepythonsdk-0.0.124/examples/oauth.py +7 -0
  14. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/argument_parser/_is_namedtuple.py +3 -0
  15. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/type_info/emit_type_info.py +10 -1
  16. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pyproject.toml +1 -1
  17. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/http_server/types.py +3 -1
  18. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/scheduler.py +62 -17
  19. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/telemetry.py +9 -1
  20. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/__init__.py +10 -0
  21. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/export_entities.py +13 -0
  22. uncountablepythonsdk-0.0.124/uncountable/types/api/integrations/push_notification.py +47 -0
  23. uncountablepythonsdk-0.0.124/uncountable/types/api/outputs/get_output_organization.py +173 -0
  24. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/async_batch_processor.py +41 -0
  25. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/async_batch_t.py +1 -0
  26. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/client_base.py +30 -0
  27. uncountablepythonsdk-0.0.124/uncountable/types/integration_session.py +10 -0
  28. uncountablepythonsdk-0.0.124/uncountable/types/integration_session_t.py +60 -0
  29. uncountablepythonsdk-0.0.124/uncountable/types/notifications.py +11 -0
  30. uncountablepythonsdk-0.0.124/uncountable/types/notifications_t.py +74 -0
  31. uncountablepythonsdk-0.0.124/uncountable/types/sockets.py +11 -0
  32. uncountablepythonsdk-0.0.124/uncountable/types/sockets_t.py +70 -0
  33. uncountablepythonsdk-0.0.122/docs/index.md +0 -16
  34. uncountablepythonsdk-0.0.122/docs/quickstart.md +0 -19
  35. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/.github/workflows/documentation.yml +0 -0
  36. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/.github/workflows/publish.yml +0 -0
  37. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/.gitignore +0 -0
  38. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/.python-version +0 -0
  39. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/README.md +0 -0
  40. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
  41. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
  42. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/.gitignore +0 -0
  43. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/justfile +0 -0
  44. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/android-chrome-192x192.png +0 -0
  45. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/android-chrome-512x512.png +0 -0
  46. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/apple-touch-icon.png +0 -0
  47. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/browserconfig.xml +0 -0
  48. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/favicon-16x16.png +0 -0
  49. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/favicon-32x32.png +0 -0
  50. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/manifest.json +0 -0
  51. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/mstile-150x150.png +0 -0
  52. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/favicons/safari-pinned-tab.svg +0 -0
  53. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/docs/static/logo_blue.png +0 -0
  54. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/async_batch.py +0 -0
  55. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/create_entity.py +0 -0
  56. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/create_ingredient_sdk.py +0 -0
  57. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/download_files.py +0 -0
  58. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/edit_recipe_inputs.py +0 -0
  59. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/concurrent_cron.py +0 -0
  60. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/example_cron.py +0 -0
  61. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/example_http.py +0 -0
  62. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/example_instrument.py +0 -0
  63. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/example_runsheet_wh.py +0 -0
  64. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/example_wh.py +0 -0
  65. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/integration-server/jobs/materials_auto/profile.yaml +0 -0
  66. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/invoke_uploader.py +0 -0
  67. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/set_recipe_metadata_file.py +0 -0
  68. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/set_recipe_output_file_sdk.py +0 -0
  69. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/examples/upload_files.py +0 -0
  70. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/__init__.py +0 -0
  71. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/argument_parser/__init__.py +0 -0
  72. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/argument_parser/_is_enum.py +0 -0
  73. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/argument_parser/argument_parser.py +0 -0
  74. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/argument_parser/case_convert.py +0 -0
  75. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/__init__.py +0 -0
  76. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/_blob_session.py +0 -0
  77. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/_gdrive_session.py +0 -0
  78. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/_local_session.py +0 -0
  79. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/_s3_session.py +0 -0
  80. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/_sftp_session.py +0 -0
  81. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/file_type_utils.py +0 -0
  82. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/filesystem_utils/filesystem_session.py +0 -0
  83. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/py.typed +0 -0
  84. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/__init__.py +0 -0
  85. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/annotation.py +0 -0
  86. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/missing_sentry.py +0 -0
  87. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/opaque_key.py +0 -0
  88. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/serial_alias.py +0 -0
  89. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/serial_class.py +0 -0
  90. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/serial_generic.py +0 -0
  91. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/serial_union.py +0 -0
  92. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization/yaml.py +0 -0
  93. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization_util/__init__.py +0 -0
  94. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
  95. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization_util/convert_to_snakecase.py +0 -0
  96. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization_util/dataclasses.py +0 -0
  97. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/serialization_util/serialization_helpers.py +0 -0
  98. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/strenum_compat/__init__.py +0 -0
  99. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/strenum_compat/strenum_compat.py +0 -0
  100. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/__init__.py +0 -0
  101. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/__main__.py +0 -0
  102. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/actions_registry/__init__.py +0 -0
  103. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/actions_registry/__main__.py +0 -0
  104. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/actions_registry/emit_typescript.py +0 -0
  105. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/builder.py +0 -0
  106. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/config.py +0 -0
  107. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/cross_output_links.py +0 -0
  108. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_io_ts.py +0 -0
  109. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_open_api.py +0 -0
  110. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_open_api_util.py +0 -0
  111. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_python.py +0 -0
  112. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_typescript.py +0 -0
  113. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/emit_typescript_util.py +0 -0
  114. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/load_types.py +0 -0
  115. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/non_discriminated_union_exceptions.py +0 -0
  116. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/open_api_util.py +0 -0
  117. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/parts/base.py.prepart +0 -0
  118. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/parts/base.ts.prepart +0 -0
  119. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/test.py +0 -0
  120. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/type_info/__main__.py +0 -0
  121. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/ui_entry_actions/__init__.py +0 -0
  122. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/ui_entry_actions/generate_ui_entry_actions.py +0 -0
  123. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/util.py +0 -0
  124. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/value_spec/__init__.py +0 -0
  125. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/value_spec/__main__.py +0 -0
  126. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/value_spec/convert_type.py +0 -0
  127. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/value_spec/emit_python.py +0 -0
  128. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/pkgs/type_spec/value_spec/types.py +0 -0
  129. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/setup.cfg +0 -0
  130. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/__init__.py +0 -0
  131. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/__init__.py +0 -0
  132. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/async_batch.py +0 -0
  133. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/client.py +0 -0
  134. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/environment.py +0 -0
  135. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/file_upload.py +0 -0
  136. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/core/types.py +0 -0
  137. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/__init__.py +0 -0
  138. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/cli.py +0 -0
  139. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/construct_client.py +0 -0
  140. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/cron.py +0 -0
  141. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/db/__init__.py +0 -0
  142. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/db/connect.py +0 -0
  143. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/db/session.py +0 -0
  144. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/entrypoint.py +0 -0
  145. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/executors/__init__.py +0 -0
  146. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/executors/executors.py +0 -0
  147. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/executors/generic_upload_executor.py +0 -0
  148. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/executors/script_executor.py +0 -0
  149. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/http_server/__init__.py +0 -0
  150. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/job.py +0 -0
  151. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/__init__.py +0 -0
  152. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/__init__.py +0 -0
  153. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/command_client.py +0 -0
  154. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/command_server.py +0 -0
  155. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/constants.py +0 -0
  156. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
  157. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/protocol/command_server.proto +0 -0
  158. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +0 -0
  159. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +0 -0
  160. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +0 -0
  161. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/command_server/types.py +0 -0
  162. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/datastore/__init__.py +0 -0
  163. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/datastore/datastore_sqlite.py +0 -0
  164. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/datastore/interface.py +0 -0
  165. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/datastore/model.py +0 -0
  166. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/job_scheduler.py +0 -0
  167. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/queue_runner.py +0 -0
  168. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/types.py +0 -0
  169. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/queue_runner/worker.py +0 -0
  170. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/scan_profiles.py +0 -0
  171. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/secret_retrieval/__init__.py +0 -0
  172. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/secret_retrieval/retrieve_secret.py +0 -0
  173. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/server.py +0 -0
  174. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/integration/webhook_server/entrypoint.py +0 -0
  175. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/py.typed +0 -0
  176. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/__init__.py +0 -0
  177. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/batch/__init__.py +0 -0
  178. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/batch/execute_batch.py +0 -0
  179. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/batch/execute_batch_load_async.py +0 -0
  180. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/chemical/__init__.py +0 -0
  181. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/chemical/convert_chemical_formats.py +0 -0
  182. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/condition_parameters/__init__.py +0 -0
  183. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/condition_parameters/upsert_condition_match.py +0 -0
  184. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/__init__.py +0 -0
  185. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/create_entities.py +0 -0
  186. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/create_entity.py +0 -0
  187. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/create_or_update_entity.py +0 -0
  188. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/get_entities_data.py +0 -0
  189. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/grant_entity_permissions.py +0 -0
  190. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/list_entities.py +0 -0
  191. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/lock_entity.py +0 -0
  192. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/lookup_entity.py +0 -0
  193. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
  194. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/set_entity_field_values.py +0 -0
  195. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/set_values.py +0 -0
  196. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/transition_entity_phase.py +0 -0
  197. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/entity/unlock_entity.py +0 -0
  198. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/equipment/__init__.py +0 -0
  199. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/equipment/associate_equipment_input.py +0 -0
  200. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/field_options/__init__.py +0 -0
  201. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/field_options/upsert_field_options.py +0 -0
  202. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/files/__init__.py +0 -0
  203. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/files/download_file.py +0 -0
  204. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/id_source/__init__.py +0 -0
  205. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/id_source/list_id_source.py +0 -0
  206. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/id_source/match_id_source.py +0 -0
  207. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/input_groups/__init__.py +0 -0
  208. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
  209. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/__init__.py +0 -0
  210. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/create_inputs.py +0 -0
  211. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/get_input_data.py +0 -0
  212. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/get_input_names.py +0 -0
  213. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
  214. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
  215. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/set_input_category.py +0 -0
  216. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/set_input_subcategories.py +0 -0
  217. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/inputs/set_intermediate_type.py +0 -0
  218. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/integrations/__init__.py +0 -0
  219. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/integrations/publish_realtime_data.py +0 -0
  220. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/material_families/__init__.py +0 -0
  221. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/material_families/update_entity_material_families.py +0 -0
  222. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/outputs/__init__.py +0 -0
  223. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/outputs/get_output_data.py +0 -0
  224. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/outputs/get_output_names.py +0 -0
  225. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
  226. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/permissions/__init__.py +0 -0
  227. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/permissions/set_core_permissions.py +0 -0
  228. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/project/__init__.py +0 -0
  229. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/project/get_projects.py +0 -0
  230. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/project/get_projects_data.py +0 -0
  231. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipe_links/__init__.py +0 -0
  232. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipe_links/create_recipe_link.py +0 -0
  233. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipe_links/remove_recipe_link.py +0 -0
  234. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
  235. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
  236. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/__init__.py +0 -0
  237. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/add_recipe_to_project.py +0 -0
  238. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/add_time_series_data.py +0 -0
  239. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/archive_recipes.py +0 -0
  240. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/associate_recipe_as_input.py +0 -0
  241. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/associate_recipe_as_lot.py +0 -0
  242. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/clear_recipe_outputs.py +0 -0
  243. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/create_mix_order.py +0 -0
  244. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/create_recipe.py +0 -0
  245. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/create_recipes.py +0 -0
  246. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/disassociate_recipe_as_input.py +0 -0
  247. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/edit_recipe_inputs.py +0 -0
  248. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_column_calculation_values.py +0 -0
  249. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_curve.py +0 -0
  250. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
  251. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
  252. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
  253. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
  254. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/get_recipes_data.py +0 -0
  255. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/lock_recipes.py +0 -0
  256. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/remove_recipe_from_project.py +0 -0
  257. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
  258. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_metadata.py +0 -0
  259. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_output_annotations.py +0 -0
  260. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_output_file.py +0 -0
  261. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_outputs.py +0 -0
  262. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/set_recipe_tags.py +0 -0
  263. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/unarchive_recipes.py +0 -0
  264. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/recipes/unlock_recipes.py +0 -0
  265. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/runsheet/__init__.py +0 -0
  266. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/runsheet/complete_async_upload.py +0 -0
  267. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/triggers/__init__.py +0 -0
  268. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/triggers/run_trigger.py +0 -0
  269. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/uploader/__init__.py +0 -0
  270. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/uploader/invoke_uploader.py +0 -0
  271. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/user/__init__.py +0 -0
  272. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/api/user/get_current_user_info.py +0 -0
  273. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/async_batch.py +0 -0
  274. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/async_jobs.py +0 -0
  275. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/async_jobs_t.py +0 -0
  276. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/auth_retrieval.py +0 -0
  277. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/auth_retrieval_t.py +0 -0
  278. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/base.py +0 -0
  279. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/base_t.py +0 -0
  280. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/calculations.py +0 -0
  281. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/calculations_t.py +0 -0
  282. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/chemical_structure.py +0 -0
  283. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/chemical_structure_t.py +0 -0
  284. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/client_config.py +0 -0
  285. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/client_config_t.py +0 -0
  286. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/curves.py +0 -0
  287. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/curves_t.py +0 -0
  288. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/data.py +0 -0
  289. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/data_t.py +0 -0
  290. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/entity.py +0 -0
  291. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/entity_t.py +0 -0
  292. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/experiment_groups.py +0 -0
  293. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/experiment_groups_t.py +0 -0
  294. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/exports.py +0 -0
  295. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/exports_t.py +0 -0
  296. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/field_values.py +0 -0
  297. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/field_values_t.py +0 -0
  298. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/fields.py +0 -0
  299. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/fields_t.py +0 -0
  300. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/generic_upload.py +0 -0
  301. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/generic_upload_t.py +0 -0
  302. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/id_source.py +0 -0
  303. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/id_source_t.py +0 -0
  304. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/identifier.py +0 -0
  305. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/identifier_t.py +0 -0
  306. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/input_attributes.py +0 -0
  307. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/input_attributes_t.py +0 -0
  308. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/inputs.py +0 -0
  309. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/inputs_t.py +0 -0
  310. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/integration_server.py +0 -0
  311. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/integration_server_t.py +0 -0
  312. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/integrations.py +0 -0
  313. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/integrations_t.py +0 -0
  314. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/job_definition.py +0 -0
  315. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/job_definition_t.py +0 -0
  316. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/outputs.py +0 -0
  317. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/outputs_t.py +0 -0
  318. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/overrides.py +0 -0
  319. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/overrides_t.py +0 -0
  320. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/permissions.py +0 -0
  321. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/permissions_t.py +0 -0
  322. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/phases.py +0 -0
  323. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/phases_t.py +0 -0
  324. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/post_base.py +0 -0
  325. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/post_base_t.py +0 -0
  326. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/queued_job.py +0 -0
  327. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/queued_job_t.py +0 -0
  328. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_identifiers.py +0 -0
  329. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_identifiers_t.py +0 -0
  330. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_inputs.py +0 -0
  331. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_inputs_t.py +0 -0
  332. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_links.py +0 -0
  333. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_links_t.py +0 -0
  334. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_metadata.py +0 -0
  335. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_metadata_t.py +0 -0
  336. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_output_metadata.py +0 -0
  337. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_output_metadata_t.py +0 -0
  338. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_tags.py +0 -0
  339. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_tags_t.py +0 -0
  340. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_workflow_steps.py +0 -0
  341. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipe_workflow_steps_t.py +0 -0
  342. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipes.py +0 -0
  343. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/recipes_t.py +0 -0
  344. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/response.py +0 -0
  345. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/response_t.py +0 -0
  346. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/secret_retrieval.py +0 -0
  347. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/secret_retrieval_t.py +0 -0
  348. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/units.py +0 -0
  349. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/units_t.py +0 -0
  350. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/users.py +0 -0
  351. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/users_t.py +0 -0
  352. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/webhook_job.py +0 -0
  353. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/webhook_job_t.py +0 -0
  354. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/workflows.py +0 -0
  355. {uncountablepythonsdk-0.0.122 → uncountablepythonsdk-0.0.124}/uncountable/types/workflows_t.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.122
3
+ Version: 0.0.124
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
@@ -31,7 +31,7 @@ Requires-Dist: opentelemetry-api==1.*
31
31
  Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.*
32
32
  Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.*
33
33
  Requires-Dist: opentelemetry-sdk==1.*
34
- Requires-Dist: paramiko==3.*
34
+ Requires-Dist: paramiko==4.*
35
35
  Requires-Dist: boto3==1.*
36
36
  Requires-Dist: flask==3.*
37
37
  Requires-Dist: simplejson==3.*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.122
3
+ Version: 0.0.124
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
@@ -31,7 +31,7 @@ Requires-Dist: opentelemetry-api==1.*
31
31
  Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.*
32
32
  Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.*
33
33
  Requires-Dist: opentelemetry-sdk==1.*
34
- Requires-Dist: paramiko==3.*
34
+ Requires-Dist: paramiko==4.*
35
35
  Requires-Dist: boto3==1.*
36
36
  Requires-Dist: flask==3.*
37
37
  Requires-Dist: simplejson==3.*
@@ -13,8 +13,10 @@ docs/.gitignore
13
13
  docs/conf.py
14
14
  docs/index.md
15
15
  docs/justfile
16
- docs/quickstart.md
17
16
  docs/requirements.txt
17
+ docs/integration_examples/create_ingredient.md
18
+ docs/integration_examples/create_output.md
19
+ docs/integration_examples/index.md
18
20
  docs/static/logo_blue.png
19
21
  docs/static/favicons/android-chrome-192x192.png
20
22
  docs/static/favicons/android-chrome-512x512.png
@@ -26,11 +28,13 @@ docs/static/favicons/manifest.json
26
28
  docs/static/favicons/mstile-150x150.png
27
29
  docs/static/favicons/safari-pinned-tab.svg
28
30
  examples/async_batch.py
31
+ examples/basic_auth.py
29
32
  examples/create_entity.py
30
33
  examples/create_ingredient_sdk.py
31
34
  examples/download_files.py
32
35
  examples/edit_recipe_inputs.py
33
36
  examples/invoke_uploader.py
37
+ examples/oauth.py
34
38
  examples/set_recipe_metadata_file.py
35
39
  examples/set_recipe_output_file_sdk.py
36
40
  examples/upload_files.py
@@ -195,10 +199,14 @@ uncountable/types/inputs.py
195
199
  uncountable/types/inputs_t.py
196
200
  uncountable/types/integration_server.py
197
201
  uncountable/types/integration_server_t.py
202
+ uncountable/types/integration_session.py
203
+ uncountable/types/integration_session_t.py
198
204
  uncountable/types/integrations.py
199
205
  uncountable/types/integrations_t.py
200
206
  uncountable/types/job_definition.py
201
207
  uncountable/types/job_definition_t.py
208
+ uncountable/types/notifications.py
209
+ uncountable/types/notifications_t.py
202
210
  uncountable/types/outputs.py
203
211
  uncountable/types/outputs_t.py
204
212
  uncountable/types/overrides.py
@@ -231,6 +239,8 @@ uncountable/types/response.py
231
239
  uncountable/types/response_t.py
232
240
  uncountable/types/secret_retrieval.py
233
241
  uncountable/types/secret_retrieval_t.py
242
+ uncountable/types/sockets.py
243
+ uncountable/types/sockets_t.py
234
244
  uncountable/types/units.py
235
245
  uncountable/types/units_t.py
236
246
  uncountable/types/users.py
@@ -284,11 +294,13 @@ uncountable/types/api/inputs/set_input_subcategories.py
284
294
  uncountable/types/api/inputs/set_intermediate_type.py
285
295
  uncountable/types/api/integrations/__init__.py
286
296
  uncountable/types/api/integrations/publish_realtime_data.py
297
+ uncountable/types/api/integrations/push_notification.py
287
298
  uncountable/types/api/material_families/__init__.py
288
299
  uncountable/types/api/material_families/update_entity_material_families.py
289
300
  uncountable/types/api/outputs/__init__.py
290
301
  uncountable/types/api/outputs/get_output_data.py
291
302
  uncountable/types/api/outputs/get_output_names.py
303
+ uncountable/types/api/outputs/get_output_organization.py
292
304
  uncountable/types/api/outputs/resolve_output_conditions.py
293
305
  uncountable/types/api/permissions/__init__.py
294
306
  uncountable/types/api/permissions/set_core_permissions.py
@@ -13,7 +13,7 @@ opentelemetry-api==1.*
13
13
  opentelemetry-exporter-otlp-proto-common==1.*
14
14
  opentelemetry-exporter-otlp-proto-http==1.*
15
15
  opentelemetry-sdk==1.*
16
- paramiko==3.*
16
+ paramiko==4.*
17
17
  boto3==1.*
18
18
  flask==3.*
19
19
  simplejson==3.*
@@ -27,7 +27,7 @@ extensions = [
27
27
  "sphinx_copybutton",
28
28
  "sphinx_favicon",
29
29
  ]
30
- myst_enable_extensions = ["fieldlist", "deflist"]
30
+ myst_enable_extensions = ["fieldlist", "deflist", "colon_fence"]
31
31
 
32
32
  autoapi_dirs = ["../uncountable"]
33
33
  autoapi_options = [
@@ -70,14 +70,33 @@ def _hook_missing_reference(
70
70
  Manually resolve reference when autoapi reference resolution fails.
71
71
  This is necessary because autoapi does not fully support type aliases.
72
72
  """
73
+ # example reftarget value: uncountable.types.identifier_t.IdentifierKey
73
74
  target = node.get("reftarget", "")
75
+
76
+ # example refdoc value: api/uncountable/types/generic_upload_t/GenericUploadStrategy
77
+ current_doc = node.get("refdoc", "")
78
+
74
79
  if not target.startswith("uncountable"):
75
80
  return None
76
- module, name = target.rsplit(".", 1)
81
+
82
+ target_module, target_name = target.rsplit(".", 1)
83
+
84
+ # construct relative path from current doc page to target page
85
+ relative_segments_to_root = [".." for _ in current_doc.split("/")]
86
+ relative_segments_to_target = target_module.split(".")
87
+
88
+ # example full relative path: ../../../../../api/uncountable/types/identifier_t/#uncountable.types.identifier_t.IdentifierKey
89
+ full_relative_path = "/".join([
90
+ *relative_segments_to_root,
91
+ autoapi_root,
92
+ *relative_segments_to_target,
93
+ f"#{target}",
94
+ ])
95
+
77
96
  return nodes.reference(
78
- text=name if python_use_unqualified_type_names else target,
97
+ text=target_name if python_use_unqualified_type_names else target,
79
98
  children=[contnode],
80
- refuri=f"/{autoapi_root}/{module.replace('.', '/')}/#{target}",
99
+ refuri=full_relative_path,
81
100
  )
82
101
 
83
102
 
@@ -0,0 +1,116 @@
1
+ # Uncountable Python SDK
2
+
3
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/UncountablePythonSDK)
4
+
5
+
6
+ The Uncountable Python SDK is a python package that provides a wrapper around the Uncountable REST API.
7
+
8
+ Using this SDK provides the following advantages:
9
+
10
+ - In-editor parameter/type safety
11
+ - Automatic parsing of response data.
12
+ - Reduced code boilerplate
13
+ - Helper methods
14
+
15
+ ## Getting Started
16
+ The first step in any integration is to create a [Client](uncountable.core.client.Client) object. The client provides access to all available SDK methods, and includes built-in request authentication & error propagation.
17
+
18
+ ### Creating a Client
19
+ Create a client using one of the supported authentication mechanisms. API credentials can be generated by a member of Uncountable staff.
20
+
21
+ ::::{tab-set}
22
+ :::{tab-item} Basic Auth
23
+ ```{literalinclude} ../examples/basic_auth.py
24
+ ```
25
+ :::
26
+
27
+ :::{tab-item} OAuth
28
+ ```{literalinclude} ../examples/oauth.py
29
+ ```
30
+ :::
31
+ ::::
32
+
33
+ The provided code examples assume that a Client has been created and stored in the `client` variable
34
+
35
+
36
+ ### Basic Usage
37
+
38
+ :::{dropdown} List Ingredient Names & IDs
39
+ ```{code-block} python
40
+ from uncountable.types import entity_t, id_source_t
41
+
42
+ client.list_id_source(
43
+ spec=id_source_t.IdSourceSpecEntity(entity_type=entity_t.EntityType.INGREDIENT),
44
+ search_label="",
45
+ )
46
+ ```
47
+ Example Response:
48
+ ```code
49
+ Data(
50
+ results=[
51
+ IdName(id=1, name='Filler'),
52
+ IdName(id=2, name='Calcium Oxide 2'),
53
+ IdName(id=3, name='Carbon Black'),
54
+ ]
55
+ )
56
+ ```
57
+ :::
58
+
59
+ :::{dropdown} Create an Experiment
60
+ ```{code-block} python
61
+ client.create_recipe(material_family_id=1, workflow_id=1, name="Example Recipe")
62
+ ```
63
+ Example Response:
64
+ ```code
65
+ Data(result_id=52271)
66
+ ```
67
+ :::
68
+
69
+ :::{dropdown} Upload a file
70
+ ```{code-block} python
71
+ from uncountable.core.file_upload import MediaFileUpload
72
+
73
+ client.upload_files(file_uploads=[MediaFileUpload(path="/path/to/local/example_file.pdf")])
74
+ ```
75
+ Example Response:
76
+ ```code
77
+ [
78
+ UploadedFile(name='example_file.pdf', file_id=718)
79
+ ]
80
+ ```
81
+ :::
82
+
83
+ [More examples](integration_examples/index)
84
+
85
+ ## Errors
86
+ Client methods will raise Exceptions when the API returns codes in the `3xx`, `4xx` or `5xx` ranges. Ensure all method calls are wrapped in Exception handling logic.
87
+
88
+ ## Pagination
89
+ Many of the Uncountable APIs require pagination to fetch more than 100 results at once. The following code snippet implements pagination to fetch the Names & IDs of all Projects:
90
+ :::{dropdown} Pagination Example
91
+ ```{code-block} python
92
+ from uncountable.types import entity_t, id_source_t
93
+ from uncountable.types.api.id_source.list_id_source import IdName
94
+
95
+ def fetch_all_projects(client: Client) -> list[IdName]:
96
+ projects: list[IdName] = []
97
+ while True:
98
+ response = client.list_id_source(
99
+ spec=IdSourceSpecEntity(entity_type=entity_t.EntityType.PROJECT),
100
+ search_label="",
101
+ offset=len(projects),
102
+ )
103
+ projects.extend(response.results)
104
+ if len(response.results) < 100:
105
+ return projects
106
+ ```
107
+ :::
108
+
109
+
110
+ ```{toctree}
111
+ :hidden:
112
+ Overview <self>
113
+ Available SDK Methods <api/uncountable/core/client/Client>
114
+ integration_examples/index
115
+ SDK Reference <api/uncountable/index>
116
+ ```
@@ -0,0 +1,43 @@
1
+ # Create an Ingredient
2
+
3
+ Use the `create_or_update_entity` method to create Ingredients.
4
+
5
+ The following fields are required when creating an Ingredient:
6
+ - `name`: The name of the Ingredient
7
+ - `core_ingredient_ingredientMaterialFamilies`: The list of material families in which to include the Ingredient
8
+
9
+ The reference name of the default definition of Ingredients is `uncIngredient`
10
+
11
+ This is an example of a minimal ingredient creation call
12
+
13
+ ```{code-block} python
14
+ from uncountable.types import entity_t, field_values_t, identifier_t
15
+
16
+ client.create_or_update_entity(
17
+ entity_type=entity_t.EntityType.INGREDIENT,
18
+ definition_key=identifier_t.IdentifierKeyRefName(ref_name="uncIngredient"),
19
+ field_values=[
20
+ field_values_t.FieldArgumentValue(
21
+ field_key=identifier_t.IdentifierKeyRefName(
22
+ ref_name="core_ingredient_ingredientMaterialFamilies"
23
+ ),
24
+ value=field_values_t.FieldValueIds(
25
+ entity_type=entity_t.EntityType.MATERIAL_FAMILY,
26
+ identifier_keys=[identifier_t.IdentifierKeyId(id=1)],
27
+ ),
28
+ ),
29
+ field_values_t.FieldArgumentValue(
30
+ field_key=identifier_t.IdentifierKeyRefName(ref_name="name"),
31
+ value=field_values_t.FieldValueText(value="Example Ingredient"),
32
+ ),
33
+ ],
34
+ )
35
+ ```
36
+
37
+ Example Response:
38
+ ```{code}
39
+ Data(modification_made=True, result_id=3124, entity=None, result_values=None)
40
+ ```
41
+
42
+ Optional fields:
43
+ - `core_ingredient_quantityType`: The quantity type of the ingredient (default is `numeric`)
@@ -0,0 +1,56 @@
1
+ # Create an Output
2
+
3
+ Use the `create_or_update_entity` method to create Outputs.
4
+
5
+ The following fields are required when creating an Output:
6
+ - `name`: The name of the Output
7
+ - `core_output_unitsId`: The unit the output is measured in
8
+ - `core_output_outputMaterialFamilies`: The list of material families in which to include the Output
9
+ - `core_output_quantityType`: The quantity type of the output
10
+
11
+ The reference name of the default definition of Ingredients is `unc_output_definition`
12
+
13
+ This is an example of a minimal output creation call
14
+
15
+ ```{code-block} python
16
+ from uncountable.types import entity_t, field_values_t, identifier_t
17
+
18
+ client.create_or_update_entity(
19
+ entity_type=entity_t.EntityType.OUTPUT,
20
+ definition_key=identifier_t.IdentifierKeyRefName(ref_name="unc_output_definition"),
21
+ field_values=[
22
+ field_values_t.FieldArgumentValue(
23
+ field_key=identifier_t.IdentifierKeyRefName(ref_name="name"),
24
+ value=field_values_t.FieldValueText(value="Example Output"),
25
+ ),
26
+ field_values_t.FieldArgumentValue(
27
+ field_key=identifier_t.IdentifierKeyRefName(ref_name="core_output_unitsId"),
28
+ value=field_values_t.FieldValueId(
29
+ entity_type=entity_t.EntityType.UNITS,
30
+ identifier_key=identifier_t.IdentifierKeyId(id=1),
31
+ ),
32
+ ),
33
+ field_values_t.FieldArgumentValue(
34
+ field_key=identifier_t.IdentifierKeyRefName(
35
+ ref_name="core_output_outputMaterialFamilies"
36
+ ),
37
+ value=field_values_t.FieldValueIds(
38
+ entity_type=entity_t.EntityType.MATERIAL_FAMILY,
39
+ identifier_keys=[identifier_t.IdentifierKeyId(id=1)],
40
+ ),
41
+ ),
42
+ field_values_t.FieldArgumentValue(
43
+ field_key=identifier_t.IdentifierKeyRefName(
44
+ ref_name="core_output_quantityType"
45
+ ),
46
+ value=field_values_t.FieldValueFieldOption(value="numeric"),
47
+ ),
48
+ ],
49
+ )
50
+ ```
51
+
52
+ Example Response:
53
+
54
+ ```{code}
55
+ Data(modification_made=True, result_id=653, entity=None, result_values=None)
56
+ ```
@@ -0,0 +1,6 @@
1
+ # Integration Examples
2
+
3
+ ```{toctree}
4
+ create_ingredient
5
+ create_output
6
+ ```
@@ -1,5 +1,5 @@
1
1
  furo==2025.7.19
2
- myst-parser==4.0.0
2
+ myst-parser==4.0.1
3
3
  sphinx-autoapi==3.6.0
4
4
  sphinx-copybutton==0.5.2
5
5
  Sphinx==8.2.0
@@ -0,0 +1,7 @@
1
+ from uncountable.core.client import Client
2
+ from uncountable.core.types import AuthDetailsApiKey
3
+
4
+ client = Client(
5
+ base_url="https://app.uncountable.com",
6
+ auth_details=AuthDetailsApiKey(api_id="x", api_secret_key="x"),
7
+ )
@@ -9,7 +9,7 @@ dependencies = [
9
9
  "ruff == 0.*",
10
10
  "openpyxl == 3.*",
11
11
  "more_itertools == 10.*",
12
- "types-paramiko ==3.5.0.20250708",
12
+ "types-paramiko ==3.5.0.20250801",
13
13
  "types-openpyxl == 3.*",
14
14
  "types-pysftp == 0.*",
15
15
  "types-pytz ==2025.*",
@@ -0,0 +1,7 @@
1
+ from uncountable.core.client import Client
2
+ from uncountable.core.types import AuthDetailsOAuth
3
+
4
+ client = Client(
5
+ base_url="https://app.uncountable.com",
6
+ auth_details=AuthDetailsOAuth(refresh_token="x"),
7
+ )
@@ -5,6 +5,9 @@ def is_namedtuple_type(x: Any) -> bool:
5
5
  if not hasattr(x, "__annotations__"):
6
6
  return False
7
7
 
8
+ if not hasattr(x, "__bases__"):
9
+ return False
10
+
8
11
  b = x.__bases__
9
12
  if len(b) != 1 or b[0] is not tuple:
10
13
  return False
@@ -267,7 +267,9 @@ def _extract_and_validate_layout(
267
267
  for group in ext_info.layout.groups:
268
268
  fields = set(group.fields or [])
269
269
  for field in fields:
270
- assert field in stype.properties, f"layout-refers-to-missing-field:{field}"
270
+ assert field in stype.properties or field == DISCRIMINATOR_COMMON_NAME, (
271
+ f"layout-refers-to-missing-field:{field}"
272
+ )
271
273
 
272
274
  local_ref_name = None
273
275
  if group.ref_name is not None:
@@ -314,6 +316,9 @@ def _pull_property_from_type_recursively(
314
316
  return _pull_property_from_type_recursively(stype.base, property_name)
315
317
 
316
318
 
319
+ DISCRIMINATOR_COMMON_NAME = "type"
320
+
321
+
317
322
  def _validate_type_ext_info(
318
323
  stype: builder.SpecTypeDefnObject,
319
324
  ) -> tuple[ExtInfoLayout | None, type_info_t.ExtInfo | None]:
@@ -324,12 +329,16 @@ def _validate_type_ext_info(
324
329
  if ext_info.label_fields is not None:
325
330
  assert stype.properties is not None
326
331
  for name in ext_info.label_fields:
332
+ if name == DISCRIMINATOR_COMMON_NAME:
333
+ continue
327
334
  prop = _pull_property_from_type_recursively(stype, name)
328
335
  assert prop is not None, f"missing-label-field:{name}"
329
336
 
330
337
  if ext_info.actions is not None:
331
338
  assert stype.properties is not None
332
339
  for action in ext_info.actions:
340
+ if action.property == DISCRIMINATOR_COMMON_NAME:
341
+ continue
333
342
  prop = _pull_property_from_type_recursively(stype, action.property)
334
343
  assert prop is not None, f"missing-action-field:{action.property}"
335
344
 
@@ -64,7 +64,7 @@ dependencies = [
64
64
  "opentelemetry-exporter-otlp-proto-common==1.*",
65
65
  "opentelemetry-exporter-otlp-proto-http==1.*",
66
66
  "opentelemetry-sdk==1.*",
67
- "paramiko == 3.*",
67
+ "paramiko ==4.*",
68
68
  "boto3 == 1.*",
69
69
  "flask == 3.*",
70
70
  "simplejson == 3.*",
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import functools
3
+ import json
3
4
  from dataclasses import dataclass
4
5
 
5
6
  from flask.wrappers import Response
@@ -42,7 +43,8 @@ class HttpException(Exception):
42
43
 
43
44
  def make_error_response(self) -> Response:
44
45
  return Response(
45
- status=self.error_code, response={"error": {"message": str(self)}}
46
+ status=self.error_code,
47
+ response=json.dumps({"error": {"message": str(self)}}),
46
48
  )
47
49
 
48
50
 
@@ -5,6 +5,7 @@ import sys
5
5
  import time
6
6
  from dataclasses import dataclass
7
7
  from datetime import UTC
8
+ from enum import StrEnum
8
9
 
9
10
  from opentelemetry.trace import get_current_span
10
11
 
@@ -19,11 +20,19 @@ from uncountable.integration.telemetry import Logger
19
20
 
20
21
  SHUTDOWN_TIMEOUT_SECS = 30
21
22
 
23
+ AnyProcess = multiprocessing.Process | subprocess.Popen[bytes]
24
+
25
+
26
+ class ProcessName(StrEnum):
27
+ QUEUE_RUNNER = "queue_runner"
28
+ CRON_SERVER = "cron_server"
29
+ UWSGI = "uwsgi"
30
+
22
31
 
23
32
  @dataclass(kw_only=True)
24
33
  class ProcessInfo:
25
- name: str
26
- process: multiprocessing.Process | subprocess.Popen[bytes]
34
+ name: ProcessName
35
+ process: AnyProcess
27
36
 
28
37
  @property
29
38
  def is_alive(self) -> bool:
@@ -46,14 +55,14 @@ class ProcessInfo:
46
55
  return self.process.poll()
47
56
 
48
57
 
49
- def handle_shutdown(logger: Logger, processes: list[ProcessInfo]) -> None:
58
+ def handle_shutdown(logger: Logger, processes: dict[ProcessName, ProcessInfo]) -> None:
50
59
  logger.log_info("received shutdown command, shutting down sub-processes")
51
- for proc_info in processes:
60
+ for proc_info in processes.values():
52
61
  if proc_info.is_alive:
53
62
  proc_info.process.terminate()
54
63
 
55
64
  shutdown_start = time.time()
56
- still_living_processes = processes
65
+ still_living_processes = list(processes.values())
57
66
  while (
58
67
  time.time() - shutdown_start < SHUTDOWN_TIMEOUT_SECS
59
68
  and len(still_living_processes) > 0
@@ -82,14 +91,50 @@ def handle_shutdown(logger: Logger, processes: list[ProcessInfo]) -> None:
82
91
  proc_info.process.kill()
83
92
 
84
93
 
85
- def check_process_alive(logger: Logger, processes: list[ProcessInfo]) -> None:
86
- for proc_info in processes:
94
+ def restart_process(
95
+ logger: Logger, proc_info: ProcessInfo, processes: dict[ProcessName, ProcessInfo]
96
+ ) -> None:
97
+ logger.log_error(
98
+ f"process {proc_info.name} shut down unexpectedly - exit code {proc_info.exitcode}. Restarting..."
99
+ )
100
+
101
+ match proc_info.name:
102
+ case ProcessName.QUEUE_RUNNER:
103
+ queue_proc = multiprocessing.Process(target=start_queue_runner)
104
+ queue_proc.start()
105
+ new_info = ProcessInfo(name=ProcessName.QUEUE_RUNNER, process=queue_proc)
106
+ processes[ProcessName.QUEUE_RUNNER] = new_info
107
+ try:
108
+ _wait_queue_runner_online()
109
+ logger.log_info("queue runner restarted successfully")
110
+ except Exception as e:
111
+ logger.log_exception(e)
112
+ logger.log_error(
113
+ "queue runner failed to restart, shutting down scheduler"
114
+ )
115
+ handle_shutdown(logger, processes)
116
+ sys.exit(1)
117
+
118
+ case ProcessName.CRON_SERVER:
119
+ cron_proc = multiprocessing.Process(target=cron_target)
120
+ cron_proc.start()
121
+ new_info = ProcessInfo(name=ProcessName.CRON_SERVER, process=cron_proc)
122
+ processes[ProcessName.CRON_SERVER] = new_info
123
+ logger.log_info("cron server restarted successfully")
124
+
125
+ case ProcessName.UWSGI:
126
+ uwsgi_proc: AnyProcess = subprocess.Popen(["uwsgi", "--die-on-term"])
127
+ new_info = ProcessInfo(name=ProcessName.UWSGI, process=uwsgi_proc)
128
+ processes[ProcessName.UWSGI] = new_info
129
+ logger.log_info("uwsgi restarted successfully")
130
+
131
+
132
+ def check_process_alive(
133
+ logger: Logger, processes: dict[ProcessName, ProcessInfo]
134
+ ) -> None:
135
+ for proc_info in processes.values():
87
136
  if not proc_info.is_alive:
88
- logger.log_error(
89
- f"process {proc_info.name} shut down unexpectedly! shutting down scheduler; exit code is {proc_info.exitcode}"
90
- )
91
- handle_shutdown(logger, processes)
92
- sys.exit(1)
137
+ restart_process(logger, proc_info, processes)
93
138
 
94
139
 
95
140
  def _wait_queue_runner_online() -> None:
@@ -113,17 +158,17 @@ def _wait_queue_runner_online() -> None:
113
158
 
114
159
  def main() -> None:
115
160
  logger = Logger(get_current_span())
116
- processes: list[ProcessInfo] = []
161
+ processes: dict[ProcessName, ProcessInfo] = {}
117
162
 
118
163
  multiprocessing.set_start_method("forkserver")
119
164
 
120
165
  def add_process(process: ProcessInfo) -> None:
121
- processes.append(process)
166
+ processes[process.name] = process
122
167
  logger.log_info(f"started process {process.name}")
123
168
 
124
169
  runner_process = multiprocessing.Process(target=start_queue_runner)
125
170
  runner_process.start()
126
- add_process(ProcessInfo(name="queue runner", process=runner_process))
171
+ add_process(ProcessInfo(name=ProcessName.QUEUE_RUNNER, process=runner_process))
127
172
 
128
173
  try:
129
174
  _wait_queue_runner_online()
@@ -134,13 +179,13 @@ def main() -> None:
134
179
 
135
180
  cron_process = multiprocessing.Process(target=cron_target)
136
181
  cron_process.start()
137
- add_process(ProcessInfo(name="cron server", process=cron_process))
182
+ add_process(ProcessInfo(name=ProcessName.CRON_SERVER, process=cron_process))
138
183
 
139
184
  uwsgi_process = subprocess.Popen([
140
185
  "uwsgi",
141
186
  "--die-on-term",
142
187
  ])
143
- add_process(ProcessInfo(name="uwsgi", process=uwsgi_process))
188
+ add_process(ProcessInfo(name=ProcessName.UWSGI, process=uwsgi_process))
144
189
 
145
190
  try:
146
191
  while True:
@@ -1,4 +1,5 @@
1
1
  import functools
2
+ import json
2
3
  import os
3
4
  import time
4
5
  import traceback
@@ -32,6 +33,11 @@ def _cast_attributes(attributes: dict[str, base_t.JsonValue]) -> Attributes:
32
33
  return cast(Attributes, attributes)
33
34
 
34
35
 
36
+ def one_line_formatter(record: LogRecord) -> str:
37
+ json_data = record.to_json()
38
+ return json.dumps(json.loads(json_data), separators=(",", ":")) + "\n"
39
+
40
+
35
41
  @functools.cache
36
42
  def get_otel_resource() -> Resource:
37
43
  attributes: dict[str, base_t.JsonValue] = {
@@ -60,7 +66,9 @@ def get_otel_tracer() -> Tracer:
60
66
  @functools.cache
61
67
  def get_otel_logger() -> OTELLogger:
62
68
  provider = LoggerProvider(resource=get_otel_resource())
63
- provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter()))
69
+ provider.add_log_record_processor(
70
+ BatchLogRecordProcessor(ConsoleLogExporter(formatter=one_line_formatter))
71
+ )
64
72
  if get_otel_enabled():
65
73
  provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
66
74
  _logs.set_logger_provider(provider)