From 99685a27c689549eb0169926f704141deac9bd29 Mon Sep 17 00:00:00 2001 From: armandobelardo Date: Thu, 8 Aug 2024 12:58:22 -0400 Subject: [PATCH] precommit --- .gitignore | 6 +- generators/python/sdk/Dockerfile | 6 +- generators/python/sdk/VERSION | 2 +- .../fern_aware_pydantic_model.py | 6 +- ...iscriminated_union_with_utils_generator.py | 4 +- ...el_simple_discriminated_union_generator.py | 8 +- seed/python-sdk/trace/.mock/generators.yml | 1 + seed/python-sdk/trace/reference.md | 2849 +++++++++++++++++ .../trace/src/seed/core/query_encoder.py | 33 + .../trace/src/seed/core/serialization.py | 167 + seed/python-sdk/trace/tests/utils/__init__.py | 2 + .../tests/utils/assets/models/__init__.py | 21 + .../trace/tests/utils/assets/models/circle.py | 10 + .../trace/tests/utils/assets/models/color.py | 7 + .../assets/models/object_with_defaults.py | 15 + .../models/object_with_optional_field.py | 35 + .../trace/tests/utils/assets/models/shape.py | 27 + .../trace/tests/utils/assets/models/square.py | 10 + .../assets/models/undiscriminated_shape.py | 10 + .../trace/tests/utils/test_http_client.py | 47 + .../trace/tests/utils/test_query_encoding.py | 18 + .../trace/tests/utils/test_serialization.py | 66 + 22 files changed, 3338 insertions(+), 12 deletions(-) create mode 100644 seed/python-sdk/trace/.mock/generators.yml create mode 100644 seed/python-sdk/trace/reference.md create mode 100644 seed/python-sdk/trace/src/seed/core/query_encoder.py create mode 100644 seed/python-sdk/trace/src/seed/core/serialization.py create mode 100644 seed/python-sdk/trace/tests/utils/__init__.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/__init__.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/circle.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/color.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/object_with_defaults.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/object_with_optional_field.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/shape.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/square.py create mode 100644 seed/python-sdk/trace/tests/utils/assets/models/undiscriminated_shape.py create mode 100644 seed/python-sdk/trace/tests/utils/test_http_client.py create mode 100644 seed/python-sdk/trace/tests/utils/test_query_encoding.py create mode 100644 seed/python-sdk/trace/tests/utils/test_serialization.py diff --git a/.gitignore b/.gitignore index d5d7392f4e8..f6cb4550e08 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,8 @@ packages/**/generated **/.idea/* -.python-version \ No newline at end of file +.python-version + +# This file is too large to be included in the repository without LFS +seed/python-sdk/trace/snippet-templates.json +seed/python-sdk/**/output.prof diff --git a/generators/python/sdk/Dockerfile b/generators/python/sdk/Dockerfile index 007d317219a..314e94c8db0 100644 --- a/generators/python/sdk/Dockerfile +++ b/generators/python/sdk/Dockerfile @@ -30,14 +30,14 @@ COPY ./src ./src RUN poetry install -# ENTRYPOINT ["python", "-m", "src.fern_python.generators.sdk.cli"] +ENTRYPOINT ["python", "-m", "src.fern_python.generators.sdk.cli"] ## NOTE: Uncomment the below to generate a flame graph for the python generator. ## To visualize the flamegraph you can run: ## - poetry add snakeviz ## - poetry run snakeviz output.prof -RUN mkdir -p /fern/output +# RUN mkdir -p /fern/output ## For a time-limited run, uncomment the below line and comment the next line. -ENTRYPOINT ["timeout", "-s", "INT", "10m", "python", "-m", "cProfile", "-o", "/fern/output/output.prof", "/src/fern_python/generators/sdk/cli.py"] +# ENTRYPOINT ["timeout", "-s", "INT", "5m", "python", "-m", "cProfile", "-o", "/fern/output/output.prof", "/src/fern_python/generators/sdk/cli.py"] ## For a regularly profiled run, uncomment the below line and comment the previous line. # ENTRYPOINT ["python", "-m", "cProfile", "-o", "/fern/output/output.prof", "/src/fern_python/generators/sdk/cli.py"] diff --git a/generators/python/sdk/VERSION b/generators/python/sdk/VERSION index 40c341bdcdb..7c69a55dbb1 100644 --- a/generators/python/sdk/VERSION +++ b/generators/python/sdk/VERSION @@ -1 +1 @@ -3.6.0 +3.7.0 diff --git a/generators/python/src/fern_python/generators/pydantic_model/fern_aware_pydantic_model.py b/generators/python/src/fern_python/generators/pydantic_model/fern_aware_pydantic_model.py index eefc5f3e7fd..aed5317abc9 100644 --- a/generators/python/src/fern_python/generators/pydantic_model/fern_aware_pydantic_model.py +++ b/generators/python/src/fern_python/generators/pydantic_model/fern_aware_pydantic_model.py @@ -1,7 +1,7 @@ from __future__ import annotations from types import TracebackType -from typing import List, Optional, Sequence, Set, Tuple, Type +from typing import List, Optional, Sequence, Tuple, Type import fern.ir.resources as ir_types @@ -181,7 +181,9 @@ def _must_import_after_current_declaration(self, type_name: ir_types.DeclaredTyp type_id_to_reference = self._type_id_for_forward_ref() is_circular_reference = False if type_id_to_reference is not None: - is_circular_reference = self._context.does_type_reference_other_type(type_id=type_name.type_id, other_type_id=type_id_to_reference) + is_circular_reference = self._context.does_type_reference_other_type( + type_id=type_name.type_id, other_type_id=type_id_to_reference + ) if is_circular_reference: self._model_contains_forward_refs = True diff --git a/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/discriminated_union/discriminated_union_with_utils_generator.py b/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/discriminated_union/discriminated_union_with_utils_generator.py index 5eecbc42dba..2e2a33d372e 100644 --- a/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/discriminated_union/discriminated_union_with_utils_generator.py +++ b/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/discriminated_union/discriminated_union_with_utils_generator.py @@ -278,7 +278,9 @@ def generate(self) -> None: forward_refed_types = [ referenced_type_id for referenced_type_id in referenced_type_ids - if self._context.does_type_reference_other_type(type_id=referenced_type_id, other_type_id=self._name.type_id) + if self._context.does_type_reference_other_type( + type_id=referenced_type_id, other_type_id=self._name.type_id + ) ] if len(forward_refed_types) > 0: diff --git a/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/pydantic_models/pydantic_model_simple_discriminated_union_generator.py b/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/pydantic_models/pydantic_model_simple_discriminated_union_generator.py index 70ba97a8f81..df43df1de7a 100644 --- a/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/pydantic_models/pydantic_model_simple_discriminated_union_generator.py +++ b/generators/python/src/fern_python/generators/pydantic_model/type_declaration_handler/pydantic_models/pydantic_model_simple_discriminated_union_generator.py @@ -159,7 +159,7 @@ def _finish(self, type_alias_declaration: AST.TypeAliasDeclaration) -> None: # There are some types that will not cause their dependent types to rebuild # for example other unions, and so to make sure those types are rebuilt # we import them all here. - for type_id in (self._context.maybe_get_type_ids_for_type_reference(referenced_type) or []): + for type_id in self._context.maybe_get_type_ids_for_type_reference(referenced_type) or []: type_alias_declaration.add_ghost_reference( self._context.get_class_reference_for_type_id( type_id, @@ -184,9 +184,9 @@ def _update_forward_refs_for_single_property_member( ) -> None: referenced_type_ids: Set[ir_types.TypeId] = single_union_type.shape.visit( same_properties_as_object=lambda _: set(), - single_property=lambda single_property: set(self._context.get_referenced_types_of_type_reference( - single_property.type - ) or []), + single_property=lambda single_property: set( + self._context.get_referenced_types_of_type_reference(single_property.type) or [] + ), no_properties=lambda: set(), ) diff --git a/seed/python-sdk/trace/.mock/generators.yml b/seed/python-sdk/trace/.mock/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/seed/python-sdk/trace/.mock/generators.yml @@ -0,0 +1 @@ +{} diff --git a/seed/python-sdk/trace/reference.md b/seed/python-sdk/trace/reference.md new file mode 100644 index 00000000000..c5d8f615bd6 --- /dev/null +++ b/seed/python-sdk/trace/reference.md @@ -0,0 +1,2849 @@ +# Reference +## V2 +
client.v_2.test() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.test() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Admin +
client.admin.update_test_submission_status(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.submission import TestSubmissionStatus + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.update_test_submission_status( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + request=TestSubmissionStatus(), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**request:** `TestSubmissionStatus` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.send_test_submission_update(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedTrace +from seed.submission import TestSubmissionUpdateInfo_Running + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.send_test_submission_update( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + update_time=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + update_info=TestSubmissionUpdateInfo_Running(value="QUEUEING_SUBMISSION"), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**update_time:** `dt.datetime` + +
+
+ +
+
+ +**update_info:** `TestSubmissionUpdateInfo` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.update_workspace_submission_status(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.submission import WorkspaceSubmissionStatus + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.update_workspace_submission_status( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + request=WorkspaceSubmissionStatus(), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**request:** `WorkspaceSubmissionStatus` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.send_workspace_submission_update(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedTrace +from seed.submission import WorkspaceSubmissionUpdateInfo_Running + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.send_workspace_submission_update( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + update_time=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + update_info=WorkspaceSubmissionUpdateInfo_Running( + value="QUEUEING_SUBMISSION" + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**update_time:** `dt.datetime` + +
+
+ +
+
+ +**update_info:** `WorkspaceSubmissionUpdateInfo` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.store_traced_test_case(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.commons import DebugVariableValue_IntegerValue +from seed.submission import ( + ExpressionLocation, + StackInformation, + TestCaseResult, + TestCaseResultWithStdout, + TraceResponse, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.store_traced_test_case( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + test_case_id="string", + result=TestCaseResultWithStdout( + result=TestCaseResult(), + stdout="string", + ), + trace_responses=[ + TraceResponse( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + line_number=1, + return_value=DebugVariableValue_IntegerValue(value=1), + expression_location=ExpressionLocation(), + stack=StackInformation(), + stdout="string", + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**test_case_id:** `str` + +
+
+ +
+
+ +**result:** `TestCaseResultWithStdout` + +
+
+ +
+
+ +**trace_responses:** `typing.Sequence[TraceResponse]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.store_traced_test_case_v_2(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.commons import DebugVariableValue_IntegerValue +from seed.submission import ( + ExpressionLocation, + StackInformation, + TracedFile, + TraceResponseV2, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.store_traced_test_case_v_2( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + test_case_id="string", + request=[ + TraceResponseV2( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + line_number=1, + file=TracedFile(), + return_value=DebugVariableValue_IntegerValue(value=1), + expression_location=ExpressionLocation(), + stack=StackInformation(), + stdout="string", + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**test_case_id:** `TestCaseId` + +
+
+ +
+
+ +**request:** `typing.Sequence[TraceResponseV2]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.store_traced_workspace(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.commons import DebugVariableValue_IntegerValue +from seed.submission import ( + ExceptionInfo, + ExceptionV2_Generic, + ExpressionLocation, + StackInformation, + TraceResponse, + WorkspaceRunDetails, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.store_traced_workspace( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + workspace_run_details=WorkspaceRunDetails( + exception_v_2=ExceptionV2_Generic(), + exception=ExceptionInfo(), + stdout="string", + ), + trace_responses=[ + TraceResponse( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + line_number=1, + return_value=DebugVariableValue_IntegerValue(value=1), + expression_location=ExpressionLocation(), + stack=StackInformation(), + stdout="string", + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**workspace_run_details:** `WorkspaceRunDetails` + +
+
+ +
+
+ +**trace_responses:** `typing.Sequence[TraceResponse]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.admin.store_traced_workspace_v_2(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedTrace +from seed.commons import DebugVariableValue_IntegerValue +from seed.submission import ( + ExpressionLocation, + StackInformation, + TracedFile, + TraceResponseV2, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.admin.store_traced_workspace_v_2( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + request=[ + TraceResponseV2( + submission_id=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + line_number=1, + file=TracedFile(), + return_value=DebugVariableValue_IntegerValue(value=1), + expression_location=ExpressionLocation(), + stack=StackInformation(), + stdout="string", + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**submission_id:** `SubmissionId` + +
+
+ +
+
+ +**request:** `typing.Sequence[TraceResponseV2]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Homepage +
client.homepage.get_homepage_problems() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.homepage.get_homepage_problems() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.homepage.set_homepage_problems(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.homepage.set_homepage_problems( + request=["string"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Sequence[ProblemId]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Migration +
client.migration.get_attempted_migrations(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.migration.get_attempted_migrations( + admin_key_header="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**admin_key_header:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Playlist +
client.playlist.create_playlist(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a new playlist +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.playlist.create_playlist( + service_param=1, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + optional_datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + name="string", + problems=["string"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**service_param:** `int` + +
+
+ +
+
+ +**datetime:** `dt.datetime` + +
+
+ +
+
+ +**name:** `str` + +
+
+ +
+
+ +**problems:** `typing.Sequence[ProblemId]` + +
+
+ +
+
+ +**optional_datetime:** `typing.Optional[dt.datetime]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.playlist.get_playlists(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns the user's playlists +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.playlist.get_playlists( + service_param=1, + limit=1, + other_field="string", + multi_line_docs="string", + optional_multiple_field="string", + multiple_field="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**service_param:** `int` + +
+
+ +
+
+ +**other_field:** `str` — i'm another field + +
+
+ +
+
+ +**multi_line_docs:** `str` + +I'm a multiline +description + +
+
+ +
+
+ +**multiple_field:** `typing.Union[str, typing.Sequence[str]]` + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` + +
+
+ +
+
+ +**optional_multiple_field:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.playlist.get_playlist(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns a playlist +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.playlist.get_playlist( + service_param=1, + playlist_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**service_param:** `int` + +
+
+ +
+
+ +**playlist_id:** `PlaylistId` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.playlist.update_playlist(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates a playlist +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace +from seed.playlist import UpdatePlaylistRequest + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.playlist.update_playlist( + service_param=1, + playlist_id="string", + request=UpdatePlaylistRequest( + name="string", + problems=["string"], + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**service_param:** `int` + +
+
+ +
+
+ +**playlist_id:** `PlaylistId` + +
+
+ +
+
+ +**request:** `typing.Optional[UpdatePlaylistRequest]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.playlist.delete_playlist(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Deletes a playlist +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.playlist.delete_playlist( + service_param=1, + playlist_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**service_param:** `int` + +
+
+ +
+
+ +**playlist_id:** `PlaylistId` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Problem +
client.problem.create_problem(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Creates a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace +from seed.commons import ( + FileInfo, + TestCase, + TestCaseWithExpectedResult, + VariableType, + VariableValue_IntegerValue, +) +from seed.problem import ( + ProblemDescription, + ProblemDescriptionBoard_Html, + ProblemFiles, + VariableTypeAndName, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.problem.create_problem( + problem_name="string", + problem_description=ProblemDescription( + boards=[ProblemDescriptionBoard_Html(value="string")], + ), + files={ + "JAVA": ProblemFiles( + solution_file=FileInfo( + filename="string", + contents="string", + ), + read_only_files=[ + FileInfo( + filename="string", + contents="string", + ) + ], + ) + }, + input_params=[ + VariableTypeAndName( + variable_type=VariableType(), + name="string", + ) + ], + output_type=VariableType(), + testcases=[ + TestCaseWithExpectedResult( + test_case=TestCase( + id="string", + params=[VariableValue_IntegerValue(value=1)], + ), + expected_result=VariableValue_IntegerValue(value=1), + ) + ], + method_name="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_name:** `str` + +
+
+ +
+
+ +**problem_description:** `ProblemDescription` + +
+
+ +
+
+ +**files:** `typing.Dict[Language, ProblemFiles]` + +
+
+ +
+
+ +**input_params:** `typing.Sequence[VariableTypeAndName]` + +
+
+ +
+
+ +**output_type:** `VariableType` + +
+
+ +
+
+ +**testcases:** `typing.Sequence[TestCaseWithExpectedResult]` + +
+
+ +
+
+ +**method_name:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.problem.update_problem(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace +from seed.commons import ( + FileInfo, + TestCase, + TestCaseWithExpectedResult, + VariableType, + VariableValue_IntegerValue, +) +from seed.problem import ( + ProblemDescription, + ProblemDescriptionBoard_Html, + ProblemFiles, + VariableTypeAndName, +) + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.problem.update_problem( + problem_id="string", + problem_name="string", + problem_description=ProblemDescription( + boards=[ProblemDescriptionBoard_Html(value="string")], + ), + files={ + "JAVA": ProblemFiles( + solution_file=FileInfo( + filename="string", + contents="string", + ), + read_only_files=[ + FileInfo( + filename="string", + contents="string", + ) + ], + ) + }, + input_params=[ + VariableTypeAndName( + variable_type=VariableType(), + name="string", + ) + ], + output_type=VariableType(), + testcases=[ + TestCaseWithExpectedResult( + test_case=TestCase( + id="string", + params=[VariableValue_IntegerValue(value=1)], + ), + expected_result=VariableValue_IntegerValue(value=1), + ) + ], + method_name="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**problem_name:** `str` + +
+
+ +
+
+ +**problem_description:** `ProblemDescription` + +
+
+ +
+
+ +**files:** `typing.Dict[Language, ProblemFiles]` + +
+
+ +
+
+ +**input_params:** `typing.Sequence[VariableTypeAndName]` + +
+
+ +
+
+ +**output_type:** `VariableType` + +
+
+ +
+
+ +**testcases:** `typing.Sequence[TestCaseWithExpectedResult]` + +
+
+ +
+
+ +**method_name:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.problem.delete_problem(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Soft deletes a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.problem.delete_problem( + problem_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.problem.get_default_starter_files(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns default starter files for problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace +from seed.commons import VariableType +from seed.problem import VariableTypeAndName + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.problem.get_default_starter_files( + input_params=[ + VariableTypeAndName( + variable_type=VariableType(), + name="string", + ) + ], + output_type=VariableType(), + method_name="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**input_params:** `typing.Sequence[VariableTypeAndName]` + +
+
+ +
+
+ +**output_type:** `VariableType` + +
+
+ +
+
+ +**method_name:** `str` + +The name of the `method` that the student has to complete. +The method name cannot include the following characters: + - Greater Than `>` + - Less Than `<`` + - Equals `=` + - Period `.` + + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Submission +
client.submission.create_execution_session(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns sessionId and execution server URL for session. Spins up server. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.submission.create_execution_session( + language="JAVA", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**language:** `Language` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.submission.get_execution_session(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns execution server URL for session. Returns empty if session isn't registered. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.submission.get_execution_session( + session_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**session_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.submission.stop_execution_session(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Stops execution session. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.submission.stop_execution_session( + session_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**session_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.submission.get_execution_sessions_state() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.submission.get_execution_sessions_state() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sysprop +
client.sysprop.set_num_warm_instances(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.sysprop.set_num_warm_instances( + language="JAVA", + num_warm_instances=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**language:** `Language` + +
+
+ +
+
+ +**num_warm_instances:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sysprop.get_num_warm_instances() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.sysprop.get_num_warm_instances() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## V2 Problem +
client.v_2.problem.get_lightweight_problems() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns lightweight versions of all problems +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.problem.get_lightweight_problems() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.problem.get_problems() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns latest versions of all problems +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.problem.get_problems() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.problem.get_latest_problem(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns latest version of a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.problem.get_latest_problem( + problem_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.problem.get_problem_version(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns requested version of a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.problem.get_problem_version( + problem_id="string", + problem_version=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**problem_version:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## V2 V3 Problem +
client.v_2.v_3.problem.get_lightweight_problems() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns lightweight versions of all problems +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.v_3.problem.get_lightweight_problems() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.v_3.problem.get_problems() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns latest versions of all problems +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.v_3.problem.get_problems() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.v_3.problem.get_latest_problem(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns latest version of a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.v_3.problem.get_latest_problem( + problem_id="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.v_2.v_3.problem.get_problem_version(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Returns requested version of a problem +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedTrace + +client = SeedTrace( + x_random_header="YOUR_X_RANDOM_HEADER", + token="YOUR_TOKEN", +) +client.v_2.v_3.problem.get_problem_version( + problem_id="string", + problem_version=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**problem_id:** `ProblemId` + +
+
+ +
+
+ +**problem_version:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/seed/python-sdk/trace/src/seed/core/query_encoder.py b/seed/python-sdk/trace/src/seed/core/query_encoder.py new file mode 100644 index 00000000000..24076d72ee9 --- /dev/null +++ b/seed/python-sdk/trace/src/seed/core/query_encoder.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from collections import ChainMap +from typing import Any, Dict, Optional + +import pydantic + + +# Flattens dicts to be of the form {"key[subkey][subkey2]": value} where value is not a dict +def traverse_query_dict(dict_flat: Dict[str, Any], key_prefix: Optional[str] = None) -> Dict[str, Any]: + result = {} + for k, v in dict_flat.items(): + key = f"{key_prefix}[{k}]" if key_prefix is not None else k + if isinstance(v, dict): + result.update(traverse_query_dict(v, key)) + else: + result[key] = v + return result + + +def single_query_encoder(query_key: str, query_value: Any) -> Dict[str, Any]: + if isinstance(query_value, pydantic.BaseModel) or isinstance(query_value, dict): + if isinstance(query_value, pydantic.BaseModel): + obj_dict = query_value.dict(by_alias=True) + else: + obj_dict = query_value + return traverse_query_dict(obj_dict, query_key) + + return {query_key: query_value} + + +def encode_query(query: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: + return dict(ChainMap(*[single_query_encoder(k, v) for k, v in query.items()])) if query is not None else None diff --git a/seed/python-sdk/trace/src/seed/core/serialization.py b/seed/python-sdk/trace/src/seed/core/serialization.py new file mode 100644 index 00000000000..8ad5cf8125f --- /dev/null +++ b/seed/python-sdk/trace/src/seed/core/serialization.py @@ -0,0 +1,167 @@ +# This file was auto-generated by Fern from our API Definition. + +import collections +import typing + +import typing_extensions + + +class FieldMetadata: + """ + Metadata class used to annotate fields to provide additional information. + + Example: + class MyDict(TypedDict): + field: typing.Annotated[str, FieldMetadata(alias="field_name")] + + Will serialize: `{"field": "value"}` + To: `{"field_name": "value"}` + """ + + alias: str + + def __init__(self, *, alias: str) -> None: + self.alias = alias + + +def convert_and_respect_annotation_metadata( + *, object_: typing.Any, annotation: typing.Any, inner_type: typing.Optional[typing.Any] = None +) -> typing.Any: + """ + Respect the metadata annotations on a field, such as aliasing. This function effectively + manipulates the dict-form of an object to respect the metadata annotations. This is primarily used for + TypedDicts, which cannot support aliasing out of the box, and can be extended for additional + utilities, such as defaults. + + Parameters + ---------- + object_ : typing.Any + + annotation : type + The type we're looking to apply typing annotations from + + inner_type : typing.Optional[type] + + Returns + ------- + typing.Any + """ + + if object_ is None: + return None + if inner_type is None: + inner_type = annotation + + clean_type = _remove_annotations(inner_type) + if typing_extensions.is_typeddict(clean_type) and isinstance(object_, typing.Mapping): + return _convert_typeddict(object_, clean_type) + + if ( + # If you're iterating on a string, do not bother to coerce it to a sequence. + (not isinstance(object_, str)) + and ( + ( + ( + typing_extensions.get_origin(clean_type) == typing.List + or typing_extensions.get_origin(clean_type) == list + or clean_type == typing.List + ) + and isinstance(object_, typing.List) + ) + or ( + ( + typing_extensions.get_origin(clean_type) == typing.Set + or typing_extensions.get_origin(clean_type) == set + or clean_type == typing.Set + ) + and isinstance(object_, typing.Set) + ) + or ( + ( + typing_extensions.get_origin(clean_type) == typing.Sequence + or typing_extensions.get_origin(clean_type) == collections.abc.Sequence + or clean_type == typing.Sequence + ) + and isinstance(object_, typing.Sequence) + ) + ) + ): + inner_type = typing_extensions.get_args(clean_type)[0] + return [ + convert_and_respect_annotation_metadata(object_=item, annotation=annotation, inner_type=inner_type) + for item in object_ + ] + + if typing_extensions.get_origin(clean_type) == typing.Union: + # We should be able to ~relatively~ safely try to convert keys against all + # member types in the union, the edge case here is if one member aliases a field + # of the same name to a different name from another member + # Or if another member aliases a field of the same name that another member does not. + for member in typing_extensions.get_args(clean_type): + object_ = convert_and_respect_annotation_metadata(object_=object_, annotation=annotation, inner_type=member) + return object_ + + annotated_type = _get_annotation(annotation) + if annotated_type is None: + return object_ + + # If the object is not a TypedDict, a Union, or other container (list, set, sequence, etc.) + # Then we can safely call it on the recursive conversion. + return object_ + + +def _convert_typeddict(object_: typing.Mapping[str, object], expected_type: typing.Any) -> typing.Mapping[str, object]: + converted_object: typing.Dict[str, object] = {} + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + for key, value in object_.items(): + type_ = annotations.get(key) + if type_ is None: + converted_object[key] = value + else: + converted_object[_alias_key(key, type_)] = convert_and_respect_annotation_metadata( + object_=value, annotation=type_ + ) + return converted_object + + +def _get_annotation(type_: typing.Any) -> typing.Optional[typing.Any]: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return None + + if maybe_annotated_type == typing_extensions.NotRequired: + type_ = typing_extensions.get_args(type_)[0] + maybe_annotated_type = typing_extensions.get_origin(type_) + + if maybe_annotated_type == typing_extensions.Annotated: + return type_ + + return None + + +def _remove_annotations(type_: typing.Any) -> typing.Any: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return type_ + + if maybe_annotated_type == typing_extensions.NotRequired: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + if maybe_annotated_type == typing_extensions.Annotated: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + return type_ + + +def _alias_key(key: str, type_: typing.Any) -> str: + maybe_annotated_type = _get_annotation(type_) + + if maybe_annotated_type is not None: + # The actual annotations are 1 onward, the first is the annotated type + annotations = typing_extensions.get_args(maybe_annotated_type)[1:] + + for annotation in annotations: + if isinstance(annotation, FieldMetadata) and annotation.alias is not None: + return annotation.alias + + return key diff --git a/seed/python-sdk/trace/tests/utils/__init__.py b/seed/python-sdk/trace/tests/utils/__init__.py new file mode 100644 index 00000000000..f3ea2659bb1 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/seed/python-sdk/trace/tests/utils/assets/models/__init__.py b/seed/python-sdk/trace/tests/utils/assets/models/__init__.py new file mode 100644 index 00000000000..2cf01263529 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from .circle import CircleParams +from .object_with_defaults import ObjectWithDefaultsParams +from .object_with_optional_field import ObjectWithOptionalFieldParams +from .shape import Shape_CircleParams, Shape_SquareParams, ShapeParams +from .square import SquareParams +from .undiscriminated_shape import UndiscriminatedShapeParams + +__all__ = [ + "CircleParams", + "ObjectWithDefaultsParams", + "ObjectWithOptionalFieldParams", + "ShapeParams", + "Shape_CircleParams", + "Shape_SquareParams", + "SquareParams", + "UndiscriminatedShapeParams", +] diff --git a/seed/python-sdk/trace/tests/utils/assets/models/circle.py b/seed/python-sdk/trace/tests/utils/assets/models/circle.py new file mode 100644 index 00000000000..af7a1bf8a8e --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/circle.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +from seed.core.serialization import FieldMetadata + + +class CircleParams(typing_extensions.TypedDict): + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] diff --git a/seed/python-sdk/trace/tests/utils/assets/models/color.py b/seed/python-sdk/trace/tests/utils/assets/models/color.py new file mode 100644 index 00000000000..2aa2c4c52f0 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/color.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing + +Color = typing.Union[typing.Literal["red", "blue"], typing.Any] diff --git a/seed/python-sdk/trace/tests/utils/assets/models/object_with_defaults.py b/seed/python-sdk/trace/tests/utils/assets/models/object_with_defaults.py new file mode 100644 index 00000000000..a977b1d2aa1 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/object_with_defaults.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions + + +class ObjectWithDefaultsParams(typing_extensions.TypedDict): + """ + Defines properties with default values and validation rules. + """ + + decimal: typing_extensions.NotRequired[float] + string: typing_extensions.NotRequired[str] + required_string: str diff --git a/seed/python-sdk/trace/tests/utils/assets/models/object_with_optional_field.py b/seed/python-sdk/trace/tests/utils/assets/models/object_with_optional_field.py new file mode 100644 index 00000000000..3ad93d5f305 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/object_with_optional_field.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +import typing_extensions +from seed.core.serialization import FieldMetadata + +from .color import Color +from .shape import ShapeParams +from .undiscriminated_shape import UndiscriminatedShapeParams + + +class ObjectWithOptionalFieldParams(typing_extensions.TypedDict): + literal: typing.Literal["lit_one"] + string: typing_extensions.NotRequired[str] + integer: typing_extensions.NotRequired[int] + long_: typing_extensions.NotRequired[typing_extensions.Annotated[int, FieldMetadata(alias="long")]] + double: typing_extensions.NotRequired[float] + bool_: typing_extensions.NotRequired[typing_extensions.Annotated[bool, FieldMetadata(alias="bool")]] + datetime: typing_extensions.NotRequired[dt.datetime] + date: typing_extensions.NotRequired[dt.date] + uuid_: typing_extensions.NotRequired[typing_extensions.Annotated[uuid.UUID, FieldMetadata(alias="uuid")]] + base_64: typing_extensions.NotRequired[typing_extensions.Annotated[str, FieldMetadata(alias="base64")]] + list_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Sequence[str], FieldMetadata(alias="list")]] + set_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Set[str], FieldMetadata(alias="set")]] + map_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Dict[int, str], FieldMetadata(alias="map")]] + enum: typing_extensions.NotRequired[Color] + union: typing_extensions.NotRequired[ShapeParams] + second_union: typing_extensions.NotRequired[ShapeParams] + undiscriminated_union: typing_extensions.NotRequired[UndiscriminatedShapeParams] + any: typing.Any diff --git a/seed/python-sdk/trace/tests/utils/assets/models/shape.py b/seed/python-sdk/trace/tests/utils/assets/models/shape.py new file mode 100644 index 00000000000..2c33c877951 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/shape.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import typing_extensions +from seed.core.serialization import FieldMetadata + + +class Base(typing_extensions.TypedDict): + id: str + + +class Shape_CircleParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["circle"], FieldMetadata(alias="shapeType")] + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] + + +class Shape_SquareParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["square"], FieldMetadata(alias="shapeType")] + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] + + +ShapeParams = typing.Union[Shape_CircleParams, Shape_SquareParams] diff --git a/seed/python-sdk/trace/tests/utils/assets/models/square.py b/seed/python-sdk/trace/tests/utils/assets/models/square.py new file mode 100644 index 00000000000..b9b7dd319bc --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/square.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +from seed.core.serialization import FieldMetadata + + +class SquareParams(typing_extensions.TypedDict): + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] diff --git a/seed/python-sdk/trace/tests/utils/assets/models/undiscriminated_shape.py b/seed/python-sdk/trace/tests/utils/assets/models/undiscriminated_shape.py new file mode 100644 index 00000000000..99f12b300d1 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/assets/models/undiscriminated_shape.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .circle import CircleParams +from .square import SquareParams + +UndiscriminatedShapeParams = typing.Union[CircleParams, SquareParams] diff --git a/seed/python-sdk/trace/tests/utils/test_http_client.py b/seed/python-sdk/trace/tests/utils/test_http_client.py new file mode 100644 index 00000000000..edd11ca7afb --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/test_http_client.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from seed.core.http_client import get_request_body +from seed.core.request_options import RequestOptions + + +def get_request_options() -> RequestOptions: + return {"additional_body_parameters": {"see you": "later"}} + + +def test_get_json_request_body() -> None: + json_body, data_body = get_request_body(json={"hello": "world"}, data=None, request_options=None, omit=None) + assert json_body == {"hello": "world"} + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={"goodbye": "world"}, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"goodbye": "world", "see you": "later"} + assert data_body_extras is None + + +def test_get_files_request_body() -> None: + json_body, data_body = get_request_body(json=None, data={"hello": "world"}, request_options=None, omit=None) + assert data_body == {"hello": "world"} + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data={"goodbye": "world"}, request_options=get_request_options(), omit=None + ) + + assert data_body_extras == {"goodbye": "world", "see you": "later"} + assert json_body_extras is None + + +def test_get_none_request_body() -> None: + json_body, data_body = get_request_body(json=None, data=None, request_options=None, omit=None) + assert data_body is None + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"see you": "later"} + assert data_body_extras is None diff --git a/seed/python-sdk/trace/tests/utils/test_query_encoding.py b/seed/python-sdk/trace/tests/utils/test_query_encoding.py new file mode 100644 index 00000000000..247e1551b46 --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/test_query_encoding.py @@ -0,0 +1,18 @@ +# This file was auto-generated by Fern from our API Definition. + +from seed.core.query_encoder import encode_query + + +def test_query_encoding() -> None: + assert encode_query({"hello world": "hello world"}) == {"hello world": "hello world"} + assert encode_query({"hello_world": {"hello": "world"}}) == {"hello_world[hello]": "world"} + assert encode_query({"hello_world": {"hello": {"world": "today"}, "test": "this"}, "hi": "there"}) == { + "hello_world[hello][world]": "today", + "hello_world[test]": "this", + "hi": "there", + } + + +def test_encode_query_with_none() -> None: + encoded = encode_query(None) + assert encoded == None diff --git a/seed/python-sdk/trace/tests/utils/test_serialization.py b/seed/python-sdk/trace/tests/utils/test_serialization.py new file mode 100644 index 00000000000..58b1ed66e6d --- /dev/null +++ b/seed/python-sdk/trace/tests/utils/test_serialization.py @@ -0,0 +1,66 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, List + +from seed.core.serialization import convert_and_respect_annotation_metadata + +from .assets.models import ObjectWithOptionalFieldParams, ShapeParams + +UNION_TEST: ShapeParams = {"radius_measurement": 1.0, "shape_type": "circle", "id": "1"} +UNION_TEST_CONVERTED = {"shapeType": "circle", "radiusMeasurement": 1.0, "id": "1"} + + +def test_convert_and_respect_annotation_metadata() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "bool_": True, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata(object_=data, annotation=ObjectWithOptionalFieldParams) + assert converted == {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"} + + +def test_convert_and_respect_annotation_metadata_in_list() -> None: + data: List[ObjectWithOptionalFieldParams] = [ + {"string": "string", "long_": 12345, "bool_": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long_": 67890, "list_": [], "literal": "lit_one", "any": "any"}, + ] + converted = convert_and_respect_annotation_metadata(object_=data, annotation=List[ObjectWithOptionalFieldParams]) + + assert converted == [ + {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long": 67890, "list": [], "literal": "lit_one", "any": "any"}, + ] + + +def test_convert_and_respect_annotation_metadata_in_nested_object() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "union": UNION_TEST, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata(object_=data, annotation=ObjectWithOptionalFieldParams) + + assert converted == { + "string": "string", + "long": 12345, + "union": UNION_TEST_CONVERTED, + "literal": "lit_one", + "any": "any", + } + + +def test_convert_and_respect_annotation_metadata_in_union() -> None: + converted = convert_and_respect_annotation_metadata(object_=UNION_TEST, annotation=ShapeParams) + + assert converted == UNION_TEST_CONVERTED + + +def test_convert_and_respect_annotation_metadata_with_empty_object() -> None: + data: Any = {} + converted = convert_and_respect_annotation_metadata(object_=data, annotation=ShapeParams) + assert converted == data