UncountablePythonSDK 0.0.30__tar.gz → 0.0.33__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 (195) hide show
  1. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/.github/workflows/documentation.yml +4 -4
  2. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/.github/workflows/publish.yml +5 -5
  3. {uncountablepythonsdk-0.0.30/UncountablePythonSDK.egg-info → uncountablepythonsdk-0.0.33}/PKG-INFO +3 -3
  4. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33/UncountablePythonSDK.egg-info}/PKG-INFO +3 -3
  5. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/UncountablePythonSDK.egg-info/SOURCES.txt +6 -0
  6. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/UncountablePythonSDK.egg-info/requires.txt +2 -2
  7. uncountablepythonsdk-0.0.33/docs/requirements.txt +7 -0
  8. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/argument_parser/argument_parser.py +41 -2
  9. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/argument_parser/case_convert.py +4 -3
  10. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization/__init__.py +2 -0
  11. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization/serial_class.py +31 -37
  12. uncountablepythonsdk-0.0.33/pkgs/serialization/serial_union.py +81 -0
  13. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization_util/__init__.py +1 -7
  14. uncountablepythonsdk-0.0.33/pkgs/serialization_util/convert_to_snakecase.py +27 -0
  15. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization_util/serialization_helpers.py +48 -59
  16. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/builder.py +57 -1
  17. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_open_api.py +6 -0
  18. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_python.py +23 -0
  19. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_typescript.py +6 -0
  20. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/type_info/emit_type_info.py +43 -9
  21. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pyproject.toml +2 -2
  22. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/__init__.py +8 -0
  23. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/list_entities.py +7 -0
  24. uncountablepythonsdk-0.0.33/uncountable/types/api/inputs/set_intermediate_type.py +43 -0
  25. uncountablepythonsdk-0.0.33/uncountable/types/api/recipes/add_recipe_to_project.py +35 -0
  26. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/associate_recipe_as_input.py +1 -0
  27. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/edit_recipe_inputs.py +39 -1
  28. uncountablepythonsdk-0.0.33/uncountable/types/api/recipes/remove_recipe_from_project.py +35 -0
  29. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/set_recipe_outputs.py +2 -0
  30. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/client_base.py +72 -0
  31. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/inputs.py +1 -0
  32. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_workflow_steps.py +14 -3
  33. uncountablepythonsdk-0.0.33/uncountable/types/recipes.py +21 -0
  34. uncountablepythonsdk-0.0.30/docs/requirements.txt +0 -7
  35. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/.gitignore +0 -0
  36. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/README.md +0 -0
  37. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
  38. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
  39. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/.gitignore +0 -0
  40. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/conf.py +0 -0
  41. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/index.md +0 -0
  42. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/justfile +0 -0
  43. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/quickstart.md +0 -0
  44. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/android-chrome-192x192.png +0 -0
  45. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/android-chrome-512x512.png +0 -0
  46. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/apple-touch-icon.png +0 -0
  47. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/browserconfig.xml +0 -0
  48. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/favicon-16x16.png +0 -0
  49. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/favicon-32x32.png +0 -0
  50. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/manifest.json +0 -0
  51. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/mstile-150x150.png +0 -0
  52. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/favicons/safari-pinned-tab.svg +0 -0
  53. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/docs/static/logo_blue.png +0 -0
  54. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/examples/async_batch.py +0 -0
  55. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/examples/create_entity.py +0 -0
  56. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/examples/upload_files.py +0 -0
  57. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/__init__.py +0 -0
  58. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/argument_parser/__init__.py +0 -0
  59. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/argument_parser/_is_enum.py +0 -0
  60. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/argument_parser/_is_namedtuple.py +0 -0
  61. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization/missing_sentry.py +0 -0
  62. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization/opaque_key.py +0 -0
  63. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
  64. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/strenum_compat/__init__.py +0 -0
  65. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/strenum_compat/strenum_compat.py +0 -0
  66. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/__init__.py +0 -0
  67. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/__main__.py +0 -0
  68. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/actions_registry/__init__.py +0 -0
  69. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/actions_registry/__main__.py +0 -0
  70. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/actions_registry/emit_typescript.py +0 -0
  71. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/config.py +0 -0
  72. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_io_ts.py +0 -0
  73. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_open_api_util.py +0 -0
  74. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/emit_typescript_util.py +0 -0
  75. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/load_types.py +0 -0
  76. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/open_api_util.py +0 -0
  77. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/parts/base.py.prepart +0 -0
  78. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/parts/base.ts.prepart +0 -0
  79. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/test.py +0 -0
  80. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/type_info/__main__.py +0 -0
  81. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/util.py +0 -0
  82. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/value_spec/__init__.py +0 -0
  83. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/value_spec/__main__.py +0 -0
  84. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/value_spec/convert_type.py +0 -0
  85. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/value_spec/emit_python.py +0 -0
  86. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/pkgs/type_spec/value_spec/types.py +0 -0
  87. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/setup.cfg +0 -0
  88. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/__init__.py +0 -0
  89. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/core/__init__.py +0 -0
  90. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/core/async_batch.py +0 -0
  91. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/core/client.py +0 -0
  92. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/core/file_upload.py +0 -0
  93. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/core/types.py +0 -0
  94. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/__init__.py +0 -0
  95. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/construct_client.py +0 -0
  96. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/cron.py +0 -0
  97. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/db/__init__.py +0 -0
  98. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/db/connect.py +0 -0
  99. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/entrypoint.py +0 -0
  100. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/executors/__init__.py +0 -0
  101. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/executors/script_executor.py +0 -0
  102. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/job.py +0 -0
  103. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/server.py +0 -0
  104. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/integration/types.py +0 -0
  105. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/py.typed +0 -0
  106. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/__init__.py +0 -0
  107. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/batch/__init__.py +0 -0
  108. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/batch/execute_batch.py +0 -0
  109. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/batch/execute_batch_load_async.py +0 -0
  110. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/chemical/__init__.py +0 -0
  111. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/chemical/convert_chemical_formats.py +0 -0
  112. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/__init__.py +0 -0
  113. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/create_entities.py +0 -0
  114. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/create_entity.py +0 -0
  115. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/get_entities_data.py +0 -0
  116. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/lock_entity.py +0 -0
  117. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
  118. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/set_values.py +0 -0
  119. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/transition_entity_phase.py +0 -0
  120. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/entity/unlock_entity.py +0 -0
  121. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/field_options/__init__.py +0 -0
  122. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/field_options/upsert_field_options.py +0 -0
  123. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/id_source/__init__.py +0 -0
  124. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/id_source/list_id_source.py +0 -0
  125. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/id_source/match_id_source.py +0 -0
  126. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/input_groups/__init__.py +0 -0
  127. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
  128. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/__init__.py +0 -0
  129. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/create_inputs.py +0 -0
  130. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/get_input_data.py +0 -0
  131. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/get_input_names.py +0 -0
  132. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
  133. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
  134. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/set_input_category.py +0 -0
  135. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/inputs/set_input_subcategories.py +0 -0
  136. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/material_families/__init__.py +0 -0
  137. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/material_families/update_entity_material_families.py +0 -0
  138. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/outputs/__init__.py +0 -0
  139. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/outputs/get_output_data.py +0 -0
  140. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/outputs/get_output_names.py +0 -0
  141. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
  142. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/permissions/__init__.py +0 -0
  143. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/permissions/set_core_permissions.py +0 -0
  144. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/project/__init__.py +0 -0
  145. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/project/get_projects.py +0 -0
  146. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/project/get_projects_data.py +0 -0
  147. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipe_links/__init__.py +0 -0
  148. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipe_links/create_recipe_link.py +0 -0
  149. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
  150. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
  151. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/__init__.py +0 -0
  152. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/archive_recipes.py +0 -0
  153. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/associate_recipe_as_lot.py +0 -0
  154. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/create_recipe.py +0 -0
  155. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/create_recipes.py +0 -0
  156. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/disassociate_recipe_as_input.py +0 -0
  157. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_curve.py +0 -0
  158. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
  159. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
  160. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
  161. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
  162. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/get_recipes_data.py +0 -0
  163. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
  164. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/set_recipe_metadata.py +0 -0
  165. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/set_recipe_tags.py +0 -0
  166. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/recipes/unarchive_recipes.py +0 -0
  167. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/triggers/__init__.py +0 -0
  168. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/api/triggers/run_trigger.py +0 -0
  169. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/async_batch.py +0 -0
  170. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/async_batch_processor.py +0 -0
  171. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/base.py +0 -0
  172. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/calculations.py +0 -0
  173. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/chemical_structure.py +0 -0
  174. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/curves.py +0 -0
  175. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/entity.py +0 -0
  176. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/experiment_groups.py +0 -0
  177. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/field_values.py +0 -0
  178. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/fields.py +0 -0
  179. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/id_source.py +0 -0
  180. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/identifier.py +0 -0
  181. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/input_attributes.py +0 -0
  182. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/outputs.py +0 -0
  183. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/permissions.py +0 -0
  184. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/phases.py +0 -0
  185. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/post_base.py +0 -0
  186. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_identifiers.py +0 -0
  187. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_inputs.py +0 -0
  188. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_links.py +0 -0
  189. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_metadata.py +0 -0
  190. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_output_metadata.py +0 -0
  191. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/recipe_tags.py +0 -0
  192. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/response.py +0 -0
  193. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/units.py +0 -0
  194. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/users.py +0 -0
  195. {uncountablepythonsdk-0.0.30 → uncountablepythonsdk-0.0.33}/uncountable/types/workflows.py +0 -0
