UncountablePythonSDK 0.0.8__tar.gz → 0.0.9__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.
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/PKG-INFO +4 -2
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/PKG-INFO +4 -2
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/SOURCES.txt +11 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/requires.txt +3 -1
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/argument_parser.py +2 -2
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_open_api.py +34 -17
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_open_api_util.py +4 -9
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/open_api_util.py +13 -12
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pyproject.toml +3 -1
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/inputs/get_input_data.yaml +1 -1
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/outputs/get_output_data.yaml +2 -2
- UncountablePythonSDK-0.0.9/uncountable/integration/construct_client.py +30 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/cron.py +29 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/db/__init__.py +0 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/db/connect.py +8 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/entrypoint.py +41 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/executors/__init__.py +0 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/executors/script_executor.py +18 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/job.py +39 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/server.py +86 -0
- UncountablePythonSDK-0.0.9/uncountable/integration/types.py +89 -0
- UncountablePythonSDK-0.0.9/uncountable/py.typed +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/get_input_data.py +1 -1
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/outputs/get_output_data.py +2 -2
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/workflows.py +1 -1
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/.github/workflows/publish.yml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/.gitignore +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/dependency_links.txt +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/top_level.txt +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/examples/create_entity.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/examples/recipe-import/importer.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/_is_enum.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/_is_namedtuple.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/case_convert.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/missing_sentry.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/opaque_key.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/serial_class.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization_util/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization_util/_get_type_for_serialization.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization_util/serialization_helpers.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/strenum_compat/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/strenum_compat/strenum_compat.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/__main__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/builder.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/config.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_io_ts.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_python.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_typescript.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_typescript_util.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/load_types.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/parts/base.py.prepart +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/parts/base.ts.prepart +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/test.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/type_info/__main__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/type_info/emit_type_info.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/util.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/__main__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/convert_type.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/emit_python.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/types.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/requirements.txt +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/setup.cfg +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/batch/execute_batch.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/create_entities.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/create_entity.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/get_entities_data.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/list_entities.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/resolve_entity_ids.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/entity/set_values.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/input_groups/get_input_group_names.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/inputs/create_inputs.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/inputs/get_input_names.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/inputs/get_inputs_data.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/outputs/get_output_names.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/outputs/resolve_output_conditions.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/project/get_projects.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/project/get_projects_data.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/create_recipes.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_curve.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_recipe_links.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_recipe_names.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_recipe_output_metadata.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/get_recipes_data.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/core/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/core/client.py +0 -0
- /UncountablePythonSDK-0.0.8/uncountable/py.typed → /UncountablePythonSDK-0.0.9/uncountable/integration/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/batch/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/batch/execute_batch.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/create_entities.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/create_entity.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/get_entities_data.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/list_entities.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/resolve_entity_ids.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/set_values.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/input_groups/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/input_groups/get_input_group_names.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/create_inputs.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/get_input_names.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/get_inputs_data.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/set_input_attribute_values.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/outputs/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/outputs/get_output_names.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/outputs/resolve_output_conditions.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/project/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/project/get_projects.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/project/get_projects_data.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipe_metadata/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/__init__.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/create_recipes.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_curve.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_recipe_calculations.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_recipe_links.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_recipe_names.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_recipe_output_metadata.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_recipes_data.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/set_recipe_inputs.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/set_recipe_outputs.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/base.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/calculations.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/client_base.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/curves.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/entity.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/experiment_groups.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/field_values.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/fields.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/input_attributes.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/inputs.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/outputs.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/phases.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/recipe_links.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/recipe_metadata.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/recipe_output_metadata.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/recipe_tags.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/response.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/units.py +0 -0
- {UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/users.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: UncountablePythonSDK
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.9
|
|
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
|
|
@@ -16,7 +16,9 @@ Classifier: Topic :: Utilities
|
|
|
16
16
|
Classifier: Typing :: Typed
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
|
-
Requires-Dist: requests
|
|
19
|
+
Requires-Dist: requests==2.31.0
|
|
20
|
+
Requires-Dist: SQLAlchemy==2.0.29
|
|
21
|
+
Requires-Dist: APScheduler==3.10.4
|
|
20
22
|
Provides-Extra: test
|
|
21
23
|
Requires-Dist: mypy>=1.8.1; extra == "test"
|
|
22
24
|
Requires-Dist: ruff>=0.2.1; extra == "test"
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/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.9
|
|
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
|
|
@@ -16,7 +16,9 @@ Classifier: Topic :: Utilities
|
|
|
16
16
|
Classifier: Typing :: Typed
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
|
-
Requires-Dist: requests
|
|
19
|
+
Requires-Dist: requests==2.31.0
|
|
20
|
+
Requires-Dist: SQLAlchemy==2.0.29
|
|
21
|
+
Requires-Dist: APScheduler==3.10.4
|
|
20
22
|
Provides-Extra: test
|
|
21
23
|
Requires-Dist: mypy>=1.8.1; extra == "test"
|
|
22
24
|
Requires-Dist: ruff>=0.2.1; extra == "test"
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/UncountablePythonSDK.egg-info/SOURCES.txt
RENAMED
|
@@ -79,6 +79,17 @@ uncountable/__init__.py
|
|
|
79
79
|
uncountable/py.typed
|
|
80
80
|
uncountable/core/__init__.py
|
|
81
81
|
uncountable/core/client.py
|
|
82
|
+
uncountable/integration/__init__.py
|
|
83
|
+
uncountable/integration/construct_client.py
|
|
84
|
+
uncountable/integration/cron.py
|
|
85
|
+
uncountable/integration/entrypoint.py
|
|
86
|
+
uncountable/integration/job.py
|
|
87
|
+
uncountable/integration/server.py
|
|
88
|
+
uncountable/integration/types.py
|
|
89
|
+
uncountable/integration/db/__init__.py
|
|
90
|
+
uncountable/integration/db/connect.py
|
|
91
|
+
uncountable/integration/executors/__init__.py
|
|
92
|
+
uncountable/integration/executors/script_executor.py
|
|
82
93
|
uncountable/types/__init__.py
|
|
83
94
|
uncountable/types/base.py
|
|
84
95
|
uncountable/types/calculations.py
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/argument_parser.py
RENAMED
|
@@ -407,5 +407,5 @@ class CachedParser(typing.Generic[T]):
|
|
|
407
407
|
return self.parse_storage(yaml.safe_load(data_in))
|
|
408
408
|
|
|
409
409
|
def parse_yaml_resource(self, package: resources.Package, resource: str) -> T:
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
with resources.open_text(package, resource) as fp:
|
|
411
|
+
return self.parse_storage(yaml.safe_load(fp))
|
|
@@ -141,6 +141,18 @@ def _serialize_global_context(ctx: EmitOpenAPIGlobalContext) -> str:
|
|
|
141
141
|
return yaml.dump(oa_root, sort_keys=False)
|
|
142
142
|
|
|
143
143
|
|
|
144
|
+
def _emit_endpoint_parameters(typ: OpenAPIType | None) -> dict[str, list[dict[str, str]]]:
|
|
145
|
+
if not isinstance(typ, OpenAPIObjectType):
|
|
146
|
+
return {}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
"parameters": [
|
|
150
|
+
{"$ref": f"#/components/schema/Arguments/{prop_name}"}
|
|
151
|
+
for prop_name in typ.properties
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
144
156
|
def _emit_namespace(
|
|
145
157
|
gctx: EmitOpenAPIGlobalContext,
|
|
146
158
|
ctx: EmitOpenAPIContext,
|
|
@@ -159,23 +171,28 @@ def _emit_namespace(
|
|
|
159
171
|
if ctx.endpoint is not None:
|
|
160
172
|
endpoint = ctx.endpoint
|
|
161
173
|
|
|
174
|
+
argument_type = ctx.types.get("Arguments")
|
|
162
175
|
oa_endpoint = dict()
|
|
163
|
-
oa_endpoint[endpoint.method] =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
oa_endpoint[endpoint.method] = (
|
|
177
|
+
{
|
|
178
|
+
"tags": endpoint.tags,
|
|
179
|
+
"summary": endpoint.summary,
|
|
180
|
+
"description": endpoint.description,
|
|
181
|
+
}
|
|
182
|
+
| _emit_endpoint_parameters(argument_type)
|
|
183
|
+
| {
|
|
184
|
+
"responses": {
|
|
185
|
+
"200": {
|
|
186
|
+
"description": "OK",
|
|
187
|
+
"content": {
|
|
188
|
+
"application/json": {
|
|
189
|
+
"schema": {"$ref": "#/components/schema/Data"}
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
)
|
|
179
196
|
oa_components["endpoint"] = oa_endpoint
|
|
180
197
|
|
|
181
198
|
types = ctx.types
|
|
@@ -460,5 +477,5 @@ def open_api_type(
|
|
|
460
477
|
ctx.namespaces.add(stype.namespace)
|
|
461
478
|
# external namespace resolution
|
|
462
479
|
return OpenAPIRefType(
|
|
463
|
-
source=f"{resolve_namespace_ref(ctx, stype.namespace,
|
|
480
|
+
source=f"{resolve_namespace_ref(source_path=ctx.namespace.path, ref_path=stype.namespace.path, ref='/components/schema')}/{stype.name}"
|
|
464
481
|
)
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_open_api_util.py
RENAMED
|
@@ -9,7 +9,6 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from typing import TypeAlias
|
|
10
10
|
|
|
11
11
|
from . import builder
|
|
12
|
-
from .config import OpenAPIConfig
|
|
13
12
|
from .open_api_util import OpenAPIType
|
|
14
13
|
|
|
15
14
|
MODIFY_NOTICE = "# DO NOT MODIFY -- This file is generated by type_spec"
|
|
@@ -75,12 +74,8 @@ class EmitOpenAPIContext:
|
|
|
75
74
|
|
|
76
75
|
|
|
77
76
|
def resolve_namespace_ref(
|
|
78
|
-
|
|
79
|
-
namespace: builder.SpecNamespace,
|
|
80
|
-
*,
|
|
81
|
-
config: OpenAPIConfig,
|
|
77
|
+
*, source_path: list[str], ref_path: list[str], ref: str
|
|
82
78
|
) -> str:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return f"{config.static_url_path}/common/{namespace.name}.yaml#/components/schema"
|
|
79
|
+
to_root = "/".join(".." for _ in source_path)
|
|
80
|
+
location = "/".join(ref_path)
|
|
81
|
+
return f"{to_root}/common/{location}.yaml#{ref}"
|
|
@@ -13,9 +13,10 @@ class OpenAPIType(ABC):
|
|
|
13
13
|
self.nullable = nullable
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
16
|
-
def asdict(self) -> dict[str, object]:
|
|
16
|
+
def asdict(self) -> dict[str, object]:
|
|
17
|
+
pass
|
|
17
18
|
|
|
18
|
-
def asarguments(self) ->
|
|
19
|
+
def asarguments(self) -> dict[str, dict[str, object]]:
|
|
19
20
|
raise UnsupportedOperation
|
|
20
21
|
|
|
21
22
|
def add_addl_info(self, emitted: dict[str, object]) -> dict[str, object]:
|
|
@@ -147,8 +148,8 @@ class OpenAPIFreeFormObjectType(OpenAPIType):
|
|
|
147
148
|
def asdict(self) -> dict[str, object]:
|
|
148
149
|
return self.add_addl_info({"type": "object"})
|
|
149
150
|
|
|
150
|
-
def asarguments(self) ->
|
|
151
|
-
return
|
|
151
|
+
def asarguments(self) -> dict[str, dict[str, object]]:
|
|
152
|
+
return {}
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
class OpenAPIObjectType(OpenAPIType):
|
|
@@ -185,17 +186,17 @@ class OpenAPIObjectType(OpenAPIType):
|
|
|
185
186
|
},
|
|
186
187
|
})
|
|
187
188
|
|
|
188
|
-
def asarguments(self) ->
|
|
189
|
-
argument_types:
|
|
189
|
+
def asarguments(self) -> dict[str, dict[str, object]]:
|
|
190
|
+
argument_types: dict[str, dict[str, object]] = {}
|
|
190
191
|
for property_name, property_type in self.properties.items():
|
|
191
192
|
desc = self.property_desc.get(property_name)
|
|
192
|
-
argument_types
|
|
193
|
+
argument_types[property_name] = {
|
|
193
194
|
"name": property_name,
|
|
194
195
|
"in": "query",
|
|
195
196
|
"schema": property_type.asdict(),
|
|
196
197
|
"required": not property_type.nullable,
|
|
197
198
|
"description": desc or "",
|
|
198
|
-
}
|
|
199
|
+
}
|
|
199
200
|
return argument_types
|
|
200
201
|
|
|
201
202
|
|
|
@@ -219,11 +220,11 @@ class OpenAPIUnionType(OpenAPIType):
|
|
|
219
220
|
# TODO: use parents description and nullable
|
|
220
221
|
return {"oneOf": [base_type.asdict() for base_type in self.base_types]}
|
|
221
222
|
|
|
222
|
-
def asarguments(self) ->
|
|
223
|
+
def asarguments(self) -> dict[str, dict[str, object]]:
|
|
223
224
|
# TODO handle inheritence (allOf and refs); need to inline here...
|
|
224
225
|
# for now skip this endpoint
|
|
225
226
|
|
|
226
|
-
return
|
|
227
|
+
return {}
|
|
227
228
|
|
|
228
229
|
|
|
229
230
|
class OpenAPIIntersectionType(OpenAPIType):
|
|
@@ -246,8 +247,8 @@ class OpenAPIIntersectionType(OpenAPIType):
|
|
|
246
247
|
# TODO: use parents description and nullable
|
|
247
248
|
return {"allOf": [base_type.asdict() for base_type in self.base_types]}
|
|
248
249
|
|
|
249
|
-
def asarguments(self) ->
|
|
250
|
+
def asarguments(self) -> dict[str, dict[str, object]]:
|
|
250
251
|
# TODO handle inheritence (allOf and refs); need to inline here...
|
|
251
252
|
# for now skip this endpoint
|
|
252
253
|
|
|
253
|
-
return
|
|
254
|
+
return {}
|
|
@@ -48,7 +48,9 @@ keywords = [ "uncountable", "sdk", "api", "uncountable-sdk" ]
|
|
|
48
48
|
requires-python = ">=3.11"
|
|
49
49
|
# May be compatible with older versions
|
|
50
50
|
dependencies = [
|
|
51
|
-
"requests
|
|
51
|
+
"requests == 2.31.0",
|
|
52
|
+
"SQLAlchemy == 2.0.29",
|
|
53
|
+
"APScheduler == 3.10.4",
|
|
52
54
|
]
|
|
53
55
|
dynamic = ["version"]
|
|
54
56
|
|
|
@@ -76,7 +76,7 @@ FullInput:
|
|
|
76
76
|
type: List<input_attributes.InputAttributeValue>
|
|
77
77
|
desc: "Attributes associated with an input, such as CAS number, density, etc."
|
|
78
78
|
global_category_id:
|
|
79
|
-
type: ObjectId
|
|
79
|
+
type: Optional<ObjectId>
|
|
80
80
|
desc: "The global category ID associated with the input"
|
|
81
81
|
subcategory_ids:
|
|
82
82
|
type: List<ObjectId>
|
|
@@ -73,10 +73,10 @@ FullOutput:
|
|
|
73
73
|
type: List<OutputAttrVal>
|
|
74
74
|
desc: "Attributes associated with an output, such as a test documentation"
|
|
75
75
|
global_category_id:
|
|
76
|
-
type: ObjectId
|
|
76
|
+
type: Optional<ObjectId>
|
|
77
77
|
desc: "The global category ID associated with the output"
|
|
78
78
|
unit_id:
|
|
79
|
-
type: ObjectId
|
|
79
|
+
type: Optional<ObjectId>
|
|
80
80
|
desc: "The unit for the output, which all data is stored in. This may be different than the users default displayed information for the output"
|
|
81
81
|
|
|
82
82
|
Data:
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import assert_never
|
|
3
|
+
|
|
4
|
+
from uncountable.core.client import AuthDetailsApiKey, Client
|
|
5
|
+
from uncountable.integration.types import (
|
|
6
|
+
AuthRetrievalEnv,
|
|
7
|
+
ProfileMetadata,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def construct_uncountable_client(
|
|
12
|
+
profile_meta: ProfileMetadata
|
|
13
|
+
) -> Client:
|
|
14
|
+
match profile_meta.auth_retrieval:
|
|
15
|
+
case AuthRetrievalEnv():
|
|
16
|
+
api_id = os.getenv(f"UNC_PROFILE_{profile_meta.name}_API_ID")
|
|
17
|
+
api_secret_key = os.getenv(
|
|
18
|
+
f"UNC_PROFILE_{profile_meta.name}_API_SECRET_KEY"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
assert api_id is not None
|
|
22
|
+
assert api_secret_key is not None
|
|
23
|
+
|
|
24
|
+
return Client(
|
|
25
|
+
base_url=profile_meta.base_url,
|
|
26
|
+
auth_details=AuthDetailsApiKey(
|
|
27
|
+
api_id=api_id, api_secret_key=api_secret_key
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
assert_never(profile_meta.auth_retrieval)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from pkgs.argument_parser import CachedParser
|
|
4
|
+
from uncountable.integration.construct_client import construct_uncountable_client
|
|
5
|
+
from uncountable.integration.executors.script_executor import resolve_script_executor
|
|
6
|
+
from uncountable.integration.job import CronJobArguments
|
|
7
|
+
from uncountable.integration.types import JobDefinition, ProfileMetadata
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class CronJobArgs:
|
|
12
|
+
definition: JobDefinition
|
|
13
|
+
profile_metadata: ProfileMetadata
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
cron_args_parser = CachedParser(CronJobArgs)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def cron_job_executor(**kwargs: dict) -> None:
|
|
20
|
+
args_passed = cron_args_parser.parse_storage(kwargs)
|
|
21
|
+
args = CronJobArguments(
|
|
22
|
+
job_definition=args_passed.definition,
|
|
23
|
+
client=construct_uncountable_client(profile_meta=args_passed.profile_metadata),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
job_class = resolve_script_executor(args_passed.definition.executor)
|
|
27
|
+
|
|
28
|
+
job = job_class()
|
|
29
|
+
job.run(args)
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from importlib import resources
|
|
3
|
+
|
|
4
|
+
from uncountable.integration.server import IntegrationServer
|
|
5
|
+
from uncountable.integration.types import ProfileDefinition
|
|
6
|
+
from pkgs.argument_parser import CachedParser
|
|
7
|
+
from uncountable.integration.db.connect import create_db_engine
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
profile_parser = CachedParser(ProfileDefinition)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> None:
|
|
14
|
+
profiles_module = os.environ["UNC_PROFILES_MODULE"]
|
|
15
|
+
with IntegrationServer(create_db_engine()) as server:
|
|
16
|
+
# TODO: Loop through all job spec yaml files and call server.add_job
|
|
17
|
+
profiles = [
|
|
18
|
+
entry
|
|
19
|
+
for entry in resources.files(profiles_module).iterdir()
|
|
20
|
+
if entry.is_dir()
|
|
21
|
+
]
|
|
22
|
+
for profile in profiles:
|
|
23
|
+
profile_name = profile.name
|
|
24
|
+
try:
|
|
25
|
+
profile = profile_parser.parse_yaml_resource(
|
|
26
|
+
package=".".join([profiles_module, profile_name]),
|
|
27
|
+
resource="profile.yaml",
|
|
28
|
+
)
|
|
29
|
+
except FileNotFoundError as e:
|
|
30
|
+
print("WARN: profile.yaml not found", e)
|
|
31
|
+
continue
|
|
32
|
+
server.register_profile(
|
|
33
|
+
profile_name=profile_name,
|
|
34
|
+
base_url=profile.base_url,
|
|
35
|
+
auth_retrieval=profile.auth_retrieval,
|
|
36
|
+
jobs=profile.jobs,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
import inspect
|
|
5
|
+
from uncountable.integration.job import Job
|
|
6
|
+
from uncountable.integration.types import JobExecutorScript
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def resolve_script_executor(executor: JobExecutorScript) -> type[Job]:
|
|
10
|
+
job_module = importlib.import_module(executor.import_path)
|
|
11
|
+
found_jobs: list[type[Job]] = []
|
|
12
|
+
for _, job_class in inspect.getmembers(job_module, inspect.isclass):
|
|
13
|
+
if Job in job_class.__bases__:
|
|
14
|
+
found_jobs.append(job_class())
|
|
15
|
+
assert (
|
|
16
|
+
len(found_jobs) == 1
|
|
17
|
+
), f"expected exactly one job class in {executor.import_path}"
|
|
18
|
+
return found_jobs[0]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from uncountable.core.client import Client
|
|
3
|
+
from uncountable.integration.types import JobDefinition
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class JobArgumentsBase:
|
|
10
|
+
job_definition: JobDefinition
|
|
11
|
+
client: Client
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class CronJobArguments(JobArgumentsBase):
|
|
16
|
+
# can imagine passing additional data such as in the sftp or webhook cases
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
JobArguments = CronJobArguments
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class JobResult:
|
|
25
|
+
success: bool
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Job(ABC):
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def run(self, args: JobArguments) -> JobResult:
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CronJob(Job):
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def run(self, args: CronJobArguments) -> JobResult:
|
|
39
|
+
...
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from dataclasses import asdict
|
|
2
|
+
from typing import assert_never
|
|
3
|
+
from apscheduler.schedulers.background import BackgroundScheduler
|
|
4
|
+
from apscheduler.schedulers.base import BaseScheduler
|
|
5
|
+
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
|
|
6
|
+
from apscheduler.executors.pool import ThreadPoolExecutor
|
|
7
|
+
from uncountable.integration.cron import CronJobArgs, cron_job_executor
|
|
8
|
+
from apscheduler.triggers.cron import CronTrigger
|
|
9
|
+
from sqlalchemy.engine.base import Engine
|
|
10
|
+
|
|
11
|
+
from uncountable.integration.types import (
|
|
12
|
+
AuthRetrieval,
|
|
13
|
+
CronJobDefinition,
|
|
14
|
+
JobDefinition,
|
|
15
|
+
ProfileMetadata,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_MAX_APSCHEDULER_CONCURRENT_JOBS = 1
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class IntegrationServer:
|
|
23
|
+
_scheduler: BaseScheduler
|
|
24
|
+
_engine: Engine
|
|
25
|
+
|
|
26
|
+
def __init__(self, engine: Engine) -> None:
|
|
27
|
+
self._engine = engine
|
|
28
|
+
self._scheduler = BackgroundScheduler(
|
|
29
|
+
timezone="UTC",
|
|
30
|
+
jobstores={"default": SQLAlchemyJobStore(engine=engine)},
|
|
31
|
+
executors={"default": ThreadPoolExecutor(_MAX_APSCHEDULER_CONCURRENT_JOBS)},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def register_profile(
|
|
35
|
+
self,
|
|
36
|
+
*,
|
|
37
|
+
profile_name: str,
|
|
38
|
+
base_url: str,
|
|
39
|
+
auth_retrieval: AuthRetrieval,
|
|
40
|
+
jobs: list[JobDefinition],
|
|
41
|
+
) -> None:
|
|
42
|
+
for job_defn in jobs:
|
|
43
|
+
profile_metadata = ProfileMetadata(
|
|
44
|
+
name=profile_name, auth_retrieval=auth_retrieval, base_url=base_url
|
|
45
|
+
)
|
|
46
|
+
match job_defn:
|
|
47
|
+
case CronJobDefinition():
|
|
48
|
+
# Add to ap scheduler
|
|
49
|
+
job_kwargs = asdict(
|
|
50
|
+
CronJobArgs(
|
|
51
|
+
definition=job_defn, profile_metadata=profile_metadata
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
existing_job = self._scheduler.get_job(job_defn.id)
|
|
55
|
+
if existing_job is not None:
|
|
56
|
+
existing_job.modify(
|
|
57
|
+
name=job_defn.name,
|
|
58
|
+
kwargs=job_kwargs,
|
|
59
|
+
)
|
|
60
|
+
existing_job.reschedule(job_defn.cron_spec)
|
|
61
|
+
else:
|
|
62
|
+
self._scheduler.add_job(
|
|
63
|
+
cron_job_executor,
|
|
64
|
+
# IMPROVE: reconsider these defaults
|
|
65
|
+
max_instances=1,
|
|
66
|
+
coalesce=True,
|
|
67
|
+
trigger=CronTrigger.from_crontab(job_defn.cron_spec),
|
|
68
|
+
name=job_defn.name,
|
|
69
|
+
id=job_defn.id,
|
|
70
|
+
kwargs=job_kwargs,
|
|
71
|
+
)
|
|
72
|
+
case _:
|
|
73
|
+
assert_never(job_defn.trigger)
|
|
74
|
+
|
|
75
|
+
def _start_apscheduler(self) -> None:
|
|
76
|
+
self._scheduler.start()
|
|
77
|
+
|
|
78
|
+
def _stop_apscheduler(self) -> None:
|
|
79
|
+
self._scheduler.shutdown()
|
|
80
|
+
|
|
81
|
+
def __enter__(self) -> "IntegrationServer":
|
|
82
|
+
self._start_apscheduler()
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
def __exit__(self) -> None:
|
|
86
|
+
self._stop_apscheduler()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# TODO: move to type spec
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JobDefinitionType(StrEnum):
|
|
10
|
+
CRON = "cron"
|
|
11
|
+
# also imagine other job types like webhook-triggered or sftp-triggered,
|
|
12
|
+
# manual, etc
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class JobExecutorType(StrEnum):
|
|
16
|
+
SCRIPT = "script"
|
|
17
|
+
# also imagine builtin executors like 'sftp_sync'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AuthRetrievalType(StrEnum):
|
|
21
|
+
ENV = "env"
|
|
22
|
+
# also imagine secrets manager, keyvault, etc
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class JobExecutorBase:
|
|
27
|
+
type: JobExecutorType
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class JobExecutorScript(JobExecutorBase):
|
|
32
|
+
type: Literal[JobExecutorType.SCRIPT]
|
|
33
|
+
import_path: str
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
JobExecutor = JobExecutorScript
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class JobDefinitionBase:
|
|
41
|
+
id: str
|
|
42
|
+
name: str
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class CronJobDefinition(JobDefinitionBase):
|
|
47
|
+
type: Literal[JobDefinitionType.CRON]
|
|
48
|
+
cron_spec: str
|
|
49
|
+
# Here we assert that the executor has to be a script, but we could add
|
|
50
|
+
# other builtin executor types that cron jobs can support later
|
|
51
|
+
executor: JobExecutorScript
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
JobDefinition = CronJobDefinition
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class AuthRetrievalBase:
|
|
59
|
+
type: AuthRetrievalType
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class AuthRetrievalEnv:
|
|
64
|
+
# We don't really need any extra info here, we can enforce that the auth
|
|
65
|
+
# keys are named like UNC_PROFILE_{profile name}_API_SECRET_KEY. For
|
|
66
|
+
# supporting pulling secrets from secrets manager etc it will be nice to
|
|
67
|
+
# use dataclass properties to get the secret name, region etc.
|
|
68
|
+
type: Literal[AuthRetrievalType.ENV]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
AuthRetrieval = AuthRetrievalEnv
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class ProfileDefinition:
|
|
76
|
+
# profile name (expected to be something like customer_name) will be
|
|
77
|
+
# obtained from the folder name instead of specified here. Forces jobs to
|
|
78
|
+
# be organized nicely in folders that separate their identities.
|
|
79
|
+
auth_retrieval: AuthRetrieval
|
|
80
|
+
base_url: str
|
|
81
|
+
jobs: list[JobDefinition]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass
|
|
85
|
+
class ProfileMetadata:
|
|
86
|
+
# supplied by inspecting the folder name that the profile is in
|
|
87
|
+
name: str
|
|
88
|
+
base_url: str
|
|
89
|
+
auth_retrieval: AuthRetrieval
|
|
File without changes
|
|
@@ -66,7 +66,7 @@ class FullInput:
|
|
|
66
66
|
quantity_type: str
|
|
67
67
|
is_parameter: bool
|
|
68
68
|
attributes: list[input_attributes_t.InputAttributeValue]
|
|
69
|
-
global_category_id: base_t.ObjectId
|
|
69
|
+
global_category_id: typing.Optional[base_t.ObjectId]
|
|
70
70
|
subcategory_ids: list[base_t.ObjectId]
|
|
71
71
|
|
|
72
72
|
|
|
@@ -70,8 +70,8 @@ class FullOutput:
|
|
|
70
70
|
name: str
|
|
71
71
|
quantity_type: str
|
|
72
72
|
attributes: list[OutputAttrVal]
|
|
73
|
-
global_category_id: base_t.ObjectId
|
|
74
|
-
unit_id: base_t.ObjectId
|
|
73
|
+
global_category_id: typing.Optional[base_t.ObjectId]
|
|
74
|
+
unit_id: typing.Optional[base_t.ObjectId]
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
# DO NOT MODIFY -- This file is generated by type_spec
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/examples/recipe-import/importer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/_is_namedtuple.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/argument_parser/case_convert.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/missing_sentry.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization/serial_class.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/serialization_util/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/strenum_compat/strenum_compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/emit_typescript_util.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/parts/base.py.prepart
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/parts/base.ts.prepart
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/type_info/__main__.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/type_info/emit_type_info.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/__init__.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/__main__.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/convert_type.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/emit_python.py
RENAMED
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/pkgs/type_spec/value_spec/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/batch/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/entity/set_values.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/inputs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/outputs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/project/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/api/recipes/get_curve.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/experiment_groups.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/input_attributes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{UncountablePythonSDK-0.0.8 → UncountablePythonSDK-0.0.9}/uncountable/types/recipe_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|