UncountablePythonSDK 0.0.73__tar.gz → 0.0.75__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 (293) hide show
  1. {uncountablepythonsdk-0.0.73/UncountablePythonSDK.egg-info → uncountablepythonsdk-0.0.75}/PKG-INFO +1 -1
  2. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75/UncountablePythonSDK.egg-info}/PKG-INFO +1 -1
  3. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/argument_parser/__init__.py +1 -0
  4. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/argument_parser/argument_parser.py +13 -1
  5. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/serial_class.py +13 -0
  6. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/builder.py +68 -21
  7. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/emit_python.py +0 -3
  8. uncountablepythonsdk-0.0.75/pkgs/type_spec/emit_typescript.py +256 -0
  9. uncountablepythonsdk-0.0.75/pkgs/type_spec/emit_typescript_util.py +265 -0
  10. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/type_info/emit_type_info.py +7 -7
  11. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/util.py +1 -1
  12. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/worker.py +14 -14
  13. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/create_entities.py +1 -1
  14. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/create_entity.py +1 -1
  15. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/uploader/invoke_uploader.py +2 -1
  16. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/async_batch_processor.py +4 -1
  17. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/client_base.py +6 -3
  18. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/entity_t.py +2 -0
  19. uncountablepythonsdk-0.0.73/pkgs/type_spec/emit_typescript.py +0 -477
  20. uncountablepythonsdk-0.0.73/pkgs/type_spec/emit_typescript_util.py +0 -32
  21. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/.github/workflows/documentation.yml +0 -0
  22. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/.github/workflows/publish.yml +0 -0
  23. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/.gitignore +0 -0
  24. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/README.md +0 -0
  25. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/UncountablePythonSDK.egg-info/SOURCES.txt +0 -0
  26. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
  27. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/UncountablePythonSDK.egg-info/requires.txt +0 -0
  28. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
  29. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/.gitignore +0 -0
  30. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/conf.py +0 -0
  31. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/index.md +0 -0
  32. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/justfile +0 -0
  33. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/quickstart.md +0 -0
  34. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/requirements.txt +0 -0
  35. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/android-chrome-192x192.png +0 -0
  36. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/android-chrome-512x512.png +0 -0
  37. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/apple-touch-icon.png +0 -0
  38. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/browserconfig.xml +0 -0
  39. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/favicon-16x16.png +0 -0
  40. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/favicon-32x32.png +0 -0
  41. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/manifest.json +0 -0
  42. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/mstile-150x150.png +0 -0
  43. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/favicons/safari-pinned-tab.svg +0 -0
  44. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/docs/static/logo_blue.png +0 -0
  45. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/async_batch.py +0 -0
  46. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/create_entity.py +0 -0
  47. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/edit_recipe_inputs.py +0 -0
  48. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/integration-server/jobs/materials_auto/example_cron.py +0 -0
  49. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/integration-server/jobs/materials_auto/profile.yaml +0 -0
  50. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/integration-server/pyproject.toml +0 -0
  51. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/invoke_uploader.py +0 -0
  52. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/set_recipe_metadata_file.py +0 -0
  53. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/set_recipe_output_file_sdk.py +0 -0
  54. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/examples/upload_files.py +0 -0
  55. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/__init__.py +0 -0
  56. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/argument_parser/_is_enum.py +0 -0
  57. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/argument_parser/_is_namedtuple.py +0 -0
  58. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/argument_parser/case_convert.py +0 -0
  59. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/__init__.py +0 -0
  60. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/_gdrive_session.py +0 -0
  61. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/_local_session.py +0 -0
  62. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/_s3_session.py +0 -0
  63. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/_sftp_session.py +0 -0
  64. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/file_type_utils.py +0 -0
  65. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/filesystem_utils/filesystem_session.py +0 -0
  66. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/py.typed +0 -0
  67. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/__init__.py +0 -0
  68. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/missing_sentry.py +0 -0
  69. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/opaque_key.py +0 -0
  70. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/serial_union.py +0 -0
  71. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization/yaml.py +0 -0
  72. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization_util/__init__.py +0 -0
  73. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
  74. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization_util/convert_to_snakecase.py +0 -0
  75. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/serialization_util/serialization_helpers.py +0 -0
  76. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/strenum_compat/__init__.py +0 -0
  77. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/strenum_compat/strenum_compat.py +0 -0
  78. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/__init__.py +0 -0
  79. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/__main__.py +0 -0
  80. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/actions_registry/__init__.py +0 -0
  81. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/actions_registry/__main__.py +0 -0
  82. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/actions_registry/emit_typescript.py +0 -0
  83. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/config.py +0 -0
  84. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/emit_io_ts.py +0 -0
  85. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/emit_open_api.py +0 -0
  86. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/emit_open_api_util.py +0 -0
  87. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/load_types.py +0 -0
  88. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/open_api_util.py +0 -0
  89. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/parts/base.py.prepart +0 -0
  90. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/parts/base.ts.prepart +0 -0
  91. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/test.py +0 -0
  92. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/type_info/__main__.py +0 -0
  93. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/value_spec/__init__.py +0 -0
  94. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/value_spec/__main__.py +0 -0
  95. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/value_spec/convert_type.py +0 -0
  96. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/value_spec/emit_python.py +0 -0
  97. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pkgs/type_spec/value_spec/types.py +0 -0
  98. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/pyproject.toml +0 -0
  99. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/setup.cfg +0 -0
  100. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/__init__.py +0 -0
  101. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/__init__.py +0 -0
  102. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/async_batch.py +0 -0
  103. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/client.py +0 -0
  104. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/environment.py +0 -0
  105. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/file_upload.py +0 -0
  106. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/core/types.py +0 -0
  107. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/__init__.py +0 -0
  108. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/cli.py +0 -0
  109. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/construct_client.py +0 -0
  110. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/cron.py +0 -0
  111. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/db/__init__.py +0 -0
  112. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/db/connect.py +0 -0
  113. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/db/session.py +0 -0
  114. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/entrypoint.py +0 -0
  115. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/executors/__init__.py +0 -0
  116. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/executors/executors.py +0 -0
  117. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/executors/generic_upload_executor.py +0 -0
  118. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/executors/script_executor.py +0 -0
  119. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/job.py +0 -0
  120. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/__init__.py +0 -0
  121. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/__init__.py +0 -0
  122. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/command_client.py +0 -0
  123. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/command_server.py +0 -0
  124. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
  125. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/protocol/command_server.proto +0 -0
  126. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +0 -0
  127. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +0 -0
  128. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +0 -0
  129. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/command_server/types.py +0 -0
  130. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/datastore/__init__.py +0 -0
  131. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/datastore/datastore_sqlite.py +0 -0
  132. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/datastore/interface.py +0 -0
  133. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/datastore/model.py +0 -0
  134. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/job_scheduler.py +0 -0
  135. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/queue_runner.py +0 -0
  136. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/queue_runner/types.py +0 -0
  137. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/scan_profiles.py +0 -0
  138. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/scheduler.py +0 -0
  139. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/secret_retrieval/__init__.py +0 -0
  140. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/secret_retrieval/retrieve_secret.py +0 -0
  141. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/server.py +0 -0
  142. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/telemetry.py +0 -0
  143. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/integration/webhook_server/entrypoint.py +0 -0
  144. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/py.typed +0 -0
  145. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/__init__.py +0 -0
  146. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/__init__.py +0 -0
  147. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/batch/__init__.py +0 -0
  148. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/batch/execute_batch.py +0 -0
  149. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/batch/execute_batch_load_async.py +0 -0
  150. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/chemical/__init__.py +0 -0
  151. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/chemical/convert_chemical_formats.py +0 -0
  152. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/__init__.py +0 -0
  153. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/get_entities_data.py +0 -0
  154. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/list_entities.py +0 -0
  155. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/lock_entity.py +0 -0
  156. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
  157. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/set_values.py +0 -0
  158. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/transition_entity_phase.py +0 -0
  159. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/entity/unlock_entity.py +0 -0
  160. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/equipment/__init__.py +0 -0
  161. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/equipment/associate_equipment_input.py +0 -0
  162. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/field_options/__init__.py +0 -0
  163. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/field_options/upsert_field_options.py +0 -0
  164. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/id_source/__init__.py +0 -0
  165. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/id_source/list_id_source.py +0 -0
  166. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/id_source/match_id_source.py +0 -0
  167. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/input_groups/__init__.py +0 -0
  168. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
  169. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/__init__.py +0 -0
  170. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/create_inputs.py +0 -0
  171. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/get_input_data.py +0 -0
  172. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/get_input_names.py +0 -0
  173. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
  174. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
  175. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/set_input_category.py +0 -0
  176. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/set_input_subcategories.py +0 -0
  177. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/inputs/set_intermediate_type.py +0 -0
  178. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/material_families/__init__.py +0 -0
  179. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/material_families/update_entity_material_families.py +0 -0
  180. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/outputs/__init__.py +0 -0
  181. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/outputs/get_output_data.py +0 -0
  182. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/outputs/get_output_names.py +0 -0
  183. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
  184. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/permissions/__init__.py +0 -0
  185. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/permissions/set_core_permissions.py +0 -0
  186. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/project/__init__.py +0 -0
  187. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/project/get_projects.py +0 -0
  188. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/project/get_projects_data.py +0 -0
  189. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipe_links/__init__.py +0 -0
  190. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipe_links/create_recipe_link.py +0 -0
  191. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipe_links/remove_recipe_link.py +0 -0
  192. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
  193. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
  194. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/__init__.py +0 -0
  195. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/add_recipe_to_project.py +0 -0
  196. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/archive_recipes.py +0 -0
  197. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/associate_recipe_as_input.py +0 -0
  198. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/associate_recipe_as_lot.py +0 -0
  199. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/clear_recipe_outputs.py +0 -0
  200. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/create_recipe.py +0 -0
  201. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/create_recipes.py +0 -0
  202. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/disassociate_recipe_as_input.py +0 -0
  203. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/edit_recipe_inputs.py +0 -0
  204. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_curve.py +0 -0
  205. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
  206. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
  207. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
  208. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
  209. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/get_recipes_data.py +0 -0
  210. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/lock_recipes.py +0 -0
  211. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/remove_recipe_from_project.py +0 -0
  212. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
  213. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_metadata.py +0 -0
  214. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_output_annotations.py +0 -0
  215. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_output_file.py +0 -0
  216. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_outputs.py +0 -0
  217. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/set_recipe_tags.py +0 -0
  218. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/unarchive_recipes.py +0 -0
  219. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/recipes/unlock_recipes.py +0 -0
  220. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/triggers/__init__.py +0 -0
  221. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/triggers/run_trigger.py +0 -0
  222. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/api/uploader/__init__.py +0 -0
  223. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/async_batch.py +0 -0
  224. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/async_batch_t.py +0 -0
  225. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/base.py +0 -0
  226. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/base_t.py +0 -0
  227. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/calculations.py +0 -0
  228. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/calculations_t.py +0 -0
  229. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/chemical_structure.py +0 -0
  230. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/chemical_structure_t.py +0 -0
  231. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/client_config.py +0 -0
  232. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/client_config_t.py +0 -0
  233. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/curves.py +0 -0
  234. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/curves_t.py +0 -0
  235. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/entity.py +0 -0
  236. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/experiment_groups.py +0 -0
  237. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/experiment_groups_t.py +0 -0
  238. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/field_values.py +0 -0
  239. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/field_values_t.py +0 -0
  240. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/fields.py +0 -0
  241. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/fields_t.py +0 -0
  242. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/generic_upload.py +0 -0
  243. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/generic_upload_t.py +0 -0
  244. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/id_source.py +0 -0
  245. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/id_source_t.py +0 -0
  246. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/identifier.py +0 -0
  247. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/identifier_t.py +0 -0
  248. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/input_attributes.py +0 -0
  249. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/input_attributes_t.py +0 -0
  250. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/inputs.py +0 -0
  251. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/inputs_t.py +0 -0
  252. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/job_definition.py +0 -0
  253. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/job_definition_t.py +0 -0
  254. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/outputs.py +0 -0
  255. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/outputs_t.py +0 -0
  256. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/overrides.py +0 -0
  257. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/overrides_t.py +0 -0
  258. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/permissions.py +0 -0
  259. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/permissions_t.py +0 -0
  260. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/phases.py +0 -0
  261. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/phases_t.py +0 -0
  262. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/post_base.py +0 -0
  263. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/post_base_t.py +0 -0
  264. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/queued_job.py +0 -0
  265. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/queued_job_t.py +0 -0
  266. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_identifiers.py +0 -0
  267. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_identifiers_t.py +0 -0
  268. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_inputs.py +0 -0
  269. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_inputs_t.py +0 -0
  270. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_links.py +0 -0
  271. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_links_t.py +0 -0
  272. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_metadata.py +0 -0
  273. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_metadata_t.py +0 -0
  274. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_output_metadata.py +0 -0
  275. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_output_metadata_t.py +0 -0
  276. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_tags.py +0 -0
  277. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_tags_t.py +0 -0
  278. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_workflow_steps.py +0 -0
  279. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipe_workflow_steps_t.py +0 -0
  280. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipes.py +0 -0
  281. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/recipes_t.py +0 -0
  282. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/response.py +0 -0
  283. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/response_t.py +0 -0
  284. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/secret_retrieval.py +0 -0
  285. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/secret_retrieval_t.py +0 -0
  286. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/units.py +0 -0
  287. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/units_t.py +0 -0
  288. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/users.py +0 -0
  289. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/users_t.py +0 -0
  290. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/webhook_job.py +0 -0
  291. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/webhook_job_t.py +0 -0
  292. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/uncountable/types/workflows.py +0 -0
  293. {uncountablepythonsdk-0.0.73 → uncountablepythonsdk-0.0.75}/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.73