@@ -9,9 +9,9 @@ jobs:
9
9
  docs:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - uses: actions/checkout@v3
13
- - uses: actions/setup-python@v3
14
- - uses: extractions/setup-just@v1
12
+ - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
13
+ - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5
14
+ - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2
15
15
  with:
16
16
  just-version: '1.8.0'
17
17
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -25,7 +25,7 @@ jobs:
25
25
  run: |
26
26
  just -f docs/justfile docs-build
27
27
  - name: Deploy to GitHub Pages
28
- uses: peaceiris/actions-gh-pages@v3
28
+ uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
29
29
  if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
30
30
  with:
31
31
  publish_branch: gh-pages
@@ -19,10 +19,10 @@ jobs:
19
19
  name: Build distribution packages
20
20
  runs-on: ubuntu-latest
21
21
  steps:
22
- - uses: actions/checkout@v4
22
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
23
23
  with:
24
24
  fetch-depth: 0
25
- - uses: actions/setup-python@v5
25
+ - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5
26
26
  with:
27
27
  python-version: '3.11'
28
28
  - name: Install build dependencies
@@ -31,7 +31,7 @@ jobs:
31
31
  - name: Build distributions and wheels
32
32
  run: |
33
33
  python3 -m build
34
- - uses: actions/upload-artifact@v4
34
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
35
35
  with:
