UncountablePythonSDK 0.0.24__py3-none-any.whl → 0.0.131__py3-none-any.whl
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.
- docs/conf.py +60 -8
- docs/index.md +107 -4
- docs/integration_examples/create_ingredient.md +43 -0
- docs/integration_examples/create_output.md +56 -0
- docs/integration_examples/index.md +6 -0
- docs/justfile +2 -2
- docs/requirements.txt +7 -5
- examples/async_batch.py +5 -6
- examples/basic_auth.py +7 -0
- examples/create_entity.py +4 -6
- examples/create_ingredient_sdk.py +34 -0
- examples/download_files.py +26 -0
- examples/edit_recipe_inputs.py +50 -0
- examples/integration-server/jobs/materials_auto/concurrent_cron.py +11 -0
- examples/integration-server/jobs/materials_auto/example_cron.py +21 -0
- examples/integration-server/jobs/materials_auto/example_http.py +47 -0
- examples/integration-server/jobs/materials_auto/example_instrument.py +100 -0
- examples/integration-server/jobs/materials_auto/example_parse.py +140 -0
- examples/integration-server/jobs/materials_auto/example_predictions.py +61 -0
- examples/integration-server/jobs/materials_auto/example_runsheet_wh.py +39 -0
- examples/integration-server/jobs/materials_auto/example_wh.py +23 -0
- examples/integration-server/jobs/materials_auto/profile.yaml +104 -0
- examples/integration-server/pyproject.toml +224 -0
- examples/invoke_uploader.py +26 -0
- examples/oauth.py +7 -0
- examples/set_recipe_metadata_file.py +40 -0
- examples/set_recipe_output_file_sdk.py +26 -0
- examples/upload_files.py +2 -3
- pkgs/argument_parser/__init__.py +9 -0
- pkgs/argument_parser/_is_namedtuple.py +3 -0
- pkgs/argument_parser/argument_parser.py +295 -74
- pkgs/argument_parser/case_convert.py +4 -3
- pkgs/filesystem_utils/__init__.py +20 -0
- pkgs/filesystem_utils/_blob_session.py +144 -0
- pkgs/filesystem_utils/_gdrive_session.py +309 -0
- pkgs/filesystem_utils/_local_session.py +69 -0
- pkgs/filesystem_utils/_s3_session.py +118 -0
- pkgs/filesystem_utils/_sftp_session.py +151 -0
- pkgs/filesystem_utils/file_type_utils.py +91 -0
- pkgs/filesystem_utils/filesystem_session.py +39 -0
- pkgs/py.typed +0 -0
- pkgs/serialization/__init__.py +8 -1
- pkgs/serialization/annotation.py +64 -0
- pkgs/serialization/missing_sentry.py +1 -1
- pkgs/serialization/opaque_key.py +1 -1
- pkgs/serialization/serial_alias.py +47 -0
- pkgs/serialization/serial_class.py +69 -54
- pkgs/serialization/serial_generic.py +16 -0
- pkgs/serialization/serial_union.py +84 -0
- pkgs/serialization/yaml.py +57 -0
- pkgs/serialization_util/__init__.py +7 -7
- pkgs/serialization_util/convert_to_snakecase.py +27 -0
- pkgs/serialization_util/dataclasses.py +14 -0
- pkgs/serialization_util/serialization_helpers.py +117 -71
- pkgs/type_spec/actions_registry/__main__.py +0 -4
- pkgs/type_spec/actions_registry/emit_typescript.py +5 -5
- pkgs/type_spec/builder.py +438 -109
- pkgs/type_spec/builder_types.py +9 -0
- pkgs/type_spec/config.py +52 -24
- pkgs/type_spec/cross_output_links.py +99 -0
- pkgs/type_spec/emit_io_ts.py +1 -1
- pkgs/type_spec/emit_open_api.py +160 -41
- pkgs/type_spec/emit_open_api_util.py +13 -7
- pkgs/type_spec/emit_python.py +450 -136
- pkgs/type_spec/emit_typescript.py +117 -250
- pkgs/type_spec/emit_typescript_util.py +293 -4
- pkgs/type_spec/load_types.py +20 -5
- pkgs/type_spec/non_discriminated_union_exceptions.py +14 -0
- pkgs/type_spec/open_api_util.py +29 -4
- pkgs/type_spec/parts/base.py.prepart +13 -10
- pkgs/type_spec/parts/base.ts.prepart +4 -0
- pkgs/type_spec/type_info/__main__.py +3 -1
- pkgs/type_spec/type_info/emit_type_info.py +161 -32
- pkgs/type_spec/ui_entry_actions/__init__.py +4 -0
- pkgs/type_spec/ui_entry_actions/generate_ui_entry_actions.py +308 -0
- pkgs/type_spec/util.py +4 -4
- pkgs/type_spec/value_spec/__main__.py +27 -10
- pkgs/type_spec/value_spec/convert_type.py +21 -1
- pkgs/type_spec/value_spec/emit_python.py +25 -7
- pkgs/type_spec/value_spec/types.py +1 -1
- uncountable/__init__.py +1 -2
- uncountable/core/__init__.py +11 -3
- uncountable/core/async_batch.py +16 -1
- uncountable/core/client.py +247 -52
- uncountable/core/environment.py +41 -0
- uncountable/core/file_upload.py +67 -22
- uncountable/core/types.py +8 -13
- uncountable/integration/cli.py +142 -0
- uncountable/integration/construct_client.py +43 -27
- uncountable/integration/cron.py +12 -11
- uncountable/integration/db/connect.py +12 -2
- uncountable/integration/db/session.py +25 -0
- uncountable/integration/entrypoint.py +4 -34
- uncountable/integration/executors/executors.py +147 -0
- uncountable/integration/executors/generic_upload_executor.py +336 -0
- uncountable/integration/executors/script_executor.py +15 -9
- uncountable/integration/http_server/__init__.py +5 -0
- uncountable/integration/http_server/types.py +69 -0
- uncountable/integration/job.py +246 -19
- uncountable/integration/queue_runner/__init__.py +0 -0
- uncountable/integration/queue_runner/command_server/__init__.py +28 -0
- uncountable/integration/queue_runner/command_server/command_client.py +133 -0
- uncountable/integration/queue_runner/command_server/command_server.py +142 -0
- uncountable/integration/queue_runner/command_server/constants.py +4 -0
- uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server.proto +58 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +57 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +114 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +264 -0
- uncountable/integration/queue_runner/command_server/types.py +75 -0
- uncountable/integration/queue_runner/datastore/__init__.py +3 -0
- uncountable/integration/queue_runner/datastore/datastore_sqlite.py +250 -0
- uncountable/integration/queue_runner/datastore/interface.py +29 -0
- uncountable/integration/queue_runner/datastore/model.py +24 -0
- uncountable/integration/queue_runner/job_scheduler.py +200 -0
- uncountable/integration/queue_runner/queue_runner.py +34 -0
- uncountable/integration/queue_runner/types.py +7 -0
- uncountable/integration/queue_runner/worker.py +116 -0
- uncountable/integration/scan_profiles.py +67 -0
- uncountable/integration/scheduler.py +199 -0
- uncountable/integration/secret_retrieval/__init__.py +3 -0
- uncountable/integration/secret_retrieval/retrieve_secret.py +93 -0
- uncountable/integration/server.py +103 -54
- uncountable/integration/telemetry.py +251 -0
- uncountable/integration/webhook_server/entrypoint.py +97 -0
- uncountable/types/__init__.py +149 -30
- uncountable/types/api/batch/execute_batch.py +16 -9
- uncountable/types/api/batch/execute_batch_load_async.py +13 -7
- uncountable/types/api/chemical/convert_chemical_formats.py +20 -8
- uncountable/types/api/condition_parameters/__init__.py +1 -0
- uncountable/types/api/condition_parameters/upsert_condition_match.py +72 -0
- uncountable/types/api/entity/create_entities.py +24 -12
- uncountable/types/api/entity/create_entity.py +22 -13
- uncountable/types/api/entity/create_or_update_entity.py +48 -0
- uncountable/types/api/entity/export_entities.py +59 -0
- uncountable/types/api/entity/get_entities_data.py +18 -9
- uncountable/types/api/entity/grant_entity_permissions.py +48 -0
- uncountable/types/api/entity/list_aggregate.py +79 -0
- uncountable/types/api/entity/list_entities.py +53 -14
- uncountable/types/api/entity/lock_entity.py +45 -0
- uncountable/types/api/entity/lookup_entity.py +116 -0
- uncountable/types/api/entity/resolve_entity_ids.py +19 -10
- uncountable/types/api/entity/set_entity_field_values.py +44 -0
- uncountable/types/api/entity/set_values.py +15 -8
- uncountable/types/api/entity/transition_entity_phase.py +27 -12
- uncountable/types/api/entity/unlock_entity.py +44 -0
- uncountable/types/api/equipment/__init__.py +1 -0
- uncountable/types/api/equipment/associate_equipment_input.py +43 -0
- uncountable/types/api/field_options/__init__.py +1 -0
- uncountable/types/api/field_options/upsert_field_options.py +55 -0
- uncountable/types/api/files/__init__.py +1 -0
- uncountable/types/api/files/download_file.py +77 -0
- uncountable/types/api/id_source/list_id_source.py +20 -11
- uncountable/types/api/id_source/match_id_source.py +15 -10
- uncountable/types/api/input_groups/get_input_group_names.py +16 -7
- uncountable/types/api/inputs/create_inputs.py +28 -14
- uncountable/types/api/inputs/get_input_data.py +34 -16
- uncountable/types/api/inputs/get_input_names.py +19 -10
- uncountable/types/api/inputs/get_inputs_data.py +29 -11
- uncountable/types/api/inputs/set_input_attribute_values.py +16 -10
- uncountable/types/api/inputs/set_input_category.py +44 -0
- uncountable/types/api/inputs/set_input_subcategories.py +45 -0
- uncountable/types/api/inputs/set_intermediate_type.py +50 -0
- uncountable/types/api/integrations/__init__.py +1 -0
- uncountable/types/api/integrations/publish_realtime_data.py +41 -0
- uncountable/types/api/integrations/push_notification.py +49 -0
- uncountable/types/api/integrations/register_sockets_token.py +41 -0
- uncountable/types/api/listing/__init__.py +1 -0
- uncountable/types/api/listing/fetch_listing.py +58 -0
- uncountable/types/api/material_families/__init__.py +1 -0
- uncountable/types/api/material_families/update_entity_material_families.py +47 -0
- uncountable/types/api/notebooks/__init__.py +1 -0
- uncountable/types/api/notebooks/add_notebook_content.py +119 -0
- uncountable/types/api/outputs/get_output_data.py +32 -17
- uncountable/types/api/outputs/get_output_names.py +18 -9
- uncountable/types/api/outputs/get_output_organization.py +173 -0
- uncountable/types/api/outputs/resolve_output_conditions.py +23 -11
- uncountable/types/api/permissions/set_core_permissions.py +31 -15
- uncountable/types/api/project/get_projects.py +20 -11
- uncountable/types/api/project/get_projects_data.py +23 -14
- uncountable/types/api/recipe_links/create_recipe_link.py +17 -10
- uncountable/types/api/recipe_links/remove_recipe_link.py +45 -0
- uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +19 -10
- uncountable/types/api/recipes/add_recipe_to_project.py +42 -0
- uncountable/types/api/recipes/add_time_series_data.py +64 -0
- uncountable/types/api/recipes/archive_recipes.py +14 -7
- uncountable/types/api/recipes/associate_recipe_as_input.py +16 -8
- uncountable/types/api/recipes/associate_recipe_as_lot.py +14 -7
- uncountable/types/api/recipes/clear_recipe_outputs.py +42 -0
- uncountable/types/api/recipes/create_mix_order.py +44 -0
- uncountable/types/api/recipes/create_recipe.py +21 -14
- uncountable/types/api/recipes/create_recipes.py +25 -13
- uncountable/types/api/recipes/disassociate_recipe_as_input.py +14 -7
- uncountable/types/api/recipes/edit_recipe_inputs.py +208 -19
- uncountable/types/api/recipes/get_column_calculation_values.py +57 -0
- uncountable/types/api/recipes/get_curve.py +15 -9
- uncountable/types/api/recipes/get_recipe_calculations.py +17 -11
- uncountable/types/api/recipes/get_recipe_links.py +14 -8
- uncountable/types/api/recipes/get_recipe_names.py +16 -7
- uncountable/types/api/recipes/get_recipe_output_metadata.py +16 -10
- uncountable/types/api/recipes/get_recipes_data.py +96 -45
- uncountable/types/api/recipes/lock_recipes.py +64 -0
- uncountable/types/api/recipes/remove_recipe_from_project.py +42 -0
- uncountable/types/api/recipes/set_recipe_inputs.py +19 -13
- uncountable/types/api/recipes/set_recipe_metadata.py +14 -7
- uncountable/types/api/recipes/set_recipe_output_annotations.py +114 -0
- uncountable/types/api/recipes/set_recipe_output_file.py +55 -0
- uncountable/types/api/recipes/set_recipe_outputs.py +40 -15
- uncountable/types/api/recipes/set_recipe_tags.py +30 -13
- uncountable/types/api/recipes/set_recipe_total.py +59 -0
- uncountable/types/api/recipes/unarchive_recipes.py +41 -0
- uncountable/types/api/recipes/unlock_recipes.py +51 -0
- uncountable/types/api/runsheet/__init__.py +1 -0
- uncountable/types/api/runsheet/complete_async_upload.py +41 -0
- uncountable/types/api/triggers/run_trigger.py +15 -8
- uncountable/types/api/uploader/__init__.py +1 -0
- uncountable/types/api/uploader/complete_async_parse.py +46 -0
- uncountable/types/api/uploader/invoke_uploader.py +46 -0
- uncountable/types/api/user/__init__.py +1 -0
- uncountable/types/api/user/get_current_user_info.py +40 -0
- uncountable/types/async_batch.py +8 -52
- uncountable/types/async_batch_processor.py +694 -18
- uncountable/types/async_batch_t.py +108 -0
- uncountable/types/async_jobs.py +8 -0
- uncountable/types/async_jobs_t.py +52 -0
- uncountable/types/auth_retrieval.py +11 -0
- uncountable/types/auth_retrieval_t.py +75 -0
- uncountable/types/base.py +5 -80
- uncountable/types/base_t.py +87 -0
- uncountable/types/calculations.py +3 -19
- uncountable/types/calculations_t.py +26 -0
- uncountable/types/chemical_structure.py +3 -23
- uncountable/types/chemical_structure_t.py +28 -0
- uncountable/types/client_base.py +1170 -88
- uncountable/types/client_config.py +8 -0
- uncountable/types/client_config_t.py +36 -0
- uncountable/types/curves.py +5 -43
- uncountable/types/curves_t.py +50 -0
- uncountable/types/data.py +12 -0
- uncountable/types/data_t.py +103 -0
- uncountable/types/entity.py +8 -270
- uncountable/types/entity_t.py +446 -0
- uncountable/types/experiment_groups.py +3 -19
- uncountable/types/experiment_groups_t.py +26 -0
- uncountable/types/exports.py +8 -0
- uncountable/types/exports_t.py +34 -0
- uncountable/types/field_values.py +25 -61
- uncountable/types/field_values_t.py +302 -0
- uncountable/types/fields.py +3 -20
- uncountable/types/fields_t.py +27 -0
- uncountable/types/generic_upload.py +14 -0
- uncountable/types/generic_upload_t.py +119 -0
- uncountable/types/id_source.py +7 -45
- uncountable/types/id_source_t.py +68 -0
- uncountable/types/identifier.py +6 -50
- uncountable/types/identifier_t.py +62 -0
- uncountable/types/input_attributes.py +3 -25
- uncountable/types/input_attributes_t.py +29 -0
- uncountable/types/inputs.py +6 -57
- uncountable/types/inputs_t.py +82 -0
- uncountable/types/integration_server.py +8 -0
- uncountable/types/integration_server_t.py +46 -0
- uncountable/types/integration_session.py +10 -0
- uncountable/types/integration_session_t.py +60 -0
- uncountable/types/integrations.py +10 -0
- uncountable/types/integrations_t.py +62 -0
- uncountable/types/job_definition.py +28 -0
- uncountable/types/job_definition_t.py +285 -0
- uncountable/types/listing.py +9 -0
- uncountable/types/listing_t.py +51 -0
- uncountable/types/notices.py +8 -0
- uncountable/types/notices_t.py +37 -0
- uncountable/types/notifications.py +11 -0
- uncountable/types/notifications_t.py +74 -0
- uncountable/types/outputs.py +3 -22
- uncountable/types/outputs_t.py +29 -0
- uncountable/types/overrides.py +9 -0
- uncountable/types/overrides_t.py +49 -0
- uncountable/types/permissions.py +3 -42
- uncountable/types/permissions_t.py +45 -0
- uncountable/types/phases.py +3 -19
- uncountable/types/phases_t.py +26 -0
- uncountable/types/post_base.py +3 -26
- uncountable/types/post_base_t.py +29 -0
- uncountable/types/queued_job.py +17 -0
- uncountable/types/queued_job_t.py +140 -0
- uncountable/types/recipe_identifiers.py +7 -58
- uncountable/types/recipe_identifiers_t.py +75 -0
- uncountable/types/recipe_inputs.py +4 -26
- uncountable/types/recipe_inputs_t.py +29 -0
- uncountable/types/recipe_links.py +4 -46
- uncountable/types/recipe_links_t.py +53 -0
- uncountable/types/recipe_metadata.py +5 -48
- uncountable/types/recipe_metadata_t.py +57 -0
- uncountable/types/recipe_output_metadata.py +3 -20
- uncountable/types/recipe_output_metadata_t.py +27 -0
- uncountable/types/recipe_tags.py +3 -19
- uncountable/types/recipe_tags_t.py +26 -0
- uncountable/types/recipe_workflow_steps.py +9 -73
- uncountable/types/recipe_workflow_steps_t.py +95 -0
- uncountable/types/recipes.py +7 -0
- uncountable/types/recipes_t.py +25 -0
- uncountable/types/response.py +3 -21
- uncountable/types/response_t.py +26 -0
- uncountable/types/secret_retrieval.py +11 -0
- uncountable/types/secret_retrieval_t.py +75 -0
- uncountable/types/sockets.py +20 -0
- uncountable/types/sockets_t.py +169 -0
- uncountable/types/structured_filters.py +25 -0
- uncountable/types/structured_filters_t.py +248 -0
- uncountable/types/units.py +3 -19
- uncountable/types/units_t.py +26 -0
- uncountable/types/uploader.py +24 -0
- uncountable/types/uploader_t.py +222 -0
- uncountable/types/users.py +3 -20
- uncountable/types/users_t.py +27 -0
- uncountable/types/webhook_job.py +9 -0
- uncountable/types/webhook_job_t.py +48 -0
- uncountable/types/workflows.py +4 -28
- uncountable/types/workflows_t.py +38 -0
- uncountablepythonsdk-0.0.131.dist-info/METADATA +64 -0
- uncountablepythonsdk-0.0.131.dist-info/RECORD +363 -0
- {UncountablePythonSDK-0.0.24.dist-info → uncountablepythonsdk-0.0.131.dist-info}/WHEEL +1 -1
- {UncountablePythonSDK-0.0.24.dist-info → uncountablepythonsdk-0.0.131.dist-info}/top_level.txt +0 -1
- UncountablePythonSDK-0.0.24.dist-info/METADATA +0 -47
- UncountablePythonSDK-0.0.24.dist-info/RECORD +0 -216
- docs/quickstart.md +0 -19
- examples/recipe-import/importer.py +0 -39
- type_spec/external/api/batch/execute_batch.yaml +0 -56
- type_spec/external/api/batch/execute_batch_load_async.yaml +0 -18
- type_spec/external/api/chemical/convert_chemical_formats.yaml +0 -33
- type_spec/external/api/entity/create_entities.yaml +0 -45
- type_spec/external/api/entity/create_entity.yaml +0 -51
- type_spec/external/api/entity/get_entities_data.yaml +0 -29
- type_spec/external/api/entity/list_entities.yaml +0 -52
- type_spec/external/api/entity/resolve_entity_ids.yaml +0 -29
- type_spec/external/api/entity/set_values.yaml +0 -18
- type_spec/external/api/entity/transition_entity_phase.yaml +0 -44
- type_spec/external/api/id_source/list_id_source.yaml +0 -35
- type_spec/external/api/id_source/match_id_source.yaml +0 -32
- type_spec/external/api/input_groups/get_input_group_names.yaml +0 -29
- type_spec/external/api/inputs/create_inputs.yaml +0 -48
- type_spec/external/api/inputs/get_input_data.yaml +0 -95
- type_spec/external/api/inputs/get_input_names.yaml +0 -38
- type_spec/external/api/inputs/get_inputs_data.yaml +0 -82
- type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -33
- type_spec/external/api/outputs/get_output_data.yaml +0 -92
- type_spec/external/api/outputs/get_output_names.yaml +0 -35
- type_spec/external/api/outputs/resolve_output_conditions.yaml +0 -50
- type_spec/external/api/permissions/set_core_permissions.yaml +0 -69
- type_spec/external/api/project/get_projects.yaml +0 -42
- type_spec/external/api/project/get_projects_data.yaml +0 -50
- type_spec/external/api/recipe_links/create_recipe_link.yaml +0 -25
- type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -41
- type_spec/external/api/recipes/archive_recipes.yaml +0 -20
- type_spec/external/api/recipes/associate_recipe_as_input.yaml +0 -19
- type_spec/external/api/recipes/associate_recipe_as_lot.yaml +0 -19
- type_spec/external/api/recipes/create_recipe.yaml +0 -39
- type_spec/external/api/recipes/create_recipes.yaml +0 -47
- type_spec/external/api/recipes/disassociate_recipe_as_input.yaml +0 -16
- type_spec/external/api/recipes/edit_recipe_inputs.yaml +0 -85
- type_spec/external/api/recipes/get_curve.yaml +0 -21
- type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -39
- type_spec/external/api/recipes/get_recipe_links.yaml +0 -26
- type_spec/external/api/recipes/get_recipe_names.yaml +0 -29
- type_spec/external/api/recipes/get_recipe_output_metadata.yaml +0 -36
- type_spec/external/api/recipes/get_recipes_data.yaml +0 -244
- type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -42
- type_spec/external/api/recipes/set_recipe_metadata.yaml +0 -20
- type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -52
- type_spec/external/api/recipes/set_recipe_tags.yaml +0 -62
- type_spec/external/api/triggers/run_trigger.yaml +0 -18
- uncountable/integration/types.py +0 -89
|
@@ -1,24 +1,42 @@
|
|
|
1
1
|
import io
|
|
2
|
+
import typing
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
|
|
4
5
|
from . import builder, util
|
|
5
|
-
from .
|
|
6
|
+
from .builder_types import CrossOutputPaths
|
|
6
7
|
|
|
7
8
|
INDENT = " "
|
|
8
9
|
|
|
9
10
|
MODIFY_NOTICE = "// DO NOT MODIFY -- This file is generated by type_spec\n"
|
|
10
11
|
|
|
12
|
+
base_name_map = {
|
|
13
|
+
builder.BaseTypeName.s_boolean: "boolean",
|
|
14
|
+
builder.BaseTypeName.s_date: "string", # IMPROVE: Aliased DateStr
|
|
15
|
+
builder.BaseTypeName.s_date_time: "string", # IMPROVE: Aliased DateTimeStr
|
|
16
|
+
# Decimal's are marked as to_string_values thus are strings in the front-end
|
|
17
|
+
builder.BaseTypeName.s_decimal: "string",
|
|
18
|
+
builder.BaseTypeName.s_dict: "PartialRecord",
|
|
19
|
+
builder.BaseTypeName.s_integer: "number",
|
|
20
|
+
builder.BaseTypeName.s_lossy_decimal: "number",
|
|
21
|
+
builder.BaseTypeName.s_opaque_key: "string",
|
|
22
|
+
builder.BaseTypeName.s_none: "null",
|
|
23
|
+
builder.BaseTypeName.s_string: "string",
|
|
24
|
+
# UNC: global types
|
|
25
|
+
builder.BaseTypeName.s_json_value: "JsonValue",
|
|
26
|
+
}
|
|
27
|
+
|
|
11
28
|
|
|
12
29
|
@dataclass(kw_only=True)
|
|
13
30
|
class EmitTypescriptContext:
|
|
14
|
-
config: TypeScriptConfig
|
|
15
31
|
out: io.StringIO
|
|
16
32
|
namespace: builder.SpecNamespace
|
|
17
33
|
namespaces: set[builder.SpecNamespace] = field(default_factory=set)
|
|
34
|
+
cross_output_paths: CrossOutputPaths | None = None
|
|
35
|
+
api_endpoints: dict[builder.EndpointKey, builder.APIEndpointInfo]
|
|
18
36
|
|
|
19
37
|
|
|
20
38
|
def ts_type_name(name: str) -> str:
|
|
21
|
-
return "".join([x.
|
|
39
|
+
return "".join([x.title() for x in name.split("_")])
|
|
22
40
|
|
|
23
41
|
|
|
24
42
|
def resolve_namespace_ref(namespace: builder.SpecNamespace) -> str:
|
|
@@ -29,4 +47,275 @@ def ts_name(name: str, name_case: builder.NameCase) -> str:
|
|
|
29
47
|
if name_case == builder.NameCase.preserve:
|
|
30
48
|
return name
|
|
31
49
|
bits = util.split_any_name(name)
|
|
32
|
-
return "".join([bits[0], *[x.
|
|
50
|
+
return "".join([bits[0], *[x.title() for x in bits[1:]]])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def emit_value_ts(
|
|
54
|
+
ctx: EmitTypescriptContext,
|
|
55
|
+
stype: builder.SpecType,
|
|
56
|
+
value: typing.Any,
|
|
57
|
+
indent: int = 0,
|
|
58
|
+
) -> str:
|
|
59
|
+
"""Mimics emit_python even if not all types are used in TypeScript yet"""
|
|
60
|
+
literal = builder.unwrap_literal_type(stype)
|
|
61
|
+
if literal is not None:
|
|
62
|
+
return emit_value_ts(ctx, literal.value_type, literal.value)
|
|
63
|
+
|
|
64
|
+
if stype.is_base_type(builder.BaseTypeName.s_string):
|
|
65
|
+
assert isinstance(value, str)
|
|
66
|
+
return util.encode_common_string(value)
|
|
67
|
+
elif stype.is_base_type(builder.BaseTypeName.s_integer):
|
|
68
|
+
assert isinstance(value, int)
|
|
69
|
+
return str(value)
|
|
70
|
+
elif stype.is_base_type(builder.BaseTypeName.s_boolean):
|
|
71
|
+
assert isinstance(value, bool)
|
|
72
|
+
return "true" if value else "false"
|
|
73
|
+
elif stype.is_base_type(builder.BaseTypeName.s_lossy_decimal):
|
|
74
|
+
return str(value)
|
|
75
|
+
elif stype.is_base_type(builder.BaseTypeName.s_decimal):
|
|
76
|
+
return f"'{value}'"
|
|
77
|
+
elif isinstance(stype, builder.SpecTypeInstance):
|
|
78
|
+
if stype.defn_type.is_base_type(builder.BaseTypeName.s_list):
|
|
79
|
+
sub_type = stype.parameters[0]
|
|
80
|
+
return (
|
|
81
|
+
"[" + ", ".join([emit_value_ts(ctx, sub_type, x) for x in value]) + "]"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
if stype.defn_type.is_base_type(builder.BaseTypeName.s_dict):
|
|
85
|
+
key_type = stype.parameters[0]
|
|
86
|
+
value_type = stype.parameters[1]
|
|
87
|
+
|
|
88
|
+
if not key_type.is_base_type(
|
|
89
|
+
builder.BaseTypeName.s_string
|
|
90
|
+
) and not isinstance(key_type, builder.SpecTypeDefnStringEnum):
|
|
91
|
+
raise Exception("invalid dict keys -- dict keys must be string or enum")
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
f"{{\n{INDENT * (indent + 1)}"
|
|
95
|
+
+ f",\n{INDENT * (indent + 1)}".join(
|
|
96
|
+
(
|
|
97
|
+
f"[{emit_value_ts(ctx, key_type, dkey)}]: "
|
|
98
|
+
if not key_type.is_base_type(builder.BaseTypeName.s_string)
|
|
99
|
+
else f"{dkey}: "
|
|
100
|
+
)
|
|
101
|
+
+ emit_value_ts(ctx, value_type, dvalue, indent=indent + 1)
|
|
102
|
+
for dkey, dvalue in value.items()
|
|
103
|
+
)
|
|
104
|
+
+ f"\n{INDENT * (indent)}}}"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if stype.defn_type.is_base_type(builder.BaseTypeName.s_optional):
|
|
108
|
+
sub_type = stype.parameters[0]
|
|
109
|
+
if value is None:
|
|
110
|
+
return "null"
|
|
111
|
+
return emit_value_ts(ctx, sub_type, value)
|
|
112
|
+
|
|
113
|
+
elif isinstance(stype, builder.SpecTypeDefnStringEnum):
|
|
114
|
+
return f"{refer_to(ctx, stype)}.{ts_enum_name(value, stype.name_case)}"
|
|
115
|
+
elif isinstance(stype, builder.SpecTypeDefnObject):
|
|
116
|
+
assert isinstance(value, dict), (
|
|
117
|
+
f"Expected dict value for {stype.name} but got {value}"
|
|
118
|
+
)
|
|
119
|
+
obj_out = "{"
|
|
120
|
+
did_emit = False
|
|
121
|
+
for prop_name, prop in (stype.properties or {}).items():
|
|
122
|
+
if prop_name not in value and prop.has_default:
|
|
123
|
+
value_to_emit = prop.default
|
|
124
|
+
elif prop_name not in value:
|
|
125
|
+
continue
|
|
126
|
+
else:
|
|
127
|
+
value_to_emit = value[prop_name]
|
|
128
|
+
did_emit = True
|
|
129
|
+
typescript_name = ts_name(prop.name, prop.name_case)
|
|
130
|
+
obj_out += f"\n{INDENT * (indent + 1)}{typescript_name}: {emit_value_ts(ctx, prop.spec_type, value_to_emit, indent=indent + 1)},"
|
|
131
|
+
whitespace = f"\n{INDENT * indent}" if did_emit else ""
|
|
132
|
+
obj_out += f"{whitespace}}} as const"
|
|
133
|
+
return obj_out
|
|
134
|
+
|
|
135
|
+
raise Exception("invalid constant type", value, stype, type(stype))
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def emit_constant_ts(ctx: EmitTypescriptContext, sconst: builder.SpecConstant) -> None:
|
|
139
|
+
ctx.out.write("\n\n")
|
|
140
|
+
ctx.out.write(MODIFY_NOTICE)
|
|
141
|
+
value = emit_value_ts(ctx, sconst.value_type, sconst.value)
|
|
142
|
+
const_name = sconst.name.upper()
|
|
143
|
+
ctx.out.write(f"export const {const_name} = {value}\n")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def emit_type_ts(ctx: EmitTypescriptContext, stype: builder.SpecType) -> None:
|
|
147
|
+
if not isinstance(stype, builder.SpecTypeDefn):
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
if stype.is_base or stype.is_predefined:
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
ctx.out.write("\n")
|
|
154
|
+
ctx.out.write(MODIFY_NOTICE)
|
|
155
|
+
|
|
156
|
+
if isinstance(stype, builder.SpecTypeDefnExternal):
|
|
157
|
+
assert not stype.is_exported, "expecting private names"
|
|
158
|
+
ctx.out.write("\n")
|
|
159
|
+
ctx.out.write(stype.external_map["ts"])
|
|
160
|
+
ctx.out.write("\n")
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
assert stype.is_exported, "expecting exported names"
|
|
164
|
+
if isinstance(stype, builder.SpecTypeDefnAlias):
|
|
165
|
+
ctx.out.write(f"export type {stype.name} = {refer_to(ctx, stype.alias)}\n")
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
if isinstance(stype, builder.SpecTypeDefnUnion):
|
|
169
|
+
ctx.out.write(
|
|
170
|
+
f"export type {stype.name} = {refer_to(ctx, stype.get_backing_type())}\n"
|
|
171
|
+
)
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
if isinstance(stype, builder.SpecTypeDefnStringEnum):
|
|
175
|
+
ctx.out.write(f"export enum {stype.name} {{\n")
|
|
176
|
+
assert stype.values
|
|
177
|
+
for name, entry in stype.values.items():
|
|
178
|
+
ctx.out.write(
|
|
179
|
+
f'{INDENT}{ts_enum_name(name, stype.name_case)} = "{entry.value}",\n'
|
|
180
|
+
)
|
|
181
|
+
ctx.out.write("}\n")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
assert isinstance(stype, builder.SpecTypeDefnObject)
|
|
185
|
+
assert stype.base is not None
|
|
186
|
+
|
|
187
|
+
base_type = ""
|
|
188
|
+
if not stype.base.is_base:
|
|
189
|
+
base_type = f"{refer_to(ctx, stype.base)} & "
|
|
190
|
+
|
|
191
|
+
if stype.properties is None and base_type == "":
|
|
192
|
+
ctx.out.write(f"export type {stype.name} = TEmpty\n")
|
|
193
|
+
elif stype.properties is None:
|
|
194
|
+
ctx.out.write(f"export type {stype.name} = {base_type}{{}}\n")
|
|
195
|
+
else:
|
|
196
|
+
if isinstance(stype, builder.SpecTypeDefnObject) and len(stype.parameters) > 0:
|
|
197
|
+
full_type_name = f"{stype.name}<{', '.join(stype.parameters)}>"
|
|
198
|
+
else:
|
|
199
|
+
full_type_name = stype.name
|
|
200
|
+
ctx.out.write(f"export type {full_type_name} = {base_type}{{")
|
|
201
|
+
ctx.out.write("\n")
|
|
202
|
+
for prop in stype.properties.values():
|
|
203
|
+
ref_type = refer_to(ctx, prop.spec_type)
|
|
204
|
+
prop_name = ts_name(prop.name, prop.name_case)
|
|
205
|
+
if prop.has_default and not prop.parse_require:
|
|
206
|
+
# For now, we'll assume the generated types with defaults are meant as
|
|
207
|
+
# arguments, thus treat like extant==missing
|
|
208
|
+
# IMPROVE: if we can decide they are meant as output instead, then
|
|
209
|
+
# they should be marked as required
|
|
210
|
+
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type}")
|
|
211
|
+
elif prop.extant == builder.PropertyExtant.missing:
|
|
212
|
+
# Unlike optional below, missing does not imply null is possible. They
|
|
213
|
+
# treated distinctly.
|
|
214
|
+
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type}")
|
|
215
|
+
elif prop.extant == builder.PropertyExtant.optional:
|
|
216
|
+
# Need to add in |null since Python side can produce null's right now
|
|
217
|
+
# IMPROVE: It would be better if the serializer could instead omit the None's
|
|
218
|
+
# Dropping the null should be forward compatible
|
|
219
|
+
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type} | null")
|
|
220
|
+
else:
|
|
221
|
+
ctx.out.write(f"{INDENT}{prop_name}: {ref_type}")
|
|
222
|
+
ctx.out.write("\n")
|
|
223
|
+
ctx.out.write("}\n")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def refer_to(ctx: EmitTypescriptContext, stype: builder.SpecType) -> str:
|
|
227
|
+
return refer_to_impl(ctx, stype)[0]
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def refer_to_impl(
|
|
231
|
+
ctx: EmitTypescriptContext, stype: builder.SpecType
|
|
232
|
+
) -> tuple[str, bool]:
|
|
233
|
+
"""
|
|
234
|
+
@return (string-specific, multiple-types)
|
|
235
|
+
"""
|
|
236
|
+
if isinstance(stype, builder.SpecTypeInstance):
|
|
237
|
+
if stype.defn_type.name == builder.BaseTypeName.s_list:
|
|
238
|
+
spec, multi = refer_to_impl(ctx, stype.parameters[0])
|
|
239
|
+
return f"({spec})[]" if multi else f"{spec}[]", False
|
|
240
|
+
if stype.defn_type.name == builder.BaseTypeName.s_readonly_array:
|
|
241
|
+
spec, multi = refer_to_impl(ctx, stype.parameters[0])
|
|
242
|
+
return f"readonly ({spec})[]" if multi else f"readonly {spec}[]", False
|
|
243
|
+
if stype.defn_type.name == builder.BaseTypeName.s_union:
|
|
244
|
+
return (
|
|
245
|
+
f"({' | '.join([refer_to(ctx, p) for p in stype.parameters])})",
|
|
246
|
+
False,
|
|
247
|
+
)
|
|
248
|
+
if stype.defn_type.name == builder.BaseTypeName.s_literal:
|
|
249
|
+
parts = []
|
|
250
|
+
for parameter in stype.parameters:
|
|
251
|
+
assert isinstance(parameter, builder.SpecTypeLiteralWrapper)
|
|
252
|
+
parts.append(refer_to(ctx, parameter))
|
|
253
|
+
return f"({' | '.join(parts)})", False
|
|
254
|
+
if stype.defn_type.name == builder.BaseTypeName.s_optional:
|
|
255
|
+
return f"{refer_to(ctx, stype.parameters[0])} | null", True
|
|
256
|
+
if stype.defn_type.name == builder.BaseTypeName.s_tuple:
|
|
257
|
+
return f"[{', '.join([refer_to(ctx, p) for p in stype.parameters])}]", False
|
|
258
|
+
params = ", ".join([refer_to(ctx, p) for p in stype.parameters])
|
|
259
|
+
return f"{refer_to(ctx, stype.defn_type)}<{params}>", False
|
|
260
|
+
|
|
261
|
+
if isinstance(stype, builder.SpecTypeLiteralWrapper):
|
|
262
|
+
return emit_value_ts(ctx, stype.value_type, stype.value), False
|
|
263
|
+
|
|
264
|
+
if isinstance(stype, builder.SpecTypeGenericParameter):
|
|
265
|
+
return stype.name, False
|
|
266
|
+
|
|
267
|
+
assert isinstance(stype, builder.SpecTypeDefn)
|
|
268
|
+
if stype.is_base: # assume correct namespace
|
|
269
|
+
if stype.name == builder.BaseTypeName.s_list:
|
|
270
|
+
return "any[]", False # TODO: generic type
|
|
271
|
+
return base_name_map[builder.BaseTypeName(stype.name)], False
|
|
272
|
+
|
|
273
|
+
if stype.namespace == ctx.namespace:
|
|
274
|
+
return stype.name, False
|
|
275
|
+
|
|
276
|
+
ctx.namespaces.add(stype.namespace)
|
|
277
|
+
return f"{resolve_namespace_ref(stype.namespace)}.{stype.name}", False
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def ts_enum_name(name: str, name_case: builder.NameCase) -> str:
|
|
281
|
+
if name_case == builder.NameCase.js_upper:
|
|
282
|
+
return name.upper()
|
|
283
|
+
return ts_name(name, name_case)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def resolve_namespace_name(namespace: builder.SpecNamespace) -> str:
|
|
287
|
+
return namespace.name
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def emit_namespace_imports_ts(
|
|
291
|
+
namespaces: set[builder.SpecNamespace],
|
|
292
|
+
out: io.StringIO,
|
|
293
|
+
current_namespace: builder.SpecNamespace,
|
|
294
|
+
) -> None:
|
|
295
|
+
for ns in sorted(
|
|
296
|
+
namespaces,
|
|
297
|
+
key=lambda name: resolve_namespace_name(name),
|
|
298
|
+
):
|
|
299
|
+
import_as = resolve_namespace_ref(ns)
|
|
300
|
+
import_path = (
|
|
301
|
+
"./"
|
|
302
|
+
if len(current_namespace.path) == 1
|
|
303
|
+
else "../" * (len(current_namespace.path) - 1)
|
|
304
|
+
)
|
|
305
|
+
import_from = f"{import_path}{resolve_namespace_name(ns)}"
|
|
306
|
+
out.write(f'import * as {import_as} from "{import_from}"\n') # noqa: E501
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def emit_namespace_imports_from_root_ts(
|
|
310
|
+
namespaces: set[builder.SpecNamespace],
|
|
311
|
+
out: io.StringIO,
|
|
312
|
+
root: str,
|
|
313
|
+
) -> None:
|
|
314
|
+
for ns in sorted(
|
|
315
|
+
namespaces,
|
|
316
|
+
key=lambda name: resolve_namespace_name(name),
|
|
317
|
+
):
|
|
318
|
+
import_as = resolve_namespace_ref(ns)
|
|
319
|
+
out.write(
|
|
320
|
+
f'import * as {import_as} from "{root}/{resolve_namespace_name(ns)}"\n'
|
|
321
|
+
) # noqa: E501
|
pkgs/type_spec/load_types.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from io import StringIO
|
|
4
|
-
from typing import Optional
|
|
5
4
|
|
|
6
|
-
import yaml
|
|
7
5
|
from shelljob import fs
|
|
8
6
|
|
|
7
|
+
from pkgs.serialization import yaml
|
|
8
|
+
|
|
9
9
|
from .builder import SpecBuilder
|
|
10
|
+
from .builder_types import CrossOutputPaths
|
|
10
11
|
from .config import Config
|
|
11
12
|
|
|
12
13
|
ext_map = {
|
|
@@ -40,8 +41,23 @@ def find_and_handle_files(
|
|
|
40
41
|
handler(file_name, file.read())
|
|
41
42
|
|
|
42
43
|
|
|
43
|
-
def load_types(config: Config) ->
|
|
44
|
-
|
|
44
|
+
def load_types(config: Config) -> SpecBuilder | None:
|
|
45
|
+
if config.typescript is not None and config.python is not None:
|
|
46
|
+
cross_output_paths = CrossOutputPaths(
|
|
47
|
+
python_types_output=config.python.types_output,
|
|
48
|
+
typescript_types_output=config.typescript.types_output,
|
|
49
|
+
typescript_routes_output_by_endpoint=config.typescript.endpoint_to_routes_output,
|
|
50
|
+
typespec_files_input=config.type_spec_types,
|
|
51
|
+
# IMPROVE not sure how to know which one is the correct one in emit_typescript
|
|
52
|
+
)
|
|
53
|
+
else:
|
|
54
|
+
cross_output_paths = None
|
|
55
|
+
|
|
56
|
+
builder = SpecBuilder(
|
|
57
|
+
api_endpoints=config.api_endpoint,
|
|
58
|
+
top_namespace=config.top_namespace,
|
|
59
|
+
cross_output_paths=cross_output_paths,
|
|
60
|
+
)
|
|
45
61
|
|
|
46
62
|
def handle_builder_add(
|
|
47
63
|
file_name: str, file_content: str, handler: Callable[[str, str, str], None]
|
|
@@ -114,4 +130,3 @@ def load_types(config: Config) -> Optional[SpecBuilder]:
|
|
|
114
130
|
return None
|
|
115
131
|
|
|
116
132
|
return builder
|
|
117
|
-
return True
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
NON_DISCRIMINATED_UNION_EXCEPTIONS = [
|
|
2
|
+
"generate_tool_parameters.UnionWithoutDiscrim",
|
|
3
|
+
"output_calculation_entities.ConditionParameterFilterCondition",
|
|
4
|
+
"output_parameters.AnalyticalMethodParameterOptions",
|
|
5
|
+
"output_parameters.AnalyticalMethodLinkedOptionValue",
|
|
6
|
+
"recipes_redirect.RecipesRedirectResult",
|
|
7
|
+
"value_spec.ResolvedPathAll",
|
|
8
|
+
"weighted_sum.WeightedSumEntities",
|
|
9
|
+
"workflows.WorkflowTotalDisplay",
|
|
10
|
+
"type_info.TypeFormActionConstraint",
|
|
11
|
+
"structured_loading.CompatibleFilterNode",
|
|
12
|
+
"structured_display_element.DisplayElementColumn",
|
|
13
|
+
"field_values.FieldValue",
|
|
14
|
+
]
|
pkgs/type_spec/open_api_util.py
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from enum import StrEnum
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
from pkgs.serialization_util import JsonValue
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class OpenAPIType(ABC):
|
|
7
8
|
description: str | None = None
|
|
8
9
|
nullable: bool = False
|
|
10
|
+
default: JsonValue
|
|
9
11
|
|
|
10
|
-
def __init__(
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
description: str | None = None,
|
|
15
|
+
nullable: bool = False,
|
|
16
|
+
default: JsonValue = None,
|
|
17
|
+
) -> None:
|
|
11
18
|
self.description = description
|
|
12
19
|
self.nullable = nullable
|
|
20
|
+
self.default = default
|
|
13
21
|
|
|
14
22
|
@abstractmethod
|
|
15
23
|
def asdict(self) -> dict[str, object]:
|
|
@@ -20,6 +28,8 @@ class OpenAPIType(ABC):
|
|
|
20
28
|
emitted["description"] = self.description
|
|
21
29
|
if self.nullable:
|
|
22
30
|
emitted["nullable"] = self.nullable
|
|
31
|
+
if self.default is not None:
|
|
32
|
+
emitted["default"] = self.default
|
|
23
33
|
return emitted
|
|
24
34
|
|
|
25
35
|
|
|
@@ -158,7 +168,7 @@ class OpenAPIObjectType(OpenAPIType):
|
|
|
158
168
|
description: str | None = None,
|
|
159
169
|
nullable: bool = False,
|
|
160
170
|
*,
|
|
161
|
-
property_desc:
|
|
171
|
+
property_desc: dict[str, str] | None = None,
|
|
162
172
|
) -> None:
|
|
163
173
|
self.properties = properties
|
|
164
174
|
if property_desc is None:
|
|
@@ -213,13 +223,28 @@ class OpenAPIUnionType(OpenAPIType):
|
|
|
213
223
|
base_types: list[OpenAPIType],
|
|
214
224
|
description: str | None = None,
|
|
215
225
|
nullable: bool = False,
|
|
226
|
+
discriminator: str | None = None,
|
|
227
|
+
discriminator_map: dict[str, OpenAPIRefType] | None = None,
|
|
216
228
|
) -> None:
|
|
217
229
|
self.base_types = base_types
|
|
230
|
+
self._discriminator = discriminator
|
|
231
|
+
self._discriminator_map = discriminator_map
|
|
218
232
|
super().__init__(description=description, nullable=nullable)
|
|
219
233
|
|
|
220
234
|
def asdict(self) -> dict[str, object]:
|
|
221
235
|
# TODO: use parents description and nullable
|
|
222
|
-
return {
|
|
236
|
+
return {
|
|
237
|
+
"oneOf": [base_type.asdict() for base_type in self.base_types],
|
|
238
|
+
"discriminator": {
|
|
239
|
+
"propertyName": self._discriminator,
|
|
240
|
+
"mapping": {
|
|
241
|
+
discriminator_value: base_type.source
|
|
242
|
+
for discriminator_value, base_type in self._discriminator_map.items()
|
|
243
|
+
},
|
|
244
|
+
}
|
|
245
|
+
if self._discriminator is not None and self._discriminator_map is not None
|
|
246
|
+
else None,
|
|
247
|
+
}
|
|
223
248
|
|
|
224
249
|
|
|
225
250
|
class OpenAPIIntersectionType(OpenAPIType):
|
|
@@ -22,10 +22,16 @@ PureJsonScalar = Union[str, float, bool, None]
|
|
|
22
22
|
# Regular expressions for identifying ref names and IDs. Ref names should be
|
|
23
23
|
# using this regular expression as a constriant in the database.
|
|
24
24
|
REF_NAME_REGEX = r"^[a-zA-Z0-9_/-]+$"
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
REF_NAME_STRICT_REGEX_STRING = "^[a-zA-Z_][a-zA-Z0-9_]*$"
|
|
26
|
+
REF_NAME_STRICT_REGEX = rf"{REF_NAME_STRICT_REGEX_STRING}"
|
|
27
|
+
# Ids matching a strict integer number are converted to integers
|
|
28
|
+
ID_REGEX = r"-?[1-9][0-9]{0,20}"
|
|
27
29
|
|
|
28
30
|
|
|
31
|
+
# ENABLE_SLOTS should be removed after slots have been tested locally
|
|
32
|
+
import os
|
|
33
|
+
ENABLE_SLOTS = os.environ.get("UNC_ENABLE_DATACLASS_SLOTS") == "true"
|
|
34
|
+
|
|
29
35
|
if TYPE_CHECKING:
|
|
30
36
|
JsonValue = Union[JsonScalar, Mapping[str, "JsonValue"], Sequence["JsonValue"]]
|
|
31
37
|
ExtJsonValue = JsonValue
|
|
@@ -52,15 +58,12 @@ def is_pure_json_value(value: ExtJsonValue) -> bool:
|
|
|
52
58
|
return True
|
|
53
59
|
|
|
54
60
|
if isinstance(value, list):
|
|
55
|
-
for item in value
|
|
56
|
-
if not is_pure_json_value(item):
|
|
57
|
-
return False
|
|
58
|
-
return True
|
|
61
|
+
return all(is_pure_json_value(item) for item in value)
|
|
59
62
|
|
|
60
63
|
if isinstance(value, dict):
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
return all(
|
|
65
|
+
is_pure_json_value(key) and is_pure_json_value(item)
|
|
66
|
+
for key, item in value.items()
|
|
67
|
+
)
|
|
65
68
|
|
|
66
69
|
return False
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// doesn't allow referring explicitly to global names (thus cannot override here)
|
|
4
4
|
// IMPROVE: invert relationship for global.d.ts looks here instead
|
|
5
5
|
import * as IO from 'io-ts';
|
|
6
|
+
|
|
6
7
|
type localJsonScalar = JsonScalar
|
|
7
8
|
type localJsonValue = JsonValue
|
|
8
9
|
type localObjectId = ObjectId
|
|
@@ -28,3 +29,6 @@ export const IOJsonValue: IO.Type<JsonValue> = IO.recursion('JsonValue', () =>
|
|
|
28
29
|
export interface nominal<T> {
|
|
29
30
|
"nominal structural brand": T
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
// Ids matching a strict integer number are converted to integers
|
|
34
|
+
export const ID_REGEX = /-?[1-9][0-9]{0,20}/
|
|
@@ -9,7 +9,7 @@ import sys
|
|
|
9
9
|
|
|
10
10
|
from ..config import parse_yaml_config
|
|
11
11
|
from ..load_types import load_types
|
|
12
|
-
from .emit_type_info import emit_type_info
|
|
12
|
+
from .emit_type_info import emit_type_info, emit_type_info_python
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def main() -> bool:
|
|
@@ -26,6 +26,8 @@ def main() -> bool:
|
|
|
26
26
|
|
|
27
27
|
assert config.typescript is not None
|
|
28
28
|
emit_type_info(builder, config.typescript.type_info_output)
|
|
29
|
+
if config.python.type_info_output is not None:
|
|
30
|
+
emit_type_info_python(builder, config.python.type_info_output)
|
|
29
31
|
|
|
30
32
|
return True
|
|
31
33
|
|