UncountablePythonSDK 0.0.7__py3-none-any.whl → 0.0.92__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.
- UncountablePythonSDK-0.0.92.dist-info/METADATA +61 -0
- UncountablePythonSDK-0.0.92.dist-info/RECORD +301 -0
- {UncountablePythonSDK-0.0.7.dist-info → UncountablePythonSDK-0.0.92.dist-info}/WHEEL +1 -1
- {UncountablePythonSDK-0.0.7.dist-info → UncountablePythonSDK-0.0.92.dist-info}/top_level.txt +1 -1
- docs/.gitignore +1 -0
- docs/conf.py +57 -0
- docs/index.md +13 -0
- docs/justfile +12 -0
- docs/quickstart.md +19 -0
- docs/requirements.txt +7 -0
- docs/static/favicons/android-chrome-192x192.png +0 -0
- docs/static/favicons/android-chrome-512x512.png +0 -0
- docs/static/favicons/apple-touch-icon.png +0 -0
- docs/static/favicons/browserconfig.xml +9 -0
- docs/static/favicons/favicon-16x16.png +0 -0
- docs/static/favicons/favicon-32x32.png +0 -0
- docs/static/favicons/manifest.json +18 -0
- docs/static/favicons/mstile-150x150.png +0 -0
- docs/static/favicons/safari-pinned-tab.svg +32 -0
- docs/static/logo_blue.png +0 -0
- examples/async_batch.py +35 -0
- examples/create_entity.py +22 -17
- examples/download_files.py +26 -0
- examples/edit_recipe_inputs.py +50 -0
- examples/integration-server/jobs/materials_auto/example_cron.py +18 -0
- examples/integration-server/jobs/materials_auto/example_wh.py +15 -0
- examples/integration-server/jobs/materials_auto/profile.yaml +43 -0
- examples/integration-server/pyproject.toml +224 -0
- examples/invoke_uploader.py +26 -0
- examples/set_recipe_metadata_file.py +40 -0
- examples/set_recipe_output_file_sdk.py +26 -0
- examples/upload_files.py +18 -0
- pkgs/argument_parser/__init__.py +5 -0
- pkgs/argument_parser/_is_enum.py +1 -6
- pkgs/argument_parser/argument_parser.py +232 -76
- pkgs/argument_parser/case_convert.py +4 -3
- pkgs/filesystem_utils/__init__.py +20 -0
- pkgs/filesystem_utils/_blob_session.py +137 -0
- pkgs/filesystem_utils/_gdrive_session.py +309 -0
- pkgs/filesystem_utils/_local_session.py +69 -0
- pkgs/filesystem_utils/_s3_session.py +117 -0
- pkgs/filesystem_utils/_sftp_session.py +147 -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/opaque_key.py +1 -1
- pkgs/serialization/serial_alias.py +47 -0
- pkgs/serialization/serial_class.py +65 -50
- 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/_get_type_for_serialization.py +1 -3
- pkgs/serialization_util/convert_to_snakecase.py +27 -0
- pkgs/serialization_util/dataclasses.py +14 -0
- pkgs/serialization_util/serialization_helpers.py +118 -73
- pkgs/strenum_compat/strenum_compat.py +1 -9
- pkgs/type_spec/actions_registry/__init__.py +0 -0
- pkgs/type_spec/actions_registry/__main__.py +126 -0
- pkgs/type_spec/actions_registry/emit_typescript.py +182 -0
- pkgs/type_spec/builder.py +475 -89
- pkgs/type_spec/config.py +24 -19
- pkgs/type_spec/emit_io_ts.py +5 -2
- pkgs/type_spec/emit_open_api.py +266 -32
- pkgs/type_spec/emit_open_api_util.py +32 -13
- pkgs/type_spec/emit_python.py +601 -150
- pkgs/type_spec/emit_typescript.py +74 -273
- pkgs/type_spec/emit_typescript_util.py +239 -5
- pkgs/type_spec/load_types.py +55 -10
- pkgs/type_spec/open_api_util.py +30 -41
- pkgs/type_spec/parts/base.py.prepart +4 -3
- pkgs/type_spec/type_info/emit_type_info.py +178 -16
- pkgs/type_spec/util.py +11 -11
- pkgs/type_spec/value_spec/__main__.py +3 -3
- pkgs/type_spec/value_spec/convert_type.py +8 -1
- pkgs/type_spec/value_spec/emit_python.py +13 -4
- uncountable/__init__.py +1 -2
- uncountable/core/__init__.py +12 -2
- uncountable/core/async_batch.py +37 -0
- uncountable/core/client.py +293 -43
- uncountable/core/environment.py +41 -0
- uncountable/core/file_upload.py +135 -0
- uncountable/core/types.py +17 -0
- uncountable/integration/__init__.py +0 -0
- uncountable/integration/cli.py +49 -0
- uncountable/integration/construct_client.py +51 -0
- uncountable/integration/cron.py +29 -0
- uncountable/integration/db/__init__.py +0 -0
- uncountable/integration/db/connect.py +18 -0
- uncountable/integration/db/session.py +25 -0
- uncountable/integration/entrypoint.py +13 -0
- uncountable/integration/executors/__init__.py +0 -0
- uncountable/integration/executors/executors.py +148 -0
- uncountable/integration/executors/generic_upload_executor.py +284 -0
- uncountable/integration/executors/script_executor.py +25 -0
- uncountable/integration/job.py +87 -0
- uncountable/integration/queue_runner/__init__.py +0 -0
- uncountable/integration/queue_runner/command_server/__init__.py +24 -0
- uncountable/integration/queue_runner/command_server/command_client.py +68 -0
- uncountable/integration/queue_runner/command_server/command_server.py +64 -0
- uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server.proto +22 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +40 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +38 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +129 -0
- uncountable/integration/queue_runner/command_server/types.py +52 -0
- uncountable/integration/queue_runner/datastore/__init__.py +3 -0
- uncountable/integration/queue_runner/datastore/datastore_sqlite.py +93 -0
- uncountable/integration/queue_runner/datastore/interface.py +19 -0
- uncountable/integration/queue_runner/datastore/model.py +17 -0
- uncountable/integration/queue_runner/job_scheduler.py +163 -0
- uncountable/integration/queue_runner/queue_runner.py +26 -0
- uncountable/integration/queue_runner/types.py +7 -0
- uncountable/integration/queue_runner/worker.py +119 -0
- uncountable/integration/scan_profiles.py +67 -0
- uncountable/integration/scheduler.py +150 -0
- uncountable/integration/secret_retrieval/__init__.py +3 -0
- uncountable/integration/secret_retrieval/retrieve_secret.py +93 -0
- uncountable/integration/server.py +117 -0
- uncountable/integration/telemetry.py +209 -0
- uncountable/integration/webhook_server/entrypoint.py +170 -0
- uncountable/types/__init__.py +151 -5
- uncountable/types/api/batch/execute_batch.py +15 -7
- uncountable/types/api/batch/execute_batch_load_async.py +42 -0
- uncountable/types/api/chemical/__init__.py +1 -0
- uncountable/types/api/chemical/convert_chemical_formats.py +63 -0
- uncountable/types/api/entity/create_entities.py +23 -10
- uncountable/types/api/entity/create_entity.py +21 -12
- uncountable/types/api/entity/get_entities_data.py +19 -29
- uncountable/types/api/entity/grant_entity_permissions.py +48 -0
- uncountable/types/api/entity/list_entities.py +28 -20
- uncountable/types/api/entity/lock_entity.py +45 -0
- uncountable/types/api/entity/resolve_entity_ids.py +19 -7
- uncountable/types/api/entity/set_entity_field_values.py +44 -0
- uncountable/types/api/entity/set_values.py +13 -28
- uncountable/types/api/entity/transition_entity_phase.py +80 -0
- 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 +44 -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/__init__.py +1 -0
- uncountable/types/api/id_source/list_id_source.py +56 -0
- uncountable/types/api/id_source/match_id_source.py +54 -0
- uncountable/types/api/input_groups/get_input_group_names.py +18 -7
- uncountable/types/api/inputs/create_inputs.py +25 -24
- uncountable/types/api/inputs/get_input_data.py +37 -31
- uncountable/types/api/inputs/get_input_names.py +20 -9
- uncountable/types/api/inputs/get_inputs_data.py +33 -27
- uncountable/types/api/inputs/set_input_attribute_values.py +18 -13
- 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/material_families/__init__.py +1 -0
- uncountable/types/api/material_families/update_entity_material_families.py +48 -0
- uncountable/types/api/outputs/get_output_data.py +38 -29
- uncountable/types/api/outputs/get_output_names.py +20 -9
- uncountable/types/api/outputs/resolve_output_conditions.py +23 -10
- uncountable/types/api/permissions/__init__.py +1 -0
- uncountable/types/api/permissions/set_core_permissions.py +105 -0
- uncountable/types/api/project/get_projects.py +23 -19
- uncountable/types/api/project/get_projects_data.py +26 -43
- uncountable/types/api/recipe_links/__init__.py +1 -0
- uncountable/types/api/recipe_links/create_recipe_link.py +46 -0
- uncountable/types/api/recipe_links/remove_recipe_link.py +45 -0
- uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +21 -10
- uncountable/types/api/recipes/add_recipe_to_project.py +42 -0
- uncountable/types/api/recipes/archive_recipes.py +42 -0
- uncountable/types/api/recipes/associate_recipe_as_input.py +44 -0
- uncountable/types/api/recipes/associate_recipe_as_lot.py +43 -0
- uncountable/types/api/recipes/clear_recipe_outputs.py +42 -0
- uncountable/types/api/recipes/create_recipe.py +51 -0
- uncountable/types/api/recipes/create_recipes.py +25 -24
- uncountable/types/api/recipes/disassociate_recipe_as_input.py +42 -0
- uncountable/types/api/recipes/edit_recipe_inputs.py +283 -0
- uncountable/types/api/recipes/get_column_calculation_values.py +58 -0
- uncountable/types/api/recipes/get_curve.py +13 -27
- uncountable/types/api/recipes/get_recipe_calculations.py +21 -21
- uncountable/types/api/recipes/get_recipe_links.py +14 -6
- uncountable/types/api/recipes/get_recipe_names.py +18 -7
- uncountable/types/api/recipes/get_recipe_output_metadata.py +18 -19
- uncountable/types/api/recipes/get_recipes_data.py +83 -144
- uncountable/types/api/recipes/lock_recipes.py +63 -0
- uncountable/types/api/recipes/remove_recipe_from_project.py +42 -0
- uncountable/types/api/recipes/set_recipe_inputs.py +21 -11
- uncountable/types/api/recipes/set_recipe_metadata.py +43 -0
- uncountable/types/api/recipes/set_recipe_output_annotations.py +115 -0
- uncountable/types/api/recipes/set_recipe_output_file.py +56 -0
- uncountable/types/api/recipes/set_recipe_outputs.py +28 -15
- uncountable/types/api/recipes/set_recipe_tags.py +109 -0
- uncountable/types/api/recipes/unarchive_recipes.py +41 -0
- uncountable/types/api/recipes/unlock_recipes.py +50 -0
- uncountable/types/api/triggers/__init__.py +1 -0
- uncountable/types/api/triggers/run_trigger.py +43 -0
- uncountable/types/api/uploader/__init__.py +1 -0
- uncountable/types/api/uploader/invoke_uploader.py +47 -0
- uncountable/types/async_batch.py +13 -0
- uncountable/types/async_batch_processor.py +384 -0
- uncountable/types/async_batch_t.py +97 -0
- uncountable/types/async_jobs.py +9 -0
- uncountable/types/async_jobs_t.py +53 -0
- uncountable/types/auth_retrieval.py +12 -0
- uncountable/types/auth_retrieval_t.py +75 -0
- uncountable/types/base.py +5 -78
- uncountable/types/base_t.py +85 -0
- uncountable/types/calculations.py +8 -0
- uncountable/types/calculations_t.py +27 -0
- uncountable/types/chemical_structure.py +8 -0
- uncountable/types/chemical_structure_t.py +28 -0
- uncountable/types/client_base.py +1115 -76
- uncountable/types/client_config.py +8 -0
- uncountable/types/client_config_t.py +26 -0
- uncountable/types/curves.py +10 -0
- uncountable/types/curves_t.py +51 -0
- uncountable/types/entity.py +8 -266
- uncountable/types/entity_t.py +393 -0
- uncountable/types/experiment_groups.py +8 -0
- uncountable/types/experiment_groups_t.py +27 -0
- uncountable/types/field_values.py +17 -23
- uncountable/types/field_values_t.py +204 -0
- uncountable/types/fields.py +8 -0
- uncountable/types/fields_t.py +28 -0
- uncountable/types/generic_upload.py +15 -0
- uncountable/types/generic_upload_t.py +119 -0
- uncountable/types/id_source.py +12 -0
- uncountable/types/id_source_t.py +68 -0
- uncountable/types/identifier.py +11 -0
- uncountable/types/identifier_t.py +63 -0
- uncountable/types/input_attributes.py +8 -0
- uncountable/types/input_attributes_t.py +30 -0
- uncountable/types/inputs.py +11 -0
- uncountable/types/inputs_t.py +83 -0
- uncountable/types/integration_server.py +9 -0
- uncountable/types/integration_server_t.py +42 -0
- uncountable/types/job_definition.py +27 -0
- uncountable/types/job_definition_t.py +260 -0
- uncountable/types/outputs.py +8 -0
- uncountable/types/outputs_t.py +30 -0
- uncountable/types/overrides.py +10 -0
- uncountable/types/overrides_t.py +49 -0
- uncountable/types/permissions.py +8 -0
- uncountable/types/permissions_t.py +46 -0
- uncountable/types/phases.py +8 -0
- uncountable/types/phases_t.py +27 -0
- uncountable/types/post_base.py +8 -0
- uncountable/types/post_base_t.py +30 -0
- uncountable/types/queued_job.py +16 -0
- uncountable/types/queued_job_t.py +123 -0
- uncountable/types/recipe_identifiers.py +12 -0
- uncountable/types/recipe_identifiers_t.py +76 -0
- uncountable/types/recipe_inputs.py +9 -0
- uncountable/types/recipe_inputs_t.py +30 -0
- uncountable/types/recipe_links.py +4 -44
- uncountable/types/recipe_links_t.py +54 -0
- uncountable/types/recipe_metadata.py +10 -0
- uncountable/types/recipe_metadata_t.py +58 -0
- uncountable/types/recipe_output_metadata.py +8 -0
- uncountable/types/recipe_output_metadata_t.py +28 -0
- uncountable/types/recipe_tags.py +8 -0
- uncountable/types/recipe_tags_t.py +27 -0
- uncountable/types/recipe_workflow_steps.py +14 -0
- uncountable/types/recipe_workflow_steps_t.py +95 -0
- uncountable/types/recipes.py +8 -0
- uncountable/types/recipes_t.py +25 -0
- uncountable/types/response.py +8 -0
- uncountable/types/response_t.py +26 -0
- uncountable/types/secret_retrieval.py +12 -0
- uncountable/types/secret_retrieval_t.py +75 -0
- uncountable/types/units.py +8 -0
- uncountable/types/units_t.py +27 -0
- uncountable/types/users.py +8 -0
- uncountable/types/users_t.py +28 -0
- uncountable/types/webhook_job.py +9 -0
- uncountable/types/webhook_job_t.py +37 -0
- uncountable/types/workflows.py +9 -0
- uncountable/types/workflows_t.py +39 -0
- UncountablePythonSDK-0.0.7.dist-info/METADATA +0 -27
- UncountablePythonSDK-0.0.7.dist-info/RECORD +0 -119
- examples/recipe-import/importer.py +0 -39
- type_spec/external/api/batch/execute_batch.yaml +0 -56
- type_spec/external/api/entity/create_entities.yaml +0 -33
- type_spec/external/api/entity/create_entity.yaml +0 -39
- type_spec/external/api/entity/get_entities_data.yaml +0 -55
- type_spec/external/api/entity/list_entities.yaml +0 -62
- type_spec/external/api/entity/resolve_entity_ids.yaml +0 -29
- type_spec/external/api/entity/set_values.yaml +0 -45
- type_spec/external/api/input_groups/get_input_group_names.yaml +0 -29
- type_spec/external/api/inputs/create_inputs.yaml +0 -61
- type_spec/external/api/inputs/get_input_data.yaml +0 -108
- type_spec/external/api/inputs/get_input_names.yaml +0 -38
- type_spec/external/api/inputs/get_inputs_data.yaml +0 -95
- type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -37
- type_spec/external/api/outputs/get_output_data.yaml +0 -103
- 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/project/get_projects.yaml +0 -52
- type_spec/external/api/project/get_projects_data.yaml +0 -86
- type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -41
- type_spec/external/api/recipes/create_recipes.yaml +0 -60
- type_spec/external/api/recipes/get_curve.yaml +0 -50
- type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -49
- 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 -49
- type_spec/external/api/recipes/get_recipes_data.yaml +0 -372
- type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -36
- type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -56
|
@@ -1,82 +1,21 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import os
|
|
3
|
-
from typing import Any, Tuple
|
|
4
3
|
|
|
5
4
|
from . import builder, util
|
|
6
|
-
from .builder import SpecTypeDefnObject
|
|
7
5
|
from .config import TypeScriptConfig
|
|
8
6
|
from .emit_io_ts import emit_type_io_ts
|
|
9
7
|
from .emit_typescript_util import (
|
|
10
|
-
INDENT,
|
|
11
8
|
MODIFY_NOTICE,
|
|
12
9
|
EmitTypescriptContext,
|
|
10
|
+
emit_namespace_imports_ts,
|
|
11
|
+
emit_type_ts,
|
|
12
|
+
emit_value_ts,
|
|
13
|
+
resolve_namespace_name,
|
|
13
14
|
resolve_namespace_ref,
|
|
14
|
-
ts_name,
|
|
15
15
|
ts_type_name,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def ts_enum_name(name: str, name_case: builder.NameCase) -> str:
|
|
20
|
-
if name_case == builder.NameCase.js_upper:
|
|
21
|
-
return name.upper()
|
|
22
|
-
return ts_name(name, name_case)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def _resolve_namespace_name(namespace: builder.SpecNamespace) -> str:
|
|
26
|
-
return namespace.name
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _emit_value(ctx: EmitTypescriptContext, stype: builder.SpecType, value: Any) -> str:
|
|
30
|
-
"""Mimics emit_python even if not all types are used in TypeScript yet"""
|
|
31
|
-
literal = builder.unwrap_literal_type(stype)
|
|
32
|
-
if literal is not None:
|
|
33
|
-
return _emit_value(ctx, literal.value_type, literal.value)
|
|
34
|
-
|
|
35
|
-
if stype.is_base_type(builder.BaseTypeName.s_string):
|
|
36
|
-
assert isinstance(value, str)
|
|
37
|
-
return util.encode_common_string(value)
|
|
38
|
-
elif stype.is_base_type(builder.BaseTypeName.s_integer):
|
|
39
|
-
assert isinstance(value, int)
|
|
40
|
-
return str(value)
|
|
41
|
-
elif stype.is_base_type(builder.BaseTypeName.s_boolean):
|
|
42
|
-
assert isinstance(value, bool)
|
|
43
|
-
return "true" if value else "false"
|
|
44
|
-
elif stype.is_base_type(builder.BaseTypeName.s_lossy_decimal):
|
|
45
|
-
return str(value)
|
|
46
|
-
elif stype.is_base_type(builder.BaseTypeName.s_decimal):
|
|
47
|
-
return f"'{value}'"
|
|
48
|
-
elif isinstance(stype, builder.SpecTypeInstance):
|
|
49
|
-
if stype.defn_type.is_base_type(builder.BaseTypeName.s_list):
|
|
50
|
-
sub_type = stype.parameters[0]
|
|
51
|
-
return "[" + ", ".join([_emit_value(ctx, sub_type, x) for x in value]) + "]"
|
|
52
|
-
|
|
53
|
-
if stype.defn_type.is_base_type(builder.BaseTypeName.s_dict):
|
|
54
|
-
key_type = stype.parameters[0]
|
|
55
|
-
value_type = stype.parameters[1]
|
|
56
|
-
return (
|
|
57
|
-
"{\n\t"
|
|
58
|
-
+ ",\n\t".join(
|
|
59
|
-
"["
|
|
60
|
-
+ _emit_value(ctx, key_type, dkey)
|
|
61
|
-
+ "]: "
|
|
62
|
-
+ _emit_value(ctx, value_type, dvalue)
|
|
63
|
-
for dkey, dvalue in value.items()
|
|
64
|
-
)
|
|
65
|
-
+ "\n}"
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
if stype.defn_type.is_base_type(builder.BaseTypeName.s_optional):
|
|
69
|
-
sub_type = stype.parameters[0]
|
|
70
|
-
if value is None:
|
|
71
|
-
return "null"
|
|
72
|
-
return _emit_value(ctx, sub_type, value)
|
|
73
|
-
|
|
74
|
-
elif isinstance(stype, builder.SpecTypeDefnStringEnum):
|
|
75
|
-
return f"{refer_to(ctx, stype)}.{ts_enum_name(value, stype.name_case)}"
|
|
76
|
-
|
|
77
|
-
raise Exception("invalid constant type", value, stype)
|
|
78
|
-
|
|
79
|
-
|
|
80
19
|
def emit_typescript(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
81
20
|
_emit_types(builder, config)
|
|
82
21
|
_emit_id_source(builder, config)
|
|
@@ -90,11 +29,11 @@ def _emit_types(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
|
90
29
|
|
|
91
30
|
for namespace in sorted(
|
|
92
31
|
builder.namespaces.values(),
|
|
93
|
-
key=lambda ns:
|
|
32
|
+
key=lambda ns: resolve_namespace_name(ns),
|
|
94
33
|
):
|
|
95
|
-
ctx = EmitTypescriptContext(out=io.StringIO(), namespace=namespace
|
|
34
|
+
ctx = EmitTypescriptContext(out=io.StringIO(), namespace=namespace)
|
|
96
35
|
|
|
97
|
-
_emit_namespace(ctx, namespace)
|
|
36
|
+
_emit_namespace(ctx, config, namespace)
|
|
98
37
|
|
|
99
38
|
prepart = builder.preparts["typescript"].get(namespace.name)
|
|
100
39
|
part = builder.parts["typescript"].get(namespace.name)
|
|
@@ -121,16 +60,7 @@ def _emit_types(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
|
121
60
|
full.write(f"// === END section from {namespace.name}.ts.prepart ===\n")
|
|
122
61
|
full.write("\n")
|
|
123
62
|
|
|
124
|
-
|
|
125
|
-
ctx.namespaces,
|
|
126
|
-
key=lambda name: _resolve_namespace_name(name),
|
|
127
|
-
):
|
|
128
|
-
import_as = resolve_namespace_ref(ns)
|
|
129
|
-
import_path = (
|
|
130
|
-
"./" if len(namespace.path) == 1 else "../" * (len(namespace.path) - 1)
|
|
131
|
-
)
|
|
132
|
-
import_from = f"{import_path}{_resolve_namespace_name(ns)}"
|
|
133
|
-
full.write(f'import * as {import_as} from "{import_from}"\n') # noqa: E501
|
|
63
|
+
emit_namespace_imports_ts(ctx.namespaces, out=full, current_namespace=namespace)
|
|
134
64
|
if namespace.emit_io_ts:
|
|
135
65
|
full.write("import * as IO from 'io-ts';")
|
|
136
66
|
full.write(ctx.out.getvalue())
|
|
@@ -150,7 +80,7 @@ def _emit_types(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
|
150
80
|
|
|
151
81
|
if len(namespace.path) == 1:
|
|
152
82
|
index_out.write(
|
|
153
|
-
f"import * as {resolve_namespace_ref(namespace)} from './{
|
|
83
|
+
f"import * as {resolve_namespace_ref(namespace)} from './{resolve_namespace_name(namespace)}'\n"
|
|
154
84
|
) # noqa: E501
|
|
155
85
|
index_out_end.write(f"export {{{resolve_namespace_ref(namespace)}}}\n")
|
|
156
86
|
|
|
@@ -161,22 +91,27 @@ def _emit_types(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
|
161
91
|
util.rewrite_file(f"{config.types_output}/index.ts", index_out.getvalue())
|
|
162
92
|
|
|
163
93
|
|
|
164
|
-
def _emit_namespace(
|
|
94
|
+
def _emit_namespace(
|
|
95
|
+
ctx: EmitTypescriptContext,
|
|
96
|
+
config: TypeScriptConfig,
|
|
97
|
+
namespace: builder.SpecNamespace,
|
|
98
|
+
) -> None:
|
|
165
99
|
for stype in namespace.types.values():
|
|
166
100
|
if namespace.emit_io_ts:
|
|
167
101
|
emit_type_io_ts(ctx, stype, namespace.derive_types_from_io_ts)
|
|
168
102
|
if not namespace.emit_io_ts or not namespace.derive_types_from_io_ts:
|
|
169
|
-
|
|
103
|
+
emit_type_ts(ctx, stype)
|
|
170
104
|
|
|
171
105
|
for sconst in namespace.constants.values():
|
|
172
106
|
_emit_constant(ctx, sconst)
|
|
173
107
|
|
|
174
108
|
if namespace.endpoint is not None:
|
|
175
|
-
_emit_endpoint(ctx, namespace, namespace.endpoint)
|
|
109
|
+
_emit_endpoint(ctx, config, namespace, namespace.endpoint)
|
|
176
110
|
|
|
177
111
|
|
|
178
112
|
def _emit_endpoint(
|
|
179
113
|
ctx: EmitTypescriptContext,
|
|
114
|
+
config: TypeScriptConfig,
|
|
180
115
|
namespace: builder.SpecNamespace,
|
|
181
116
|
endpoint: builder.SpecEndpoint,
|
|
182
117
|
) -> None:
|
|
@@ -188,6 +123,7 @@ def _emit_endpoint(
|
|
|
188
123
|
has_data = "Data" in namespace.types
|
|
189
124
|
has_deprecated_result = "DeprecatedResult" in namespace.types
|
|
190
125
|
is_binary = endpoint.result_type == builder.ResultType.binary
|
|
126
|
+
has_multiple_endpoints = len(endpoint.path_per_api_endpoint) > 1
|
|
191
127
|
|
|
192
128
|
result_type_count = sum([has_data, has_deprecated_result, is_binary])
|
|
193
129
|
assert result_type_count < 2
|
|
@@ -222,51 +158,90 @@ def _emit_endpoint(
|
|
|
222
158
|
wrap_call = (
|
|
223
159
|
f"{wrap_name}<Arguments>" if is_binary else f"{wrap_name}<Arguments, Response>"
|
|
224
160
|
)
|
|
225
|
-
type_path = f"unc_mat/types/{'/'.join(namespace.path)}"
|
|
226
161
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
162
|
+
unc_base_api_imports = (
|
|
163
|
+
f"appSpecificApiPath, {wrap_name}" if has_multiple_endpoints else wrap_name
|
|
164
|
+
)
|
|
165
|
+
unc_types_imports = (
|
|
166
|
+
'import { ApplicationT } from "unc_types"\n' if has_multiple_endpoints else ""
|
|
167
|
+
)
|
|
230
168
|
|
|
169
|
+
type_path = f"unc_types/{'/'.join(namespace.path)}"
|
|
170
|
+
|
|
171
|
+
if is_binary:
|
|
172
|
+
tsx_response_part = f"""import {{ {unc_base_api_imports} }} from "unc_base/api"
|
|
173
|
+
import type {{ Arguments }} from "{type_path}"
|
|
174
|
+
{unc_types_imports}
|
|
231
175
|
export type {{ Arguments }}
|
|
232
176
|
"""
|
|
233
177
|
elif has_data and endpoint.has_attachment:
|
|
234
|
-
tsx_response_part = f"""import {{ {
|
|
235
|
-
import {{ Arguments, Data }} from "{type_path}"
|
|
236
|
-
|
|
178
|
+
tsx_response_part = f"""import {{ {unc_base_api_imports}, type AttachmentResponse }} from "unc_base/api"
|
|
179
|
+
import type {{ Arguments, Data }} from "{type_path}"
|
|
180
|
+
{unc_types_imports}
|
|
237
181
|
export type {{ Arguments, Data }}
|
|
238
182
|
export type Response = AttachmentResponse<Data>
|
|
239
183
|
"""
|
|
240
184
|
elif has_data:
|
|
241
|
-
tsx_response_part = f"""import {{ {
|
|
242
|
-
import {{ Arguments, Data }} from "{type_path}"
|
|
243
|
-
|
|
185
|
+
tsx_response_part = f"""import {{ {unc_base_api_imports}, type JsonResponse }} from "unc_base/api"
|
|
186
|
+
import type {{ Arguments, Data }} from "{type_path}"
|
|
187
|
+
{unc_types_imports}
|
|
244
188
|
export type {{ Arguments, Data }}
|
|
245
189
|
export type Response = JsonResponse<Data>
|
|
246
190
|
"""
|
|
247
191
|
|
|
248
192
|
else:
|
|
249
193
|
assert has_deprecated_result
|
|
250
|
-
tsx_response_part = f"""import {{ {
|
|
251
|
-
import {{ Arguments, DeprecatedResult }} from "{type_path}"
|
|
252
|
-
|
|
194
|
+
tsx_response_part = f"""import {{ {unc_base_api_imports} }} from "unc_base/api"
|
|
195
|
+
import type {{ Arguments, DeprecatedResult }} from "{type_path}"
|
|
196
|
+
{unc_types_imports}
|
|
253
197
|
export type {{ Arguments }}
|
|
254
198
|
export type Response = DeprecatedResult
|
|
255
199
|
"""
|
|
256
200
|
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
export const apiCall = buildWrappedGetCall<Arguments, Response>(
|
|
204
|
+
appSpecificApiPath({
|
|
205
|
+
[ApplicationT.FrontendApplication.materials]: "api/materials/common/list_id_source",
|
|
206
|
+
}),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
endpoint_path_part = (
|
|
213
|
+
f'"{endpoint.path_root}/{endpoint.path_dirname}/{endpoint.path_basename}",'
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
if has_multiple_endpoints:
|
|
217
|
+
path_lookup_map = ""
|
|
218
|
+
for (
|
|
219
|
+
api_endpoint_key,
|
|
220
|
+
endpoint_specific_path,
|
|
221
|
+
) in endpoint.path_per_api_endpoint.items():
|
|
222
|
+
full_path = f"{endpoint_specific_path.path_root}/{endpoint_specific_path.path_dirname}/{endpoint_specific_path.path_basename}"
|
|
223
|
+
frontend_app_value = config.endpoint_to_frontend_app_type[api_endpoint_key]
|
|
224
|
+
|
|
225
|
+
path_lookup_map += (
|
|
226
|
+
f'\n [ApplicationT.{frontend_app_value}]: "{full_path}",'
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
endpoint_path_part = f"""appSpecificApiPath({{{path_lookup_map}
|
|
230
|
+
}}),"""
|
|
231
|
+
|
|
257
232
|
tsx_api = f"""{MODIFY_NOTICE}
|
|
258
233
|
{data_loader_head}{tsx_response_part}
|
|
259
234
|
export const apiCall = {wrap_call}(
|
|
260
|
-
|
|
235
|
+
{endpoint_path_part}
|
|
261
236
|
)
|
|
262
237
|
{data_loader_body}"""
|
|
263
238
|
|
|
264
|
-
output = f"{
|
|
239
|
+
output = f"{config.routes_output}/{'/'.join(namespace.path)}.tsx"
|
|
265
240
|
util.rewrite_file(output, tsx_api)
|
|
266
241
|
|
|
267
242
|
# Hacky index support, until enough is migrated to regen entirely
|
|
268
243
|
# Emits the import into the UI API index file
|
|
269
|
-
index_path = f"{
|
|
244
|
+
index_path = f"{config.routes_output}/{'/'.join(namespace.path[0:-1])}/index.tsx"
|
|
270
245
|
api_name = f"Api{ts_type_name(namespace.path[0 - 1])}"
|
|
271
246
|
if os.path.exists(index_path):
|
|
272
247
|
with open(index_path) as index:
|
|
@@ -278,192 +253,18 @@ export const apiCall = {wrap_call}(
|
|
|
278
253
|
if need_index:
|
|
279
254
|
with open(index_path, "a") as index:
|
|
280
255
|
print(f"Updated API Index {index_path}")
|
|
281
|
-
index.write("\n// eslint-disable-next-line import/first\n")
|
|
282
256
|
index.write(f'import * as {api_name} from "./{namespace.path[-1]}"\n\n')
|
|
283
257
|
index.write(f"export {{ {api_name} }}\n")
|
|
284
258
|
|
|
285
259
|
|
|
286
|
-
MARKER_BEGIN = "### BEGIN:TYPE_SPEC"
|
|
287
|
-
MARKER_END = "### END:TYPE_SPEC"
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def _patch_file_line(filename: str, line: str) -> None:
|
|
291
|
-
"""
|
|
292
|
-
Adds a line into a file inside a marked region. The file section is
|
|
293
|
-
kept ordered. The rest of the file is untouched.
|
|
294
|
-
"""
|
|
295
|
-
with open(filename) as ignore_in:
|
|
296
|
-
ignore_data = ignore_in.read()
|
|
297
|
-
need_ignore = ignore_data.find(line) == -1
|
|
298
|
-
if not need_ignore:
|
|
299
|
-
return
|
|
300
|
-
|
|
301
|
-
begin = ignore_data.find(MARKER_BEGIN)
|
|
302
|
-
end = ignore_data.find(MARKER_END)
|
|
303
|
-
if begin == -1 or end == -1:
|
|
304
|
-
predata = ignore_data
|
|
305
|
-
postdata = ""
|
|
306
|
-
linedata = ""
|
|
307
|
-
else:
|
|
308
|
-
predata = ignore_data[:begin]
|
|
309
|
-
postdata = ignore_data[(end + len(MARKER_END)) :]
|
|
310
|
-
linedata = ignore_data[begin + len(MARKER_BEGIN) : end]
|
|
311
|
-
|
|
312
|
-
lines = [y for y in [x.strip() for x in linedata.split("\n")] if len(y) > 0]
|
|
313
|
-
lines.append(line)
|
|
314
|
-
|
|
315
|
-
with open(filename, "w") as ignore_out:
|
|
316
|
-
ignore_out.write(f"{predata}{MARKER_BEGIN}\n")
|
|
317
|
-
ignore_out.write("\n".join(sorted(lines)))
|
|
318
|
-
ignore_out.write(f"\n{MARKER_END}{postdata}")
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
def _emit_type(ctx: EmitTypescriptContext, stype: builder.SpecType) -> None:
|
|
322
|
-
if not isinstance(stype, builder.SpecTypeDefn):
|
|
323
|
-
return
|
|
324
|
-
|
|
325
|
-
if stype.is_base or stype.is_predefined:
|
|
326
|
-
return
|
|
327
|
-
|
|
328
|
-
ctx.out.write("\n")
|
|
329
|
-
ctx.out.write(MODIFY_NOTICE)
|
|
330
|
-
|
|
331
|
-
if isinstance(stype, builder.SpecTypeDefnExternal):
|
|
332
|
-
assert not stype.is_exported, "expecting private names"
|
|
333
|
-
ctx.out.write(stype.external_map["ts"])
|
|
334
|
-
ctx.out.write("\n")
|
|
335
|
-
return
|
|
336
|
-
|
|
337
|
-
assert stype.is_exported, "expecting exported names"
|
|
338
|
-
if isinstance(stype, builder.SpecTypeDefnAlias):
|
|
339
|
-
ctx.out.write(f"export type {stype.name} = {refer_to(ctx, stype.alias)}\n")
|
|
340
|
-
return
|
|
341
|
-
|
|
342
|
-
if isinstance(stype, builder.SpecTypeDefnStringEnum):
|
|
343
|
-
ctx.out.write(f"export enum {stype.name} {{\n")
|
|
344
|
-
assert stype.values
|
|
345
|
-
for name, entry in stype.values.items():
|
|
346
|
-
ctx.out.write(
|
|
347
|
-
f'{INDENT}{ts_enum_name(name, stype.name_case)} = "{entry.value}",\n'
|
|
348
|
-
)
|
|
349
|
-
ctx.out.write("}\n")
|
|
350
|
-
return
|
|
351
|
-
|
|
352
|
-
assert isinstance(stype, builder.SpecTypeDefnObject)
|
|
353
|
-
assert stype.base is not None
|
|
354
|
-
|
|
355
|
-
base_type = ""
|
|
356
|
-
if not stype.base.is_base:
|
|
357
|
-
base_type = f"{refer_to(ctx, stype.base)} & "
|
|
358
|
-
|
|
359
|
-
if stype.properties is None and base_type == "":
|
|
360
|
-
ctx.out.write(f"export type {stype.name} = TEmpty\n")
|
|
361
|
-
elif stype.properties is None:
|
|
362
|
-
ctx.out.write(f"export type {stype.name} = {base_type}{{}}\n")
|
|
363
|
-
else:
|
|
364
|
-
if isinstance(stype, SpecTypeDefnObject) and len(stype.parameters) > 0:
|
|
365
|
-
full_type_name = f'{stype.name}<{", ".join(stype.parameters)}>'
|
|
366
|
-
else:
|
|
367
|
-
full_type_name = stype.name
|
|
368
|
-
ctx.out.write(f"export type {full_type_name} = {base_type}{{")
|
|
369
|
-
ctx.out.write("\n")
|
|
370
|
-
for prop in stype.properties.values():
|
|
371
|
-
ref_type = refer_to(ctx, prop.spec_type)
|
|
372
|
-
prop_name = ts_name(prop.name, prop.name_case)
|
|
373
|
-
if prop.has_default and not prop.parse_require:
|
|
374
|
-
# For now, we'll assume the generated types with defaults are meant as
|
|
375
|
-
# arguments, thus treat like extant==missing
|
|
376
|
-
# IMPROVE: if we can decide they are meant as output instead, then
|
|
377
|
-
# they should be marked as required
|
|
378
|
-
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type}")
|
|
379
|
-
elif prop.extant == builder.PropertyExtant.missing:
|
|
380
|
-
# Unlike optional below, missing does not imply null is possible. They
|
|
381
|
-
# treated distinctly.
|
|
382
|
-
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type}")
|
|
383
|
-
elif prop.extant == builder.PropertyExtant.optional:
|
|
384
|
-
# Need to add in |null since Python side can produce null's right now
|
|
385
|
-
# IMPROVE: It would be better if the serializer could instead omit the None's
|
|
386
|
-
# Dropping the null should be forward compatible
|
|
387
|
-
ctx.out.write(f"{INDENT}{prop_name}?: {ref_type} | null")
|
|
388
|
-
else:
|
|
389
|
-
ctx.out.write(f"{INDENT}{prop_name}: {ref_type}")
|
|
390
|
-
ctx.out.write("\n")
|
|
391
|
-
ctx.out.write("}\n")
|
|
392
|
-
|
|
393
|
-
|
|
394
260
|
def _emit_constant(ctx: EmitTypescriptContext, sconst: builder.SpecConstant) -> None:
|
|
395
261
|
ctx.out.write("\n\n")
|
|
396
262
|
ctx.out.write(MODIFY_NOTICE)
|
|
397
|
-
value =
|
|
263
|
+
value = emit_value_ts(ctx, sconst.value_type, sconst.value)
|
|
398
264
|
const_name = sconst.name.upper()
|
|
399
265
|
ctx.out.write(f"export const {const_name} = {value}\n")
|
|
400
266
|
|
|
401
267
|
|
|
402
|
-
base_name_map = {
|
|
403
|
-
builder.BaseTypeName.s_boolean: "boolean",
|
|
404
|
-
builder.BaseTypeName.s_date: "string", # IMPROVE: Aliased DateStr
|
|
405
|
-
builder.BaseTypeName.s_date_time: "string", # IMPROVE: Aliased DateTimeStr
|
|
406
|
-
# Decimal's are marked as to_string_values thus are strings in the front-end
|
|
407
|
-
builder.BaseTypeName.s_decimal: "string",
|
|
408
|
-
builder.BaseTypeName.s_dict: "PartialRecord",
|
|
409
|
-
builder.BaseTypeName.s_integer: "number",
|
|
410
|
-
builder.BaseTypeName.s_lossy_decimal: "number",
|
|
411
|
-
builder.BaseTypeName.s_opaque_key: "string",
|
|
412
|
-
builder.BaseTypeName.s_none: "null",
|
|
413
|
-
builder.BaseTypeName.s_string: "string",
|
|
414
|
-
# UNC: global types
|
|
415
|
-
builder.BaseTypeName.s_json_value: "JsonValue",
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
def refer_to(ctx: EmitTypescriptContext, stype: builder.SpecType) -> str:
|
|
420
|
-
return refer_to_impl(ctx, stype)[0]
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def refer_to_impl(
|
|
424
|
-
ctx: EmitTypescriptContext, stype: builder.SpecType
|
|
425
|
-
) -> Tuple[str, bool]:
|
|
426
|
-
"""
|
|
427
|
-
@return (string-specific, multiple-types)
|
|
428
|
-
"""
|
|
429
|
-
if isinstance(stype, builder.SpecTypeInstance):
|
|
430
|
-
if stype.defn_type.name == builder.BaseTypeName.s_list:
|
|
431
|
-
spec, multi = refer_to_impl(ctx, stype.parameters[0])
|
|
432
|
-
return f"({spec})[]" if multi else f"{spec}[]", False
|
|
433
|
-
if stype.defn_type.name == builder.BaseTypeName.s_union:
|
|
434
|
-
return f'({" | ".join([refer_to(ctx, p) for p in stype.parameters])})', False
|
|
435
|
-
if stype.defn_type.name == builder.BaseTypeName.s_literal:
|
|
436
|
-
parts = []
|
|
437
|
-
for parameter in stype.parameters:
|
|
438
|
-
assert isinstance(parameter, builder.SpecTypeLiteralWrapper)
|
|
439
|
-
parts.append(refer_to(ctx, parameter))
|
|
440
|
-
return f'({" | ".join(parts)})', False
|
|
441
|
-
if stype.defn_type.name == builder.BaseTypeName.s_optional:
|
|
442
|
-
return f"{refer_to(ctx, stype.parameters[0])} | null", True
|
|
443
|
-
if stype.defn_type.name == builder.BaseTypeName.s_tuple:
|
|
444
|
-
return f"[{', '.join([refer_to(ctx, p) for p in stype.parameters])}]", False
|
|
445
|
-
params = ", ".join([refer_to(ctx, p) for p in stype.parameters])
|
|
446
|
-
return f"{refer_to(ctx, stype.defn_type)}<{params}>", False
|
|
447
|
-
|
|
448
|
-
if isinstance(stype, builder.SpecTypeLiteralWrapper):
|
|
449
|
-
return _emit_value(ctx, stype.value_type, stype.value), False
|
|
450
|
-
|
|
451
|
-
if isinstance(stype, builder.SpecTypeGenericParameter):
|
|
452
|
-
return stype.name, False
|
|
453
|
-
|
|
454
|
-
assert isinstance(stype, builder.SpecTypeDefn)
|
|
455
|
-
if stype.is_base: # assume correct namespace
|
|
456
|
-
if stype.name == builder.BaseTypeName.s_list:
|
|
457
|
-
return "any[]", False # TODO: generic type
|
|
458
|
-
return base_name_map[builder.BaseTypeName(stype.name)], False
|
|
459
|
-
|
|
460
|
-
if stype.namespace == ctx.namespace:
|
|
461
|
-
return stype.name, False
|
|
462
|
-
|
|
463
|
-
ctx.namespaces.add(stype.namespace)
|
|
464
|
-
return f"{resolve_namespace_ref(stype.namespace)}.{stype.name}", False
|
|
465
|
-
|
|
466
|
-
|
|
467
268
|
def _emit_id_source(builder: builder.SpecBuilder, config: TypeScriptConfig) -> None:
|
|
468
269
|
id_source_output = config.id_source_output
|
|
469
270
|
if id_source_output is None:
|