36
36
  name: package-distributions
37
37
  path: dist/
@@ -45,9 +45,9 @@ jobs:
45
45
  permissions:
46
46
  id-token: write
47
47
  steps:
48
- - uses: actions/download-artifact@v4
48
+ - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4
49
49
  with:
50
50
  name: package-distributions
51
51
  path: dist/
52
52
  - name: Publish package distributions to PyPI
53
- uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06
53
+ uses: pypa/gh-action-pypi-publish@ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.30
3
+ Version: 0.0.33
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
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
19
19
  Requires-Dist: aiotus==0.*
20
20
  Requires-Dist: aiohttp==3.*
21
21
  Requires-Dist: requests==2.*
22
- Requires-Dist: SQLAlchemy==1.4.*
22
+ Requires-Dist: SQLAlchemy>=1.4.0
23
23
  Requires-Dist: APScheduler==3.*
24
24
  Requires-Dist: python-dateutil==2.*
25
25
  Requires-Dist: shelljob==0.*
@@ -28,7 +28,7 @@ Provides-Extra: test
28
28
  Requires-Dist: mypy==1.*; extra == "test"
29
29
  Requires-Dist: ruff==0.*; extra == "test"
30
30
  Requires-Dist: pytest==8.*; extra == "test"
31
- Requires-Dist: coverage[toml]==6.*; extra == "test"
31
+ Requires-Dist: coverage[toml]==7.*; extra == "test"
32
32
  Requires-Dist: pytest-cov==5.*; extra == "test"
33
33
  Requires-Dist: pytest-xdist==3.*; extra == "test"
34
34
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.30
3
+ Version: 0.0.33
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
@@ -19,7 +19,7 @@ Description-Content-Type: text/markdown
19
19
  Requires-Dist: aiotus==0.*
20
20
  Requires-Dist: aiohttp==3.*
21
21
  Requires-Dist: requests==2.*
