UncountablePythonSDK 0.0.21__tar.gz → 0.0.23__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.
- {uncountablepythonsdk-0.0.21/UncountablePythonSDK.egg-info → uncountablepythonsdk-0.0.23}/PKG-INFO +1 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23/UncountablePythonSDK.egg-info}/PKG-INFO +1 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/UncountablePythonSDK.egg-info/SOURCES.txt +2 -0
- uncountablepythonsdk-0.0.23/examples/async_batch.py +36 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/builder.py +113 -8
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_io_ts.py +4 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_open_api.py +192 -18
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_open_api_util.py +17 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_python.py +7 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_typescript.py +3 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/load_types.py +48 -5
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/open_api_util.py +13 -33
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/create_entities.yaml +1 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/create_entity.yaml +1 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/edit_recipe_inputs.yaml +1 -4
- uncountablepythonsdk-0.0.23/uncountable/core/__init__.py +5 -0
- uncountablepythonsdk-0.0.23/uncountable/core/async_batch.py +22 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/core/client.py +78 -6
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/create_entities.py +1 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/create_entity.py +1 -1
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/edit_recipe_inputs.py +2 -3
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/async_batch.py +1 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/async_batch_processor.py +7 -7
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/client_base.py +27 -2
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/identifier.py +3 -3
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_workflow_steps.py +1 -1
- uncountablepythonsdk-0.0.21/uncountable/core/__init__.py +0 -4
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/.github/workflows/documentation.yml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/.github/workflows/publish.yml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/.gitignore +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/README.md +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/UncountablePythonSDK.egg-info/requires.txt +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/.gitignore +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/conf.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/index.md +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/justfile +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/quickstart.md +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/requirements.txt +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/android-chrome-192x192.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/android-chrome-512x512.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/apple-touch-icon.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/browserconfig.xml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/favicon-16x16.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/favicon-32x32.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/manifest.json +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/mstile-150x150.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/favicons/safari-pinned-tab.svg +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/docs/static/logo_blue.png +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/examples/create_entity.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/examples/recipe-import/importer.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/examples/upload_files.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/argument_parser/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/argument_parser/_is_enum.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/argument_parser/_is_namedtuple.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/argument_parser/argument_parser.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/argument_parser/case_convert.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization/missing_sentry.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization/opaque_key.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization/serial_class.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization_util/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/serialization_util/serialization_helpers.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/strenum_compat/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/strenum_compat/strenum_compat.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/__main__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/actions_registry/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/actions_registry/__main__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/actions_registry/emit_typescript.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/config.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_typescript_util.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/parts/base.py.prepart +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/parts/base.ts.prepart +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/test.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/type_info/__main__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/type_info/emit_type_info.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/util.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/value_spec/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/value_spec/__main__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/value_spec/convert_type.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/value_spec/emit_python.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/value_spec/types.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pyproject.toml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/setup.cfg +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/batch/execute_batch.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/batch/execute_batch_load_async.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/chemical/convert_chemical_formats.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/get_entities_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/list_entities.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/resolve_entity_ids.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/set_values.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/entity/transition_entity_phase.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/id_source/list_id_source.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/id_source/match_id_source.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/input_groups/get_input_group_names.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/inputs/create_inputs.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/inputs/get_input_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/inputs/get_input_names.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/inputs/get_inputs_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/outputs/get_output_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/outputs/get_output_names.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/outputs/resolve_output_conditions.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/permissions/set_core_permissions.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/project/get_projects.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/project/get_projects_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipe_links/create_recipe_link.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/associate_recipe_as_input.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/associate_recipe_as_lot.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/create_recipe.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/create_recipes.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/disassociate_recipe_as_input.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_curve.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_recipe_links.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_recipe_names.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_recipe_output_metadata.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/get_recipes_data.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/set_recipe_metadata.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/recipes/set_recipe_tags.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/type_spec/external/api/triggers/run_trigger.yaml +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/core/file_upload.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/core/types.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/construct_client.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/cron.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/db/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/db/connect.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/entrypoint.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/executors/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/executors/script_executor.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/job.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/server.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/integration/types.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/py.typed +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/batch/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/batch/execute_batch.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/batch/execute_batch_load_async.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/chemical/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/chemical/convert_chemical_formats.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/get_entities_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/list_entities.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/set_values.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/entity/transition_entity_phase.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/id_source/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/id_source/list_id_source.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/id_source/match_id_source.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/input_groups/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/create_inputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/get_input_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/get_input_names.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/outputs/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/outputs/get_output_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/outputs/get_output_names.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/permissions/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/permissions/set_core_permissions.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/project/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/project/get_projects.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/project/get_projects_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipe_links/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipe_links/create_recipe_link.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/associate_recipe_as_input.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/associate_recipe_as_lot.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/create_recipe.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/create_recipes.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/disassociate_recipe_as_input.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_curve.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/get_recipes_data.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/set_recipe_metadata.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/set_recipe_outputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/recipes/set_recipe_tags.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/triggers/__init__.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/api/triggers/run_trigger.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/base.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/calculations.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/chemical_structure.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/curves.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/entity.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/experiment_groups.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/field_values.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/fields.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/id_source.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/input_attributes.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/inputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/outputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/permissions.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/phases.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/post_base.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_identifiers.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_inputs.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_links.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_metadata.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_output_metadata.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/recipe_tags.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/response.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/units.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/users.py +0 -0
- {uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/uncountable/types/workflows.py +0 -0
{uncountablepythonsdk-0.0.21/UncountablePythonSDK.egg-info → uncountablepythonsdk-0.0.23}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: UncountablePythonSDK
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.23
|
|
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
|
{uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23/UncountablePythonSDK.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: UncountablePythonSDK
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.23
|
|
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
|
|
@@ -24,6 +24,7 @@ docs/static/favicons/favicon-32x32.png
|
|
|
24
24
|
docs/static/favicons/manifest.json
|
|
25
25
|
docs/static/favicons/mstile-150x150.png
|
|
26
26
|
docs/static/favicons/safari-pinned-tab.svg
|
|
27
|
+
examples/async_batch.py
|
|
27
28
|
examples/create_entity.py
|
|
28
29
|
examples/upload_files.py
|
|
29
30
|
examples/recipe-import/importer.py
|
|
@@ -114,6 +115,7 @@ type_spec/external/api/triggers/run_trigger.yaml
|
|
|
114
115
|
uncountable/__init__.py
|
|
115
116
|
uncountable/py.typed
|
|
116
117
|
uncountable/core/__init__.py
|
|
118
|
+
uncountable/core/async_batch.py
|
|
117
119
|
uncountable/core/client.py
|
|
118
120
|
uncountable/core/file_upload.py
|
|
119
121
|
uncountable/core/types.py
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from uncountable.core import AuthDetailsApiKey, Client
|
|
3
|
+
from uncountable.core import AsyncBatchProcessor
|
|
4
|
+
from uncountable.types import (
|
|
5
|
+
recipe_metadata,
|
|
6
|
+
)
|
|
7
|
+
from uncountable.types.identifier import IdentifierKeyBatchReference
|
|
8
|
+
from uncountable.types.recipe_identifiers import (
|
|
9
|
+
RecipeIdentifierEditableName,
|
|
10
|
+
RecipeIdentifiers,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
client = Client(
|
|
15
|
+
base_url="https://app.uncountable.com",
|
|
16
|
+
auth_details=AuthDetailsApiKey(
|
|
17
|
+
api_id="X",
|
|
18
|
+
api_secret_key="X",
|
|
19
|
+
),
|
|
20
|
+
)
|
|
21
|
+
batch_loader = AsyncBatchProcessor(client=client)
|
|
22
|
+
recipe_identifiers: RecipeIdentifiers = []
|
|
23
|
+
recipe_identifiers.append(
|
|
24
|
+
RecipeIdentifierEditableName(editable_name="My recipe from API")
|
|
25
|
+
)
|
|
26
|
+
req = batch_loader.create_recipe(
|
|
27
|
+
material_family_id=1, workflow_id=1, identifiers=recipe_identifiers
|
|
28
|
+
)
|
|
29
|
+
created_recipe_reference = req.batch_reference
|
|
30
|
+
batch_loader.set_recipe_metadata(
|
|
31
|
+
recipe_key=IdentifierKeyBatchReference(reference=created_recipe_reference),
|
|
32
|
+
recipe_metadata=[
|
|
33
|
+
recipe_metadata.MetadataValue(metadata_id=7, value_numeric=Decimal(38))
|
|
34
|
+
],
|
|
35
|
+
)
|
|
36
|
+
job_id = batch_loader.send()
|
|
@@ -10,7 +10,7 @@ import re
|
|
|
10
10
|
from collections import defaultdict
|
|
11
11
|
from dataclasses import MISSING, dataclass
|
|
12
12
|
from enum import Enum, StrEnum, auto
|
|
13
|
-
from typing import Any, Optional
|
|
13
|
+
from typing import Any, Optional, Self
|
|
14
14
|
|
|
15
15
|
from . import util
|
|
16
16
|
from .util import parse_type_str, unused
|
|
@@ -86,6 +86,7 @@ class BaseTypeName(StrEnum):
|
|
|
86
86
|
s_optional = "Optional"
|
|
87
87
|
s_string = "String"
|
|
88
88
|
s_tuple = "Tuple"
|
|
89
|
+
s_readonly_array = "ReadonlyArray"
|
|
89
90
|
s_union = "Union"
|
|
90
91
|
|
|
91
92
|
# For a root class that defines properties
|
|
@@ -184,6 +185,34 @@ class SpecTypeInstance(SpecType):
|
|
|
184
185
|
return defn_type + self.parameters
|
|
185
186
|
|
|
186
187
|
|
|
188
|
+
@dataclass(kw_only=True)
|
|
189
|
+
class SpecEndpointExample:
|
|
190
|
+
summary: str
|
|
191
|
+
description: str
|
|
192
|
+
arguments: dict[str, object]
|
|
193
|
+
data: dict[str, object]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@dataclass(kw_only=True)
|
|
197
|
+
class SpecGuide:
|
|
198
|
+
title: str
|
|
199
|
+
markdown_content: str
|
|
200
|
+
html_content: str
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@dataclass(kw_only=True, frozen=True)
|
|
204
|
+
class RootGuideKey:
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass(kw_only=True, frozen=True)
|
|
209
|
+
class EndpointGuideKey:
|
|
210
|
+
path: str
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
SpecGuideKey = RootGuideKey | EndpointGuideKey
|
|
214
|
+
|
|
215
|
+
|
|
187
216
|
class SpecTypeLiteralWrapper(SpecType):
|
|
188
217
|
def __init__(
|
|
189
218
|
self,
|
|
@@ -672,6 +701,32 @@ class ResultType(StrEnum):
|
|
|
672
701
|
RE_ENDPOINT_ROOT = re.compile(r"\${([_a-z]+)}")
|
|
673
702
|
|
|
674
703
|
|
|
704
|
+
@dataclass(kw_only=True, frozen=True)
|
|
705
|
+
class _EndpointPathDetails:
|
|
706
|
+
root: str
|
|
707
|
+
root_path: str
|
|
708
|
+
resolved_path: str
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def _resolve_endpoint_path(
|
|
712
|
+
path: str, api_endpoints: dict[str, str]
|
|
713
|
+
) -> _EndpointPathDetails:
|
|
714
|
+
root_path_source = path.split("/")[0]
|
|
715
|
+
root_match = RE_ENDPOINT_ROOT.fullmatch(root_path_source)
|
|
716
|
+
if root_match is None:
|
|
717
|
+
raise Exception(f"invalid-api-path-root:{root_path_source}")
|
|
718
|
+
|
|
719
|
+
root_var = root_match.group(1)
|
|
720
|
+
root_path = api_endpoints[root_var]
|
|
721
|
+
|
|
722
|
+
_, *rest_path = path.split("/", 1)
|
|
723
|
+
resolved_path = "/".join([root_path] + rest_path)
|
|
724
|
+
|
|
725
|
+
return _EndpointPathDetails(
|
|
726
|
+
root=root_var, root_path=root_path, resolved_path=resolved_path
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
|
|
675
730
|
class SpecEndpoint:
|
|
676
731
|
method: RouteMethod
|
|
677
732
|
root: str
|
|
@@ -748,14 +803,10 @@ class SpecEndpoint:
|
|
|
748
803
|
|
|
749
804
|
self.result_type = ResultType(data.get("result_type", ResultType.json.value))
|
|
750
805
|
|
|
806
|
+
path_details = _resolve_endpoint_path(data["path"], builder.api_endpoints)
|
|
807
|
+
self.root = path_details.root
|
|
808
|
+
self.path_root = path_details.root_path
|
|
751
809
|
self.desc = data.get("desc")
|
|
752
|
-
|
|
753
|
-
root_match = RE_ENDPOINT_ROOT.fullmatch(path[0])
|
|
754
|
-
if root_match is None:
|
|
755
|
-
raise Exception(f"invalid-api-path-root:{path[0]}")
|
|
756
|
-
|
|
757
|
-
self.root = root_match.group(1)
|
|
758
|
-
self.path_root = builder.api_endpoints[self.root]
|
|
759
810
|
# IMPROVE: remove need for is_external flag
|
|
760
811
|
self.is_external = self.path_root == "api/external"
|
|
761
812
|
self.has_attachment = data.get("has_attachment", False)
|
|
@@ -764,6 +815,10 @@ class SpecEndpoint:
|
|
|
764
815
|
not is_sdk or self.desc is not None
|
|
765
816
|
), f"Endpoint description required for SDK endpoints, missing: {path}"
|
|
766
817
|
|
|
818
|
+
@property
|
|
819
|
+
def resolved_path(self: Self) -> str:
|
|
820
|
+
return f"{self.path_root}/{self.path_dirname}/{self.path_basename}"
|
|
821
|
+
|
|
767
822
|
|
|
768
823
|
def _parse_const(
|
|
769
824
|
builder: SpecBuilder,
|
|
@@ -1014,6 +1069,8 @@ class SpecBuilder:
|
|
|
1014
1069
|
self.pending: list[NamespaceDataPair] = []
|
|
1015
1070
|
self.parts: dict[str, dict[str, str]] = defaultdict(dict)
|
|
1016
1071
|
self.preparts: dict[str, dict[str, str]] = defaultdict(dict)
|
|
1072
|
+
self.examples: dict[str, list[SpecEndpointExample]] = defaultdict(list)
|
|
1073
|
+
self.guides: dict[SpecGuideKey, list[SpecGuide]] = defaultdict(list)
|
|
1017
1074
|
self.api_endpoints = api_endpoints
|
|
1018
1075
|
base_namespace = SpecNamespace(name=base_namespace_name)
|
|
1019
1076
|
for base_type in BaseTypeName:
|
|
@@ -1198,5 +1255,53 @@ class SpecBuilder:
|
|
|
1198
1255
|
def add_prepart_file(self, target: str, name: str, data: str) -> None:
|
|
1199
1256
|
self.preparts[target][name] = data
|
|
1200
1257
|
|
|
1258
|
+
def add_example_file(self, data: dict[str, object]) -> None:
|
|
1259
|
+
path_details = _resolve_endpoint_path(str(data["path"]), self.api_endpoints)
|
|
1260
|
+
|
|
1261
|
+
examples_data = data["examples"]
|
|
1262
|
+
if not isinstance(examples_data, list):
|
|
1263
|
+
raise Exception(
|
|
1264
|
+
f"'examples' in example files are expected to be a list, endpoint_path={path_details.resolved_path}"
|
|
1265
|
+
)
|
|
1266
|
+
for example in examples_data:
|
|
1267
|
+
arguments = example["arguments"]
|
|
1268
|
+
data_example = example["data"]
|
|
1269
|
+
if not isinstance(arguments, dict) or not isinstance(data_example, dict):
|
|
1270
|
+
raise Exception(
|
|
1271
|
+
f"'arguments' and 'data' fields must be dictionaries for each endpoint example, endpoint={path_details.resolved_path}"
|
|
1272
|
+
)
|
|
1273
|
+
self.examples[path_details.resolved_path].append(
|
|
1274
|
+
SpecEndpointExample(
|
|
1275
|
+
summary=str(example["summary"]),
|
|
1276
|
+
description=str(example["description"]),
|
|
1277
|
+
arguments=arguments,
|
|
1278
|
+
data=data_example,
|
|
1279
|
+
)
|
|
1280
|
+
)
|
|
1281
|
+
|
|
1282
|
+
def add_guide_file(self, file_content: str) -> None:
|
|
1283
|
+
import markdown
|
|
1284
|
+
|
|
1285
|
+
md = markdown.Markdown(extensions=["meta"])
|
|
1286
|
+
html = md.convert(file_content)
|
|
1287
|
+
meta: dict[str, list[str]] = md.Meta # type: ignore[attr-defined]
|
|
1288
|
+
title_meta: list[str] | None = meta.get("title")
|
|
1289
|
+
if title_meta is None:
|
|
1290
|
+
raise Exception("guides requier a title in the meta section")
|
|
1291
|
+
|
|
1292
|
+
path_meta: list[str] | None = meta.get("path")
|
|
1293
|
+
guide_key: SpecGuideKey = RootGuideKey()
|
|
1294
|
+
if path_meta is not None:
|
|
1295
|
+
path_details = _resolve_endpoint_path("".join(path_meta), self.api_endpoints)
|
|
1296
|
+
guide_key = EndpointGuideKey(path=path_details.resolved_path)
|
|
1297
|
+
|
|
1298
|
+
self.guides[guide_key].append(
|
|
1299
|
+
SpecGuide(
|
|
1300
|
+
title="".join(title_meta),
|
|
1301
|
+
html_content=html,
|
|
1302
|
+
markdown_content=file_content,
|
|
1303
|
+
)
|
|
1304
|
+
)
|
|
1305
|
+
|
|
1201
1306
|
def resolve_proper_name(self, stype: SpecTypeDefn) -> str:
|
|
1202
1307
|
return f"{'.'.join(stype.namespace.path)}.{stype.name}"
|
|
@@ -118,7 +118,10 @@ def refer_to_io_ts(
|
|
|
118
118
|
stype: builder.SpecType,
|
|
119
119
|
) -> str:
|
|
120
120
|
if isinstance(stype, builder.SpecTypeInstance):
|
|
121
|
-
if
|
|
121
|
+
if (
|
|
122
|
+
stype.defn_type.name == builder.BaseTypeName.s_list
|
|
123
|
+
or stype.defn_type.name == builder.BaseTypeName.s_readonly_array
|
|
124
|
+
):
|
|
122
125
|
spec = refer_to_io_ts(ctx, stype.parameters[0])
|
|
123
126
|
return f"IO.array({spec})"
|
|
124
127
|
if stype.defn_type.name == builder.BaseTypeName.s_union:
|
|
@@ -5,18 +5,22 @@ WORK-IN-PROGRESS, DON'T USE!
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import dataclasses
|
|
8
|
+
import json
|
|
8
9
|
import re
|
|
9
|
-
from typing import cast
|
|
10
|
+
from typing import Collection, cast
|
|
10
11
|
|
|
11
12
|
import yaml
|
|
12
13
|
|
|
13
14
|
from . import builder, util
|
|
15
|
+
from .builder import EndpointGuideKey, RootGuideKey
|
|
14
16
|
from .config import OpenAPIConfig
|
|
15
17
|
from .emit_open_api_util import (
|
|
16
18
|
MODIFY_NOTICE,
|
|
17
19
|
EmitOpenAPIContext,
|
|
18
20
|
EmitOpenAPIEndpoint,
|
|
21
|
+
EmitOpenAPIEndpointExample,
|
|
19
22
|
EmitOpenAPIGlobalContext,
|
|
23
|
+
EmitOpenAPIGuide,
|
|
20
24
|
EmitOpenAPIPath,
|
|
21
25
|
EmitOpenAPIServer,
|
|
22
26
|
EmitOpenAPITag,
|
|
@@ -74,12 +78,23 @@ def _rewrite_with_notice(
|
|
|
74
78
|
return util.rewrite_file(file_path, f"{notice}\n{modified_file_content}")
|
|
75
79
|
|
|
76
80
|
|
|
77
|
-
def
|
|
78
|
-
|
|
81
|
+
def _write_guide_as_html(guide: EmitOpenAPIGuide) -> str:
|
|
82
|
+
return f"""
|
|
83
|
+
<details>
|
|
84
|
+
<summary>{guide.title}</summary>
|
|
85
|
+
{guide.html_content}
|
|
86
|
+
</details>"""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _open_api_info(
|
|
90
|
+
config: OpenAPIConfig, guides: list[EmitOpenAPIGuide]
|
|
91
|
+
) -> GlobalContextInfo:
|
|
92
|
+
full_guides = "<br/>".join([_write_guide_as_html(guide) for guide in guides])
|
|
93
|
+
full_description = f"{config.description}<br/>{full_guides}"
|
|
79
94
|
info: GlobalContextInfo = dict()
|
|
80
95
|
info["version"] = "1.0.0"
|
|
81
96
|
info["title"] = "Uncountable API Documentation"
|
|
82
|
-
info["description"] =
|
|
97
|
+
info["description"] = full_description
|
|
83
98
|
info["x-logo"] = {"url": "../static/images/logo_blue.png", "altText": "Logo"}
|
|
84
99
|
return info
|
|
85
100
|
|
|
@@ -90,9 +105,14 @@ def _open_api_servers(config: OpenAPIConfig) -> list[EmitOpenAPIServer]:
|
|
|
90
105
|
|
|
91
106
|
|
|
92
107
|
def emit_open_api(builder: builder.SpecBuilder, *, config: OpenAPIConfig) -> None:
|
|
108
|
+
root_guides = builder.guides.get(RootGuideKey(), [])
|
|
109
|
+
openapi_guides = [
|
|
110
|
+
EmitOpenAPIGuide(title=guide.title, html_content=guide.html_content)
|
|
111
|
+
for guide in root_guides
|
|
112
|
+
]
|
|
93
113
|
gctx = EmitOpenAPIGlobalContext(
|
|
94
114
|
version="3.0.0",
|
|
95
|
-
info=_open_api_info(config),
|
|
115
|
+
info=_open_api_info(config, openapi_guides),
|
|
96
116
|
servers=_open_api_servers(config),
|
|
97
117
|
)
|
|
98
118
|
|
|
@@ -112,6 +132,8 @@ def emit_open_api(builder: builder.SpecBuilder, *, config: OpenAPIConfig) -> Non
|
|
|
112
132
|
ctx,
|
|
113
133
|
namespace=namespace,
|
|
114
134
|
config=config,
|
|
135
|
+
examples=builder.examples,
|
|
136
|
+
guides=builder.guides,
|
|
115
137
|
)
|
|
116
138
|
|
|
117
139
|
_rewrite_with_notice(
|
|
@@ -144,52 +166,183 @@ def _serialize_global_context(ctx: EmitOpenAPIGlobalContext) -> str:
|
|
|
144
166
|
return yaml.dump(oa_root, sort_keys=False)
|
|
145
167
|
|
|
146
168
|
|
|
147
|
-
def
|
|
169
|
+
def _is_empty_object_type(typ: OpenAPIType) -> bool:
|
|
148
170
|
if not isinstance(typ, OpenAPIObjectType):
|
|
171
|
+
return False
|
|
172
|
+
return len(typ.properties) == 0
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
_QUERY_PARM_METHODS = ("get", "head", "options")
|
|
176
|
+
_REQUEST_BODY_METHODS = ("put", "post", "patch", "delete")
|
|
177
|
+
|
|
178
|
+
ApiSchema = dict[str, "ApiSchema"] | Collection["ApiSchema"] | str | bool
|
|
179
|
+
DictApiSchema = dict[str, ApiSchema]
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _emit_endpoint_argument_examples(
|
|
183
|
+
examples: list[EmitOpenAPIEndpointExample],
|
|
184
|
+
) -> DictApiSchema:
|
|
185
|
+
if len(examples) == 0:
|
|
186
|
+
return {}
|
|
187
|
+
|
|
188
|
+
response_examples = {}
|
|
189
|
+
for example in examples:
|
|
190
|
+
response_examples[example.ref_name] = {
|
|
191
|
+
"summary": example.summary,
|
|
192
|
+
"description": example.description,
|
|
193
|
+
"value": example.arguments,
|
|
194
|
+
}
|
|
195
|
+
return {"examples": response_examples}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _emit_endpoint_parameter_examples(
|
|
199
|
+
examples: list[EmitOpenAPIEndpointExample],
|
|
200
|
+
) -> DictApiSchema:
|
|
201
|
+
if len(examples) == 0:
|
|
202
|
+
return {}
|
|
203
|
+
|
|
204
|
+
paramater_examples = []
|
|
205
|
+
comment_new_line = "\n// "
|
|
206
|
+
new_line = "\n"
|
|
207
|
+
for example in examples:
|
|
208
|
+
javascript_description = (
|
|
209
|
+
f"// {comment_new_line.join(example.description.split(new_line))}"
|
|
210
|
+
)
|
|
211
|
+
javascript_json_payload = f"{json.dumps(example.arguments, indent=2)}"
|
|
212
|
+
paramater_examples.append({
|
|
213
|
+
"lang": "JavaScript",
|
|
214
|
+
"label": f"Payload - {example.summary}",
|
|
215
|
+
"source": f"{javascript_description}\n{javascript_json_payload}",
|
|
216
|
+
})
|
|
217
|
+
return {"x-codeSamples": paramater_examples}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _emit_endpoint_parameters(
|
|
221
|
+
endpoint: EmitOpenAPIEndpoint,
|
|
222
|
+
argument_type: OpenAPIType | None,
|
|
223
|
+
examples: list[EmitOpenAPIEndpointExample],
|
|
224
|
+
) -> DictApiSchema:
|
|
225
|
+
if (
|
|
226
|
+
endpoint.method.lower() not in _QUERY_PARM_METHODS
|
|
227
|
+
or argument_type is None
|
|
228
|
+
or _is_empty_object_type(argument_type)
|
|
229
|
+
):
|
|
149
230
|
return {}
|
|
150
231
|
|
|
151
232
|
return {
|
|
152
233
|
"parameters": [
|
|
153
|
-
{
|
|
154
|
-
|
|
234
|
+
{
|
|
235
|
+
"name": "data",
|
|
236
|
+
"required": True,
|
|
237
|
+
"in": "query",
|
|
238
|
+
"content": {
|
|
239
|
+
"application/json": {
|
|
240
|
+
"schema": {"$ref": "#/components/schema/Arguments"}
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
}
|
|
155
244
|
]
|
|
156
|
-
}
|
|
245
|
+
} | _emit_endpoint_parameter_examples(examples)
|
|
157
246
|
|
|
158
247
|
|
|
159
|
-
def _emit_is_beta(is_beta: bool) ->
|
|
248
|
+
def _emit_is_beta(is_beta: bool) -> DictApiSchema:
|
|
160
249
|
if is_beta:
|
|
161
250
|
return {"x-beta": True}
|
|
162
251
|
return {}
|
|
163
252
|
|
|
164
253
|
|
|
254
|
+
def _emit_endpoint_request_body(
|
|
255
|
+
endpoint: EmitOpenAPIEndpoint,
|
|
256
|
+
arguments_type: OpenAPIType | None,
|
|
257
|
+
examples: list[EmitOpenAPIEndpointExample],
|
|
258
|
+
) -> DictApiSchema:
|
|
259
|
+
if (
|
|
260
|
+
endpoint.method.lower() not in _REQUEST_BODY_METHODS
|
|
261
|
+
or arguments_type is None
|
|
262
|
+
or _is_empty_object_type(arguments_type)
|
|
263
|
+
):
|
|
264
|
+
return {}
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
"requestBody": {
|
|
268
|
+
"content": {
|
|
269
|
+
"application/json": {
|
|
270
|
+
"schema": {
|
|
271
|
+
"type": "object",
|
|
272
|
+
"title": "Body",
|
|
273
|
+
"required": ["data"],
|
|
274
|
+
"properties": {"data": {"$ref": "#/components/schema/Arguments"}},
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
| _emit_endpoint_argument_examples(examples)
|
|
278
|
+
},
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def _emit_endpoint_response_examples(
|
|
284
|
+
examples: list[EmitOpenAPIEndpointExample],
|
|
285
|
+
) -> dict[str, dict[str, object]]:
|
|
286
|
+
if len(examples) == 0:
|
|
287
|
+
return {}
|
|
288
|
+
|
|
289
|
+
response_examples: dict[str, object] = {}
|
|
290
|
+
for example in examples:
|
|
291
|
+
response_examples[example.ref_name] = {
|
|
292
|
+
"summary": example.summary,
|
|
293
|
+
"description": example.description,
|
|
294
|
+
"value": example.data,
|
|
295
|
+
}
|
|
296
|
+
return {"examples": response_examples}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _emit_endpoint_description(
|
|
300
|
+
description: str, guides: list[EmitOpenAPIGuide]
|
|
301
|
+
) -> dict[str, str]:
|
|
302
|
+
full_guides = "<br/>".join([_write_guide_as_html(guide) for guide in guides])
|
|
303
|
+
return {
|
|
304
|
+
"description": description
|
|
305
|
+
if len(guides) == 0
|
|
306
|
+
else f"{description}<br/>{full_guides}"
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
165
310
|
def _emit_namespace(
|
|
166
311
|
gctx: EmitOpenAPIGlobalContext,
|
|
167
312
|
ctx: EmitOpenAPIContext,
|
|
168
313
|
namespace: builder.SpecNamespace,
|
|
169
314
|
*,
|
|
170
315
|
config: OpenAPIConfig,
|
|
316
|
+
examples: dict[str, list[builder.SpecEndpointExample]],
|
|
317
|
+
guides: dict[builder.SpecGuideKey, list[builder.SpecGuide]],
|
|
171
318
|
) -> None:
|
|
172
319
|
for stype in namespace.types.values():
|
|
173
320
|
_emit_type(ctx, stype, config=config)
|
|
174
321
|
|
|
175
322
|
if namespace.endpoint is not None:
|
|
176
|
-
|
|
323
|
+
endpoint_examples = examples.get(namespace.endpoint.resolved_path, [])
|
|
324
|
+
endpoint_guides = guides.get(
|
|
325
|
+
EndpointGuideKey(path=namespace.endpoint.resolved_path), []
|
|
326
|
+
)
|
|
327
|
+
_emit_endpoint(
|
|
328
|
+
gctx, ctx, namespace, namespace.endpoint, endpoint_examples, endpoint_guides
|
|
329
|
+
)
|
|
177
330
|
|
|
178
331
|
oa_components: dict[str, object] = dict()
|
|
179
332
|
|
|
180
333
|
if ctx.endpoint is not None:
|
|
181
334
|
endpoint = ctx.endpoint
|
|
182
|
-
|
|
183
335
|
argument_type = ctx.types.get("Arguments")
|
|
184
336
|
oa_endpoint = dict()
|
|
185
337
|
oa_endpoint[endpoint.method] = (
|
|
186
338
|
{
|
|
187
339
|
"tags": endpoint.tags,
|
|
188
340
|
"summary": endpoint.summary,
|
|
189
|
-
"description": endpoint.description,
|
|
190
341
|
}
|
|
342
|
+
| _emit_endpoint_description(endpoint.description, ctx.endpoint.guides)
|
|
191
343
|
| _emit_is_beta(endpoint.is_beta)
|
|
192
|
-
| _emit_endpoint_parameters(argument_type)
|
|
344
|
+
| _emit_endpoint_parameters(endpoint, argument_type, ctx.endpoint.examples)
|
|
345
|
+
| _emit_endpoint_request_body(endpoint, argument_type, ctx.endpoint.examples)
|
|
193
346
|
| {
|
|
194
347
|
"responses": {
|
|
195
348
|
"200": {
|
|
@@ -198,6 +351,7 @@ def _emit_namespace(
|
|
|
198
351
|
"application/json": {
|
|
199
352
|
"schema": {"$ref": "#/components/schema/Data"}
|
|
200
353
|
}
|
|
354
|
+
| _emit_endpoint_response_examples(ctx.endpoint.examples)
|
|
201
355
|
},
|
|
202
356
|
}
|
|
203
357
|
},
|
|
@@ -236,10 +390,7 @@ def _emit_namespace(
|
|
|
236
390
|
|
|
237
391
|
oa_components["schema"] = cast(
|
|
238
392
|
object,
|
|
239
|
-
{
|
|
240
|
-
name: (value.asdict() if name != "Arguments" else value.asarguments())
|
|
241
|
-
for name, value in types.items()
|
|
242
|
-
},
|
|
393
|
+
{name: value.asdict() for name, value in types.items()},
|
|
243
394
|
)
|
|
244
395
|
|
|
245
396
|
path = f"{config.types_output}/common/{'/'.join(namespace.path)}.yaml"
|
|
@@ -348,6 +499,8 @@ def _emit_endpoint(
|
|
|
348
499
|
ctx: EmitOpenAPIContext,
|
|
349
500
|
namespace: builder.SpecNamespace,
|
|
350
501
|
endpoint: builder.SpecEndpoint,
|
|
502
|
+
endpoint_examples: list[builder.SpecEndpointExample],
|
|
503
|
+
endpoint_guides: list[builder.SpecGuide],
|
|
351
504
|
) -> None:
|
|
352
505
|
assert namespace.endpoint is not None
|
|
353
506
|
assert namespace.path[0] == "api"
|
|
@@ -397,6 +550,23 @@ def _emit_endpoint(
|
|
|
397
550
|
summary=f"{'/'.join(namespace.path[path_cutoff:])}",
|
|
398
551
|
description=description,
|
|
399
552
|
is_beta=namespace.endpoint.is_beta,
|
|
553
|
+
examples=[
|
|
554
|
+
EmitOpenAPIEndpointExample(
|
|
555
|
+
ref_name=f"ex_{i}",
|
|
556
|
+
summary=example.summary,
|
|
557
|
+
description=example.description,
|
|
558
|
+
arguments=example.arguments,
|
|
559
|
+
data=example.data,
|
|
560
|
+
)
|
|
561
|
+
for i, example in enumerate(endpoint_examples)
|
|
562
|
+
],
|
|
563
|
+
guides=[
|
|
564
|
+
EmitOpenAPIGuide(
|
|
565
|
+
title=guide.title,
|
|
566
|
+
html_content=guide.html_content,
|
|
567
|
+
)
|
|
568
|
+
for guide in endpoint_guides
|
|
569
|
+
],
|
|
400
570
|
)
|
|
401
571
|
|
|
402
572
|
|
|
@@ -464,6 +634,10 @@ def open_api_type(
|
|
|
464
634
|
[open_api_type(ctx, p, config=config) for p in stype.parameters],
|
|
465
635
|
description="TupleType",
|
|
466
636
|
)
|
|
637
|
+
if stype.defn_type.name == builder.BaseTypeName.s_readonly_array:
|
|
638
|
+
return OpenAPIArrayType(
|
|
639
|
+
open_api_type(ctx, stype.parameters[0], config=config)
|
|
640
|
+
)
|
|
467
641
|
|
|
468
642
|
# TODO: generics are not supported by OpenAPI
|
|
469
643
|
# map to Free-Form Object and add description
|
{uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_open_api_util.py
RENAMED
|
@@ -43,6 +43,12 @@ class EmitOpenAPIServer:
|
|
|
43
43
|
url: str
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
@dataclass(kw_only=True)
|
|
47
|
+
class EmitOpenAPIGuide:
|
|
48
|
+
title: str
|
|
49
|
+
html_content: str
|
|
50
|
+
|
|
51
|
+
|
|
46
52
|
@dataclass
|
|
47
53
|
class EmitOpenAPIGlobalContext:
|
|
48
54
|
version: str
|
|
@@ -56,6 +62,15 @@ class EmitOpenAPIGlobalContext:
|
|
|
56
62
|
paths: list[EmitOpenAPIPath] = field(default_factory=list)
|
|
57
63
|
|
|
58
64
|
|
|
65
|
+
@dataclass(kw_only=True)
|
|
66
|
+
class EmitOpenAPIEndpointExample:
|
|
67
|
+
ref_name: str
|
|
68
|
+
summary: str
|
|
69
|
+
description: str
|
|
70
|
+
arguments: dict[str, object]
|
|
71
|
+
data: dict[str, object]
|
|
72
|
+
|
|
73
|
+
|
|
59
74
|
@dataclass
|
|
60
75
|
class EmitOpenAPIEndpoint:
|
|
61
76
|
method: str
|
|
@@ -63,6 +78,8 @@ class EmitOpenAPIEndpoint:
|
|
|
63
78
|
summary: str
|
|
64
79
|
description: str
|
|
65
80
|
is_beta: bool
|
|
81
|
+
examples: list[EmitOpenAPIEndpointExample]
|
|
82
|
+
guides: list[EmitOpenAPIGuide]
|
|
66
83
|
|
|
67
84
|
|
|
68
85
|
@dataclass
|
|
@@ -29,7 +29,7 @@ ASYNC_BATCH_REQUEST_STYPE = builder.SpecTypeDefnObject(
|
|
|
29
29
|
namespace=ASYNC_BATCH_TYPE_NAMESPACE, name="AsyncBatchRequest"
|
|
30
30
|
)
|
|
31
31
|
QUEUED_BATCH_REQUEST_STYPE = builder.SpecTypeDefnObject(
|
|
32
|
-
namespace=ASYNC_BATCH_TYPE_NAMESPACE, name="
|
|
32
|
+
namespace=ASYNC_BATCH_TYPE_NAMESPACE, name="QueuedAsyncBatchRequest"
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
|
|
@@ -819,6 +819,7 @@ base_name_map = {
|
|
|
819
819
|
builder.BaseTypeName.s_opaque_key: "OpaqueKey",
|
|
820
820
|
builder.BaseTypeName.s_string: "str",
|
|
821
821
|
builder.BaseTypeName.s_tuple: "tuple",
|
|
822
|
+
builder.BaseTypeName.s_readonly_array: "tuple",
|
|
822
823
|
builder.BaseTypeName.s_union: "typing.Union",
|
|
823
824
|
builder.BaseTypeName.s_literal: "typing.Literal",
|
|
824
825
|
}
|
|
@@ -827,6 +828,11 @@ base_name_map = {
|
|
|
827
828
|
def refer_to(ctx: TrackingContext, stype: builder.SpecType) -> str:
|
|
828
829
|
if isinstance(stype, builder.SpecTypeInstance):
|
|
829
830
|
params = ", ".join([refer_to(ctx, p) for p in stype.parameters])
|
|
831
|
+
|
|
832
|
+
if stype.defn_type.is_base_type(builder.BaseTypeName.s_readonly_array):
|
|
833
|
+
assert len(stype.parameters) == 1, "Read Only Array takes one parameter"
|
|
834
|
+
params = f"{params}, ..."
|
|
835
|
+
|
|
830
836
|
return f"{refer_to(ctx, stype.defn_type)}[{params}]"
|
|
831
837
|
|
|
832
838
|
if isinstance(stype, builder.SpecTypeLiteralWrapper):
|
{uncountablepythonsdk-0.0.21 → uncountablepythonsdk-0.0.23}/pkgs/type_spec/emit_typescript.py
RENAMED
|
@@ -394,6 +394,9 @@ def refer_to_impl(
|
|
|
394
394
|
if stype.defn_type.name == builder.BaseTypeName.s_list:
|
|
395
395
|
spec, multi = refer_to_impl(ctx, stype.parameters[0])
|
|
396
396
|
return f"({spec})[]" if multi else f"{spec}[]", False
|
|
397
|
+
if stype.defn_type.name == builder.BaseTypeName.s_readonly_array:
|
|
398
|
+
spec, multi = refer_to_impl(ctx, stype.parameters[0])
|
|
399
|
+
return f"readonly ({spec})[]" if multi else f"readonly {spec}[]", False
|
|
397
400
|
if stype.defn_type.name == builder.BaseTypeName.s_union:
|
|
398
401
|
return f'({" | ".join([refer_to(ctx, p) for p in stype.parameters])})', False
|
|
399
402
|
if stype.defn_type.name == builder.BaseTypeName.s_literal:
|