3
+ Version: 0.0.75
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.73
3
+ Version: 0.0.75
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
@@ -1,4 +1,5 @@
1
1
  from .argument_parser import CachedParser as CachedParser
2
+ from .argument_parser import ParserFunction as ParserFunction
2
3
  from .argument_parser import ParserOptions as ParserOptions
3
4
  from .argument_parser import build_parser as build_parser
4
5
  from .case_convert import camel_to_snake_case as camel_to_snake_case
@@ -1,4 +1,5 @@
1
1
  import dataclasses
2
+ import math
2
3
  import types
3
4
  import typing
4
5
  from collections import defaultdict
@@ -299,7 +300,18 @@ def _build_parser_inner(
299
300
 
300
301
  return parse_str
301
302
 
302
- if parsed_type in (float, dict, bool, Decimal) or is_string_enum_class(parsed_type):
303
+ if parsed_type in (float, Decimal):
304
+
305
+ def parse_as_numeric_type(value: typing.Any) -> T:
306
+ numeric_value: Decimal | float = parsed_type(value) # type: ignore
307
+ if math.isnan(numeric_value):
308
+ raise ValueError(f"Invalid numeric value: {numeric_value}")
309
+
310
+ return numeric_value # type: ignore
311
+
312
+ return parse_as_numeric_type
313
+
314
+ if parsed_type in (dict, bool) or is_string_enum_class(parsed_type):
303
315
  return lambda value: parsed_type(value) # type: ignore
304
316
 
305
317
  if parsed_type is MissingSentryType:
@@ -15,6 +15,10 @@ class _SerialClassData:
15
15
  to_string_values: set[str] = dataclasses.field(default_factory=set)
16
16
  parse_require: set[str] = dataclasses.field(default_factory=set)
17
17
  named_type_path: Optional[str] = None
18
+ # Tracks if this data was provided as a decorator to the type.
19
+ # This is used to track "proper types" which are appropriate
20
+ # for serialization and/or dynamic discovery
21
+ from_decorator: bool = False
18
22
 
19
23
 
20
24
  EMPTY_SERIAL_CLASS_DATA = _SerialClassData()
@@ -58,6 +62,7 @@ def serial_class(
58
62
  to_string_values=to_string_values or set(),
59
63
  parse_require=parse_require or set(),
60
64
  named_type_path=named_type_path,
65
+ from_decorator=True,
61
66
  )
62
67
  return orig_class
63
68
 
@@ -83,6 +88,14 @@ class SerialClassDataInspector:
83
88
  def has_parse_require(self, key: str) -> bool:
84
89
  return key in self.current.parse_require
85
90
 
91
+ @property
92
+ def from_decorator(self) -> bool:
93
+ return self.current.from_decorator
94
+
95
+ @property
96
+ def named_type_path(self) -> Optional[str]:
97
+ return self.current.named_type_path
98
+
86
99
 
87
100
  def _get_merged_serial_class_data(type_class: type[Any]) -> _SerialClassData | None:
88
101
  base_class_data = (
@@ -307,6 +307,9 @@ class SpecTypeDefn(SpecType):
307
307
  def is_base_type(self, type_: BaseTypeName) -> bool:
308
308
  return self.is_base and self.name == type_
309
309
 
310
+ def can_process(self, builder: SpecBuilder, data: RawDict) -> bool:
311
+ return True
312
+
310
313
  @abc.abstractmethod
311
314
  def process(self, builder: SpecBuilder, data: RawDict) -> None: ...
312
315
 
@@ -666,15 +669,30 @@ class SpecTypeDefnStringEnum(SpecTypeDefn):
666
669
  self.desc: str | None = None
667
670
  self.sql_type_name: Optional[str] = None
668
671
  self.emit_id_source = False
672
+ self.source_enums: list[SpecType] = []
673
+
674
+ def can_process(self, builder: SpecBuilder, data: dict[Any, Any]) -> bool:
675
+ source_enums = data.get("source_enums")
676
+ try:
677
+ for sub_type_str in source_enums or []:
678
+ sub_type = builder.parse_type(self.namespace, sub_type_str)
679
+ assert isinstance(sub_type, SpecTypeDefnStringEnum)
680
+ assert len(sub_type.values) > 0
681
+ except AssertionError:
682
+ return False
683
+ return super().can_process(builder, data)
669
684
 
670
685
  def process(self, builder: SpecBuilder, data: RawDict) -> None:
671
686
  super().base_process(
672
- builder, data, ["type", "desc", "values", "name_case", "sql", "emit"]
687
+ builder,
688
+ data,
689
+ ["type", "desc", "values", "name_case", "sql", "emit", "source_enums"],
673
690
  )
674
691
  self.name_case = NameCase(data.get("name_case", "convert"))
675
692
  self.values = {}
676
- data_values = data["values"]
693
+ data_values = data.get("values")
677
694
  self.desc = data.get("desc", None)
695
+ source_enums = data.get("source_enums", None)
678
696
  if isinstance(data_values, dict):
679
697
  for name, value in data_values.items():
680
698
  builder.push_where(name)
@@ -717,7 +735,8 @@ class SpecTypeDefnStringEnum(SpecTypeDefn):
717
735
  )
718
736
  self.values[value] = StringEnumEntry(name=value, value=value)
719
737
  else:
720
- raise Exception("unsupported values type")
738
+ if source_enums is None or data_values is not None:
739
+ raise Exception("unsupported values type")
721
740
 
722
741
  sql_data = data.get("sql")
723
742
  if sql_data is not None:
@@ -739,9 +758,18 @@ class SpecTypeDefnStringEnum(SpecTypeDefn):
739
758
  builder.ensure(
740
759
  entry.label is not None, f"need-label-for-id-source:{entry.name}"
741
760
  )
761
+ for sub_type_str in source_enums or []:
762
+ sub_type = builder.parse_type(self.namespace, sub_type_str)
763
+ self.source_enums.append(sub_type)
764
+
765
+ for sub_type in self.source_enums:
766
+ builder.push_where(sub_type.name)
767
+ if isinstance(sub_type, SpecTypeDefnStringEnum):
768
+ self.values.update(sub_type.values)
769
+ builder.pop_where()
742
770
 
743
771
  def get_referenced_types(self) -> list[SpecType]:
744
- return []
772
+ return self.source_enums
745
773
 
746
774
 
747
775
  TOKEN_ENDPOINT = "$endpoint"
@@ -1122,28 +1150,41 @@ class SpecNamespace:
1122
1150
  Complete the definition of each type.
1123
1151
  """
1124
1152
  builder.push_where(self.name)
1125
- for full_name, defn in data.items():
1126
- parsed_name = parse_type_str(full_name)[0]
1127
- name = parsed_name.name
1153
+ items_to_process: list[NameDataPair] = [
1154
+ NameDataPair(full_name=full_name, data=defn)
1155
+ for full_name, defn in data.items()
1156
+ ]
1157
+ while len(items_to_process) > 0:
1158
+ deferred_items: list[NameDataPair] = []
1159
+ for item in items_to_process:
1160
+ full_name = item.full_name
1161
+ defn = item.data
1162
+ parsed_name = parse_type_str(full_name)[0]
1163
+ name = parsed_name.name
1164
+
1165
+ if name in [TOKEN_EMIT_IO_TS, TOKEN_EMIT_TYPE_INFO, TOKEN_IMPORT]:
1166
+ continue
1128
1167
 
1129
- if name in [TOKEN_EMIT_IO_TS, TOKEN_EMIT_TYPE_INFO, TOKEN_IMPORT]:
1130
- continue
1168
+ builder.push_where(name)
1131
1169
 
1132
- builder.push_where(name)
1170
+ if "value" in defn:
1171
+ spec_constant = self.constants[name]
1172
+ spec_constant.process(builder, defn)
1133
1173
 
1134
- if "value" in defn:
1135
- spec_constant = self.constants[name]
1136
- spec_constant.process(builder, defn)
1174
+ elif name == TOKEN_ENDPOINT:
1175
+ assert self.endpoint
1176
+ self.endpoint.process(builder, defn)
1137
1177
 
1138
- elif name == TOKEN_ENDPOINT:
1139
- assert self.endpoint
1140
- self.endpoint.process(builder, defn)
1141
-
1142
- else:
1143
- spec_type = self.types[name]
1144
- spec_type.process(builder, defn)
1178
+ else:
1179
+ spec_type = self.types[name]
1180
+ if spec_type.can_process(builder, defn):
1181
+ spec_type.process(builder, defn)
1182
+ else:
1183
+ deferred_items.append(item)
1145
1184
 
1146
- builder.pop_where()
1185
+ builder.pop_where()
1186
+ assert len(deferred_items) < len(items_to_process)
1187
+ items_to_process = [deferred for deferred in deferred_items]
1147
1188
 
1148
1189
  builder.pop_where()
1149
1190
 
@@ -1158,6 +1199,12 @@ class NamespaceDataPair:
1158
1199
  data: RawDict
1159
1200
 
1160
1201
 
1202
+ @dataclass(kw_only=True)
1203
+ class NameDataPair:
1204
+ full_name: str
1205
+ data: RawDict
1206
+
1207
+
1161
1208
  class SpecBuilder:
1162
1209
  def __init__(self, *, api_endpoints: dict[str, str], top_namespace: str) -> None:
1163
1210
  self.top_namespace = top_namespace
@@ -44,7 +44,6 @@ class TrackingContext:
44
44
  use_enum: bool = False
45
45
  use_serial_string_enum: bool = False
46
46
  use_dataclass: bool = False
47
- use_serial_class: bool = False
48
47
  use_serial_union: bool = False
49
48
  use_missing: bool = False
50
49
  use_opaque_key: bool = False
@@ -223,7 +222,6 @@ def _emit_types_imports(*, out: io.StringIO, ctx: Context) -> None:
223
222
  out.write("from pkgs.strenum_compat import StrEnum\n")
224
223
  if ctx.use_dataclass:
225
224
  out.write("import dataclasses\n")
226
- if ctx.use_serial_class:
227
225
  out.write("from pkgs.serialization import serial_class\n")
228
226
  if ctx.use_serial_union:
229
227
  out.write("from pkgs.serialization import serial_union_annotation\n")
@@ -834,7 +832,6 @@ def _emit_type(ctx: Context, stype: builder.SpecType) -> None:
834
832
  _emit_generic(ctx, stype.get_generic())
835
833
 
836
834
  # Emit serial_class decorator
837
- ctx.use_serial_class = True
838
835
  ctx.out.write("@serial_class(\n")
839
836
  ctx.out.write(
840
837
  f"{INDENT}named_type_path={util.encode_common_string(_named_type_path(ctx, stype))},\n"
@@ -0,0 +1,256 @@
1
+ import io
2
+ import os
3
+
4
+ from . import builder, util
5
+ from .config import TypeScriptConfig
6
+ from .emit_io_ts import emit_type_io_ts
7
+ from .emit_typescript_util import (
8
+ MODIFY_NOTICE,
9
+ EmitTypescriptContext,
10
+ emit_namespace_imports_ts,
11
+ emit_type_ts,
12
+ emit_value_ts,
13
+ resolve_namespace_name,
14
+ resolve_namespace_ref,
15
+ ts_type_name,
16
+ )
17
+
18
+
19
+ def emit_typescript(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
20
+ _emit_types(builder, config)
21
+ _emit_id_source(builder, config)
22
+
23
+
24
+ def _emit_types(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
25
+ index_out = io.StringIO()
26
+ index_out.write(MODIFY_NOTICE)
27
+
28
+ index_out_end = io.StringIO()
29
+
30
+ for namespace in sorted(
31
+ builder.namespaces.values(),
32
+ key=lambda ns: resolve_namespace_name(ns),
33
+ ):
34
+ ctx = EmitTypescriptContext(out=io.StringIO(), namespace=namespace)
35
+
36
+ _emit_namespace(ctx, config, namespace)
37
+
38
+ prepart = builder.preparts["typescript"].get(namespace.name)
39
+ part = builder.parts["typescript"].get(namespace.name)
40
+
41
+ # Don't emit an empty file
42
+ if (
43
+ prepart is None
44
+ and part is None
45
+ and len(namespace.types) == 0
46
+ and len(namespace.constants) == 0
47
+ ):
48
+ # Try to capture some common incompleteness errors
49
+ if namespace.endpoint is None or namespace.endpoint.function is None:
50
+ raise Exception(
51
+ f"Namespace {"/".join(namespace.path)} is incomplete. It should have an endpoint with function, types, and/or constants"
52
+ )
53
+ continue
54
+
55
+ full = io.StringIO()
56
+ if prepart:
57
+ full.write(MODIFY_NOTICE)
58
+ full.write(f"// === START section from {namespace.name}.ts.prepart ===\n")
59
+ full.write(prepart)
60
+ full.write(f"// === END section from {namespace.name}.ts.prepart ===\n")
61
+ full.write("\n")
62
+
63
+ emit_namespace_imports_ts(ctx.namespaces, out=full, current_namespace=namespace)
64
+ if namespace.emit_io_ts:
65
+ full.write("import * as IO from 'io-ts';")
66
+ full.write(ctx.out.getvalue())
67
+
68
+ if part:
69
+ full.write("\n")
70
+ full.write(MODIFY_NOTICE)
71
+ full.write(f"// === START section from {namespace.name}.ts.part ===\n")
72
+ full.write(part)
73
+ full.write(f"// === END section from {namespace.name}.ts.part ===\n")
74
+
75
+ full.write(MODIFY_NOTICE)
76
+
77
+ basename = "/".join(namespace.path)
78
+ filename = f"{config.types_output}/{basename}.ts"
79
+ util.rewrite_file(filename, full.getvalue())
80
+
81
+ if len(namespace.path) == 1:
82
+ index_out.write(
83
+ f"import * as {resolve_namespace_ref(namespace)} from './{resolve_namespace_name(namespace)}'\n"
84
+ ) # noqa: E501
85
+ index_out_end.write(f"export {{{resolve_namespace_ref(namespace)}}}\n")
86
+
87
+ index_out.write("\n")
88
+ index_out.write(MODIFY_NOTICE)
89
+ index_out.write(index_out_end.getvalue())
90
+ index_out.write(MODIFY_NOTICE)
91
+ util.rewrite_file(f"{config.types_output}/index.ts", index_out.getvalue())
92
+
93
+
94
+ def _emit_namespace(
95
+ ctx: EmitTypescriptContext,
96
+ config: TypeScriptConfig,
97
+ namespace: builder.SpecNamespace,
98
+ ) -> None:
99
+ for stype in namespace.types.values():
100
+ if namespace.emit_io_ts:
101
+ emit_type_io_ts(ctx, stype, namespace.derive_types_from_io_ts)
102
+ if not namespace.emit_io_ts or not namespace.derive_types_from_io_ts:
103
+ emit_type_ts(ctx, stype)
104
+
105
+ for sconst in namespace.constants.values():
106
+ _emit_constant(ctx, sconst)
107
+
108
+ if namespace.endpoint is not None:
109
+ _emit_endpoint(ctx, config, namespace, namespace.endpoint)
110
+
111
+
112
+ def _emit_endpoint(
113
+ ctx: EmitTypescriptContext,
114
+ config: TypeScriptConfig,
115
+ namespace: builder.SpecNamespace,
116
+ endpoint: builder.SpecEndpoint,
117
+ ) -> None:
118
+ if endpoint.suppress_ts:
119
+ return
120
+
121
+ assert namespace.path[0] == "api"
122
+ has_arguments = "Arguments" in namespace.types
123
+ has_data = "Data" in namespace.types
124
+ has_deprecated_result = "DeprecatedResult" in namespace.types
125
+ is_binary = endpoint.result_type == builder.ResultType.binary
126
+
127
+ result_type_count = sum([has_data, has_deprecated_result, is_binary])
128
+ assert result_type_count < 2
129
+
130
+ # Don't emit interface for those with unsupported types
131
+ if not has_arguments or result_type_count == 0:
132
+ return
133
+
134
+ if not is_binary:
135
+ assert endpoint.result_type == builder.ResultType.json
136
+
137
+ data_loader_head = ""
138
+ data_loader_body = ""
139
+ if endpoint.data_loader:
140
+ # Don't support alternately named data for now
141
+ assert has_data
142
+
143
+ data_loader_head = (
144
+ 'import { buildApiDataLoader, argsKey } from "unc_base/data_manager"\n'
145
+ )
146
+ data_loader_body = (
147
+ "\nexport const data = buildApiDataLoader(argsKey(), apiCall)\n"
148
+ )
149
+
150
+ method = endpoint.method.capitalize()
151
+ if endpoint.has_attachment:
152
+ assert endpoint.method == "post"
153
+ method = f"{method}Attach"
154
+ wrap_name = (
155
+ f"buildWrappedBinary{method}Call" if is_binary else f"buildWrapped{method}Call"
156
+ )
157
+ wrap_call = (
158
+ f"{wrap_name}<Arguments>" if is_binary else f"{wrap_name}<Arguments, Response>"
159
+ )
160
+ type_path = f"unc_mat/types/{"/".join(namespace.path)}"
161
+
162
+ if is_binary:
163
+ tsx_response_part = f"""import {{ {wrap_name} }} from "unc_base/api"
164
+ import type {{ Arguments }} from "{type_path}"
165
+
166
+ export type {{ Arguments }}
167
+ """
168
+ elif has_data and endpoint.has_attachment:
169
+ tsx_response_part = f"""import {{ {wrap_name}, type AttachmentResponse }} from "unc_base/api"
170
+ import type {{ Arguments, Data }} from "{type_path}"
171
+
172
+ export type {{ Arguments, Data }}
173
+ export type Response = AttachmentResponse<Data>
174
+ """
175
+ elif has_data:
176
+ tsx_response_part = f"""import {{ {wrap_name}, type JsonResponse }} from "unc_base/api"
177
+ import type {{ Arguments, Data }} from "{type_path}"
178
+
179
+ export type {{ Arguments, Data }}
180
+ export type Response = JsonResponse<Data>
181
+ """
182
+
183
+ else:
184
+ assert has_deprecated_result
185
+ tsx_response_part = f"""import {{ {wrap_name} }} from "unc_base/api"
186
+ import type {{ Arguments, DeprecatedResult }} from "{type_path}"
187
+
188
+ export type {{ Arguments }}
189
+ export type Response = DeprecatedResult
190
+ """
191
+
192
+ tsx_api = f"""{MODIFY_NOTICE}
193
+ {data_loader_head}{tsx_response_part}
194
+ export const apiCall = {wrap_call}(
195
+ "{endpoint.path_root}/{endpoint.path_dirname}/{endpoint.path_basename}",
196
+ )
197
+ {data_loader_body}"""
198
+
199
+ output = f"{config.routes_output}/{"/".join(namespace.path)}.tsx"
200
+ util.rewrite_file(output, tsx_api)
201
+
202
+ # Hacky index support, until enough is migrated to regen entirely
203
+ # Emits the import into the UI API index file
204
+ index_path = f"{config.routes_output}/{"/".join(namespace.path[0:-1])}/index.tsx"
205
+ api_name = f"Api{ts_type_name(namespace.path[0 - 1])}"
206
+ if os.path.exists(index_path):
207
+ with open(index_path) as index:
208
+ index_data = index.read()
209
+ need_index = index_data.find(api_name) == -1
210
+ else:
211
+ need_index = True
212
+
213
+ if need_index:
214
+ with open(index_path, "a") as index:
215
+ print(f"Updated API Index {index_path}")
216
+ index.write(f'import * as {api_name} from "./{namespace.path[-1]}"\n\n')
217
+ index.write(f"export {{ {api_name} }}\n")
218
+
219
+
220
+ def _emit_constant(ctx: EmitTypescriptContext, sconst: builder.SpecConstant) -> None:
221
+ ctx.out.write("\n\n")
222
+ ctx.out.write(MODIFY_NOTICE)
223
+ value = emit_value_ts(ctx, sconst.value_type, sconst.value)
224
+ const_name = sconst.name.upper()
225
+ ctx.out.write(f"export const {const_name} = {value}\n")
226
+
227
+
228
+ def _emit_id_source(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
229
+ id_source_output = config.id_source_output
230
+ if id_source_output is None:
231
+ return
232
+ enum_out = io.StringIO()
233
+ enum_out.write(MODIFY_NOTICE)
234
+
235
+ enum_out.write("export type KnownEnumsType =\n")
236
+ enum_map = {
237
+ builder.resolve_proper_name(string_enum): string_enum
238
+ for string_enum in builder.emit_id_source_enums
239
+ }
240
+ sorted_keys = sorted(enum_map.keys())
241
+ for key in sorted_keys:
242
+ enum_out.write(f' | "{key}"\n')
243
+
244
+ enum_out.write(f"\n{MODIFY_NOTICE}")
245
+ enum_out.write("export const ENUM_NAME_MAPS = {\n")
246
+ for key in sorted_keys:
247
+ string_enum = enum_map[key]
248
+ enum_out.write(f' "{builder.resolve_proper_name(string_enum)}": {{\n')
249
+ for entry in string_enum.values.values():
250
+ if entry.label is not None:
251
+ enum_out.write(f' "{entry.value}": "{entry.label}",\n')
252
+ enum_out.write(" },\n")
253
+ enum_out.write("}\n")
254
+
255
+ enum_out.write(f"\n{MODIFY_NOTICE}")
256
+ util.rewrite_file(id_source_output, enum_out.getvalue())