22
- Requires-Dist: SQLAlchemy==1.4.*
22
+ Requires-Dist: SQLAlchemy>=1.4.0
23
23
  Requires-Dist: APScheduler==3.*
24
24
  Requires-Dist: python-dateutil==2.*
25
25
  Requires-Dist: shelljob==0.*
@@ -28,7 +28,7 @@ Provides-Extra: test
28
28
  Requires-Dist: mypy==1.*; extra == "test"
29
29
  Requires-Dist: ruff==0.*; extra == "test"
30
30
  Requires-Dist: pytest==8.*; extra == "test"
31
- Requires-Dist: coverage[toml]==6.*; extra == "test"
31
+ Requires-Dist: coverage[toml]==7.*; extra == "test"
32
32
  Requires-Dist: pytest-cov==5.*; extra == "test"
33
33
  Requires-Dist: pytest-xdist==3.*; extra == "test"
34
34
 
@@ -37,8 +37,10 @@ pkgs/serialization/__init__.py
37
37
  pkgs/serialization/missing_sentry.py
38
38
  pkgs/serialization/opaque_key.py
39
39
  pkgs/serialization/serial_class.py
40
+ pkgs/serialization/serial_union.py
40
41
  pkgs/serialization_util/__init__.py
41
42
  pkgs/serialization_util/_get_type_for_serialization.py
43
+ pkgs/serialization_util/convert_to_snakecase.py
42
44
  pkgs/serialization_util/serialization_helpers.py
43
45
  pkgs/strenum_compat/__init__.py
44
46
  pkgs/strenum_compat/strenum_compat.py
@@ -113,6 +115,7 @@ uncountable/types/recipe_metadata.py
113
115
  uncountable/types/recipe_output_metadata.py
114
116
  uncountable/types/recipe_tags.py
115
117
  uncountable/types/recipe_workflow_steps.py
118
+ uncountable/types/recipes.py
116
119
  uncountable/types/response.py
117
120
  uncountable/types/units.py
118
121
  uncountable/types/users.py
@@ -148,6 +151,7 @@ uncountable/types/api/inputs/get_inputs_data.py
148
151
  uncountable/types/api/inputs/set_input_attribute_values.py
149
152
  uncountable/types/api/inputs/set_input_category.py
150
153
  uncountable/types/api/inputs/set_input_subcategories.py
154
+ uncountable/types/api/inputs/set_intermediate_type.py
151
155
  uncountable/types/api/material_families/__init__.py
152
156
  uncountable/types/api/material_families/update_entity_material_families.py
153
157
  uncountable/types/api/outputs/__init__.py
@@ -164,6 +168,7 @@ uncountable/types/api/recipe_links/create_recipe_link.py
164
168
  uncountable/types/api/recipe_metadata/__init__.py
165
169
  uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py
166
170
  uncountable/types/api/recipes/__init__.py
171
+ uncountable/types/api/recipes/add_recipe_to_project.py
167
172
  uncountable/types/api/recipes/archive_recipes.py
168
173
  uncountable/types/api/recipes/associate_recipe_as_input.py
169
174
  uncountable/types/api/recipes/associate_recipe_as_lot.py
@@ -177,6 +182,7 @@ uncountable/types/api/recipes/get_recipe_links.py
177
182
  uncountable/types/api/recipes/get_recipe_names.py
178
183
  uncountable/types/api/recipes/get_recipe_output_metadata.py
179
184
  uncountable/types/api/recipes/get_recipes_data.py
185
+ uncountable/types/api/recipes/remove_recipe_from_project.py
180
186
  uncountable/types/api/recipes/set_recipe_inputs.py
181
187
  uncountable/types/api/recipes/set_recipe_metadata.py
182
188
  uncountable/types/api/recipes/set_recipe_outputs.py
@@ -1,7 +1,7 @@
1
1
  aiotus==0.*
2
2
  aiohttp==3.*
3
3
  requests==2.*
4
- SQLAlchemy==1.4.*
4
+ SQLAlchemy>=1.4.0
5
5
  APScheduler==3.*
6
6
  python-dateutil==2.*
7
7
  shelljob==0.*
@@ -11,6 +11,6 @@ PyYAML==6.*
11
11
  mypy==1.*
12
12
  ruff==0.*
13
13
  pytest==8.*
14
- coverage[toml]==6.*
14
+ coverage[toml]==7.*
15
15
  pytest-cov==5.*
16
16
  pytest-xdist==3.*
@@ -0,0 +1,7 @@
1
+ furo==2024.5.6
2
+ myst-parser==3.0.1
3
+ sphinx-autoapi==3.1.0
4
+ sphinx-copybutton==0.5.2
5
+ Sphinx==7.3.7
6
+ sphinx_design==0.6.0
7
+ sphinx-favicon==1.0.1
@@ -10,7 +10,12 @@ from importlib import resources
10
10
  import dateutil.parser
11
11
  import yaml
12
12
 
13
- from pkgs.serialization import MissingSentryType, OpaqueKey, get_serial_class_data
13
+ from pkgs.serialization import (
14
+ MissingSentryType,
15
+ OpaqueKey,
16
+ get_serial_class_data,
17
+ get_serial_union_data,
18
+ )
14
19
 
15
20
  from ._is_enum import is_string_enum_class
16
21
  from ._is_namedtuple import is_namedtuple_type
@@ -112,6 +117,23 @@ def _invoke_membership_parser(
112
117
  raise ValueError(f"Expected value from {expected_values} but got value {value}")
113
118
 
114
119
 
120
+ def _build_parser_discriminated_union(
121
+ discriminator: str, discriminator_map: dict[str, ParserFunction[T]]
122
+ ) -> ParserFunction[T]:
123
+ def parse(value: typing.Any) -> typing.Any:
124
+ discriminant = value.get(discriminator)
125
+ if discriminant is None:
126
+ raise ValueError("missing-union-discriminant")
127
+ if not isinstance(discriminant, str):
128
+ raise ValueError("union-discriminant-is-not-string")
129
+ parser = discriminator_map.get(discriminant)
130
+ if parser is None:
131
+ raise ValueError("missing-type-for-union-discriminant", discriminant)
132
+ return parser(value)
133
+
134
+ return parse
135
+
136
+
115
137
  def _build_parser_inner(
116
138
  parsed_type: type[T],
117
139
  context: ParserContext,
@@ -130,6 +152,23 @@ def _build_parser_inner(
130
152
  are cached now, as they don't use the argument, and they're known to be safe.
131
153
  This is also enough to support some recursion.
132
154
  """
155
+
156
+ serial_union = get_serial_union_data(parsed_type)
157
+ if serial_union is not None:
158
+ discriminator = serial_union.discriminator
159
+ discriminator_map = serial_union.discriminator_map
160
+ if discriminator is None or discriminator_map is None:
161
+ # fallback to standard union parsing
162
+ parsed_type = serial_union.get_union_underlying()
163
+ else:
164
+ return _build_parser_discriminated_union(
165
+ discriminator,
166
+ {
167
+ key: _build_parser_inner(value, context)
168
+ for key, value in discriminator_map.items()
169
+ },
170
+ )
171
+
133
172
  if dataclasses.is_dataclass(parsed_type):
134
173
  return _build_parser_dataclass(parsed_type, context) # type: ignore[arg-type]
135
174
 
@@ -341,7 +380,7 @@ def _build_parser_dataclass(
341
380
 
342
381
  except Exception as e:
343
382
  raise ValueError(
344
- f"unable to parse field:{field.name}", field_raw_value
383
+ f"unable-to-parse-field:{field.name}", field_raw_value
345
384
  ) from e
346
385
 
347
386
  if context.options.strict_property_parsing:
@@ -4,9 +4,10 @@ import re
4
4
 
5
5
  @functools.lru_cache(maxsize=500000)
6
6
  def snake_to_camel_case(o: str) -> str:
7
- return "".join([
8
- part.title() if i > 0 else part for i, part in enumerate(o.split("_"))
9
- ])
7
+ tokens = o.split("_")
8
+ if len(tokens) < 2:
9
+ return o
10
+ return "".join([part.title() if i > 0 else part for i, part in enumerate(tokens)])
10
11
 
11
12
 
12
13
  def kebab_to_pascal_case(o: str) -> str:
@@ -8,3 +8,5 @@ from .serial_class import get_serial_class_data as get_serial_class_data
8
8
  from .serial_class import get_serial_string_enum_data as get_serial_string_enum_data
9
9
  from .serial_class import serial_class as serial_class
10
10
  from .serial_class import serial_string_enum as serial_string_enum
11
+ from .serial_union import serial_union_annotation as serial_union_annotation
12
+ from .serial_union import get_serial_union_data as get_serial_union_data
@@ -16,6 +16,9 @@ class _SerialClassData:
16
16
  parse_require: set[str] = dataclasses.field(default_factory=set)
17
17
 
18
18
 
19
+ EMPTY_SERIAL_CLASS_DATA = _SerialClassData()
20
+
21
+
19
22
  def serial_class(
20
23
  *,
21
24
  unconverted_keys: Optional[set[str]] = None,
@@ -57,58 +60,49 @@ def serial_class(
57
60
 
58
61
 
59
62
  class SerialClassDataInspector:
60
- bases: list[SerialClassDataInspector]
61
-
62
63
  def __init__(
63
- self, bases: list[SerialClassDataInspector], current: _SerialClassData
64
+ self,
65
+ current: _SerialClassData,
64
66
  ) -> None:
65
- self.bases = bases
66
67
  self.current = current
67
68
 
68
69
  def has_unconverted_key(self, key: str) -> bool:
69
- if key in self.current.unconverted_keys:
70
- return True
71
- for base in self.bases:
72
- if base.has_unconverted_key(key):
73
- return True
74
- return False
70
+ return key in self.current.unconverted_keys
75
71
 
76
72
  def has_unconverted_value(self, key: str) -> bool:
77
- if key in self.current.unconverted_values:
78
- return True
79
- for base in self.bases:
80
- if base.has_unconverted_value(key):
81
- return True
82
- return False
73
+ return key in self.current.unconverted_values
83
74
 
84
75
  def has_to_string_value(self, key: str) -> bool:
85
- if key in self.current.to_string_values:
86
- return True
87
- for base in self.bases:
88
- if base.has_to_string_value(key):
89
- return True
90
- return False
76
+ return key in self.current.to_string_values
91
77
 
92
78
  def has_parse_require(self, key: str) -> bool:
93
- if key in self.current.parse_require:
94
- return True
95
- for base in self.bases:
96
- if base.has_parse_require(key):
97
- return True
98
- return False
79
+ return key in self.current.parse_require
99
80
 
100
81
 
101
- def get_serial_class_data(type_class: type[Any]) -> SerialClassDataInspector:
102
- bases = (
103
- [get_serial_class_data(base) for base in type_class.__bases__]
104
- if type_class.__bases__ is not None
105
- else []
106
- )
107
- return SerialClassDataInspector(
108
- bases,
82
+ def _get_merged_serial_class_data(type_class: type[Any]) -> _SerialClassData | None:
83
+ base_class_data = (
109
84
  cast(_SerialClassData, type_class.__unc_serial_data)
110
85
  if hasattr(type_class, "__unc_serial_data")
111
- else _SerialClassData(),
86
+ else None
87
+ )
88
+ if type_class.__bases__ is not None:
89
+ for base in type_class.__bases__:
90
+ curr_base_class_data = _get_merged_serial_class_data(base)
91
+ if curr_base_class_data is not None:
92
+ if base_class_data is None:
93
+ base_class_data = _SerialClassData()
94
+ base_class_data.unconverted_keys |= curr_base_class_data.unconverted_keys
95
+ base_class_data.unconverted_values |= (
96
+ curr_base_class_data.unconverted_values
97
+ )
98
+ base_class_data.to_string_values |= curr_base_class_data.to_string_values
99
+ base_class_data.parse_require |= curr_base_class_data.parse_require
100
+ return base_class_data
101
+
102
+
103
+ def get_serial_class_data(type_class: type[Any]) -> SerialClassDataInspector:
104
+ return SerialClassDataInspector(
105
+ _get_merged_serial_class_data(type_class) or EMPTY_SERIAL_CLASS_DATA
112
106
  )
113
107
 
114
108
 
@@ -0,0 +1,81 @@
1
+ import dataclasses
2
+ import typing
3
+
4
+ T = typing.TypeVar("T")
5
+
6
+
7
+ class IdentityHashWrapper(typing.Generic[T]):
8
+ """This allows unhashable types to be used in the SerialUnion, like dict.
9
+ Since we have only one copy of the types themselves, we rely on
10
+ object identity for the hashing."""
11
+
12
+ def __init__(self, inner: T) -> None:
13
+ self.inner = inner
14
+
15
+ def __hash__(self) -> int:
16
+ return id(self.inner)
17
+
18
+
19
+ @dataclasses.dataclass(kw_only=True, frozen=True, eq=True)
20
+ class _SerialUnion:
21
+ """
22
+ This class is to be kept private, to provide flexibility in registration/lookup.
23
+ Places that need the data should access it via help classes/methods.
24
+ """
25
+
26
+ # If specified, indicates the Union has a discriminator which should be used to
27
+ # determine which type to parse.
28
+ discriminator: typing.Optional[str] = None
29
+ discriminator_map: typing.Optional[IdentityHashWrapper[dict[str, type]]] = None
30
+
31
+
32
+ def serial_union_annotation(
33
+ *,
34
+ discriminator: typing.Optional[str] = None,
35
+ discriminator_map: typing.Optional[dict[str, type]] = None,
36
+ ) -> _SerialUnion:
37
+ return _SerialUnion(
38
+ discriminator=discriminator,
39
+ discriminator_map=IdentityHashWrapper(discriminator_map)
40
+ if discriminator_map is not None
41
+ else None,
42
+ )
43
+
44
+
45
+ def _get_serial_union(parsed_type: type[T]) -> _SerialUnion | None:
46
+ if not hasattr(parsed_type, "__metadata__"):
47
+ return None
48
+ metadata = parsed_type.__metadata__ # type:ignore[attr-defined]
49
+ if not isinstance(metadata, tuple) or len(metadata) != 1:
50
+ return None
51
+ serial = metadata[0]
52
+ if not isinstance(serial, _SerialUnion):
53
+ return None
54
+ return serial
55
+
56
+
57
+ class SerialClassInspector(typing.Generic[T]):
58
+ def __init__(self, parsed_type: type[T], serial_union: _SerialUnion) -> None:
59
+ self._parsed_type = parsed_type
60
+ self._serial_union = serial_union
61
+
62
+ def get_union_underlying(self) -> type[T]:
63
+ return typing.get_args(self._parsed_type)[0] # type:ignore[no-any-return]
64
+
65
+ @property
66
+ def discriminator(self) -> typing.Optional[str]:
67
+ return self._serial_union.discriminator
68
+
69
+ @property
70
+ def discriminator_map(self) -> typing.Optional[dict[str, type]]:
71
+ if self._serial_union.discriminator_map is None:
72
+ return None
73
+ return self._serial_union.discriminator_map.inner
74
+
75
+
76
+ def get_serial_union_data(parsed_type: type[T]) -> SerialClassInspector[T] | None:
77
+ serial = _get_serial_union(parsed_type)
78
+ if serial is None:
79
+ return None
80
+
81
+ return SerialClassInspector(parsed_type, serial)
@@ -1,8 +1,5 @@
1
+ from .convert_to_snakecase import convert_dict_to_snake_case
1
2
  from .serialization_helpers import (
2
- convert_dict_to_snake_case,
3
- convert_to_camelcase,
4
- resolve_missing_to_none,
5
- serialize,
6
3
  serialize_for_api,
7
4
  serialize_for_storage,
8
5
  serialize_for_storage_dict,
@@ -10,9 +7,6 @@ from .serialization_helpers import (
10
7
 
11
8
  __all__: list[str] = [
12
9
  "convert_dict_to_snake_case",
13
- "convert_to_camelcase",
14
- "resolve_missing_to_none",
15
- "serialize",
16
10
  "serialize_for_api",
17
11
  "serialize_for_storage",
18
12
  "serialize_for_storage_dict",
@@ -0,0 +1,27 @@
1
+ from typing import (
2
+ Any,
3
+ )
4
+
5
+ from pkgs.argument_parser import camel_to_snake_case
6
+ from pkgs.serialization import (
7
+ MISSING_SENTRY,
8
+ OpaqueKey,
9
+ )
10
+
11
+
12
+ def _key_convert_to_snake_case(o: Any) -> Any:
13
+ if isinstance(o, OpaqueKey):
14
+ return o
15
+ if isinstance(o, str):
16
+ return camel_to_snake_case(o)
17
+ return o
18
+
19
+
20
+ def convert_dict_to_snake_case(data: Any) -> Any:
21
+ return {
22
+ _key_convert_to_snake_case(k): convert_dict_to_snake_case(v)
23
+ if isinstance(v, dict)
24
+ else v
25
+ for k, v in data.items()
26
+ if v != MISSING_SENTRY
27
+ }