From cac6bd32468f18ed95047ebb6eb178fc3be04ac5 Mon Sep 17 00:00:00 2001 From: Aryeh Klein Date: Tue, 16 Sep 2025 09:21:58 -0400 Subject: [PATCH 1/4] Support generating pydantic models with annotated fields --- .../pydantic_model/custom_config.py | 12 ++++ .../fern_aware_pydantic_model.py | 1 + .../pydantic_codegen/pydantic_model.py | 33 ++++++++++ .../python/tests/sdk/test_custom_config.py | 52 ++++++++++++++++ .../fern/definition/api.yml | 1 + .../fern/definition/types.yml | 62 +++++++++++++++++++ .../fern/fern.config.json | 4 ++ .../fern/generators.yml | 15 +++++ 8 files changed, 180 insertions(+) create mode 100644 generators/python/tests/utils/annotated_field_models/fern/definition/api.yml create mode 100644 generators/python/tests/utils/annotated_field_models/fern/definition/types.yml create mode 100644 generators/python/tests/utils/annotated_field_models/fern/fern.config.json create mode 100644 generators/python/tests/utils/annotated_field_models/fern/generators.yml diff --git a/generators/python/src/fern_python/generators/pydantic_model/custom_config.py b/generators/python/src/fern_python/generators/pydantic_model/custom_config.py index 782a7bec7860..8d5269bbb3f7 100644 --- a/generators/python/src/fern_python/generators/pydantic_model/custom_config.py +++ b/generators/python/src/fern_python/generators/pydantic_model/custom_config.py @@ -50,6 +50,13 @@ class BasePydanticModelCustomConfig(pydantic.BaseModel): use_pydantic_field_aliases: bool = True + use_annotated_field_aliases: bool = False + """ + When enabled, generates type-safe field aliases using typing.Annotated[Type, pydantic.Field(alias="...")] + instead of field assignments. This improves type checking compatibility with pyright. + Only available for Pydantic v2. + """ + @pydantic.model_validator(mode="after") def check_wrapped_aliases_v1_or_v2_only(self) -> Self: version_compat = self.version @@ -69,6 +76,11 @@ def check_wrapped_aliases_v1_or_v2_only(self) -> Self: else: self.use_str_enums = True + if self.use_annotated_field_aliases and version_compat != PydanticVersionCompatibility.V2: + raise ValueError( + "use_annotated_field_aliases is only supported with Pydantic v2, please set version to 'v2' to use this feature." + ) + return self 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 8f2fee80abac..9baacc41c549 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 @@ -99,6 +99,7 @@ def __init__( update_forward_ref_function_reference=self._context.core_utilities.get_update_forward_refs(), field_metadata_getter=lambda: self._context.core_utilities.get_field_metadata(), use_pydantic_field_aliases=self._custom_config.use_pydantic_field_aliases, + use_annotated_field_aliases=self._custom_config.use_annotated_field_aliases, ) self._force_update_forward_refs = force_update_forward_refs diff --git a/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py b/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py index fd49ac89f398..7641c3a48e25 100644 --- a/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py +++ b/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py @@ -35,6 +35,7 @@ def __init__( update_forward_ref_function_reference: AST.Reference, field_metadata_getter: Callable[[], FieldMetadata], use_pydantic_field_aliases: bool, + use_annotated_field_aliases: bool, should_export: bool = True, base_models: Sequence[AST.ClassReference] = [], parent: Optional[ClassParent] = None, @@ -78,6 +79,7 @@ def __init__( self._update_forward_ref_function_reference = update_forward_ref_function_reference self._field_metadata_getter = field_metadata_getter self._use_pydantic_field_aliases = use_pydantic_field_aliases + self._use_annotated_field_aliases = use_annotated_field_aliases def to_reference(self) -> LocalClassReference: return self._local_class_reference @@ -141,6 +143,37 @@ def add_field(self, unsanitized_field: PydanticField) -> None: type_hint=aliased_type_hint, ) + # New annotated field aliases feature + if ( + is_aliased + and self._use_annotated_field_aliases + and self._version == PydanticVersionCompatibility.V2 + ): + # Create pydantic.Field annotation + pydantic_field_annotation = AST.Expression( + AST.FunctionInvocation( + function_definition=Pydantic(self._version).Field(), + kwargs=[("alias", AST.Expression(f'"{field.json_field_name}"'))] + ) + ) + + # Create annotated type hint + annotated_type_hint = AST.TypeHint.annotated( + type=field.type_hint, + annotation=pydantic_field_annotation, + ) + + # Update field with new type hint + prev_fields = field.__dict__ + del prev_fields["type_hint"] + field = PydanticField( + **(field.__dict__), + type_hint=annotated_type_hint, + ) + + # Use only the default value as initializer, not pydantic.Field + initializer = default_value + self._class_declaration.add_class_var( AST.VariableDeclaration(name=field.name, type_hint=field.type_hint, initializer=initializer) ) diff --git a/generators/python/tests/sdk/test_custom_config.py b/generators/python/tests/sdk/test_custom_config.py index 3fd74be86038..539381daec91 100644 --- a/generators/python/tests/sdk/test_custom_config.py +++ b/generators/python/tests/sdk/test_custom_config.py @@ -70,3 +70,55 @@ def test_parse_wrapped_aliases() -> None: match="Wrapped aliases are only supported in Pydantic V1, V1_ON_V2, or V2, please update your `version` field appropriately to continue using wrapped aliases.", ): SDKCustomConfig.parse_obj(both) + + +def test_annotated_field_aliases() -> None: + # Test that annotated field aliases work with v2 + v2_config = { + "pydantic_config": { + "version": "v2", + "use_annotated_field_aliases": True, + }, + } + sdk_custom_config = SDKCustomConfig.parse_obj(v2_config) + assert ( + sdk_custom_config.pydantic_config.version == "v2" + and sdk_custom_config.pydantic_config.use_annotated_field_aliases is True + ) + + # Test that annotated field aliases fail with non-v2 versions + v1_config = { + "pydantic_config": { + "version": "v1", + "use_annotated_field_aliases": True, + }, + } + with pytest.raises( + pydantic.ValidationError, + match="use_annotated_field_aliases is only supported with Pydantic v2, please set version to 'v2' to use this feature.", + ): + SDKCustomConfig.parse_obj(v1_config) + + both_config = { + "pydantic_config": { + "version": "both", + "use_annotated_field_aliases": True, + }, + } + with pytest.raises( + pydantic.ValidationError, + match="use_annotated_field_aliases is only supported with Pydantic v2, please set version to 'v2' to use this feature.", + ): + SDKCustomConfig.parse_obj(both_config) + + v1_on_v2_config = { + "pydantic_config": { + "version": "v1_on_v2", + "use_annotated_field_aliases": True, + }, + } + with pytest.raises( + pydantic.ValidationError, + match="use_annotated_field_aliases is only supported with Pydantic v2, please set version to 'v2' to use this feature.", + ): + SDKCustomConfig.parse_obj(v1_on_v2_config) diff --git a/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml b/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml new file mode 100644 index 000000000000..9a8ae7d166be --- /dev/null +++ b/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml @@ -0,0 +1 @@ +name: api diff --git a/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml b/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml new file mode 100644 index 000000000000..845ede2af756 --- /dev/null +++ b/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml @@ -0,0 +1,62 @@ +types: + Color: + enum: + - red + - blue + + UndiscriminatedShape: + discriminated: false + union: + - Circle + - Square + + Shape: + base-properties: + id: string + discriminant: shapeType + union: + circle: Circle + square: Square + + Circle: + properties: + radiusMeasurement: double + + Square: + properties: + lengthMeasurement: double + + ObjectWithOptionalField: #generic object that supports any type, makes it easier to use when testing + properties: + literal: literal<"lit_one"> + string: optional + integer: optional + long: optional + double: optional + bool: optional + datetime: optional + date: optional + uuid: optional + base64: optional + list: optional> + set: optional> + map: optional> + enum: optional + union: optional + second_union: optional + undiscriminated_union: optional + any: unknown + + ObjectWithDefaults: + docs: | + Defines properties with default values and validation rules. + properties: + decimal: + type: optional + default: 1.1 + string: + type: optional + default: "here's a sentence!" + required_string: + type: string + default: "I neeeeeeeeeed this!" diff --git a/generators/python/tests/utils/annotated_field_models/fern/fern.config.json b/generators/python/tests/utils/annotated_field_models/fern/fern.config.json new file mode 100644 index 000000000000..d0cb7225c8b4 --- /dev/null +++ b/generators/python/tests/utils/annotated_field_models/fern/fern.config.json @@ -0,0 +1,4 @@ +{ + "organization": "fern", + "version": "0.41.16" +} diff --git a/generators/python/tests/utils/annotated_field_models/fern/generators.yml b/generators/python/tests/utils/annotated_field_models/fern/generators.yml new file mode 100644 index 000000000000..602f5d351295 --- /dev/null +++ b/generators/python/tests/utils/annotated_field_models/fern/generators.yml @@ -0,0 +1,15 @@ +default-group: dummy_types +groups: + dummy_annotated_field_types: + generators: + - name: ferntest/fern-pydantic-model + ir-version: v53 + version: 0.0.0 + output: + location: local-file-system + path: ../types + config: + skip_validation: true + use_provided_defaults: true + version: v2 + use_annotated_field_aliases: true \ No newline at end of file From bfea4168cd46381ea847762355b4f9b881807acc Mon Sep 17 00:00:00 2001 From: Aryeh Klein Date: Tue, 16 Sep 2025 09:32:27 -0400 Subject: [PATCH 2/4] Add tests --- .../test_annotated_field_aliases.py | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 generators/python/tests/pydantic_model/test_annotated_field_aliases.py diff --git a/generators/python/tests/pydantic_model/test_annotated_field_aliases.py b/generators/python/tests/pydantic_model/test_annotated_field_aliases.py new file mode 100644 index 000000000000..5279938b40c4 --- /dev/null +++ b/generators/python/tests/pydantic_model/test_annotated_field_aliases.py @@ -0,0 +1,164 @@ +import textwrap +from fern_python.codegen import AST +from fern_python.external_dependencies import PydanticVersionCompatibility +from fern_python.generators.pydantic_model.field_metadata import FieldMetadata +from fern_python.pydantic_codegen import PydanticField, PydanticModel +from fern_python.source_file_factory import SourceFileFactory + + +def test_annotated_field_aliases_generation() -> None: + """Test that use_annotated_field_aliases generates the correct annotated type syntax""" + source_file = SourceFileFactory(should_format=True).create_snippet() + + # Mock field metadata getter + def mock_field_metadata_getter() -> FieldMetadata: + return FieldMetadata(reference=AST.ClassReference(qualified_name_excluding_import=("FieldMetadata",))) + + # Create PydanticModel with annotated field aliases enabled + model = PydanticModel( + source_file=source_file, + name="TestModel", + frozen=False, + orm_mode=False, + smart_union=False, + version=PydanticVersionCompatibility.V2, + is_pydantic_v2=AST.Expression("True"), + universal_root_validator=lambda pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("validator",)) + ), + universal_field_validator=lambda field_name, pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("field_validator",)) + ), + require_optional_fields=False, + update_forward_ref_function_reference=AST.Reference(qualified_name_excluding_import=("update_refs",)), + field_metadata_getter=mock_field_metadata_getter, + use_pydantic_field_aliases=True, # This should be ignored when use_annotated_field_aliases=True + use_annotated_field_aliases=True, # Enable the new feature + ) + + # Add a field with an alias + field = PydanticField( + name="total_items", + pascal_case_field_name="TotalItems", + json_field_name="totalItems", + type_hint=AST.TypeHint.int_(), + description="Total number of items", + ) + model.add_field(field) + + model.finish() + + # Generate the code + generated_code = source_file.to_str() + + # Verify the generated code contains the annotated syntax + assert "import typing_extensions" in generated_code + assert "import pydantic" in generated_code + assert "typing_extensions.Annotated" in generated_code + assert 'pydantic.Field(\n alias="totalItems"' in generated_code + + # Verify it does NOT contain the old syntax + assert "total_items: int = pydantic.Field(" not in generated_code + + +def test_annotated_field_aliases_disabled() -> None: + """Test that when disabled, it uses the traditional pydantic.Field syntax""" + source_file = SourceFileFactory(should_format=True).create_snippet() + + # Mock field metadata getter + def mock_field_metadata_getter() -> FieldMetadata: + return FieldMetadata(reference=AST.ClassReference(qualified_name_excluding_import=("FieldMetadata",))) + + # Create PydanticModel with annotated field aliases disabled (default) + model = PydanticModel( + source_file=source_file, + name="TestModel", + frozen=False, + orm_mode=False, + smart_union=False, + version=PydanticVersionCompatibility.V2, + is_pydantic_v2=AST.Expression("True"), + universal_root_validator=lambda pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("validator",)) + ), + universal_field_validator=lambda field_name, pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("field_validator",)) + ), + require_optional_fields=False, + update_forward_ref_function_reference=AST.Reference(qualified_name_excluding_import=("update_refs",)), + field_metadata_getter=mock_field_metadata_getter, + use_pydantic_field_aliases=True, # Traditional behavior + use_annotated_field_aliases=False, # Disabled + ) + + # Add a field with an alias + field = PydanticField( + name="total_items", + pascal_case_field_name="TotalItems", + json_field_name="totalItems", + type_hint=AST.TypeHint.int_(), + description="Total number of items", + ) + model.add_field(field) + + model.finish() + + # Generate the code + generated_code = source_file.to_str() + + # Verify the generated code uses traditional syntax + assert "total_items: int = pydantic.Field(alias=\"totalItems\"" in generated_code + + # Verify it does NOT contain the annotated syntax + assert "typing.Annotated[int, pydantic.Field(" not in generated_code + + +def test_annotated_field_aliases_only_v2() -> None: + """Test that annotated field aliases only work with Pydantic v2""" + source_file = SourceFileFactory(should_format=True).create_snippet() + + # Mock field metadata getter + def mock_field_metadata_getter() -> FieldMetadata: + return FieldMetadata(reference=AST.ClassReference(qualified_name_excluding_import=("FieldMetadata",))) + + # Create PydanticModel with annotated field aliases enabled but v1 + model = PydanticModel( + source_file=source_file, + name="TestModel", + frozen=False, + orm_mode=False, + smart_union=False, + version=PydanticVersionCompatibility.V1, # v1, not v2 + is_pydantic_v2=AST.Expression("False"), + universal_root_validator=lambda pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("validator",)) + ), + universal_field_validator=lambda field_name, pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("field_validator",)) + ), + require_optional_fields=False, + update_forward_ref_function_reference=AST.Reference(qualified_name_excluding_import=("update_refs",)), + field_metadata_getter=mock_field_metadata_getter, + use_pydantic_field_aliases=True, + use_annotated_field_aliases=True, # Enabled but should be ignored for v1 + ) + + # Add a field with an alias + field = PydanticField( + name="total_items", + pascal_case_field_name="TotalItems", + json_field_name="totalItems", + type_hint=AST.TypeHint.int_(), + ) + model.add_field(field) + + model.finish() + + # Generate the code + generated_code = source_file.to_str() + + # Should fall back to traditional syntax for v1 + assert "total_items: int = pydantic.Field(alias=\"totalItems\"" in generated_code + + # Should NOT use annotated syntax for v1 + assert "typing.Annotated[int, pydantic.Field(" not in generated_code \ No newline at end of file From 681b0b9c8d966867d88dea0796ac328551d6c068 Mon Sep 17 00:00:00 2001 From: Aryeh Klein Date: Tue, 16 Sep 2025 10:38:31 -0400 Subject: [PATCH 3/4] remove not needed files --- .../fern/definition/api.yml | 1 - .../fern/definition/types.yml | 62 ------------------- .../fern/fern.config.json | 4 -- .../fern/generators.yml | 15 ----- 4 files changed, 82 deletions(-) delete mode 100644 generators/python/tests/utils/annotated_field_models/fern/definition/api.yml delete mode 100644 generators/python/tests/utils/annotated_field_models/fern/definition/types.yml delete mode 100644 generators/python/tests/utils/annotated_field_models/fern/fern.config.json delete mode 100644 generators/python/tests/utils/annotated_field_models/fern/generators.yml diff --git a/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml b/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml deleted file mode 100644 index 9a8ae7d166be..000000000000 --- a/generators/python/tests/utils/annotated_field_models/fern/definition/api.yml +++ /dev/null @@ -1 +0,0 @@ -name: api diff --git a/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml b/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml deleted file mode 100644 index 845ede2af756..000000000000 --- a/generators/python/tests/utils/annotated_field_models/fern/definition/types.yml +++ /dev/null @@ -1,62 +0,0 @@ -types: - Color: - enum: - - red - - blue - - UndiscriminatedShape: - discriminated: false - union: - - Circle - - Square - - Shape: - base-properties: - id: string - discriminant: shapeType - union: - circle: Circle - square: Square - - Circle: - properties: - radiusMeasurement: double - - Square: - properties: - lengthMeasurement: double - - ObjectWithOptionalField: #generic object that supports any type, makes it easier to use when testing - properties: - literal: literal<"lit_one"> - string: optional - integer: optional - long: optional - double: optional - bool: optional - datetime: optional - date: optional - uuid: optional - base64: optional - list: optional> - set: optional> - map: optional> - enum: optional - union: optional - second_union: optional - undiscriminated_union: optional - any: unknown - - ObjectWithDefaults: - docs: | - Defines properties with default values and validation rules. - properties: - decimal: - type: optional - default: 1.1 - string: - type: optional - default: "here's a sentence!" - required_string: - type: string - default: "I neeeeeeeeeed this!" diff --git a/generators/python/tests/utils/annotated_field_models/fern/fern.config.json b/generators/python/tests/utils/annotated_field_models/fern/fern.config.json deleted file mode 100644 index d0cb7225c8b4..000000000000 --- a/generators/python/tests/utils/annotated_field_models/fern/fern.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "organization": "fern", - "version": "0.41.16" -} diff --git a/generators/python/tests/utils/annotated_field_models/fern/generators.yml b/generators/python/tests/utils/annotated_field_models/fern/generators.yml deleted file mode 100644 index 602f5d351295..000000000000 --- a/generators/python/tests/utils/annotated_field_models/fern/generators.yml +++ /dev/null @@ -1,15 +0,0 @@ -default-group: dummy_types -groups: - dummy_annotated_field_types: - generators: - - name: ferntest/fern-pydantic-model - ir-version: v53 - version: 0.0.0 - output: - location: local-file-system - path: ../types - config: - skip_validation: true - use_provided_defaults: true - version: v2 - use_annotated_field_aliases: true \ No newline at end of file From 695262858caaf861000722bce7d086fb74253c6f Mon Sep 17 00:00:00 2001 From: Aryeh Klein Date: Tue, 16 Sep 2025 14:31:07 -0400 Subject: [PATCH 4/4] Adds end to end tests --- ...iscriminated_union_with_utils_generator.py | 1 + .../pydantic_codegen/pydantic_model.py | 37 +- .../test_annotated_field_aliases.py | 55 +- .../use-annotated-field-aliases/__init__.py | 25 + .../core/__init__.py | 44 + .../core/abstract_fern_service.py | 10 + .../core/datetime_utils.py | 28 + .../core/exceptions/__init__.py | 15 + .../core/exceptions/fern_http_exception.py | 20 + .../core/exceptions/handlers.py | 38 + .../core/exceptions/unauthorized.py | 15 + .../core/pydantic_utilities.py | 226 + .../core/route_args.py | 67 + .../core/security/__init__.py | 7 + .../core/security/bearer.py | 21 + .../core/serialization.py | 276 ++ .../use-annotated-field-aliases/register.py | 82 + .../resources/__init__.py | 17 + .../resources/endpoints/__init__.py | 7 + .../resources/endpoints/resources/__init__.py | 8 + .../endpoints/resources/container/__init__.py | 4 + .../resources/container/service/__init__.py | 7 + .../resources/container/service/service.py | 350 ++ .../resources/content_type/__init__.py | 4 + .../content_type/service/__init__.py | 7 + .../resources/content_type/service/service.py | 123 + .../endpoints/resources/enum/__init__.py | 4 + .../resources/enum/service/__init__.py | 7 + .../resources/enum/service/service.py | 74 + .../resources/http_methods/__init__.py | 4 + .../http_methods/service/__init__.py | 7 + .../resources/http_methods/service/service.py | 247 ++ .../endpoints/resources/object/__init__.py | 4 + .../resources/object/service/__init__.py | 7 + .../resources/object/service/service.py | 322 ++ .../endpoints/resources/params/__init__.py | 4 + .../resources/params/service/__init__.py | 7 + .../resources/params/service/service.py | 422 ++ .../endpoints/resources/primitive/__init__.py | 4 + .../resources/primitive/service/__init__.py | 7 + .../resources/primitive/service/service.py | 411 ++ .../endpoints/resources/put/__init__.py | 7 + .../resources/put/service/__init__.py | 7 + .../resources/put/service/service.py | 74 + .../endpoints/resources/put/types/__init__.py | 10 + .../endpoints/resources/put/types/error.py | 17 + .../resources/put/types/error_category.py | 25 + .../resources/put/types/error_code.py | 57 + .../resources/put/types/put_response.py | 13 + .../endpoints/resources/union/__init__.py | 4 + .../resources/union/service/__init__.py | 7 + .../resources/union/service/service.py | 74 + .../endpoints/resources/urls/__init__.py | 4 + .../resources/urls/service/__init__.py | 7 + .../resources/urls/service/service.py | 191 + .../resources/general_errors/__init__.py | 8 + .../general_errors/errors/__init__.py | 7 + .../general_errors/errors/bad_request_body.py | 9 + .../general_errors/types/__init__.py | 7 + .../types/bad_object_request_info.py | 12 + .../resources/inlined_requests/__init__.py | 7 + .../inlined_requests/service/__init__.py | 8 + .../service/post_with_object_body.py | 16 + .../inlined_requests/service/service.py | 81 + .../resources/no_auth/__init__.py | 4 + .../resources/no_auth/service/__init__.py | 7 + .../resources/no_auth/service/service.py | 77 + .../resources/no_req_body/__init__.py | 4 + .../resources/no_req_body/service/__init__.py | 7 + .../resources/no_req_body/service/service.py | 112 + .../resources/req_with_headers/__init__.py | 4 + .../req_with_headers/service/__init__.py | 7 + .../req_with_headers/service/service.py | 77 + .../resources/types/__init__.py | 53 + .../resources/types/resources/__init__.py | 46 + .../types/resources/docs/__init__.py | 7 + .../types/resources/docs/types/__init__.py | 7 + .../resources/docs/types/object_with_docs.py | 69 + .../types/resources/enum/__init__.py | 8 + .../types/resources/enum/errors/__init__.py | 7 + .../enum/errors/error_with_enum_body.py | 9 + .../types/resources/enum/types/__init__.py | 7 + .../resources/enum/types/weather_report.py | 29 + .../types/resources/object/__init__.py | 33 + .../types/resources/object/errors/__init__.py | 15 + ...nested_object_with_optional_field_error.py | 9 + ...nested_object_with_required_field_error.py | 9 + .../object_with_optional_field_error.py | 9 + .../object_with_required_field_error.py | 9 + .../types/resources/object/types/__init__.py | 21 + .../resources/object/types/double_optional.py | 16 + .../nested_object_with_optional_field.py | 17 + .../nested_object_with_required_field.py | 15 + .../object/types/object_with_map_of_map.py | 13 + .../types/object_with_optional_field.py | 31 + .../types/object_with_required_field.py | 12 + .../resources/object/types/optional_alias.py | 5 + .../types/resources/union/__init__.py | 8 + .../types/resources/union/errors/__init__.py | 7 + .../union/errors/error_with_union_body.py | 9 + .../types/resources/union/types/__init__.py | 9 + .../types/resources/union/types/animal.py | 63 + .../types/resources/union/types/cat.py | 14 + .../types/resources/union/types/dog.py | 14 + .../use-annotated-field-aliases/security.py | 10 + .../snippet-templates.json | 0 .../use-annotated-field-aliases/snippet.json | 0 seed/fastapi/seed.yml | 5 + .../.github/workflows/ci.yml | 61 + .../use-annotated-field-aliases/.gitignore | 5 + .../use-annotated-field-aliases/README.md | 159 + .../use-annotated-field-aliases/poetry.lock | 550 +++ .../pyproject.toml | 84 + .../use-annotated-field-aliases/reference.md | 3656 +++++++++++++++++ .../requirements.txt | 4 + .../snippet-templates.json | 0 .../use-annotated-field-aliases/snippet.json | 642 +++ .../src/seed/__init__.py | 61 + .../src/seed/client.py | 221 + .../src/seed/core/__init__.py | 103 + .../src/seed/core/api_error.py | 23 + .../src/seed/core/client_wrapper.py | 87 + .../src/seed/core/datetime_utils.py | 28 + .../src/seed/core/file.py | 67 + .../src/seed/core/force_multipart.py | 18 + .../src/seed/core/http_client.py | 543 +++ .../src/seed/core/http_response.py | 55 + .../src/seed/core/jsonable_encoder.py | 100 + .../src/seed/core/pydantic_utilities.py | 258 ++ .../src/seed/core/query_encoder.py | 58 + .../src/seed/core/remove_none_from_dict.py | 11 + .../src/seed/core/request_options.py | 35 + .../src/seed/core/serialization.py | 276 ++ .../src/seed/endpoints/__init__.py | 63 + .../src/seed/endpoints/client.py | 234 ++ .../src/seed/endpoints/container/__init__.py | 4 + .../src/seed/endpoints/container/client.py | 599 +++ .../seed/endpoints/container/raw_client.py | 587 +++ .../seed/endpoints/content_type/__init__.py | 4 + .../src/seed/endpoints/content_type/client.py | 482 +++ .../seed/endpoints/content_type/raw_client.py | 372 ++ .../src/seed/endpoints/enum/__init__.py | 4 + .../src/seed/endpoints/enum/client.py | 111 + .../src/seed/endpoints/enum/raw_client.py | 98 + .../seed/endpoints/http_methods/__init__.py | 4 + .../src/seed/endpoints/http_methods/client.py | 544 +++ .../seed/endpoints/http_methods/raw_client.py | 511 +++ .../src/seed/endpoints/object/__init__.py | 4 + .../src/seed/endpoints/object/client.py | 869 ++++ .../src/seed/endpoints/object/raw_client.py | 652 +++ .../src/seed/endpoints/params/__init__.py | 4 + .../src/seed/endpoints/params/client.py | 662 +++ .../src/seed/endpoints/params/raw_client.py | 628 +++ .../src/seed/endpoints/primitive/__init__.py | 4 + .../src/seed/endpoints/primitive/client.py | 665 +++ .../seed/endpoints/primitive/raw_client.py | 691 ++++ .../src/seed/endpoints/put/__init__.py | 37 + .../src/seed/endpoints/put/client.py | 104 + .../src/seed/endpoints/put/raw_client.py | 90 + .../src/seed/endpoints/put/types/__init__.py | 40 + .../src/seed/endpoints/put/types/error.py | 17 + .../endpoints/put/types/error_category.py | 5 + .../seed/endpoints/put/types/error_code.py | 20 + .../seed/endpoints/put/types/put_response.py | 13 + .../src/seed/endpoints/raw_client.py | 13 + .../src/seed/endpoints/union/__init__.py | 4 + .../src/seed/endpoints/union/client.py | 119 + .../src/seed/endpoints/union/raw_client.py | 99 + .../src/seed/endpoints/urls/__init__.py | 4 + .../src/seed/endpoints/urls/client.py | 263 ++ .../src/seed/endpoints/urls/raw_client.py | 276 ++ .../src/seed/general_errors/__init__.py | 33 + .../seed/general_errors/errors/__init__.py | 32 + .../general_errors/errors/bad_request_body.py | 11 + .../src/seed/general_errors/types/__init__.py | 32 + .../types/bad_object_request_info.py | 12 + .../src/seed/inlined_requests/__init__.py | 4 + .../src/seed/inlined_requests/client.py | 188 + .../src/seed/inlined_requests/raw_client.py | 157 + .../src/seed/no_auth/__init__.py | 4 + .../src/seed/no_auth/client.py | 114 + .../src/seed/no_auth/raw_client.py | 125 + .../src/seed/no_req_body/__init__.py | 4 + .../src/seed/no_req_body/client.py | 156 + .../src/seed/no_req_body/raw_client.py | 153 + .../src/seed/py.typed | 0 .../src/seed/req_with_headers/__init__.py | 4 + .../src/seed/req_with_headers/client.py | 142 + .../src/seed/req_with_headers/raw_client.py | 108 + .../src/seed/types/__init__.py | 98 + .../src/seed/types/docs/__init__.py | 32 + .../src/seed/types/docs/types/__init__.py | 32 + .../seed/types/docs/types/object_with_docs.py | 69 + .../src/seed/types/enum/__init__.py | 33 + .../src/seed/types/enum/errors/__init__.py | 32 + .../types/enum/errors/error_with_enum_body.py | 11 + .../src/seed/types/enum/types/__init__.py | 32 + .../seed/types/enum/types/weather_report.py | 5 + .../src/seed/types/object/__init__.py | 70 + .../src/seed/types/object/errors/__init__.py | 45 + ...nested_object_with_optional_field_error.py | 11 + ...nested_object_with_required_field_error.py | 11 + .../object_with_optional_field_error.py | 11 + .../object_with_required_field_error.py | 11 + .../src/seed/types/object/types/__init__.py | 54 + .../types/object/types/double_optional.py | 16 + .../nested_object_with_optional_field.py | 17 + .../nested_object_with_required_field.py | 15 + .../object/types/object_with_map_of_map.py | 13 + .../types/object_with_optional_field.py | 31 + .../types/object_with_required_field.py | 12 + .../seed/types/object/types/optional_alias.py | 5 + .../src/seed/types/union/__init__.py | 40 + .../src/seed/types/union/errors/__init__.py | 32 + .../union/errors/error_with_union_body.py | 11 + .../src/seed/types/union/types/__init__.py | 40 + .../src/seed/types/union/types/animal.py | 28 + .../src/seed/types/union/types/cat.py | 14 + .../src/seed/types/union/types/dog.py | 14 + .../src/seed/version.py | 3 + .../tests/custom/test_client.py | 7 + .../tests/utils/__init__.py | 2 + .../tests/utils/assets/models/__init__.py | 21 + .../tests/utils/assets/models/circle.py | 11 + .../tests/utils/assets/models/color.py | 7 + .../assets/models/object_with_defaults.py | 15 + .../models/object_with_optional_field.py | 35 + .../tests/utils/assets/models/shape.py | 28 + .../tests/utils/assets/models/square.py | 11 + .../assets/models/undiscriminated_shape.py | 10 + .../tests/utils/test_http_client.py | 61 + .../tests/utils/test_query_encoding.py | 36 + .../tests/utils/test_serialization.py | 72 + seed/python-sdk/seed.yml | 5 + 234 files changed, 23005 insertions(+), 19 deletions(-) create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/abstract_fern_service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/datetime_utils.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/fern_http_exception.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/handlers.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/unauthorized.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/pydantic_utilities.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/route_args.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/bearer.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/core/serialization.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/register.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_category.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_code.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/put_response.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/bad_request_body.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/bad_object_request_info.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/post_with_object_body.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/service.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/object_with_docs.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/error_with_enum_body.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/weather_report.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_optional_field_error.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_required_field_error.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_optional_field_error.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_required_field_error.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/double_optional.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_optional_field.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_required_field.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_map_of_map.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_optional_field.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_required_field.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/optional_alias.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/error_with_union_body.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/__init__.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/animal.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/cat.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/dog.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/security.py create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/snippet-templates.json create mode 100644 seed/fastapi/exhaustive/use-annotated-field-aliases/snippet.json create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/.github/workflows/ci.yml create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/.gitignore create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/README.md create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/poetry.lock create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/pyproject.toml create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/reference.md create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/requirements.txt create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet-templates.json create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet.json create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/api_error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/client_wrapper.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/datetime_utils.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/file.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/force_multipart.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_response.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/jsonable_encoder.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/pydantic_utilities.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/query_encoder.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/remove_none_from_dict.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/request_options.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/serialization.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_category.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_code.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/put_response.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/bad_request_body.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/bad_object_request_info.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/py.typed create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/raw_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/object_with_docs.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/error_with_enum_body.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/weather_report.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_optional_field_error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_required_field_error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_optional_field_error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_required_field_error.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/double_optional.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_optional_field.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_required_field.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_map_of_map.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_optional_field.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_required_field.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/optional_alias.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/error_with_union_body.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/animal.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/cat.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/dog.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/version.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/custom/test_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/__init__.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/circle.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/color.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_defaults.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_optional_field.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/shape.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/square.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/undiscriminated_shape.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_http_client.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_query_encoding.py create mode 100644 seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_serialization.py 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 408bc2bec792..e97e23b2ddd8 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 @@ -195,6 +195,7 @@ def generate(self) -> None: update_forward_ref_function_reference=self._context.core_utilities.get_update_forward_refs(), field_metadata_getter=lambda: self._context.core_utilities.get_field_metadata(), use_pydantic_field_aliases=self._custom_config.use_pydantic_field_aliases, + use_annotated_field_aliases=self._custom_config.use_annotated_field_aliases, ) as internal_pydantic_model_for_single_union_type: internal_single_union_type = internal_pydantic_model_for_single_union_type.to_reference() internal_single_union_types.append(internal_single_union_type) diff --git a/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py b/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py index 7641c3a48e25..70da8ea7b752 100644 --- a/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py +++ b/generators/python/src/fern_python/pydantic_codegen/pydantic_model.py @@ -127,29 +127,13 @@ def add_field(self, unsanitized_field: PydanticField) -> None: version=self._version, ) - if is_aliased and not self._use_pydantic_field_aliases: - field_metadata = self._field_metadata_getter().get_instance() - field_metadata.add_alias(field.json_field_name) - - aliased_type_hint = AST.TypeHint.annotated( - type=field.type_hint, - annotation=field_metadata.get_as_node(), - ) - - prev_fields = field.__dict__ - del prev_fields["type_hint"] - field = PydanticField( - **(field.__dict__), - type_hint=aliased_type_hint, - ) - - # New annotated field aliases feature + # Handle field aliasing approaches (mutually exclusive) if ( is_aliased and self._use_annotated_field_aliases and self._version == PydanticVersionCompatibility.V2 ): - # Create pydantic.Field annotation + # New annotated field aliases feature - use pydantic.Field in Annotated pydantic_field_annotation = AST.Expression( AST.FunctionInvocation( function_definition=Pydantic(self._version).Field(), @@ -174,6 +158,23 @@ def add_field(self, unsanitized_field: PydanticField) -> None: # Use only the default value as initializer, not pydantic.Field initializer = default_value + elif is_aliased and not self._use_pydantic_field_aliases: + # Legacy approach - use FieldMetadata in Annotated + field_metadata = self._field_metadata_getter().get_instance() + field_metadata.add_alias(field.json_field_name) + + aliased_type_hint = AST.TypeHint.annotated( + type=field.type_hint, + annotation=field_metadata.get_as_node(), + ) + + prev_fields = field.__dict__ + del prev_fields["type_hint"] + field = PydanticField( + **(field.__dict__), + type_hint=aliased_type_hint, + ) + self._class_declaration.add_class_var( AST.VariableDeclaration(name=field.name, type_hint=field.type_hint, initializer=initializer) ) diff --git a/generators/python/tests/pydantic_model/test_annotated_field_aliases.py b/generators/python/tests/pydantic_model/test_annotated_field_aliases.py index 5279938b40c4..a91f6ab3200c 100644 --- a/generators/python/tests/pydantic_model/test_annotated_field_aliases.py +++ b/generators/python/tests/pydantic_model/test_annotated_field_aliases.py @@ -161,4 +161,57 @@ def mock_field_metadata_getter() -> FieldMetadata: assert "total_items: int = pydantic.Field(alias=\"totalItems\"" in generated_code # Should NOT use annotated syntax for v1 - assert "typing.Annotated[int, pydantic.Field(" not in generated_code \ No newline at end of file + assert "typing.Annotated[int, pydantic.Field(" not in generated_code + + +def test_no_double_annotation() -> None: + """Test that we don't get double annotations when use_annotated_field_aliases=True""" + source_file = SourceFileFactory(should_format=True).create_snippet() + + # Mock field metadata getter + def mock_field_metadata_getter() -> FieldMetadata: + return FieldMetadata(reference=AST.ClassReference(qualified_name_excluding_import=("FieldMetadata",))) + + # Create PydanticModel with both flags set - this used to cause double annotation + model = PydanticModel( + source_file=source_file, + name="TestModel", + frozen=False, + orm_mode=False, + smart_union=False, + version=PydanticVersionCompatibility.V2, + is_pydantic_v2=AST.Expression("True"), + universal_root_validator=lambda pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("validator",)) + ), + universal_field_validator=lambda field_name, pre: AST.FunctionInvocation( + function_definition=AST.Reference(qualified_name_excluding_import=("field_validator",)) + ), + require_optional_fields=False, + update_forward_ref_function_reference=AST.Reference(qualified_name_excluding_import=("update_refs",)), + field_metadata_getter=mock_field_metadata_getter, + use_pydantic_field_aliases=False, # This would trigger FieldMetadata approach + use_annotated_field_aliases=True, # This should override and use pydantic.Field approach + ) + + # Add a field with an alias + field = PydanticField( + name="total_items", + pascal_case_field_name="TotalItems", + json_field_name="totalItems", + type_hint=AST.TypeHint.int_(), + ) + model.add_field(field) + + model.finish() + + # Generate the code + generated_code = source_file.to_str() + + # Should only have ONE level of Annotated, not nested + assert "typing_extensions.Annotated" in generated_code + assert 'pydantic.Field(\n alias="totalItems"' in generated_code + + # Should NOT have double annotation (FieldMetadata inside pydantic.Field annotation) + assert "FieldMetadata" not in generated_code + assert generated_code.count("typing_extensions.Annotated") == 1 \ No newline at end of file diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/__init__.py new file mode 100644 index 000000000000..3f087a7059d7 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/__init__.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .resources import ( + BadObjectRequestInfo, + BadRequestBody, + PostWithObjectBody, + endpoints, + general_errors, + inlined_requests, + types, +) +from .security import ApiAuth + +__all__ = [ + "ApiAuth", + "BadObjectRequestInfo", + "BadRequestBody", + "PostWithObjectBody", + "endpoints", + "general_errors", + "inlined_requests", + "types", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/__init__.py new file mode 100644 index 000000000000..6b87874034c2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/__init__.py @@ -0,0 +1,44 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .datetime_utils import serialize_datetime +from .exceptions import ( + FernHTTPException, + UnauthorizedException, + default_exception_handler, + fern_http_exception_handler, + http_exception_handler, +) +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + UniversalBaseModel, + UniversalRootModel, + parse_obj_as, + universal_field_validator, + universal_root_validator, + update_forward_refs, +) +from .route_args import route_args +from .security import BearerToken +from .serialization import FieldMetadata, convert_and_respect_annotation_metadata + +__all__ = [ + "BearerToken", + "FernHTTPException", + "FieldMetadata", + "IS_PYDANTIC_V2", + "UnauthorizedException", + "UniversalBaseModel", + "UniversalRootModel", + "convert_and_respect_annotation_metadata", + "default_exception_handler", + "fern_http_exception_handler", + "http_exception_handler", + "parse_obj_as", + "route_args", + "serialize_datetime", + "universal_field_validator", + "universal_root_validator", + "update_forward_refs", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/abstract_fern_service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/abstract_fern_service.py new file mode 100644 index 000000000000..9966b4876da8 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/abstract_fern_service.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc + +import fastapi + + +class AbstractFernService(abc.ABC): + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: ... diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/datetime_utils.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/datetime_utils.py new file mode 100644 index 000000000000..7c9864a944c2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/datetime_utils.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt + + +def serialize_datetime(v: dt.datetime) -> str: + """ + Serialize a datetime including timezone info. + + Uses the timezone info provided if present, otherwise uses the current runtime's timezone info. + + UTC datetimes end in "Z" while all other timezones are represented as offset from UTC, e.g. +05:00. + """ + + def _serialize_zoned_datetime(v: dt.datetime) -> str: + if v.tzinfo is not None and v.tzinfo.tzname(None) == dt.timezone.utc.tzname(None): + # UTC is a special case where we use "Z" at the end instead of "+00:00" + return v.isoformat().replace("+00:00", "Z") + else: + # Delegate to the typical +/- offset format + return v.isoformat() + + if v.tzinfo is not None: + return _serialize_zoned_datetime(v) + else: + local_tz = dt.datetime.now().astimezone().tzinfo + localized_dt = v.replace(tzinfo=local_tz) + return _serialize_zoned_datetime(localized_dt) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/__init__.py new file mode 100644 index 000000000000..9771ecd53f13 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/__init__.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .fern_http_exception import FernHTTPException +from .handlers import default_exception_handler, fern_http_exception_handler, http_exception_handler +from .unauthorized import UnauthorizedException + +__all__ = [ + "FernHTTPException", + "UnauthorizedException", + "default_exception_handler", + "fern_http_exception_handler", + "http_exception_handler", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/fern_http_exception.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/fern_http_exception.py new file mode 100644 index 000000000000..bdf038624872 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/fern_http_exception.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import typing + +import fastapi + + +class FernHTTPException(abc.ABC, fastapi.HTTPException): + def __init__( + self, status_code: int, name: typing.Optional[str] = None, content: typing.Optional[typing.Any] = None + ): + super().__init__(status_code=status_code) + self.name = name + self.status_code = status_code + self.content = content + + def to_json_response(self) -> fastapi.responses.JSONResponse: + content = fastapi.encoders.jsonable_encoder(self.content, exclude_none=True) + return fastapi.responses.JSONResponse(content=content, status_code=self.status_code) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/handlers.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/handlers.py new file mode 100644 index 000000000000..56e838c460b1 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/handlers.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +import logging + +import fastapi +import starlette +import starlette.exceptions +from .fern_http_exception import FernHTTPException + + +def fern_http_exception_handler( + request: fastapi.requests.Request, + exc: FernHTTPException, + skip_log: bool = False, +) -> fastapi.responses.JSONResponse: + if not skip_log: + logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) + return exc.to_json_response() + + +def http_exception_handler( + request: fastapi.requests.Request, + exc: starlette.exceptions.HTTPException, + skip_log: bool = False, +) -> fastapi.responses.JSONResponse: + if not skip_log: + logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) + return FernHTTPException(status_code=exc.status_code, content=exc.detail).to_json_response() + + +def default_exception_handler( + request: fastapi.requests.Request, + exc: Exception, + skip_log: bool = False, +) -> fastapi.responses.JSONResponse: + if not skip_log: + logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) + return FernHTTPException(status_code=500, content="Internal Server Error").to_json_response() diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/unauthorized.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/unauthorized.py new file mode 100644 index 000000000000..32d532e5ef22 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/exceptions/unauthorized.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .fern_http_exception import FernHTTPException + + +class UnauthorizedException(FernHTTPException): + """ + This is the exception that is thrown by Fern when auth is not present on a + request. + """ + + def __init__(self, content: typing.Optional[str] = None) -> None: + super().__init__(status_code=401, content=content) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/pydantic_utilities.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/pydantic_utilities.py new file mode 100644 index 000000000000..6bea25f3a5ac --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/pydantic_utilities.py @@ -0,0 +1,226 @@ +# This file was auto-generated by Fern from our API Definition. + +# nopycln: file +import datetime as dt +from collections import defaultdict +from typing import Any, Callable, Dict, List, Mapping, Tuple, Type, TypeVar, Union, cast + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + +if IS_PYDANTIC_V2: + from pydantic.v1.datetime_parse import parse_date as parse_date + from pydantic.v1.datetime_parse import parse_datetime as parse_datetime + from pydantic.v1.fields import ModelField as ModelField + from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] + from pydantic.v1.typing import get_args as get_args + from pydantic.v1.typing import get_origin as get_origin + from pydantic.v1.typing import is_literal_type as is_literal_type + from pydantic.v1.typing import is_union as is_union +else: + from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] + from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] + from pydantic.typing import get_args as get_args # type: ignore[no-redef] + from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_union as is_union # type: ignore[no-redef] + +from .datetime_utils import serialize_datetime +from typing_extensions import TypeAlias + +T = TypeVar("T") +Model = TypeVar("Model", bound=pydantic.BaseModel) + + +def parse_obj_as(type_: Type[T], object_: Any) -> T: + if IS_PYDANTIC_V2: + adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined] + return adapter.validate_python(object_) + return pydantic.parse_obj_as(type_, object_) + + +def to_jsonable_with_fallback(obj: Any, fallback_serializer: Callable[[Any], Any]) -> Any: + if IS_PYDANTIC_V2: + from pydantic_core import to_jsonable_python + + return to_jsonable_python(obj, fallback=fallback_serializer) + return fallback_serializer(obj) + + +class UniversalBaseModel(pydantic.BaseModel): + class Config: + populate_by_name = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} + # Allow fields beginning with `model_` to be used in the model + protected_namespaces = () + + def json(self, **kwargs: Any) -> str: + kwargs_with_defaults = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + if IS_PYDANTIC_V2: + return super().model_dump_json(**kwargs_with_defaults) # type: ignore[misc] + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: Any) -> Dict[str, Any]: + """ + Override the default dict method to `exclude_unset` by default. This function patches + `exclude_unset` to work include fields within non-None default values. + """ + # Note: the logic here is multiplexed given the levers exposed in Pydantic V1 vs V2 + # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. + # + # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models + # that we have less control over, and this is less intrusive than custom serializers for now. + if IS_PYDANTIC_V2: + kwargs_with_defaults_exclude_unset = { + **kwargs, + "by_alias": True, + "exclude_unset": True, + "exclude_none": False, + } + kwargs_with_defaults_exclude_none = { + **kwargs, + "by_alias": True, + "exclude_none": True, + "exclude_unset": False, + } + return deep_union_pydantic_dicts( + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore[misc] + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore[misc] + ) + + _fields_set = self.__fields_set__.copy() + + fields = _get_model_fields(self.__class__) + for name, field in fields.items(): + if name not in _fields_set: + default = _get_field_default(field) + + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default is not None or ("exclude_unset" in kwargs and not kwargs["exclude_unset"]): + _fields_set.add(name) + + if default is not None: + self.__fields_set__.add(name) + + kwargs_with_defaults_exclude_unset_include_fields = { + "by_alias": True, + "exclude_unset": True, + "include": _fields_set, + **kwargs, + } + + return super().dict(**kwargs_with_defaults_exclude_unset_include_fields) + + +def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]: + converted_list: List[Any] = [] + for i, item in enumerate(source): + destination_value = destination[i] + if isinstance(item, dict): + converted_list.append(deep_union_pydantic_dicts(item, destination_value)) + elif isinstance(item, list): + converted_list.append(_union_list_of_pydantic_dicts(item, destination_value)) + else: + converted_list.append(item) + return converted_list + + +def deep_union_pydantic_dicts(source: Dict[str, Any], destination: Dict[str, Any]) -> Dict[str, Any]: + for key, value in source.items(): + node = destination.setdefault(key, {}) + if isinstance(value, dict): + deep_union_pydantic_dicts(value, node) + # Note: we do not do this same processing for sets given we do not have sets of models + # and given the sets are unordered, the processing of the set and matching objects would + # be non-trivial. + elif isinstance(value, list): + destination[key] = _union_list_of_pydantic_dicts(value, node) + else: + destination[key] = value + + return destination + + +if IS_PYDANTIC_V2: + + class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore[name-defined, type-arg] + pass + + UniversalRootModel: TypeAlias = V2RootModel +else: + UniversalRootModel: TypeAlias = UniversalBaseModel # type: ignore[misc, no-redef] + + +def encode_by_type(o: Any) -> Any: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple) + for type_, encoder in encoders_by_type.items(): + encoders_by_class_tuples[encoder] += (type_,) + + if type(o) in encoders_by_type: + return encoders_by_type[type(o)](o) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(o, classes_tuple): + return encoder(o) + + +def update_forward_refs(model: Type["Model"], **localns: Any) -> None: + if IS_PYDANTIC_V2: + model.model_rebuild(raise_errors=False) # type: ignore[attr-defined] + else: + model.update_forward_refs(**localns) + + +# Mirrors Pydantic's internal typing +AnyCallable = Callable[..., Any] + + +def universal_root_validator(pre: bool = False) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload] + + return decorator + + +def universal_field_validator(field_name: str, pre: bool = False) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.field_validator(field_name, mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.validator(field_name, pre=pre)(func)) + + return decorator + + +PydanticField = Union[ModelField, pydantic.fields.FieldInfo] + + +def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: + if IS_PYDANTIC_V2: + return cast(Mapping[str, PydanticField], model.model_fields) # type: ignore[attr-defined] + return cast(Mapping[str, PydanticField], model.__fields__) + + +def _get_field_default(field: PydanticField) -> Any: + try: + value = field.get_default() # type: ignore[union-attr] + except: + value = field.default + if IS_PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/route_args.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/route_args.py new file mode 100644 index 000000000000..dd09f7bbf3eb --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/route_args.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import inspect +import typing + +import typing_extensions + +T = typing.TypeVar("T", bound=typing.Callable[..., typing.Any]) + +FERN_CONFIG_KEY = "__fern" + + +class RouteArgs(typing_extensions.TypedDict): + openapi_extra: typing.Optional[typing.Dict[str, typing.Any]] + tags: typing.Optional[typing.List[typing.Union[str, enum.Enum]]] + include_in_schema: bool + + +DEFAULT_ROUTE_ARGS = RouteArgs(openapi_extra=None, tags=None, include_in_schema=True) + + +def get_route_args(endpoint_function: typing.Callable[..., typing.Any], *, default_tag: str) -> RouteArgs: + unwrapped = inspect.unwrap(endpoint_function, stop=(lambda f: hasattr(f, FERN_CONFIG_KEY))) + route_args = typing.cast(RouteArgs, getattr(unwrapped, FERN_CONFIG_KEY, DEFAULT_ROUTE_ARGS)) + if route_args["tags"] is None: + return RouteArgs( + openapi_extra=route_args["openapi_extra"], + tags=[default_tag], + include_in_schema=route_args["include_in_schema"], + ) + return route_args + + +def route_args( + openapi_extra: typing.Optional[typing.Dict[str, typing.Any]] = None, + tags: typing.Optional[typing.List[typing.Union[str, enum.Enum]]] = None, + include_in_schema: bool = True, +) -> typing.Callable[[T], T]: + """ + this decorator allows you to forward certain args to the FastAPI route decorator. + + usage: + @route_args(openapi_extra=...) + def your_endpoint_method(... + + currently supported args: + - openapi_extra + - tags + + if there's another FastAPI route arg you need to pass through, please + contact the Fern team! + """ + + def decorator(endpoint_function: T) -> T: + setattr( + endpoint_function, + FERN_CONFIG_KEY, + RouteArgs( + openapi_extra=openapi_extra, + tags=tags, + include_in_schema=include_in_schema, + ), + ) + return endpoint_function + + return decorator diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/__init__.py new file mode 100644 index 000000000000..1b689959219a --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .bearer import BearerToken + +__all__ = ["BearerToken"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/bearer.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/bearer.py new file mode 100644 index 000000000000..6d9f854d8b67 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/security/bearer.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +import fastapi +from ..exceptions import UnauthorizedException + + +class BearerToken: + def __init__(self, token: str): + self.token = token + + +def HTTPBearer(request: fastapi.requests.Request) -> BearerToken: + authorization_header_value = request.headers.get("Authorization") + if not authorization_header_value: + raise UnauthorizedException("Missing Authorization header") + scheme, _, token = authorization_header_value.partition(" ") + if scheme.lower() != "bearer": + raise UnauthorizedException("Authorization header scheme is not bearer") + if not token: + raise UnauthorizedException("Authorization header is missing a token") + return BearerToken(token) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/core/serialization.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/serialization.py new file mode 100644 index 000000000000..c36e865cc729 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/core/serialization.py @@ -0,0 +1,276 @@ +# This file was auto-generated by Fern from our API Definition. + +import collections +import inspect +import typing + +import pydantic +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, + direction: typing.Literal["read", "write"], +) -> 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) + # Pydantic models + if ( + inspect.isclass(clean_type) + and issubclass(clean_type, pydantic.BaseModel) + and isinstance(object_, typing.Mapping) + ): + return _convert_mapping(object_, clean_type, direction) + # TypedDicts + if typing_extensions.is_typeddict(clean_type) and isinstance(object_, typing.Mapping): + return _convert_mapping(object_, clean_type, direction) + + if ( + typing_extensions.get_origin(clean_type) == typing.Dict + or typing_extensions.get_origin(clean_type) == dict + or clean_type == typing.Dict + ) and isinstance(object_, typing.Dict): + key_type = typing_extensions.get_args(clean_type)[0] + value_type = typing_extensions.get_args(clean_type)[1] + + return { + key: convert_and_respect_annotation_metadata( + object_=value, + annotation=annotation, + inner_type=value_type, + direction=direction, + ) + for key, value in object_.items() + } + + # If you're iterating on a string, do not bother to coerce it to a sequence. + if not isinstance(object_, str): + if ( + 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): + inner_type = typing_extensions.get_args(clean_type)[0] + return { + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + } + elif ( + ( + 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.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, + direction=direction, + ) + 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, + direction=direction, + ) + 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_mapping( + object_: typing.Mapping[str, object], + expected_type: typing.Any, + direction: typing.Literal["read", "write"], +) -> typing.Mapping[str, object]: + converted_object: typing.Dict[str, object] = {} + try: + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + except NameError: + # The TypedDict contains a circular reference, so + # we use the __annotations__ attribute directly. + annotations = getattr(expected_type, "__annotations__", {}) + aliases_to_field_names = _get_alias_to_field_name(annotations) + for key, value in object_.items(): + if direction == "read" and key in aliases_to_field_names: + dealiased_key = aliases_to_field_names.get(key) + if dealiased_key is not None: + type_ = annotations.get(dealiased_key) + else: + type_ = annotations.get(key) + # Note you can't get the annotation by the field name if you're in read mode, so you must check the aliases map + # + # So this is effectively saying if we're in write mode, and we don't have a type, or if we're in read mode and we don't have an alias + # then we can just pass the value through as is + if type_ is None: + converted_object[key] = value + elif direction == "read" and key not in aliases_to_field_names: + converted_object[key] = convert_and_respect_annotation_metadata( + object_=value, annotation=type_, direction=direction + ) + else: + converted_object[_alias_key(key, type_, direction, aliases_to_field_names)] = ( + convert_and_respect_annotation_metadata(object_=value, annotation=type_, direction=direction) + ) + 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 get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_alias_to_field_name(annotations) + + +def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_field_to_alias_name(annotations) + + +def _get_alias_to_field_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[maybe_alias] = field + return aliases + + +def _get_field_to_alias_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[field] = maybe_alias + return aliases + + +def _get_alias_from_type(type_: typing.Any) -> typing.Optional[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 None + + +def _alias_key( + key: str, + type_: typing.Any, + direction: typing.Literal["read", "write"], + aliases_to_field_names: typing.Dict[str, str], +) -> str: + if direction == "read": + return aliases_to_field_names.get(key, key) + return _get_alias_from_type(type_=type_) or key diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/register.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/register.py new file mode 100644 index 000000000000..7957be8c5ee5 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/register.py @@ -0,0 +1,82 @@ +# This file was auto-generated by Fern from our API Definition. + +import glob +import importlib +import os +import types +import typing + +import fastapi +import starlette.exceptions +from .core.abstract_fern_service import AbstractFernService +from .core.exceptions import default_exception_handler, fern_http_exception_handler, http_exception_handler +from .core.exceptions.fern_http_exception import FernHTTPException +from .resources.endpoints.resources.container.service.service import AbstractEndpointsContainerService +from .resources.endpoints.resources.content_type.service.service import AbstractEndpointsContentTypeService +from .resources.endpoints.resources.enum.service.service import AbstractEndpointsEnumService +from .resources.endpoints.resources.http_methods.service.service import AbstractEndpointsHttpMethodsService +from .resources.endpoints.resources.object.service.service import AbstractEndpointsObjectService +from .resources.endpoints.resources.params.service.service import AbstractEndpointsParamsService +from .resources.endpoints.resources.primitive.service.service import AbstractEndpointsPrimitiveService +from .resources.endpoints.resources.put.service.service import AbstractEndpointsPutService +from .resources.endpoints.resources.union.service.service import AbstractEndpointsUnionService +from .resources.endpoints.resources.urls.service.service import AbstractEndpointsUrlsService +from .resources.inlined_requests.service.service import AbstractInlinedRequestsService +from .resources.no_auth.service.service import AbstractNoAuthService +from .resources.no_req_body.service.service import AbstractNoReqBodyService +from .resources.req_with_headers.service.service import AbstractReqWithHeadersService +from fastapi import params + + +def register( + _app: fastapi.FastAPI, + *, + endpoints_container: AbstractEndpointsContainerService, + endpoints_content_type: AbstractEndpointsContentTypeService, + endpoints_enum: AbstractEndpointsEnumService, + endpoints_http_methods: AbstractEndpointsHttpMethodsService, + endpoints_object: AbstractEndpointsObjectService, + endpoints_params: AbstractEndpointsParamsService, + endpoints_primitive: AbstractEndpointsPrimitiveService, + endpoints_put: AbstractEndpointsPutService, + endpoints_union: AbstractEndpointsUnionService, + endpoints_urls: AbstractEndpointsUrlsService, + inlined_requests: AbstractInlinedRequestsService, + no_auth: AbstractNoAuthService, + no_req_body: AbstractNoReqBodyService, + req_with_headers: AbstractReqWithHeadersService, + dependencies: typing.Optional[typing.Sequence[params.Depends]] = None, +) -> None: + _app.include_router(__register_service(endpoints_container), dependencies=dependencies) + _app.include_router(__register_service(endpoints_content_type), dependencies=dependencies) + _app.include_router(__register_service(endpoints_enum), dependencies=dependencies) + _app.include_router(__register_service(endpoints_http_methods), dependencies=dependencies) + _app.include_router(__register_service(endpoints_object), dependencies=dependencies) + _app.include_router(__register_service(endpoints_params), dependencies=dependencies) + _app.include_router(__register_service(endpoints_primitive), dependencies=dependencies) + _app.include_router(__register_service(endpoints_put), dependencies=dependencies) + _app.include_router(__register_service(endpoints_union), dependencies=dependencies) + _app.include_router(__register_service(endpoints_urls), dependencies=dependencies) + _app.include_router(__register_service(inlined_requests), dependencies=dependencies) + _app.include_router(__register_service(no_auth), dependencies=dependencies) + _app.include_router(__register_service(no_req_body), dependencies=dependencies) + _app.include_router(__register_service(req_with_headers), dependencies=dependencies) + + _app.add_exception_handler(FernHTTPException, fern_http_exception_handler) # type: ignore + _app.add_exception_handler(starlette.exceptions.HTTPException, http_exception_handler) # type: ignore + _app.add_exception_handler(Exception, default_exception_handler) # type: ignore + + +def __register_service(service: AbstractFernService) -> fastapi.APIRouter: + router = fastapi.APIRouter() + type(service)._init_fern(router) + return router + + +def register_validators(module: types.ModuleType) -> None: + validators_directory: str = os.path.dirname(module.__file__) # type: ignore + for path in glob.glob(os.path.join(validators_directory, "**/*.py"), recursive=True): + if os.path.isfile(path): + relative_path = os.path.relpath(path, start=validators_directory) + module_path = ".".join([module.__name__] + relative_path[:-3].split("/")) + importlib.import_module(module_path) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/__init__.py new file mode 100644 index 000000000000..599fd5dbbb14 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/__init__.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from . import endpoints, general_errors, inlined_requests, types +from .general_errors import BadObjectRequestInfo, BadRequestBody +from .inlined_requests import PostWithObjectBody + +__all__ = [ + "BadObjectRequestInfo", + "BadRequestBody", + "PostWithObjectBody", + "endpoints", + "general_errors", + "inlined_requests", + "types", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/__init__.py new file mode 100644 index 000000000000..0cdf30b40cce --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .resources import Error, ErrorCategory, ErrorCode, PutResponse, put + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse", "put"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/__init__.py new file mode 100644 index 000000000000..fc90187d8ac0 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from . import put +from .put import Error, ErrorCategory, ErrorCode, PutResponse + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse", "put"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/__init__.py new file mode 100644 index 000000000000..ad708e427173 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsContainerService + +__all__ = ["AbstractEndpointsContainerService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/service.py new file mode 100644 index 000000000000..d76b4fb6eff1 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/container/service/service.py @@ -0,0 +1,350 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.object.types.object_with_required_field import ObjectWithRequiredField + + +class AbstractEndpointsContainerService(AbstractFernService): + """ + AbstractEndpointsContainerService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_and_return_list_of_primitives(self, *, body: typing.List[str], auth: ApiAuth) -> typing.Sequence[str]: ... + + @abc.abstractmethod + def get_and_return_list_of_objects( + self, *, body: typing.List[ObjectWithRequiredField], auth: ApiAuth + ) -> typing.Sequence[ObjectWithRequiredField]: ... + + @abc.abstractmethod + def get_and_return_set_of_primitives(self, *, body: typing.Set[str], auth: ApiAuth) -> typing.Set[str]: ... + + @abc.abstractmethod + def get_and_return_set_of_objects( + self, *, body: typing.List[ObjectWithRequiredField], auth: ApiAuth + ) -> typing.Sequence[ObjectWithRequiredField]: ... + + @abc.abstractmethod + def get_and_return_map_prim_to_prim( + self, *, body: typing.Dict[str, str], auth: ApiAuth + ) -> typing.Dict[str, str]: ... + + @abc.abstractmethod + def get_and_return_map_of_prim_to_object( + self, *, body: typing.Dict[str, ObjectWithRequiredField], auth: ApiAuth + ) -> typing.Dict[str, ObjectWithRequiredField]: ... + + @abc.abstractmethod + def get_and_return_optional( + self, *, body: typing.Optional[ObjectWithRequiredField] = None, auth: ApiAuth + ) -> typing.Optional[ObjectWithRequiredField]: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_and_return_list_of_primitives(router=router) + cls.__init_get_and_return_list_of_objects(router=router) + cls.__init_get_and_return_set_of_primitives(router=router) + cls.__init_get_and_return_set_of_objects(router=router) + cls.__init_get_and_return_map_prim_to_prim(router=router) + cls.__init_get_and_return_map_of_prim_to_object(router=router) + cls.__init_get_and_return_optional(router=router) + + @classmethod + def __init_get_and_return_list_of_primitives(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_list_of_primitives) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_list_of_primitives, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_list_of_primitives) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Sequence[str]: + try: + return cls.get_and_return_list_of_primitives(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_list_of_primitives' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_list_of_primitives.__globals__) + + router.post( + path="/container/list-of-primitives", + response_model=typing.Sequence[str], + description=AbstractEndpointsContainerService.get_and_return_list_of_primitives.__doc__, + **get_route_args(cls.get_and_return_list_of_primitives, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_list_of_objects(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_list_of_objects) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_list_of_objects, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_list_of_objects) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Sequence[ObjectWithRequiredField]: + try: + return cls.get_and_return_list_of_objects(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_list_of_objects' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_list_of_objects.__globals__) + + router.post( + path="/container/list-of-objects", + response_model=typing.Sequence[ObjectWithRequiredField], + description=AbstractEndpointsContainerService.get_and_return_list_of_objects.__doc__, + **get_route_args(cls.get_and_return_list_of_objects, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_set_of_primitives(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_set_of_primitives) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_set_of_primitives, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_set_of_primitives) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Set[str]: + try: + return cls.get_and_return_set_of_primitives(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_set_of_primitives' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_set_of_primitives.__globals__) + + router.post( + path="/container/set-of-primitives", + response_model=typing.Set[str], + description=AbstractEndpointsContainerService.get_and_return_set_of_primitives.__doc__, + **get_route_args(cls.get_and_return_set_of_primitives, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_set_of_objects(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_set_of_objects) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_set_of_objects, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_set_of_objects) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Sequence[ObjectWithRequiredField]: + try: + return cls.get_and_return_set_of_objects(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_set_of_objects' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_set_of_objects.__globals__) + + router.post( + path="/container/set-of-objects", + response_model=typing.Sequence[ObjectWithRequiredField], + description=AbstractEndpointsContainerService.get_and_return_set_of_objects.__doc__, + **get_route_args(cls.get_and_return_set_of_objects, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_map_prim_to_prim(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_map_prim_to_prim) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_map_prim_to_prim, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_map_prim_to_prim) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Dict[str, str]: + try: + return cls.get_and_return_map_prim_to_prim(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_map_prim_to_prim' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_map_prim_to_prim.__globals__) + + router.post( + path="/container/map-prim-to-prim", + response_model=typing.Dict[str, str], + description=AbstractEndpointsContainerService.get_and_return_map_prim_to_prim.__doc__, + **get_route_args(cls.get_and_return_map_prim_to_prim, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_map_of_prim_to_object(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_map_of_prim_to_object) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_map_of_prim_to_object, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_map_of_prim_to_object) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Dict[str, ObjectWithRequiredField]: + try: + return cls.get_and_return_map_of_prim_to_object(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_map_of_prim_to_object' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_map_of_prim_to_object.__globals__) + + router.post( + path="/container/map-prim-to-object", + response_model=typing.Dict[str, ObjectWithRequiredField], + description=AbstractEndpointsContainerService.get_and_return_map_of_prim_to_object.__doc__, + **get_route_args(cls.get_and_return_map_of_prim_to_object, default_tag="endpoints.container"), + )(wrapper) + + @classmethod + def __init_get_and_return_optional(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_optional) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_optional, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_optional) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Optional[ObjectWithRequiredField]: + try: + return cls.get_and_return_optional(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_optional' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_optional.__globals__) + + router.post( + path="/container/opt-objects", + response_model=typing.Optional[ObjectWithRequiredField], + description=AbstractEndpointsContainerService.get_and_return_optional.__doc__, + **get_route_args(cls.get_and_return_optional, default_tag="endpoints.container"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/__init__.py new file mode 100644 index 000000000000..6fa1200f67b2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsContentTypeService + +__all__ = ["AbstractEndpointsContentTypeService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/service.py new file mode 100644 index 000000000000..9e9f4977b032 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/content_type/service/service.py @@ -0,0 +1,123 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +import starlette +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.object.types.object_with_optional_field import ObjectWithOptionalField + + +class AbstractEndpointsContentTypeService(AbstractFernService): + """ + AbstractEndpointsContentTypeService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def post_json_patch_content_type(self, *, body: ObjectWithOptionalField, auth: ApiAuth) -> None: ... + + @abc.abstractmethod + def post_json_patch_content_with_charset_type(self, *, body: ObjectWithOptionalField, auth: ApiAuth) -> None: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_post_json_patch_content_type(router=router) + cls.__init_post_json_patch_content_with_charset_type(router=router) + + @classmethod + def __init_post_json_patch_content_type(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.post_json_patch_content_type) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.post_json_patch_content_type, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.post_json_patch_content_type) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.post_json_patch_content_type(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'post_json_patch_content_type' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.post_json_patch_content_type.__globals__) + + router.post( + path="/foo/bar", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsContentTypeService.post_json_patch_content_type.__doc__, + **get_route_args(cls.post_json_patch_content_type, default_tag="endpoints.content_type"), + )(wrapper) + + @classmethod + def __init_post_json_patch_content_with_charset_type(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.post_json_patch_content_with_charset_type) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.post_json_patch_content_with_charset_type, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.post_json_patch_content_with_charset_type) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.post_json_patch_content_with_charset_type(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'post_json_patch_content_with_charset_type' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.post_json_patch_content_with_charset_type.__globals__) + + router.post( + path="/foo/baz", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsContentTypeService.post_json_patch_content_with_charset_type.__doc__, + **get_route_args(cls.post_json_patch_content_with_charset_type, default_tag="endpoints.content_type"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/__init__.py new file mode 100644 index 000000000000..ba3e3a0544a5 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsEnumService + +__all__ = ["AbstractEndpointsEnumService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/service.py new file mode 100644 index 000000000000..44d5b8f1d299 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/enum/service/service.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.enum.types.weather_report import WeatherReport + + +class AbstractEndpointsEnumService(AbstractFernService): + """ + AbstractEndpointsEnumService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_and_return_enum(self, *, body: WeatherReport, auth: ApiAuth) -> WeatherReport: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_and_return_enum(router=router) + + @classmethod + def __init_get_and_return_enum(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_enum) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_enum, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_enum) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> WeatherReport: + try: + return cls.get_and_return_enum(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_enum' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_enum.__globals__) + + router.post( + path="/enum", + response_model=WeatherReport, + description=AbstractEndpointsEnumService.get_and_return_enum.__doc__, + **get_route_args(cls.get_and_return_enum, default_tag="endpoints.enum"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/__init__.py new file mode 100644 index 000000000000..dd17e9e13130 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsHttpMethodsService + +__all__ = ["AbstractEndpointsHttpMethodsService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/service.py new file mode 100644 index 000000000000..628f5ca37b79 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/http_methods/service/service.py @@ -0,0 +1,247 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.object.types.object_with_optional_field import ObjectWithOptionalField +from .....types.resources.object.types.object_with_required_field import ObjectWithRequiredField + + +class AbstractEndpointsHttpMethodsService(AbstractFernService): + """ + AbstractEndpointsHttpMethodsService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def test_get(self, *, id: str, auth: ApiAuth) -> str: ... + + @abc.abstractmethod + def test_post(self, *, body: ObjectWithRequiredField, auth: ApiAuth) -> ObjectWithOptionalField: ... + + @abc.abstractmethod + def test_put(self, *, body: ObjectWithRequiredField, id: str, auth: ApiAuth) -> ObjectWithOptionalField: ... + + @abc.abstractmethod + def test_patch(self, *, body: ObjectWithOptionalField, id: str, auth: ApiAuth) -> ObjectWithOptionalField: ... + + @abc.abstractmethod + def test_delete(self, *, id: str, auth: ApiAuth) -> bool: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_test_get(router=router) + cls.__init_test_post(router=router) + cls.__init_test_put(router=router) + cls.__init_test_patch(router=router) + cls.__init_test_delete(router=router) + + @classmethod + def __init_test_get(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.test_get) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "id": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.test_get, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.test_get) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.test_get(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'test_get' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.test_get.__globals__) + + router.get( + path="/http-methods/{id}", + response_model=str, + description=AbstractEndpointsHttpMethodsService.test_get.__doc__, + **get_route_args(cls.test_get, default_tag="endpoints.http_methods"), + )(wrapper) + + @classmethod + def __init_test_post(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.test_post) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.test_post, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.test_post) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.test_post(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'test_post' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.test_post.__globals__) + + router.post( + path="/http-methods", + response_model=ObjectWithOptionalField, + description=AbstractEndpointsHttpMethodsService.test_post.__doc__, + **get_route_args(cls.test_post, default_tag="endpoints.http_methods"), + )(wrapper) + + @classmethod + def __init_test_put(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.test_put) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "id": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.test_put, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.test_put) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.test_put(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'test_put' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.test_put.__globals__) + + router.put( + path="/http-methods/{id}", + response_model=ObjectWithOptionalField, + description=AbstractEndpointsHttpMethodsService.test_put.__doc__, + **get_route_args(cls.test_put, default_tag="endpoints.http_methods"), + )(wrapper) + + @classmethod + def __init_test_patch(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.test_patch) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "id": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.test_patch, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.test_patch) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.test_patch(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'test_patch' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.test_patch.__globals__) + + router.patch( + path="/http-methods/{id}", + response_model=ObjectWithOptionalField, + description=AbstractEndpointsHttpMethodsService.test_patch.__doc__, + **get_route_args(cls.test_patch, default_tag="endpoints.http_methods"), + )(wrapper) + + @classmethod + def __init_test_delete(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.test_delete) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "id": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.test_delete, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.test_delete) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> bool: + try: + return cls.test_delete(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'test_delete' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.test_delete.__globals__) + + router.delete( + path="/http-methods/{id}", + response_model=bool, + description=AbstractEndpointsHttpMethodsService.test_delete.__doc__, + **get_route_args(cls.test_delete, default_tag="endpoints.http_methods"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/__init__.py new file mode 100644 index 000000000000..a8eadd46b752 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsObjectService + +__all__ = ["AbstractEndpointsObjectService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/service.py new file mode 100644 index 000000000000..c99b6ef96628 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/object/service/service.py @@ -0,0 +1,322 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.object.types.nested_object_with_optional_field import NestedObjectWithOptionalField +from .....types.resources.object.types.nested_object_with_required_field import NestedObjectWithRequiredField +from .....types.resources.object.types.object_with_map_of_map import ObjectWithMapOfMap +from .....types.resources.object.types.object_with_optional_field import ObjectWithOptionalField +from .....types.resources.object.types.object_with_required_field import ObjectWithRequiredField + + +class AbstractEndpointsObjectService(AbstractFernService): + """ + AbstractEndpointsObjectService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_and_return_with_optional_field( + self, *, body: ObjectWithOptionalField, auth: ApiAuth + ) -> ObjectWithOptionalField: ... + + @abc.abstractmethod + def get_and_return_with_required_field( + self, *, body: ObjectWithRequiredField, auth: ApiAuth + ) -> ObjectWithRequiredField: ... + + @abc.abstractmethod + def get_and_return_with_map_of_map(self, *, body: ObjectWithMapOfMap, auth: ApiAuth) -> ObjectWithMapOfMap: ... + + @abc.abstractmethod + def get_and_return_nested_with_optional_field( + self, *, body: NestedObjectWithOptionalField, auth: ApiAuth + ) -> NestedObjectWithOptionalField: ... + + @abc.abstractmethod + def get_and_return_nested_with_required_field( + self, *, body: NestedObjectWithRequiredField, string: str, auth: ApiAuth + ) -> NestedObjectWithRequiredField: ... + + @abc.abstractmethod + def get_and_return_nested_with_required_field_as_list( + self, *, body: typing.List[NestedObjectWithRequiredField], auth: ApiAuth + ) -> NestedObjectWithRequiredField: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_and_return_with_optional_field(router=router) + cls.__init_get_and_return_with_required_field(router=router) + cls.__init_get_and_return_with_map_of_map(router=router) + cls.__init_get_and_return_nested_with_optional_field(router=router) + cls.__init_get_and_return_nested_with_required_field(router=router) + cls.__init_get_and_return_nested_with_required_field_as_list(router=router) + + @classmethod + def __init_get_and_return_with_optional_field(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_with_optional_field) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_with_optional_field, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_with_optional_field) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.get_and_return_with_optional_field(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_with_optional_field' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_with_optional_field.__globals__) + + router.post( + path="/object/get-and-return-with-optional-field", + response_model=ObjectWithOptionalField, + description=AbstractEndpointsObjectService.get_and_return_with_optional_field.__doc__, + **get_route_args(cls.get_and_return_with_optional_field, default_tag="endpoints.object"), + )(wrapper) + + @classmethod + def __init_get_and_return_with_required_field(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_with_required_field) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_with_required_field, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_with_required_field) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithRequiredField: + try: + return cls.get_and_return_with_required_field(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_with_required_field' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_with_required_field.__globals__) + + router.post( + path="/object/get-and-return-with-required-field", + response_model=ObjectWithRequiredField, + description=AbstractEndpointsObjectService.get_and_return_with_required_field.__doc__, + **get_route_args(cls.get_and_return_with_required_field, default_tag="endpoints.object"), + )(wrapper) + + @classmethod + def __init_get_and_return_with_map_of_map(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_with_map_of_map) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_with_map_of_map, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_and_return_with_map_of_map) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithMapOfMap: + try: + return cls.get_and_return_with_map_of_map(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_with_map_of_map' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_with_map_of_map.__globals__) + + router.post( + path="/object/get-and-return-with-map-of-map", + response_model=ObjectWithMapOfMap, + description=AbstractEndpointsObjectService.get_and_return_with_map_of_map.__doc__, + **get_route_args(cls.get_and_return_with_map_of_map, default_tag="endpoints.object"), + )(wrapper) + + @classmethod + def __init_get_and_return_nested_with_optional_field(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_nested_with_optional_field) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_nested_with_optional_field, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_nested_with_optional_field) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> NestedObjectWithOptionalField: + try: + return cls.get_and_return_nested_with_optional_field(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_nested_with_optional_field' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_nested_with_optional_field.__globals__) + + router.post( + path="/object/get-and-return-nested-with-optional-field", + response_model=NestedObjectWithOptionalField, + description=AbstractEndpointsObjectService.get_and_return_nested_with_optional_field.__doc__, + **get_route_args(cls.get_and_return_nested_with_optional_field, default_tag="endpoints.object"), + )(wrapper) + + @classmethod + def __init_get_and_return_nested_with_required_field(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_nested_with_required_field) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "string": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_nested_with_required_field, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_nested_with_required_field) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> NestedObjectWithRequiredField: + try: + return cls.get_and_return_nested_with_required_field(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_nested_with_required_field' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_nested_with_required_field.__globals__) + + router.post( + path="/object/get-and-return-nested-with-required-field/{string}", + response_model=NestedObjectWithRequiredField, + description=AbstractEndpointsObjectService.get_and_return_nested_with_required_field.__doc__, + **get_route_args(cls.get_and_return_nested_with_required_field, default_tag="endpoints.object"), + )(wrapper) + + @classmethod + def __init_get_and_return_nested_with_required_field_as_list(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_nested_with_required_field_as_list) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_and_return_nested_with_required_field_as_list, + "__signature__", + endpoint_function.replace(parameters=new_parameters), + ) + + @functools.wraps(cls.get_and_return_nested_with_required_field_as_list) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> NestedObjectWithRequiredField: + try: + return cls.get_and_return_nested_with_required_field_as_list(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_nested_with_required_field_as_list' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_nested_with_required_field_as_list.__globals__) + + router.post( + path="/object/get-and-return-nested-with-required-field-list", + response_model=NestedObjectWithRequiredField, + description=AbstractEndpointsObjectService.get_and_return_nested_with_required_field_as_list.__doc__, + **get_route_args(cls.get_and_return_nested_with_required_field_as_list, default_tag="endpoints.object"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/__init__.py new file mode 100644 index 000000000000..4bb9de253a19 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsParamsService + +__all__ = ["AbstractEndpointsParamsService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/service.py new file mode 100644 index 000000000000..306b9f3bf394 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/params/service/service.py @@ -0,0 +1,422 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +import starlette +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth + + +class AbstractEndpointsParamsService(AbstractFernService): + """ + AbstractEndpointsParamsService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_with_path(self, *, param: str, auth: ApiAuth) -> str: + """ + GET with path param + """ + ... + + @abc.abstractmethod + def get_with_inline_path(self, *, param: str, auth: ApiAuth) -> str: + """ + GET with path param + """ + ... + + @abc.abstractmethod + def get_with_query(self, *, query: str, number: int, auth: ApiAuth) -> None: + """ + GET with query param + """ + ... + + @abc.abstractmethod + def get_with_allow_multiple_query( + self, *, query: typing.List[str], number: typing.List[int], auth: ApiAuth + ) -> None: + """ + GET with multiple of same query param + """ + ... + + @abc.abstractmethod + def get_with_path_and_query(self, *, param: str, query: str, auth: ApiAuth) -> None: + """ + GET with path and query params + """ + ... + + @abc.abstractmethod + def get_with_inline_path_and_query(self, *, param: str, query: str, auth: ApiAuth) -> None: + """ + GET with path and query params + """ + ... + + @abc.abstractmethod + def modify_with_path(self, *, body: str, param: str, auth: ApiAuth) -> str: + """ + PUT to update with path param + """ + ... + + @abc.abstractmethod + def modify_with_inline_path(self, *, body: str, param: str, auth: ApiAuth) -> str: + """ + PUT to update with path param + """ + ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_with_path(router=router) + cls.__init_get_with_inline_path(router=router) + cls.__init_get_with_query(router=router) + cls.__init_get_with_allow_multiple_query(router=router) + cls.__init_get_with_path_and_query(router=router) + cls.__init_get_with_inline_path_and_query(router=router) + cls.__init_modify_with_path(router=router) + cls.__init_modify_with_inline_path(router=router) + + @classmethod + def __init_get_with_path(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_path) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_path, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_path) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.get_with_path(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_path' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_path.__globals__) + + router.get( + path="/params/path/{param}", + response_model=str, + description=AbstractEndpointsParamsService.get_with_path.__doc__, + **get_route_args(cls.get_with_path, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_get_with_inline_path(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_inline_path) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_inline_path, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_inline_path) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.get_with_inline_path(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_inline_path' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_inline_path.__globals__) + + router.get( + path="/params/path/{param}", + response_model=str, + description=AbstractEndpointsParamsService.get_with_inline_path.__doc__, + **get_route_args(cls.get_with_inline_path, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_get_with_query(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_query) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "query": + new_parameters.append(parameter.replace(default=fastapi.Query(default=...))) + elif parameter_name == "number": + new_parameters.append(parameter.replace(default=fastapi.Query(default=...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_query, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_query) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.get_with_query(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_query' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_query.__globals__) + + router.get( + path="/params", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsParamsService.get_with_query.__doc__, + **get_route_args(cls.get_with_query, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_get_with_allow_multiple_query(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_allow_multiple_query) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "query": + new_parameters.append(parameter.replace(default=fastapi.Query(default=[]))) + elif parameter_name == "number": + new_parameters.append(parameter.replace(default=fastapi.Query(default=[]))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_with_allow_multiple_query, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_with_allow_multiple_query) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.get_with_allow_multiple_query(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_allow_multiple_query' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_allow_multiple_query.__globals__) + + router.get( + path="/params", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsParamsService.get_with_allow_multiple_query.__doc__, + **get_route_args(cls.get_with_allow_multiple_query, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_get_with_path_and_query(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_path_and_query) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "query": + new_parameters.append(parameter.replace(default=fastapi.Query(default=...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_path_and_query, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_path_and_query) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.get_with_path_and_query(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_path_and_query' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_path_and_query.__globals__) + + router.get( + path="/params/path-query/{param}", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsParamsService.get_with_path_and_query.__doc__, + **get_route_args(cls.get_with_path_and_query, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_get_with_inline_path_and_query(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_inline_path_and_query) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "query": + new_parameters.append(parameter.replace(default=fastapi.Query(default=...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr( + cls.get_with_inline_path_and_query, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.get_with_inline_path_and_query) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.get_with_inline_path_and_query(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_inline_path_and_query' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_inline_path_and_query.__globals__) + + router.get( + path="/params/path-query/{param}", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractEndpointsParamsService.get_with_inline_path_and_query.__doc__, + **get_route_args(cls.get_with_inline_path_and_query, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_modify_with_path(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.modify_with_path) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.modify_with_path, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.modify_with_path) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.modify_with_path(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'modify_with_path' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.modify_with_path.__globals__) + + router.put( + path="/params/path/{param}", + response_model=str, + description=AbstractEndpointsParamsService.modify_with_path.__doc__, + **get_route_args(cls.modify_with_path, default_tag="endpoints.params"), + )(wrapper) + + @classmethod + def __init_modify_with_inline_path(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.modify_with_inline_path) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "param": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.modify_with_inline_path, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.modify_with_inline_path) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.modify_with_inline_path(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'modify_with_inline_path' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.modify_with_inline_path.__globals__) + + router.put( + path="/params/path/{param}", + response_model=str, + description=AbstractEndpointsParamsService.modify_with_inline_path.__doc__, + **get_route_args(cls.modify_with_inline_path, default_tag="endpoints.params"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/__init__.py new file mode 100644 index 000000000000..8975e1cea807 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsPrimitiveService + +__all__ = ["AbstractEndpointsPrimitiveService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/service.py new file mode 100644 index 000000000000..deb53c4dcb4d --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/primitive/service/service.py @@ -0,0 +1,411 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import datetime as dt +import functools +import inspect +import logging +import typing +import uuid + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth + + +class AbstractEndpointsPrimitiveService(AbstractFernService): + """ + AbstractEndpointsPrimitiveService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_and_return_string(self, *, body: str, auth: ApiAuth) -> str: ... + + @abc.abstractmethod + def get_and_return_int(self, *, body: int, auth: ApiAuth) -> int: ... + + @abc.abstractmethod + def get_and_return_long(self, *, body: int, auth: ApiAuth) -> int: ... + + @abc.abstractmethod + def get_and_return_double(self, *, body: float, auth: ApiAuth) -> float: ... + + @abc.abstractmethod + def get_and_return_bool(self, *, body: bool, auth: ApiAuth) -> bool: ... + + @abc.abstractmethod + def get_and_return_datetime(self, *, body: dt.datetime, auth: ApiAuth) -> dt.datetime: ... + + @abc.abstractmethod + def get_and_return_date(self, *, body: dt.date, auth: ApiAuth) -> dt.date: ... + + @abc.abstractmethod + def get_and_return_uuid(self, *, body: uuid.UUID, auth: ApiAuth) -> uuid.UUID: ... + + @abc.abstractmethod + def get_and_return_base_64(self, *, body: str, auth: ApiAuth) -> str: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_and_return_string(router=router) + cls.__init_get_and_return_int(router=router) + cls.__init_get_and_return_long(router=router) + cls.__init_get_and_return_double(router=router) + cls.__init_get_and_return_bool(router=router) + cls.__init_get_and_return_datetime(router=router) + cls.__init_get_and_return_date(router=router) + cls.__init_get_and_return_uuid(router=router) + cls.__init_get_and_return_base_64(router=router) + + @classmethod + def __init_get_and_return_string(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_string) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_string, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_string) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.get_and_return_string(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_string' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_string.__globals__) + + router.post( + path="/primitive/string", + response_model=str, + description=AbstractEndpointsPrimitiveService.get_and_return_string.__doc__, + **get_route_args(cls.get_and_return_string, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_int(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_int) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_int, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_int) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> int: + try: + return cls.get_and_return_int(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_int' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_int.__globals__) + + router.post( + path="/primitive/integer", + response_model=int, + description=AbstractEndpointsPrimitiveService.get_and_return_int.__doc__, + **get_route_args(cls.get_and_return_int, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_long(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_long) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_long, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_long) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> int: + try: + return cls.get_and_return_long(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_long' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_long.__globals__) + + router.post( + path="/primitive/long", + response_model=int, + description=AbstractEndpointsPrimitiveService.get_and_return_long.__doc__, + **get_route_args(cls.get_and_return_long, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_double(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_double) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_double, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_double) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> float: + try: + return cls.get_and_return_double(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_double' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_double.__globals__) + + router.post( + path="/primitive/double", + response_model=float, + description=AbstractEndpointsPrimitiveService.get_and_return_double.__doc__, + **get_route_args(cls.get_and_return_double, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_bool(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_bool) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_bool, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_bool) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> bool: + try: + return cls.get_and_return_bool(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_bool' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_bool.__globals__) + + router.post( + path="/primitive/boolean", + response_model=bool, + description=AbstractEndpointsPrimitiveService.get_and_return_bool.__doc__, + **get_route_args(cls.get_and_return_bool, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_datetime(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_datetime) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_datetime, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_datetime) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> dt.datetime: + try: + return cls.get_and_return_datetime(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_datetime' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_datetime.__globals__) + + router.post( + path="/primitive/datetime", + response_model=dt.datetime, + description=AbstractEndpointsPrimitiveService.get_and_return_datetime.__doc__, + **get_route_args(cls.get_and_return_datetime, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_date(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_date) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_date, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_date) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> dt.date: + try: + return cls.get_and_return_date(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_date' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_date.__globals__) + + router.post( + path="/primitive/date", + response_model=dt.date, + description=AbstractEndpointsPrimitiveService.get_and_return_date.__doc__, + **get_route_args(cls.get_and_return_date, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_uuid(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_uuid) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_uuid, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_uuid) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> uuid.UUID: + try: + return cls.get_and_return_uuid(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_uuid' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_uuid.__globals__) + + router.post( + path="/primitive/uuid", + response_model=uuid.UUID, + description=AbstractEndpointsPrimitiveService.get_and_return_uuid.__doc__, + **get_route_args(cls.get_and_return_uuid, default_tag="endpoints.primitive"), + )(wrapper) + + @classmethod + def __init_get_and_return_base_64(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_base_64) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_base_64, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_base_64) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.get_and_return_base_64(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_base_64' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_base_64.__globals__) + + router.post( + path="/primitive/base64", + response_model=str, + description=AbstractEndpointsPrimitiveService.get_and_return_base_64.__doc__, + **get_route_args(cls.get_and_return_base_64, default_tag="endpoints.primitive"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/__init__.py new file mode 100644 index 000000000000..5729e92d5207 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .types import Error, ErrorCategory, ErrorCode, PutResponse + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/__init__.py new file mode 100644 index 000000000000..4af47bcf592a --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsPutService + +__all__ = ["AbstractEndpointsPutService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/service.py new file mode 100644 index 000000000000..0fe3f411803b --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/service/service.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from ..types.put_response import PutResponse + + +class AbstractEndpointsPutService(AbstractFernService): + """ + AbstractEndpointsPutService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def add(self, *, id: str, auth: ApiAuth) -> PutResponse: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_add(router=router) + + @classmethod + def __init_add(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.add) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "id": + new_parameters.append(parameter.replace(default=fastapi.Path(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.add, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.add) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> PutResponse: + try: + return cls.add(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'add' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.add.__globals__) + + router.put( + path="/{id}", + response_model=PutResponse, + description=AbstractEndpointsPutService.add.__doc__, + **get_route_args(cls.add, default_tag="endpoints.put"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/__init__.py new file mode 100644 index 000000000000..2232ae453607 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/__init__.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .error import Error +from .error_category import ErrorCategory +from .error_code import ErrorCode +from .put_response import PutResponse + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error.py new file mode 100644 index 000000000000..983331e9ad76 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ......core.pydantic_utilities import UniversalBaseModel +from .error_category import ErrorCategory +from .error_code import ErrorCode + + +class Error(UniversalBaseModel): + category: ErrorCategory + code: ErrorCode + detail: typing.Optional[str] = None + field: typing.Optional[str] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_category.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_category.py new file mode 100644 index 000000000000..c092d1577551 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_category.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ErrorCategory(str, enum.Enum): + API_ERROR = "API_ERROR" + AUTHENTICATION_ERROR = "AUTHENTICATION_ERROR" + INVALID_REQUEST_ERROR = "INVALID_REQUEST_ERROR" + + def visit( + self, + api_error: typing.Callable[[], T_Result], + authentication_error: typing.Callable[[], T_Result], + invalid_request_error: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ErrorCategory.API_ERROR: + return api_error() + if self is ErrorCategory.AUTHENTICATION_ERROR: + return authentication_error() + if self is ErrorCategory.INVALID_REQUEST_ERROR: + return invalid_request_error() diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_code.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_code.py new file mode 100644 index 000000000000..60b2d7561ed4 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/error_code.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ErrorCode(str, enum.Enum): + INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR" + UNAUTHORIZED = "UNAUTHORIZED" + FORBIDDEN = "FORBIDDEN" + BAD_REQUEST = "BAD_REQUEST" + CONFLICT = "CONFLICT" + GONE = "GONE" + UNPROCESSABLE_ENTITY = "UNPROCESSABLE_ENTITY" + NOT_IMPLEMENTED = "NOT_IMPLEMENTED" + BAD_GATEWAY = "BAD_GATEWAY" + SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE" + UNKNOWN = "Unknown" + + def visit( + self, + internal_server_error: typing.Callable[[], T_Result], + unauthorized: typing.Callable[[], T_Result], + forbidden: typing.Callable[[], T_Result], + bad_request: typing.Callable[[], T_Result], + conflict: typing.Callable[[], T_Result], + gone: typing.Callable[[], T_Result], + unprocessable_entity: typing.Callable[[], T_Result], + not_implemented: typing.Callable[[], T_Result], + bad_gateway: typing.Callable[[], T_Result], + service_unavailable: typing.Callable[[], T_Result], + unknown: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ErrorCode.INTERNAL_SERVER_ERROR: + return internal_server_error() + if self is ErrorCode.UNAUTHORIZED: + return unauthorized() + if self is ErrorCode.FORBIDDEN: + return forbidden() + if self is ErrorCode.BAD_REQUEST: + return bad_request() + if self is ErrorCode.CONFLICT: + return conflict() + if self is ErrorCode.GONE: + return gone() + if self is ErrorCode.UNPROCESSABLE_ENTITY: + return unprocessable_entity() + if self is ErrorCode.NOT_IMPLEMENTED: + return not_implemented() + if self is ErrorCode.BAD_GATEWAY: + return bad_gateway() + if self is ErrorCode.SERVICE_UNAVAILABLE: + return service_unavailable() + if self is ErrorCode.UNKNOWN: + return unknown() diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/put_response.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/put_response.py new file mode 100644 index 000000000000..00615ecf111b --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/put/types/put_response.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ......core.pydantic_utilities import UniversalBaseModel +from .error import Error + + +class PutResponse(UniversalBaseModel): + errors: typing.Optional[typing.List[Error]] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/__init__.py new file mode 100644 index 000000000000..64f5d62ba64e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsUnionService + +__all__ = ["AbstractEndpointsUnionService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/service.py new file mode 100644 index 000000000000..b650034aa193 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/union/service/service.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth +from .....types.resources.union.types.animal import Animal + + +class AbstractEndpointsUnionService(AbstractFernService): + """ + AbstractEndpointsUnionService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_and_return_union(self, *, body: Animal, auth: ApiAuth) -> Animal: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_and_return_union(router=router) + + @classmethod + def __init_get_and_return_union(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_and_return_union) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_and_return_union, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_and_return_union) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> Animal: + try: + return cls.get_and_return_union(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_and_return_union' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_and_return_union.__globals__) + + router.post( + path="/union", + response_model=Animal, + description=AbstractEndpointsUnionService.get_and_return_union.__doc__, + **get_route_args(cls.get_and_return_union, default_tag="endpoints.union"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/__init__.py new file mode 100644 index 000000000000..b7ccf4f1b6c2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractEndpointsUrlsService + +__all__ = ["AbstractEndpointsUrlsService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/service.py new file mode 100644 index 000000000000..06ba2eed9199 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/endpoints/resources/urls/service/service.py @@ -0,0 +1,191 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ......core.abstract_fern_service import AbstractFernService +from ......core.exceptions.fern_http_exception import FernHTTPException +from ......core.route_args import get_route_args +from ......security import ApiAuth, FernAuth + + +class AbstractEndpointsUrlsService(AbstractFernService): + """ + AbstractEndpointsUrlsService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def with_mixed_case(self, *, auth: ApiAuth) -> str: ... + + @abc.abstractmethod + def no_ending_slash(self, *, auth: ApiAuth) -> str: ... + + @abc.abstractmethod + def with_ending_slash(self, *, auth: ApiAuth) -> str: ... + + @abc.abstractmethod + def with_underscores(self, *, auth: ApiAuth) -> str: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_with_mixed_case(router=router) + cls.__init_no_ending_slash(router=router) + cls.__init_with_ending_slash(router=router) + cls.__init_with_underscores(router=router) + + @classmethod + def __init_with_mixed_case(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.with_mixed_case) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.with_mixed_case, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.with_mixed_case) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.with_mixed_case(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'with_mixed_case' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.with_mixed_case.__globals__) + + router.get( + path="/urls/MixedCase", + response_model=str, + description=AbstractEndpointsUrlsService.with_mixed_case.__doc__, + **get_route_args(cls.with_mixed_case, default_tag="endpoints.urls"), + )(wrapper) + + @classmethod + def __init_no_ending_slash(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.no_ending_slash) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.no_ending_slash, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.no_ending_slash) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.no_ending_slash(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'no_ending_slash' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.no_ending_slash.__globals__) + + router.get( + path="/urls/no-ending-slash", + response_model=str, + description=AbstractEndpointsUrlsService.no_ending_slash.__doc__, + **get_route_args(cls.no_ending_slash, default_tag="endpoints.urls"), + )(wrapper) + + @classmethod + def __init_with_ending_slash(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.with_ending_slash) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.with_ending_slash, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.with_ending_slash) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.with_ending_slash(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'with_ending_slash' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.with_ending_slash.__globals__) + + router.get( + path="/urls/with-ending-slash/", + response_model=str, + description=AbstractEndpointsUrlsService.with_ending_slash.__doc__, + **get_route_args(cls.with_ending_slash, default_tag="endpoints.urls"), + )(wrapper) + + @classmethod + def __init_with_underscores(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.with_underscores) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.with_underscores, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.with_underscores) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.with_underscores(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'with_underscores' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.with_underscores.__globals__) + + router.get( + path="/urls/with_underscores", + response_model=str, + description=AbstractEndpointsUrlsService.with_underscores.__doc__, + **get_route_args(cls.with_underscores, default_tag="endpoints.urls"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/__init__.py new file mode 100644 index 000000000000..76f59f37be7b --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .errors import BadRequestBody +from .types import BadObjectRequestInfo + +__all__ = ["BadObjectRequestInfo", "BadRequestBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/__init__.py new file mode 100644 index 000000000000..1432e9f39493 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .bad_request_body import BadRequestBody + +__all__ = ["BadRequestBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/bad_request_body.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/bad_request_body.py new file mode 100644 index 000000000000..9c75b4bcf0c9 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/errors/bad_request_body.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.exceptions.fern_http_exception import FernHTTPException +from ..types.bad_object_request_info import BadObjectRequestInfo + + +class BadRequestBody(FernHTTPException): + def __init__(self, error: BadObjectRequestInfo): + super().__init__(status_code=400, name="BadRequestBody", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/__init__.py new file mode 100644 index 000000000000..9ca329aab9f7 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .bad_object_request_info import BadObjectRequestInfo + +__all__ = ["BadObjectRequestInfo"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/bad_object_request_info.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/bad_object_request_info.py new file mode 100644 index 000000000000..6363683e5152 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/general_errors/types/bad_object_request_info.py @@ -0,0 +1,12 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel + + +class BadObjectRequestInfo(UniversalBaseModel): + message: str + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/__init__.py new file mode 100644 index 000000000000..5ba9bec73a37 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import PostWithObjectBody + +__all__ = ["PostWithObjectBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/__init__.py new file mode 100644 index 000000000000..4191f417a707 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .post_with_object_body import PostWithObjectBody +from .service import AbstractInlinedRequestsService + +__all__ = ["AbstractInlinedRequestsService", "PostWithObjectBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/post_with_object_body.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/post_with_object_body.py new file mode 100644 index 000000000000..3d7dfe85c7e0 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/post_with_object_body.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel +from ...types.resources.object.types.object_with_optional_field import ObjectWithOptionalField + + +class PostWithObjectBody(UniversalBaseModel): + string: str + integer: int + nested_object: typing_extensions.Annotated[ObjectWithOptionalField, pydantic.Field(alias="NestedObject")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/service.py new file mode 100644 index 000000000000..f3a6a7f1402d --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/inlined_requests/service/service.py @@ -0,0 +1,81 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ....core.abstract_fern_service import AbstractFernService +from ....core.exceptions.fern_http_exception import FernHTTPException +from ....core.route_args import get_route_args +from ...general_errors.errors.bad_request_body import BadRequestBody +from ...types.resources.object.types.object_with_optional_field import ObjectWithOptionalField +from .post_with_object_body import PostWithObjectBody + + +class AbstractInlinedRequestsService(AbstractFernService): + """ + AbstractInlinedRequestsService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def post_with_object_bodyand_response(self, *, body: PostWithObjectBody) -> ObjectWithOptionalField: + """ + POST with custom object in request body, response is an object + """ + ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_post_with_object_bodyand_response(router=router) + + @classmethod + def __init_post_with_object_bodyand_response(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.post_with_object_bodyand_response) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + else: + new_parameters.append(parameter) + setattr( + cls.post_with_object_bodyand_response, "__signature__", endpoint_function.replace(parameters=new_parameters) + ) + + @functools.wraps(cls.post_with_object_bodyand_response) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.post_with_object_bodyand_response(*args, **kwargs) + except BadRequestBody as e: + raise e + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'post_with_object_bodyand_response' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.post_with_object_bodyand_response.__globals__) + + router.post( + path="/req-bodies/object", + response_model=ObjectWithOptionalField, + description=AbstractInlinedRequestsService.post_with_object_bodyand_response.__doc__, + **get_route_args(cls.post_with_object_bodyand_response, default_tag="inlined_requests"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/__init__.py new file mode 100644 index 000000000000..8179de0b5a65 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractNoAuthService + +__all__ = ["AbstractNoAuthService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/service.py new file mode 100644 index 000000000000..ebc409508162 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_auth/service/service.py @@ -0,0 +1,77 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ....core.abstract_fern_service import AbstractFernService +from ....core.exceptions.fern_http_exception import FernHTTPException +from ....core.route_args import get_route_args +from ...general_errors.errors.bad_request_body import BadRequestBody + + +class AbstractNoAuthService(AbstractFernService): + """ + AbstractNoAuthService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def post_with_no_auth(self, *, body: typing.Optional[typing.Any] = None) -> bool: + """ + POST request with no auth + """ + ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_post_with_no_auth(router=router) + + @classmethod + def __init_post_with_no_auth(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.post_with_no_auth) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + else: + new_parameters.append(parameter) + setattr(cls.post_with_no_auth, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.post_with_no_auth) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> bool: + try: + return cls.post_with_no_auth(*args, **kwargs) + except BadRequestBody as e: + raise e + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'post_with_no_auth' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.post_with_no_auth.__globals__) + + router.post( + path="/no-auth", + response_model=bool, + description=AbstractNoAuthService.post_with_no_auth.__doc__, + **get_route_args(cls.post_with_no_auth, default_tag="no_auth"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/__init__.py new file mode 100644 index 000000000000..60db4f845cb1 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractNoReqBodyService + +__all__ = ["AbstractNoReqBodyService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/service.py new file mode 100644 index 000000000000..b7bf9ae02556 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/no_req_body/service/service.py @@ -0,0 +1,112 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +from ....core.abstract_fern_service import AbstractFernService +from ....core.exceptions.fern_http_exception import FernHTTPException +from ....core.route_args import get_route_args +from ....security import ApiAuth, FernAuth +from ...types.resources.object.types.object_with_optional_field import ObjectWithOptionalField + + +class AbstractNoReqBodyService(AbstractFernService): + """ + AbstractNoReqBodyService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_with_no_request_body(self, *, auth: ApiAuth) -> ObjectWithOptionalField: ... + + @abc.abstractmethod + def post_with_no_request_body(self, *, auth: ApiAuth) -> str: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_with_no_request_body(router=router) + cls.__init_post_with_no_request_body(router=router) + + @classmethod + def __init_get_with_no_request_body(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_no_request_body) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_no_request_body, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_no_request_body) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> ObjectWithOptionalField: + try: + return cls.get_with_no_request_body(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_no_request_body' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_no_request_body.__globals__) + + router.get( + path="/no-req-body", + response_model=ObjectWithOptionalField, + description=AbstractNoReqBodyService.get_with_no_request_body.__doc__, + **get_route_args(cls.get_with_no_request_body, default_tag="no_req_body"), + )(wrapper) + + @classmethod + def __init_post_with_no_request_body(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.post_with_no_request_body) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.post_with_no_request_body, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.post_with_no_request_body) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.post_with_no_request_body(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'post_with_no_request_body' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.post_with_no_request_body.__globals__) + + router.post( + path="/no-req-body", + response_model=str, + description=AbstractNoReqBodyService.post_with_no_request_body.__doc__, + **get_route_args(cls.post_with_no_request_body, default_tag="no_req_body"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/__init__.py new file mode 100644 index 000000000000..bd6525207420 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .service import AbstractReqWithHeadersService + +__all__ = ["AbstractReqWithHeadersService"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/service.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/service.py new file mode 100644 index 000000000000..10beef54304b --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/req_with_headers/service/service.py @@ -0,0 +1,77 @@ +# This file was auto-generated by Fern from our API Definition. + +import abc +import functools +import inspect +import logging +import typing + +import fastapi +import starlette +from ....core.abstract_fern_service import AbstractFernService +from ....core.exceptions.fern_http_exception import FernHTTPException +from ....core.route_args import get_route_args +from ....security import ApiAuth, FernAuth + + +class AbstractReqWithHeadersService(AbstractFernService): + """ + AbstractReqWithHeadersService is an abstract class containing the methods that you should implement. + + Each method is associated with an API route, which will be registered + with FastAPI when you register your implementation using Fern's register() + function. + """ + + @abc.abstractmethod + def get_with_custom_header(self, *, body: str, x_test_endpoint_header: str, auth: ApiAuth) -> None: ... + + """ + Below are internal methods used by Fern to register your implementation. + You can ignore them. + """ + + @classmethod + def _init_fern(cls, router: fastapi.APIRouter) -> None: + cls.__init_get_with_custom_header(router=router) + + @classmethod + def __init_get_with_custom_header(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_custom_header) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "body": + new_parameters.append(parameter.replace(default=fastapi.Body(...))) + elif parameter_name == "x_test_endpoint_header": + new_parameters.append(parameter.replace(default=fastapi.Header(alias="X-TEST-ENDPOINT-HEADER"))) + elif parameter_name == "auth": + new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_custom_header, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_custom_header) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> None: + try: + return cls.get_with_custom_header(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_custom_header' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_custom_header.__globals__) + + router.post( + path="/test-headers/custom-header", + response_model=None, + status_code=starlette.status.HTTP_204_NO_CONTENT, + description=AbstractReqWithHeadersService.get_with_custom_header.__doc__, + **get_route_args(cls.get_with_custom_header, default_tag="req_with_headers"), + )(wrapper) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/__init__.py new file mode 100644 index 000000000000..b0378d316b6a --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/__init__.py @@ -0,0 +1,53 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .resources import ( + Animal, + Cat, + Dog, + DoubleOptional, + ErrorWithEnumBody, + ErrorWithUnionBody, + NestedObjectWithOptionalField, + NestedObjectWithOptionalFieldError, + NestedObjectWithRequiredField, + NestedObjectWithRequiredFieldError, + ObjectWithDocs, + ObjectWithMapOfMap, + ObjectWithOptionalField, + ObjectWithOptionalFieldError, + ObjectWithRequiredField, + ObjectWithRequiredFieldError, + OptionalAlias, + WeatherReport, + docs, + enum, + object, + union, +) + +__all__ = [ + "Animal", + "Cat", + "Dog", + "DoubleOptional", + "ErrorWithEnumBody", + "ErrorWithUnionBody", + "NestedObjectWithOptionalField", + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredField", + "NestedObjectWithRequiredFieldError", + "ObjectWithDocs", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredField", + "ObjectWithRequiredFieldError", + "OptionalAlias", + "WeatherReport", + "docs", + "enum", + "object", + "union", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/__init__.py new file mode 100644 index 000000000000..41434b76d66a --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/__init__.py @@ -0,0 +1,46 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from . import docs, enum, object, union +from .docs import ObjectWithDocs +from .enum import ErrorWithEnumBody, WeatherReport +from .object import ( + DoubleOptional, + NestedObjectWithOptionalField, + NestedObjectWithOptionalFieldError, + NestedObjectWithRequiredField, + NestedObjectWithRequiredFieldError, + ObjectWithMapOfMap, + ObjectWithOptionalField, + ObjectWithOptionalFieldError, + ObjectWithRequiredField, + ObjectWithRequiredFieldError, + OptionalAlias, +) +from .union import Animal, Cat, Dog, ErrorWithUnionBody + +__all__ = [ + "Animal", + "Cat", + "Dog", + "DoubleOptional", + "ErrorWithEnumBody", + "ErrorWithUnionBody", + "NestedObjectWithOptionalField", + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredField", + "NestedObjectWithRequiredFieldError", + "ObjectWithDocs", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredField", + "ObjectWithRequiredFieldError", + "OptionalAlias", + "WeatherReport", + "docs", + "enum", + "object", + "union", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/__init__.py new file mode 100644 index 000000000000..1721a2e6270e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .types import ObjectWithDocs + +__all__ = ["ObjectWithDocs"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/__init__.py new file mode 100644 index 000000000000..ec7604b678c2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .object_with_docs import ObjectWithDocs + +__all__ = ["ObjectWithDocs"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/object_with_docs.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/object_with_docs.py new file mode 100644 index 000000000000..3dbd4169fc83 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/docs/types/object_with_docs.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ......core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithDocs(UniversalBaseModel): + string: str = pydantic.Field() + """ + Characters that could lead to broken generated SDKs: + + JSDoc (JavaScript/TypeScript): + - @: Used for JSDoc tags + - {: }: Used for type definitions + - <: >: HTML tags + - *: Can interfere with comment blocks + - /**: JSDoc comment start + - ** /: JSDoc comment end + - &: HTML entities + + XMLDoc (C#): + - <: >: XML tags + - &: ': ": <: >: XML special characters + - {: }: Used for interpolated strings + - ///: Comment marker + - /**: Block comment start + - ** /: Block comment end + + Javadoc (Java): + - @: Used for Javadoc tags + - <: >: HTML tags + - &: HTML entities + - *: Can interfere with comment blocks + - /**: Javadoc comment start + - ** /: Javadoc comment end + + Doxygen (C++): + - \: Used for Doxygen commands + - @: Alternative command prefix + - <: >: XML/HTML tags + - &: HTML entities + - /**: C-style comment start + - ** /: C-style comment end + + RDoc (Ruby): + - :: Used in symbol notation + - =: Section markers + - #: Comment marker + - =begin: Block comment start + - =end: Block comment end + - @: Instance variable prefix + - $: Global variable prefix + - %: String literal delimiter + - #{: String interpolation start + - }: String interpolation end + + PHPDoc (PHP): + - @: Used for PHPDoc tags + - {: }: Used for type definitions + - $: Variable prefix + - /**: PHPDoc comment start + - ** /: PHPDoc comment end + - *: Can interfere with comment blocks + - &: HTML entities + """ + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/__init__.py new file mode 100644 index 000000000000..170b3fb58a5e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .errors import ErrorWithEnumBody +from .types import WeatherReport + +__all__ = ["ErrorWithEnumBody", "WeatherReport"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/__init__.py new file mode 100644 index 000000000000..383ccc2db71a --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .error_with_enum_body import ErrorWithEnumBody + +__all__ = ["ErrorWithEnumBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/error_with_enum_body.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/error_with_enum_body.py new file mode 100644 index 000000000000..8b8a0d981c36 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/errors/error_with_enum_body.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.weather_report import WeatherReport + + +class ErrorWithEnumBody(FernHTTPException): + def __init__(self, error: WeatherReport): + super().__init__(status_code=400, name="ErrorWithEnumBody", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/__init__.py new file mode 100644 index 000000000000..928bb349ab59 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .weather_report import WeatherReport + +__all__ = ["WeatherReport"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/weather_report.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/weather_report.py new file mode 100644 index 000000000000..0f2fc3aee2ad --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/enum/types/weather_report.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class WeatherReport(str, enum.Enum): + SUNNY = "SUNNY" + CLOUDY = "CLOUDY" + RAINING = "RAINING" + SNOWING = "SNOWING" + + def visit( + self, + sunny: typing.Callable[[], T_Result], + cloudy: typing.Callable[[], T_Result], + raining: typing.Callable[[], T_Result], + snowing: typing.Callable[[], T_Result], + ) -> T_Result: + if self is WeatherReport.SUNNY: + return sunny() + if self is WeatherReport.CLOUDY: + return cloudy() + if self is WeatherReport.RAINING: + return raining() + if self is WeatherReport.SNOWING: + return snowing() diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/__init__.py new file mode 100644 index 000000000000..4630ec84f83e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/__init__.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .errors import ( + NestedObjectWithOptionalFieldError, + NestedObjectWithRequiredFieldError, + ObjectWithOptionalFieldError, + ObjectWithRequiredFieldError, +) +from .types import ( + DoubleOptional, + NestedObjectWithOptionalField, + NestedObjectWithRequiredField, + ObjectWithMapOfMap, + ObjectWithOptionalField, + ObjectWithRequiredField, + OptionalAlias, +) + +__all__ = [ + "DoubleOptional", + "NestedObjectWithOptionalField", + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredField", + "NestedObjectWithRequiredFieldError", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredField", + "ObjectWithRequiredFieldError", + "OptionalAlias", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/__init__.py new file mode 100644 index 000000000000..fd6e91037909 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/__init__.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .nested_object_with_optional_field_error import NestedObjectWithOptionalFieldError +from .nested_object_with_required_field_error import NestedObjectWithRequiredFieldError +from .object_with_optional_field_error import ObjectWithOptionalFieldError +from .object_with_required_field_error import ObjectWithRequiredFieldError + +__all__ = [ + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredFieldError", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredFieldError", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_optional_field_error.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_optional_field_error.py new file mode 100644 index 000000000000..3ba440b272a2 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_optional_field_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.nested_object_with_optional_field import NestedObjectWithOptionalField + + +class NestedObjectWithOptionalFieldError(FernHTTPException): + def __init__(self, error: NestedObjectWithOptionalField): + super().__init__(status_code=400, name="NestedObjectWithOptionalFieldError", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_required_field_error.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_required_field_error.py new file mode 100644 index 000000000000..10b5e8500661 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/nested_object_with_required_field_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.nested_object_with_required_field import NestedObjectWithRequiredField + + +class NestedObjectWithRequiredFieldError(FernHTTPException): + def __init__(self, error: NestedObjectWithRequiredField): + super().__init__(status_code=400, name="NestedObjectWithRequiredFieldError", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_optional_field_error.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_optional_field_error.py new file mode 100644 index 000000000000..09a92f4c4662 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_optional_field_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.object_with_optional_field import ObjectWithOptionalField + + +class ObjectWithOptionalFieldError(FernHTTPException): + def __init__(self, error: ObjectWithOptionalField): + super().__init__(status_code=400, name="ObjectWithOptionalFieldError", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_required_field_error.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_required_field_error.py new file mode 100644 index 000000000000..c0c5cc118120 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/errors/object_with_required_field_error.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.object_with_required_field import ObjectWithRequiredField + + +class ObjectWithRequiredFieldError(FernHTTPException): + def __init__(self, error: ObjectWithRequiredField): + super().__init__(status_code=400, name="ObjectWithRequiredFieldError", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/__init__.py new file mode 100644 index 000000000000..9630b90e6627 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .double_optional import DoubleOptional +from .nested_object_with_optional_field import NestedObjectWithOptionalField +from .nested_object_with_required_field import NestedObjectWithRequiredField +from .object_with_map_of_map import ObjectWithMapOfMap +from .object_with_optional_field import ObjectWithOptionalField +from .object_with_required_field import ObjectWithRequiredField +from .optional_alias import OptionalAlias + +__all__ = [ + "DoubleOptional", + "NestedObjectWithOptionalField", + "NestedObjectWithRequiredField", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithRequiredField", + "OptionalAlias", +] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/double_optional.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/double_optional.py new file mode 100644 index 000000000000..873b6445809e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/double_optional.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel +from .optional_alias import OptionalAlias + + +class DoubleOptional(UniversalBaseModel): + optional_alias: typing_extensions.Annotated[ + typing.Optional[OptionalAlias], pydantic.Field(alias="optionalAlias") + ] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_optional_field.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_optional_field.py new file mode 100644 index 000000000000..8412b1a60e26 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_optional_field.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel +from .object_with_optional_field import ObjectWithOptionalField + + +class NestedObjectWithOptionalField(UniversalBaseModel): + string: typing.Optional[str] = None + nested_object: typing_extensions.Annotated[ + typing.Optional[ObjectWithOptionalField], pydantic.Field(alias="NestedObject") + ] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_required_field.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_required_field.py new file mode 100644 index 000000000000..e60346ecd74e --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/nested_object_with_required_field.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel +from .object_with_optional_field import ObjectWithOptionalField + + +class NestedObjectWithRequiredField(UniversalBaseModel): + string: str + nested_object: typing_extensions.Annotated[ObjectWithOptionalField, pydantic.Field(alias="NestedObject")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_map_of_map.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_map_of_map.py new file mode 100644 index 000000000000..4bb3a3e7144b --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_map_of_map.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithMapOfMap(UniversalBaseModel): + map_: typing_extensions.Annotated[typing.Dict[str, typing.Dict[str, str]], pydantic.Field(alias="map")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_optional_field.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_optional_field.py new file mode 100644 index 000000000000..3c5652b523dc --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_optional_field.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithOptionalField(UniversalBaseModel): + string: typing.Optional[str] = pydantic.Field(default=None) + """ + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + """ + + integer: typing.Optional[int] = None + long_: typing_extensions.Annotated[typing.Optional[int], pydantic.Field(alias="long")] = None + double: typing.Optional[float] = None + bool_: typing_extensions.Annotated[typing.Optional[bool], pydantic.Field(alias="bool")] = None + datetime: typing.Optional[dt.datetime] = None + date: typing.Optional[dt.date] = None + uuid_: typing_extensions.Annotated[typing.Optional[uuid.UUID], pydantic.Field(alias="uuid")] = None + base_64: typing_extensions.Annotated[typing.Optional[str], pydantic.Field(alias="base64")] = None + list_: typing_extensions.Annotated[typing.Optional[typing.List[str]], pydantic.Field(alias="list")] = None + set_: typing_extensions.Annotated[typing.Optional[typing.Set[str]], pydantic.Field(alias="set")] = None + map_: typing_extensions.Annotated[typing.Optional[typing.Dict[int, str]], pydantic.Field(alias="map")] = None + bigint: typing.Optional[str] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_required_field.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_required_field.py new file mode 100644 index 000000000000..62cb64d2b5f9 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/object_with_required_field.py @@ -0,0 +1,12 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ......core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithRequiredField(UniversalBaseModel): + string: str + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/optional_alias.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/optional_alias.py new file mode 100644 index 000000000000..fa09e3be001c --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/object/types/optional_alias.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OptionalAlias = typing.Optional[str] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/__init__.py new file mode 100644 index 000000000000..39f265cd5cfb --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .errors import ErrorWithUnionBody +from .types import Animal, Cat, Dog + +__all__ = ["Animal", "Cat", "Dog", "ErrorWithUnionBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/__init__.py new file mode 100644 index 000000000000..0f0eaf564480 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .error_with_union_body import ErrorWithUnionBody + +__all__ = ["ErrorWithUnionBody"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/error_with_union_body.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/error_with_union_body.py new file mode 100644 index 000000000000..d4343a0aea51 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/errors/error_with_union_body.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.exceptions.fern_http_exception import FernHTTPException +from ..types.animal import Animal + + +class ErrorWithUnionBody(FernHTTPException): + def __init__(self, error: Animal): + super().__init__(status_code=400, name="ErrorWithUnionBody", content=error) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/__init__.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/__init__.py new file mode 100644 index 000000000000..ea0334dd2bd6 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/__init__.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .animal import Animal +from .cat import Cat +from .dog import Dog + +__all__ = ["Animal", "Cat", "Dog"] diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/animal.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/animal.py new file mode 100644 index 000000000000..9a6a9f382c9c --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/animal.py @@ -0,0 +1,63 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import update_forward_refs +from .cat import Cat as resources_types_resources_union_types_cat_Cat +from .dog import Dog as resources_types_resources_union_types_dog_Dog + +T_Result = typing.TypeVar("T_Result") + + +class _Factory: + def dog(self, value: resources_types_resources_union_types_dog_Dog) -> Animal: + return Animal(root=_Animal.Dog(**value.dict(exclude_unset=True), animal="dog")) # type: ignore + + def cat(self, value: resources_types_resources_union_types_cat_Cat) -> Animal: + return Animal(root=_Animal.Cat(**value.dict(exclude_unset=True), animal="cat")) # type: ignore + + +class Animal(pydantic.RootModel): + factory: typing.ClassVar[_Factory] = _Factory() + + root: typing_extensions.Annotated[typing.Union[_Animal.Dog, _Animal.Cat], pydantic.Field(discriminator="animal")] + + def get_as_union(self) -> typing.Union[_Animal.Dog, _Animal.Cat]: + return self.root + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + return self.root.dict(**kwargs) + + def visit( + self, + dog: typing.Callable[[resources_types_resources_union_types_dog_Dog], T_Result], + cat: typing.Callable[[resources_types_resources_union_types_cat_Cat], T_Result], + ) -> T_Result: + unioned_value = self.get_as_union() + if unioned_value.animal == "dog": + return dog( + resources_types_resources_union_types_dog_Dog( + **unioned_value.dict(exclude_unset=True, exclude={"animal"}) + ) + ) + if unioned_value.animal == "cat": + return cat( + resources_types_resources_union_types_cat_Cat( + **unioned_value.dict(exclude_unset=True, exclude={"animal"}) + ) + ) + + +class _Animal: + class Dog(resources_types_resources_union_types_dog_Dog): + animal: typing.Literal["dog"] = "dog" + + class Cat(resources_types_resources_union_types_cat_Cat): + animal: typing.Literal["cat"] = "cat" + + +update_forward_refs(Animal) diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/cat.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/cat.py new file mode 100644 index 000000000000..cc5a8ad16dd4 --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/cat.py @@ -0,0 +1,14 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel + + +class Cat(UniversalBaseModel): + name: str + likes_to_meow: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToMeow")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/dog.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/dog.py new file mode 100644 index 000000000000..143dd733b03c --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/resources/types/resources/union/types/dog.py @@ -0,0 +1,14 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ......core.pydantic_utilities import UniversalBaseModel + + +class Dog(UniversalBaseModel): + name: str + likes_to_woof: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToWoof")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="forbid") # type: ignore # Pydantic v2 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/security.py b/seed/fastapi/exhaustive/use-annotated-field-aliases/security.py new file mode 100644 index 000000000000..aea384acb9fa --- /dev/null +++ b/seed/fastapi/exhaustive/use-annotated-field-aliases/security.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import fastapi +from .core.security.bearer import BearerToken, HTTPBearer + +ApiAuth = BearerToken + + +def FernAuth(auth: BearerToken = fastapi.Depends(HTTPBearer)) -> BearerToken: + return auth diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/snippet-templates.json b/seed/fastapi/exhaustive/use-annotated-field-aliases/snippet-templates.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/seed/fastapi/exhaustive/use-annotated-field-aliases/snippet.json b/seed/fastapi/exhaustive/use-annotated-field-aliases/snippet.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/seed/fastapi/seed.yml b/seed/fastapi/seed.yml index 1b36966aeed9..0b47856cea6c 100644 --- a/seed/fastapi/seed.yml +++ b/seed/fastapi/seed.yml @@ -77,6 +77,11 @@ fixtures: pydantic_config: extra_fields: ignore outputFolder: ignore-extra-fields + - customConfig: + pydantic_config: + version: v2 + use_annotated_field_aliases: true + outputFolder: use-annotated-field-aliases file-download: - customConfig: null outputFolder: no-custom-config diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/.github/workflows/ci.yml b/seed/python-sdk/exhaustive/use-annotated-field-aliases/.github/workflows/ci.yml new file mode 100644 index 000000000000..bfde52e511c8 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/.github/workflows/ci.yml @@ -0,0 +1,61 @@ +name: ci + +on: [push] +jobs: + compile: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + - name: Compile + run: poetry run mypy . + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + + - name: Test + run: poetry run pytest -rP . + + publish: + needs: [compile, test] + if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + - name: Publish to pypi + run: | + poetry config repositories.remote + poetry --no-interaction -v publish --build --repository remote --username "$" --password "$" + env: + : ${{ secrets. }} + : ${{ secrets. }} diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/.gitignore b/seed/python-sdk/exhaustive/use-annotated-field-aliases/.gitignore new file mode 100644 index 000000000000..d2e4ca808d21 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/.gitignore @@ -0,0 +1,5 @@ +.mypy_cache/ +.ruff_cache/ +__pycache__/ +dist/ +poetry.toml diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/README.md b/seed/python-sdk/exhaustive/use-annotated-field-aliases/README.md new file mode 100644 index 000000000000..f1cd73bb4c09 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/README.md @@ -0,0 +1,159 @@ +# Seed Python Library + +[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-Built%20with%20Fern-brightgreen)](https://buildwithfern.com?utm_source=github&utm_medium=github&utm_campaign=readme&utm_source=Seed%2FPython) +[![pypi](https://img.shields.io/pypi/v/fern_exhaustive)](https://pypi.python.org/pypi/fern_exhaustive) + +The Seed Python library provides convenient access to the Seed APIs from Python. + +## Installation + +```sh +pip install fern_exhaustive +``` + +## Reference + +A full reference for this library is available [here](./reference.md). + +## Usage + +Instantiate and use the client with the following: + +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_list_of_primitives( + request=["string", "string"], +) +``` + +## Async Client + +The SDK also exports an `async` client so that you can make non-blocking calls to our API. + +```python +import asyncio + +from seed import AsyncSeedExhaustive + +client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) + + +async def main() -> None: + await client.endpoints.container.get_and_return_list_of_primitives( + request=["string", "string"], + ) + + +asyncio.run(main()) +``` + +## Exception Handling + +When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error +will be thrown. + +```python +from seed.core.api_error import ApiError + +try: + client.endpoints.container.get_and_return_list_of_primitives(...) +except ApiError as e: + print(e.status_code) + print(e.body) +``` + +## Advanced + +### Access Raw Response Data + +The SDK provides access to raw response data, including headers, through the `.with_raw_response` property. +The `.with_raw_response` property returns a "raw" client that can be used to access the `.headers` and `.data` attributes. + +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + ..., +) +response = client.endpoints.container.with_raw_response.get_and_return_list_of_primitives( + ... +) +print(response.headers) # access the response headers +print(response.data) # access the underlying object +``` + +### Retries + +The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long +as the request is deemed retryable and the number of retry attempts has not grown larger than the configured +retry limit (default: 2). + +A request is deemed retryable when any of the following HTTP status codes is returned: + +- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout) +- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests) +- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors) + +Use the `max_retries` request option to configure this behavior. + +```python +client.endpoints.container.get_and_return_list_of_primitives(..., request_options={ + "max_retries": 1 +}) +``` + +### Timeouts + +The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level. + +```python + +from seed import SeedExhaustive + +client = SeedExhaustive( + ..., + timeout=20.0, +) + + +# Override timeout for a specific method +client.endpoints.container.get_and_return_list_of_primitives(..., request_options={ + "timeout_in_seconds": 1 +}) +``` + +### Custom Client + +You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies +and transports. + +```python +import httpx +from seed import SeedExhaustive + +client = SeedExhaustive( + ..., + httpx_client=httpx.Client( + proxy="http://my.test.proxy.example.com", + transport=httpx.HTTPTransport(local_address="0.0.0.0"), + ), +) +``` + +## Contributing + +While we value open-source contributions to this SDK, this library is generated programmatically. +Additions made directly to this library would have to be moved over to our generation code, +otherwise they would be overwritten upon the next generated release. Feel free to open a PR as +a proof of concept, but know that we will not be able to merge it as-is. We suggest opening +an issue first to discuss with us! + +On the other hand, contributions to the README are always very welcome! diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/poetry.lock b/seed/python-sdk/exhaustive/use-annotated-field-aliases/poetry.lock new file mode 100644 index 000000000000..b005dc04fa75 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/poetry.lock @@ -0,0 +1,550 @@ +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} + +[[package]] +name = "anyio" +version = "4.5.2" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, + {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] + +[[package]] +name = "certifi" +version = "2025.8.3" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.7" +files = [ + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.8" +files = [ + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "mypy" +version = "1.13.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.6.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, +] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pydantic" +version = "2.10.6" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.27.2" +typing-extensions = ">=4.12.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] + +[[package]] +name = "pydantic-core" +version = "2.27.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.23.8" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, + {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, +] + +[package.dependencies] +pytest = ">=7.0.0,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "ruff" +version = "0.11.5" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b"}, + {file = "ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077"}, + {file = "ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783"}, + {file = "ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe"}, + {file = "ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800"}, + {file = "ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e"}, + {file = "ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef"}, +] + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20241206" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, + {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "7518fee7b23c577dbcb91fab7281a185529efc31b3d735becf97fb10f96bbdec" diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/pyproject.toml b/seed/python-sdk/exhaustive/use-annotated-field-aliases/pyproject.toml new file mode 100644 index 000000000000..6811972ab375 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/pyproject.toml @@ -0,0 +1,84 @@ +[project] +name = "fern_exhaustive" + +[tool.poetry] +name = "fern_exhaustive" +version = "0.0.1" +description = "" +readme = "README.md" +authors = [] +keywords = [] + +classifiers = [ + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed" +] +packages = [ + { include = "seed", from = "src"} +] + +[project.urls] +Repository = 'https://github.com/exhaustive/fern' + +[tool.poetry.dependencies] +python = "^3.8" +httpx = ">=0.21.2" +pydantic = ">= 2.0.0" +pydantic-core = ">=2.18.2" +typing_extensions = ">= 4.0.0" + +[tool.poetry.group.dev.dependencies] +mypy = "==1.13.0" +pytest = "^7.4.0" +pytest-asyncio = "^0.23.5" +python-dateutil = "^2.9.0" +types-python-dateutil = "^2.9.0.20240316" +ruff = "==0.11.5" + +[tool.pytest.ini_options] +testpaths = [ "tests" ] +asyncio_mode = "auto" + +[tool.mypy] +plugins = ["pydantic.mypy"] + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort +] +ignore = [ + "E402", # Module level import not at top of file + "E501", # Line too long + "E711", # Comparison to `None` should be `cond is not None` + "E712", # Avoid equality comparisons to `True`; use `if ...:` checks + "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for insinstance checks + "E722", # Do not use bare `except` + "E731", # Do not assign a `lambda` expression, use a `def` + "F821", # Undefined name + "F841" # Local variable ... is assigned to but never used +] + +[tool.ruff.lint.isort] +section-order = ["future", "standard-library", "third-party", "first-party"] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/reference.md b/seed/python-sdk/exhaustive/use-annotated-field-aliases/reference.md new file mode 100644 index 000000000000..6d48129f7ea8 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/reference.md @@ -0,0 +1,3656 @@ +# Reference +## Endpoints Container +
client.endpoints.container.get_and_return_list_of_primitives(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_list_of_primitives( + request=["string", "string"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Sequence[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_list_of_objects(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive +from seed.types.object import ObjectWithRequiredField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_list_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ), + ObjectWithRequiredField( + string="string", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Sequence[ObjectWithRequiredField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_set_of_primitives(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_set_of_primitives( + request={"string"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Set[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_set_of_objects(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive +from seed.types.object import ObjectWithRequiredField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_set_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Sequence[ObjectWithRequiredField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_map_prim_to_prim(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_map_prim_to_prim( + request={"string": "string"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Dict[str, str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_map_of_prim_to_object(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive +from seed.types.object import ObjectWithRequiredField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_map_of_prim_to_object( + request={ + "string": ObjectWithRequiredField( + string="string", + ) + }, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Dict[str, ObjectWithRequiredField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.container.get_and_return_optional(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive +from seed.types.object import ObjectWithRequiredField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.container.get_and_return_optional( + request=ObjectWithRequiredField( + string="string", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Optional[ObjectWithRequiredField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints ContentType +
client.endpoints.content_type.post_json_patch_content_type(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.content_type.post_json_patch_content_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `typing.Optional[str]` — This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + +
+
+ +
+
+ +**integer:** `typing.Optional[int]` + +
+
+ +
+
+ +**long_:** `typing.Optional[int]` + +
+
+ +
+
+ +**double:** `typing.Optional[float]` + +
+
+ +
+
+ +**bool_:** `typing.Optional[bool]` + +
+
+ +
+
+ +**datetime:** `typing.Optional[dt.datetime]` + +
+
+ +
+
+ +**date:** `typing.Optional[dt.date]` + +
+
+ +
+
+ +**uuid_:** `typing.Optional[uuid.UUID]` + +
+
+ +
+
+ +**base_64:** `typing.Optional[str]` + +
+
+ +
+
+ +**list_:** `typing.Optional[typing.Sequence[str]]` + +
+
+ +
+
+ +**set_:** `typing.Optional[typing.Set[str]]` + +
+
+ +
+
+ +**map_:** `typing.Optional[typing.Dict[int, str]]` + +
+
+ +
+
+ +**bigint:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.content_type.post_json_patch_content_with_charset_type(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.content_type.post_json_patch_content_with_charset_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `typing.Optional[str]` — This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + +
+
+ +
+
+ +**integer:** `typing.Optional[int]` + +
+
+ +
+
+ +**long_:** `typing.Optional[int]` + +
+
+ +
+
+ +**double:** `typing.Optional[float]` + +
+
+ +
+
+ +**bool_:** `typing.Optional[bool]` + +
+
+ +
+
+ +**datetime:** `typing.Optional[dt.datetime]` + +
+
+ +
+
+ +**date:** `typing.Optional[dt.date]` + +
+
+ +
+
+ +**uuid_:** `typing.Optional[uuid.UUID]` + +
+
+ +
+
+ +**base_64:** `typing.Optional[str]` + +
+
+ +
+
+ +**list_:** `typing.Optional[typing.Sequence[str]]` + +
+
+ +
+
+ +**set_:** `typing.Optional[typing.Set[str]]` + +
+
+ +
+
+ +**map_:** `typing.Optional[typing.Dict[int, str]]` + +
+
+ +
+
+ +**bigint:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Enum +
client.endpoints.enum.get_and_return_enum(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.enum.get_and_return_enum( + request="SUNNY", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `WeatherReport` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints HttpMethods +
client.endpoints.http_methods.test_get(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.http_methods.test_get( + id="id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.http_methods.test_post(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.http_methods.test_post( + string="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.http_methods.test_put(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.http_methods.test_put( + id="id", + string="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**string:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.http_methods.test_patch(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.http_methods.test_patch( + id="id", + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**string:** `typing.Optional[str]` — This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + +
+
+ +
+
+ +**integer:** `typing.Optional[int]` + +
+
+ +
+
+ +**long_:** `typing.Optional[int]` + +
+
+ +
+
+ +**double:** `typing.Optional[float]` + +
+
+ +
+
+ +**bool_:** `typing.Optional[bool]` + +
+
+ +
+
+ +**datetime:** `typing.Optional[dt.datetime]` + +
+
+ +
+
+ +**date:** `typing.Optional[dt.date]` + +
+
+ +
+
+ +**uuid_:** `typing.Optional[uuid.UUID]` + +
+
+ +
+
+ +**base_64:** `typing.Optional[str]` + +
+
+ +
+
+ +**list_:** `typing.Optional[typing.Sequence[str]]` + +
+
+ +
+
+ +**set_:** `typing.Optional[typing.Set[str]]` + +
+
+ +
+
+ +**map_:** `typing.Optional[typing.Dict[int, str]]` + +
+
+ +
+
+ +**bigint:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.http_methods.test_delete(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.http_methods.test_delete( + id="id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Object +
client.endpoints.object.get_and_return_with_optional_field(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_with_optional_field( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `typing.Optional[str]` — This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + +
+
+ +
+
+ +**integer:** `typing.Optional[int]` + +
+
+ +
+
+ +**long_:** `typing.Optional[int]` + +
+
+ +
+
+ +**double:** `typing.Optional[float]` + +
+
+ +
+
+ +**bool_:** `typing.Optional[bool]` + +
+
+ +
+
+ +**datetime:** `typing.Optional[dt.datetime]` + +
+
+ +
+
+ +**date:** `typing.Optional[dt.date]` + +
+
+ +
+
+ +**uuid_:** `typing.Optional[uuid.UUID]` + +
+
+ +
+
+ +**base_64:** `typing.Optional[str]` + +
+
+ +
+
+ +**list_:** `typing.Optional[typing.Sequence[str]]` + +
+
+ +
+
+ +**set_:** `typing.Optional[typing.Set[str]]` + +
+
+ +
+
+ +**map_:** `typing.Optional[typing.Dict[int, str]]` + +
+
+ +
+
+ +**bigint:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.object.get_and_return_with_required_field(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_with_required_field( + string="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.object.get_and_return_with_map_of_map(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_with_map_of_map( + map_={"map": {"map": "map"}}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**map_:** `typing.Dict[str, typing.Dict[str, str]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.object.get_and_return_nested_with_optional_field(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive +from seed.types.object import ObjectWithOptionalField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_nested_with_optional_field( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `typing.Optional[str]` + +
+
+ +
+
+ +**nested_object:** `typing.Optional[ObjectWithOptionalField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.object.get_and_return_nested_with_required_field(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive +from seed.types.object import ObjectWithOptionalField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_nested_with_required_field( + string_="string", + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string_:** `str` + +
+
+ +
+
+ +**string:** `str` + +
+
+ +
+
+ +**nested_object:** `ObjectWithOptionalField` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.object.get_and_return_nested_with_required_field_as_list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive +from seed.types.object import ( + NestedObjectWithRequiredField, + ObjectWithOptionalField, +) + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.object.get_and_return_nested_with_required_field_as_list( + request=[ + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Sequence[NestedObjectWithRequiredField]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Params +
client.endpoints.params.get_with_path(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with path param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_path( + param="param", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.get_with_inline_path(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with path param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_inline_path( + param="param", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.get_with_query(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with query param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_query( + query="query", + number=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**query:** `str` + +
+
+ +
+
+ +**number:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.get_with_allow_multiple_query(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with multiple of same query param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_allow_multiple_query( + query="query", + number=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**query:** `typing.Union[str, typing.Sequence[str]]` + +
+
+ +
+
+ +**number:** `typing.Union[int, typing.Sequence[int]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.get_with_path_and_query(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with path and query params +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_path_and_query( + param="param", + query="query", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**query:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.get_with_inline_path_and_query(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +GET with path and query params +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.get_with_inline_path_and_query( + param="param", + query="query", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**query:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.modify_with_path(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +PUT to update with path param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.modify_with_path( + param="param", + request="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**request:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.params.modify_with_inline_path(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +PUT to update with path param +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.params.modify_with_inline_path( + param="param", + request="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**param:** `str` + +
+
+ +
+
+ +**request:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Primitive +
client.endpoints.primitive.get_and_return_string(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_string( + request="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_int(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_int( + request=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_long(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_long( + request=1000000, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `int` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_double(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_double( + request=1.1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `float` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_bool(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_bool( + request=True, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `bool` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_datetime(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_datetime( + request=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `dt.datetime` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_date(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_date( + request=datetime.date.fromisoformat( + "2023-01-15", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `dt.date` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_uuid(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import uuid + +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_uuid( + request=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `uuid.UUID` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.primitive.get_and_return_base_64(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.primitive.get_and_return_base_64( + request="SGVsbG8gd29ybGQh", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Put +
client.endpoints.put.add(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.put.add( + id="id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Union +
client.endpoints.union.get_and_return_union(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive +from seed.types.union import Animal_Dog + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.union.get_and_return_union( + request=Animal_Dog( + name="name", + likes_to_woof=True, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `Animal` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Endpoints Urls +
client.endpoints.urls.with_mixed_case() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.urls.with_mixed_case() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.urls.no_ending_slash() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.urls.no_ending_slash() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.urls.with_ending_slash() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.urls.with_ending_slash() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.endpoints.urls.with_underscores() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.endpoints.urls.with_underscores() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## InlinedRequests +
client.inlined_requests.post_with_object_bodyand_response(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +POST with custom object in request body, response is an object +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime +import uuid + +from seed import SeedExhaustive +from seed.types.object import ObjectWithOptionalField + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.inlined_requests.post_with_object_bodyand_response( + string="string", + integer=1, + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**string:** `str` + +
+
+ +
+
+ +**integer:** `int` + +
+
+ +
+
+ +**nested_object:** `ObjectWithOptionalField` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## NoAuth +
client.no_auth.post_with_no_auth(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +POST request with no auth +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.no_auth.post_with_no_auth( + request={"key": "value"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `typing.Optional[typing.Any]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## NoReqBody +
client.no_req_body.get_with_no_request_body() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.no_req_body.get_with_no_request_body() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.no_req_body.post_with_no_request_body() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.no_req_body.post_with_no_request_body() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## ReqWithHeaders +
client.req_with_headers.get_with_custom_header(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from seed import SeedExhaustive + +client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", +) +client.req_with_headers.get_with_custom_header( + x_test_service_header="X-TEST-SERVICE-HEADER", + x_test_endpoint_header="X-TEST-ENDPOINT-HEADER", + request="string", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**x_test_service_header:** `str` + +
+
+ +
+
+ +**x_test_endpoint_header:** `str` + +
+
+ +
+
+ +**request:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/requirements.txt b/seed/python-sdk/exhaustive/use-annotated-field-aliases/requirements.txt new file mode 100644 index 000000000000..0e1d565a9d6f --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/requirements.txt @@ -0,0 +1,4 @@ +httpx>=0.21.2 +pydantic>= 2.0.0 +pydantic-core>=2.18.2 +typing_extensions>= 4.0.0 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet-templates.json b/seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet-templates.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet.json b/seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet.json new file mode 100644 index 000000000000..daf6797078d0 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/snippet.json @@ -0,0 +1,642 @@ +{ + "types": {}, + "endpoints": [ + { + "example_identifier": "default", + "id": { + "path": "/container/list-of-primitives", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnListOfPrimitives" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_list_of_primitives(\n request=[\"string\", \"string\"],\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_list_of_primitives(\n request=[\"string\", \"string\"],\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/list-of-objects", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnListOfObjects" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_list_of_objects(\n request=[\n ObjectWithRequiredField(\n string=\"string\",\n ),\n ObjectWithRequiredField(\n string=\"string\",\n ),\n ],\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_list_of_objects(\n request=[\n ObjectWithRequiredField(\n string=\"string\",\n ),\n ObjectWithRequiredField(\n string=\"string\",\n ),\n ],\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/set-of-primitives", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnSetOfPrimitives" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_set_of_primitives(\n request={\"string\"},\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_set_of_primitives(\n request={\"string\"},\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/set-of-objects", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnSetOfObjects" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_set_of_objects(\n request=[\n ObjectWithRequiredField(\n string=\"string\",\n )\n ],\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_set_of_objects(\n request=[\n ObjectWithRequiredField(\n string=\"string\",\n )\n ],\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/map-prim-to-prim", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnMapPrimToPrim" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_map_prim_to_prim(\n request={\"string\": \"string\"},\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_map_prim_to_prim(\n request={\"string\": \"string\"},\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/map-prim-to-object", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnMapOfPrimToObject" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_map_of_prim_to_object(\n request={\n \"string\": ObjectWithRequiredField(\n string=\"string\",\n )\n },\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_map_of_prim_to_object(\n request={\n \"string\": ObjectWithRequiredField(\n string=\"string\",\n )\n },\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/container/opt-objects", + "method": "POST", + "identifier_override": "endpoint_endpoints/container.getAndReturnOptional" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.container.get_and_return_optional(\n request=ObjectWithRequiredField(\n string=\"string\",\n ),\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithRequiredField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.container.get_and_return_optional(\n request=ObjectWithRequiredField(\n string=\"string\",\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/foo/bar", + "method": "POST", + "identifier_override": "endpoint_endpoints/content-type.postJsonPatchContentType" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.content_type.post_json_patch_content_type(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.content_type.post_json_patch_content_type(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/foo/baz", + "method": "POST", + "identifier_override": "endpoint_endpoints/content-type.postJsonPatchContentWithCharsetType" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.content_type.post_json_patch_content_with_charset_type(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.content_type.post_json_patch_content_with_charset_type(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/enum", + "method": "POST", + "identifier_override": "endpoint_endpoints/enum.getAndReturnEnum" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.enum.get_and_return_enum(\n request=\"SUNNY\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.enum.get_and_return_enum(\n request=\"SUNNY\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/http-methods/{id}", + "method": "GET", + "identifier_override": "endpoint_endpoints/http-methods.testGet" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.http_methods.test_get(\n id=\"id\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.http_methods.test_get(\n id=\"id\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/http-methods", + "method": "POST", + "identifier_override": "endpoint_endpoints/http-methods.testPost" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.http_methods.test_post(\n string=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.http_methods.test_post(\n string=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/http-methods/{id}", + "method": "PUT", + "identifier_override": "endpoint_endpoints/http-methods.testPut" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.http_methods.test_put(\n id=\"id\",\n string=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.http_methods.test_put(\n id=\"id\",\n string=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/http-methods/{id}", + "method": "PATCH", + "identifier_override": "endpoint_endpoints/http-methods.testPatch" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.http_methods.test_patch(\n id=\"id\",\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.http_methods.test_patch(\n id=\"id\",\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/http-methods/{id}", + "method": "DELETE", + "identifier_override": "endpoint_endpoints/http-methods.testDelete" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.http_methods.test_delete(\n id=\"id\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.http_methods.test_delete(\n id=\"id\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-with-optional-field", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnWithOptionalField" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_with_optional_field(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_with_optional_field(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-with-required-field", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnWithRequiredField" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_with_required_field(\n string=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_with_required_field(\n string=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-with-map-of-map", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnWithMapOfMap" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_with_map_of_map(\n map_={\"map\": {\"map\": \"map\"}},\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_with_map_of_map(\n map_={\"map\": {\"map\": \"map\"}},\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-nested-with-optional-field", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnNestedWithOptionalField" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_nested_with_optional_field(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_nested_with_optional_field(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-nested-with-required-field/{string}", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnNestedWithRequiredField" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_nested_with_required_field(\n string_=\"string\",\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_nested_with_required_field(\n string_=\"string\",\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/object/get-and-return-nested-with-required-field-list", + "method": "POST", + "identifier_override": "endpoint_endpoints/object.getAndReturnNestedWithRequiredFieldAsList" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\nfrom seed.types.object import (\n NestedObjectWithRequiredField,\n ObjectWithOptionalField,\n)\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.object.get_and_return_nested_with_required_field_as_list(\n request=[\n NestedObjectWithRequiredField(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n ),\n NestedObjectWithRequiredField(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n ),\n ],\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import (\n NestedObjectWithRequiredField,\n ObjectWithOptionalField,\n)\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.object.get_and_return_nested_with_required_field_as_list(\n request=[\n NestedObjectWithRequiredField(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n ),\n NestedObjectWithRequiredField(\n string=\"string\",\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n ),\n ],\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path/{param}", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithPath" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_path(\n param=\"param\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_path(\n param=\"param\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path/{param}", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithInlinePath" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_inline_path(\n param=\"param\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_inline_path(\n param=\"param\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithQuery" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_query(\n query=\"query\",\n number=1,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_query(\n query=\"query\",\n number=1,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithAllowMultipleQuery" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_allow_multiple_query(\n query=\"query\",\n number=1,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_allow_multiple_query(\n query=\"query\",\n number=1,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path-query/{param}", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithPathAndQuery" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_path_and_query(\n param=\"param\",\n query=\"query\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_path_and_query(\n param=\"param\",\n query=\"query\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path-query/{param}", + "method": "GET", + "identifier_override": "endpoint_endpoints/params.getWithInlinePathAndQuery" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.get_with_inline_path_and_query(\n param=\"param\",\n query=\"query\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.get_with_inline_path_and_query(\n param=\"param\",\n query=\"query\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path/{param}", + "method": "PUT", + "identifier_override": "endpoint_endpoints/params.modifyWithPath" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.modify_with_path(\n param=\"param\",\n request=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.modify_with_path(\n param=\"param\",\n request=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/params/path/{param}", + "method": "PUT", + "identifier_override": "endpoint_endpoints/params.modifyWithInlinePath" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.params.modify_with_inline_path(\n param=\"param\",\n request=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.params.modify_with_inline_path(\n param=\"param\",\n request=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/string", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnString" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_string(\n request=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_string(\n request=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/integer", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnInt" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_int(\n request=1,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_int(\n request=1,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/long", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnLong" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_long(\n request=1000000,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_long(\n request=1000000,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/double", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnDouble" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_double(\n request=1.1,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_double(\n request=1.1,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/boolean", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnBool" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_bool(\n request=True,\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_bool(\n request=True,\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/datetime", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnDatetime" + }, + "snippet": { + "sync_client": "import datetime\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_datetime(\n request=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n)\n", + "async_client": "import asyncio\nimport datetime\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_datetime(\n request=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/date", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnDate" + }, + "snippet": { + "sync_client": "import datetime\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_date(\n request=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n)\n", + "async_client": "import asyncio\nimport datetime\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_date(\n request=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/uuid", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnUUID" + }, + "snippet": { + "sync_client": "import uuid\n\nfrom seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_uuid(\n request=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n)\n", + "async_client": "import asyncio\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_uuid(\n request=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/primitive/base64", + "method": "POST", + "identifier_override": "endpoint_endpoints/primitive.getAndReturnBase64" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.primitive.get_and_return_base_64(\n request=\"SGVsbG8gd29ybGQh\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.primitive.get_and_return_base_64(\n request=\"SGVsbG8gd29ybGQh\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/{id}", + "method": "PUT", + "identifier_override": "endpoint_endpoints/put.add" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.put.add(\n id=\"id\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.put.add(\n id=\"id\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/union", + "method": "POST", + "identifier_override": "endpoint_endpoints/union.getAndReturnUnion" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\nfrom seed.types.union import Animal_Dog\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.union.get_and_return_union(\n request=Animal_Dog(\n name=\"name\",\n likes_to_woof=True,\n ),\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.union import Animal_Dog\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.union.get_and_return_union(\n request=Animal_Dog(\n name=\"name\",\n likes_to_woof=True,\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/urls/MixedCase", + "method": "GET", + "identifier_override": "endpoint_endpoints/urls.withMixedCase" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.urls.with_mixed_case()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.urls.with_mixed_case()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/urls/no-ending-slash", + "method": "GET", + "identifier_override": "endpoint_endpoints/urls.noEndingSlash" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.urls.no_ending_slash()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.urls.no_ending_slash()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/urls/with-ending-slash/", + "method": "GET", + "identifier_override": "endpoint_endpoints/urls.withEndingSlash" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.urls.with_ending_slash()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.urls.with_ending_slash()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/urls/with_underscores", + "method": "GET", + "identifier_override": "endpoint_endpoints/urls.withUnderscores" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.endpoints.urls.with_underscores()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.endpoints.urls.with_underscores()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/req-bodies/object", + "method": "POST", + "identifier_override": "endpoint_inlined-requests.postWithObjectBodyandResponse" + }, + "snippet": { + "sync_client": "import datetime\nimport uuid\n\nfrom seed import SeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.inlined_requests.post_with_object_bodyand_response(\n string=\"string\",\n integer=1,\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n)\n", + "async_client": "import asyncio\nimport datetime\nimport uuid\n\nfrom seed import AsyncSeedExhaustive\nfrom seed.types.object import ObjectWithOptionalField\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.inlined_requests.post_with_object_bodyand_response(\n string=\"string\",\n integer=1,\n nested_object=ObjectWithOptionalField(\n string=\"string\",\n integer=1,\n long_=1000000,\n double=1.1,\n bool_=True,\n datetime=datetime.datetime.fromisoformat(\n \"2024-01-15 09:30:00+00:00\",\n ),\n date=datetime.date.fromisoformat(\n \"2023-01-15\",\n ),\n uuid_=uuid.UUID(\n \"d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32\",\n ),\n base_64=\"SGVsbG8gd29ybGQh\",\n list_=[\"list\", \"list\"],\n set_={\"set\"},\n map_={1: \"map\"},\n bigint=1000000,\n ),\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/no-auth", + "method": "POST", + "identifier_override": "endpoint_no-auth.postWithNoAuth" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.no_auth.post_with_no_auth(\n request={\"key\": \"value\"},\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.no_auth.post_with_no_auth(\n request={\"key\": \"value\"},\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/no-req-body", + "method": "GET", + "identifier_override": "endpoint_no-req-body.getWithNoRequestBody" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.no_req_body.get_with_no_request_body()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.no_req_body.get_with_no_request_body()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/no-req-body", + "method": "POST", + "identifier_override": "endpoint_no-req-body.postWithNoRequestBody" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.no_req_body.post_with_no_request_body()\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.no_req_body.post_with_no_request_body()\n\n\nasyncio.run(main())\n", + "type": "python" + } + }, + { + "example_identifier": "default", + "id": { + "path": "/test-headers/custom-header", + "method": "POST", + "identifier_override": "endpoint_req-with-headers.getWithCustomHeader" + }, + "snippet": { + "sync_client": "from seed import SeedExhaustive\n\nclient = SeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\nclient.req_with_headers.get_with_custom_header(\n x_test_service_header=\"X-TEST-SERVICE-HEADER\",\n x_test_endpoint_header=\"X-TEST-ENDPOINT-HEADER\",\n request=\"string\",\n)\n", + "async_client": "import asyncio\n\nfrom seed import AsyncSeedExhaustive\n\nclient = AsyncSeedExhaustive(\n token=\"YOUR_TOKEN\",\n base_url=\"https://yourhost.com/path/to/api\",\n)\n\n\nasync def main() -> None:\n await client.req_with_headers.get_with_custom_header(\n x_test_service_header=\"X-TEST-SERVICE-HEADER\",\n x_test_endpoint_header=\"X-TEST-ENDPOINT-HEADER\",\n request=\"string\",\n )\n\n\nasyncio.run(main())\n", + "type": "python" + } + } + ] +} \ No newline at end of file diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/__init__.py new file mode 100644 index 000000000000..4fd8927df13d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/__init__.py @@ -0,0 +1,61 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import endpoints, general_errors, inlined_requests, no_auth, no_req_body, req_with_headers, types + from .client import AsyncSeedExhaustive, SeedExhaustive + from .general_errors import BadObjectRequestInfo, BadRequestBody + from .version import __version__ +_dynamic_imports: typing.Dict[str, str] = { + "AsyncSeedExhaustive": ".client", + "BadObjectRequestInfo": ".general_errors", + "BadRequestBody": ".general_errors", + "SeedExhaustive": ".client", + "__version__": ".version", + "endpoints": ".", + "general_errors": ".", + "inlined_requests": ".", + "no_auth": ".", + "no_req_body": ".", + "req_with_headers": ".", + "types": ".", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "AsyncSeedExhaustive", + "BadObjectRequestInfo", + "BadRequestBody", + "SeedExhaustive", + "__version__", + "endpoints", + "general_errors", + "inlined_requests", + "no_auth", + "no_req_body", + "req_with_headers", + "types", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/client.py new file mode 100644 index 000000000000..4395a9411a5f --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/client.py @@ -0,0 +1,221 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import httpx +from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper + +if typing.TYPE_CHECKING: + from .endpoints.client import AsyncEndpointsClient, EndpointsClient + from .inlined_requests.client import AsyncInlinedRequestsClient, InlinedRequestsClient + from .no_auth.client import AsyncNoAuthClient, NoAuthClient + from .no_req_body.client import AsyncNoReqBodyClient, NoReqBodyClient + from .req_with_headers.client import AsyncReqWithHeadersClient, ReqWithHeadersClient + + +class SeedExhaustive: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. + + Parameters + ---------- + base_url : str + The base url to use for requests from the client. + + token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] + headers : typing.Optional[typing.Dict[str, str]] + Additional headers to send with every request. + + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. + + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. + + httpx_client : typing.Optional[httpx.Client] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + """ + + def __init__( + self, + *, + base_url: str, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.Client] = None, + ): + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) + self._client_wrapper = SyncClientWrapper( + base_url=base_url, + token=token, + headers=headers, + httpx_client=httpx_client + if httpx_client is not None + else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ) + self._endpoints: typing.Optional[EndpointsClient] = None + self._inlined_requests: typing.Optional[InlinedRequestsClient] = None + self._no_auth: typing.Optional[NoAuthClient] = None + self._no_req_body: typing.Optional[NoReqBodyClient] = None + self._req_with_headers: typing.Optional[ReqWithHeadersClient] = None + + @property + def endpoints(self): + if self._endpoints is None: + from .endpoints.client import EndpointsClient # noqa: E402 + + self._endpoints = EndpointsClient(client_wrapper=self._client_wrapper) + return self._endpoints + + @property + def inlined_requests(self): + if self._inlined_requests is None: + from .inlined_requests.client import InlinedRequestsClient # noqa: E402 + + self._inlined_requests = InlinedRequestsClient(client_wrapper=self._client_wrapper) + return self._inlined_requests + + @property + def no_auth(self): + if self._no_auth is None: + from .no_auth.client import NoAuthClient # noqa: E402 + + self._no_auth = NoAuthClient(client_wrapper=self._client_wrapper) + return self._no_auth + + @property + def no_req_body(self): + if self._no_req_body is None: + from .no_req_body.client import NoReqBodyClient # noqa: E402 + + self._no_req_body = NoReqBodyClient(client_wrapper=self._client_wrapper) + return self._no_req_body + + @property + def req_with_headers(self): + if self._req_with_headers is None: + from .req_with_headers.client import ReqWithHeadersClient # noqa: E402 + + self._req_with_headers = ReqWithHeadersClient(client_wrapper=self._client_wrapper) + return self._req_with_headers + + +class AsyncSeedExhaustive: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. + + Parameters + ---------- + base_url : str + The base url to use for requests from the client. + + token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] + headers : typing.Optional[typing.Dict[str, str]] + Additional headers to send with every request. + + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. + + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. + + httpx_client : typing.Optional[httpx.AsyncClient] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + + Examples + -------- + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + """ + + def __init__( + self, + *, + base_url: str, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.AsyncClient] = None, + ): + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) + self._client_wrapper = AsyncClientWrapper( + base_url=base_url, + token=token, + headers=headers, + httpx_client=httpx_client + if httpx_client is not None + else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.AsyncClient(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ) + self._endpoints: typing.Optional[AsyncEndpointsClient] = None + self._inlined_requests: typing.Optional[AsyncInlinedRequestsClient] = None + self._no_auth: typing.Optional[AsyncNoAuthClient] = None + self._no_req_body: typing.Optional[AsyncNoReqBodyClient] = None + self._req_with_headers: typing.Optional[AsyncReqWithHeadersClient] = None + + @property + def endpoints(self): + if self._endpoints is None: + from .endpoints.client import AsyncEndpointsClient # noqa: E402 + + self._endpoints = AsyncEndpointsClient(client_wrapper=self._client_wrapper) + return self._endpoints + + @property + def inlined_requests(self): + if self._inlined_requests is None: + from .inlined_requests.client import AsyncInlinedRequestsClient # noqa: E402 + + self._inlined_requests = AsyncInlinedRequestsClient(client_wrapper=self._client_wrapper) + return self._inlined_requests + + @property + def no_auth(self): + if self._no_auth is None: + from .no_auth.client import AsyncNoAuthClient # noqa: E402 + + self._no_auth = AsyncNoAuthClient(client_wrapper=self._client_wrapper) + return self._no_auth + + @property + def no_req_body(self): + if self._no_req_body is None: + from .no_req_body.client import AsyncNoReqBodyClient # noqa: E402 + + self._no_req_body = AsyncNoReqBodyClient(client_wrapper=self._client_wrapper) + return self._no_req_body + + @property + def req_with_headers(self): + if self._req_with_headers is None: + from .req_with_headers.client import AsyncReqWithHeadersClient # noqa: E402 + + self._req_with_headers = AsyncReqWithHeadersClient(client_wrapper=self._client_wrapper) + return self._req_with_headers diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/__init__.py new file mode 100644 index 000000000000..2909af5b29c2 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/__init__.py @@ -0,0 +1,103 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .api_error import ApiError + from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper + from .datetime_utils import serialize_datetime + from .file import File, convert_file_dict_to_httpx_tuples, with_content_type + from .http_client import AsyncHttpClient, HttpClient + from .http_response import AsyncHttpResponse, HttpResponse + from .jsonable_encoder import jsonable_encoder + from .pydantic_utilities import ( + IS_PYDANTIC_V2, + UniversalBaseModel, + UniversalRootModel, + parse_obj_as, + universal_field_validator, + universal_root_validator, + update_forward_refs, + ) + from .query_encoder import encode_query + from .remove_none_from_dict import remove_none_from_dict + from .request_options import RequestOptions + from .serialization import FieldMetadata, convert_and_respect_annotation_metadata +_dynamic_imports: typing.Dict[str, str] = { + "ApiError": ".api_error", + "AsyncClientWrapper": ".client_wrapper", + "AsyncHttpClient": ".http_client", + "AsyncHttpResponse": ".http_response", + "BaseClientWrapper": ".client_wrapper", + "FieldMetadata": ".serialization", + "File": ".file", + "HttpClient": ".http_client", + "HttpResponse": ".http_response", + "IS_PYDANTIC_V2": ".pydantic_utilities", + "RequestOptions": ".request_options", + "SyncClientWrapper": ".client_wrapper", + "UniversalBaseModel": ".pydantic_utilities", + "UniversalRootModel": ".pydantic_utilities", + "convert_and_respect_annotation_metadata": ".serialization", + "convert_file_dict_to_httpx_tuples": ".file", + "encode_query": ".query_encoder", + "jsonable_encoder": ".jsonable_encoder", + "parse_obj_as": ".pydantic_utilities", + "remove_none_from_dict": ".remove_none_from_dict", + "serialize_datetime": ".datetime_utils", + "universal_field_validator": ".pydantic_utilities", + "universal_root_validator": ".pydantic_utilities", + "update_forward_refs": ".pydantic_utilities", + "with_content_type": ".file", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "ApiError", + "AsyncClientWrapper", + "AsyncHttpClient", + "AsyncHttpResponse", + "BaseClientWrapper", + "FieldMetadata", + "File", + "HttpClient", + "HttpResponse", + "IS_PYDANTIC_V2", + "RequestOptions", + "SyncClientWrapper", + "UniversalBaseModel", + "UniversalRootModel", + "convert_and_respect_annotation_metadata", + "convert_file_dict_to_httpx_tuples", + "encode_query", + "jsonable_encoder", + "parse_obj_as", + "remove_none_from_dict", + "serialize_datetime", + "universal_field_validator", + "universal_root_validator", + "update_forward_refs", + "with_content_type", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/api_error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/api_error.py new file mode 100644 index 000000000000..6f850a60cba3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/api_error.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +class ApiError(Exception): + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any + + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + ) -> None: + self.headers = headers + self.status_code = status_code + self.body = body + + def __str__(self) -> str: + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}" diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/client_wrapper.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/client_wrapper.py new file mode 100644 index 000000000000..e1828bae0a8f --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/client_wrapper.py @@ -0,0 +1,87 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx +from .http_client import AsyncHttpClient, HttpClient + + +class BaseClientWrapper: + def __init__( + self, + *, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + ): + self._token = token + self._headers = headers + self._base_url = base_url + self._timeout = timeout + + def get_headers(self) -> typing.Dict[str, str]: + headers: typing.Dict[str, str] = { + "User-Agent": "fern_exhaustive/0.0.1", + "X-Fern-Language": "Python", + "X-Fern-SDK-Name": "fern_exhaustive", + "X-Fern-SDK-Version": "0.0.1", + **(self.get_custom_headers() or {}), + } + token = self._get_token() + if token is not None: + headers["Authorization"] = f"Bearer {token}" + return headers + + def _get_token(self) -> typing.Optional[str]: + if isinstance(self._token, str) or self._token is None: + return self._token + else: + return self._token() + + def get_custom_headers(self) -> typing.Optional[typing.Dict[str, str]]: + return self._headers + + def get_base_url(self) -> str: + return self._base_url + + def get_timeout(self) -> typing.Optional[float]: + return self._timeout + + +class SyncClientWrapper(BaseClientWrapper): + def __init__( + self, + *, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + httpx_client: httpx.Client, + ): + super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout) + self.httpx_client = HttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, + ) + + +class AsyncClientWrapper(BaseClientWrapper): + def __init__( + self, + *, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + httpx_client: httpx.AsyncClient, + ): + super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout) + self.httpx_client = AsyncHttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, + ) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/datetime_utils.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/datetime_utils.py new file mode 100644 index 000000000000..7c9864a944c2 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/datetime_utils.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt + + +def serialize_datetime(v: dt.datetime) -> str: + """ + Serialize a datetime including timezone info. + + Uses the timezone info provided if present, otherwise uses the current runtime's timezone info. + + UTC datetimes end in "Z" while all other timezones are represented as offset from UTC, e.g. +05:00. + """ + + def _serialize_zoned_datetime(v: dt.datetime) -> str: + if v.tzinfo is not None and v.tzinfo.tzname(None) == dt.timezone.utc.tzname(None): + # UTC is a special case where we use "Z" at the end instead of "+00:00" + return v.isoformat().replace("+00:00", "Z") + else: + # Delegate to the typical +/- offset format + return v.isoformat() + + if v.tzinfo is not None: + return _serialize_zoned_datetime(v) + else: + local_tz = dt.datetime.now().astimezone().tzinfo + localized_dt = v.replace(tzinfo=local_tz) + return _serialize_zoned_datetime(localized_dt) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/file.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/file.py new file mode 100644 index 000000000000..44b0d27c0895 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/file.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import IO, Dict, List, Mapping, Optional, Tuple, Union, cast + +# File typing inspired by the flexibility of types within the httpx library +# https://github.com/encode/httpx/blob/master/httpx/_types.py +FileContent = Union[IO[bytes], bytes, str] +File = Union[ + # file (or bytes) + FileContent, + # (filename, file (or bytes)) + Tuple[Optional[str], FileContent], + # (filename, file (or bytes), content_type) + Tuple[Optional[str], FileContent, Optional[str]], + # (filename, file (or bytes), content_type, headers) + Tuple[ + Optional[str], + FileContent, + Optional[str], + Mapping[str, str], + ], +] + + +def convert_file_dict_to_httpx_tuples( + d: Dict[str, Union[File, List[File]]], +) -> List[Tuple[str, File]]: + """ + The format we use is a list of tuples, where the first element is the + name of the file and the second is the file object. Typically HTTPX wants + a dict, but to be able to send lists of files, you have to use the list + approach (which also works for non-lists) + https://github.com/encode/httpx/pull/1032 + """ + + httpx_tuples = [] + for key, file_like in d.items(): + if isinstance(file_like, list): + for file_like_item in file_like: + httpx_tuples.append((key, file_like_item)) + else: + httpx_tuples.append((key, file_like)) + return httpx_tuples + + +def with_content_type(*, file: File, default_content_type: str) -> File: + """ + This function resolves to the file's content type, if provided, and defaults + to the default_content_type value if not. + """ + if isinstance(file, tuple): + if len(file) == 2: + filename, content = cast(Tuple[Optional[str], FileContent], file) # type: ignore + return (filename, content, default_content_type) + elif len(file) == 3: + filename, content, file_content_type = cast(Tuple[Optional[str], FileContent, Optional[str]], file) # type: ignore + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type) + elif len(file) == 4: + filename, content, file_content_type, headers = cast( # type: ignore + Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], file + ) + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type, headers) + else: + raise ValueError(f"Unexpected tuple length: {len(file)}") + return (None, file, default_content_type) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/force_multipart.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/force_multipart.py new file mode 100644 index 000000000000..5440913fd4bc --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/force_multipart.py @@ -0,0 +1,18 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict + + +class ForceMultipartDict(Dict[str, Any]): + """ + A dictionary subclass that always evaluates to True in boolean contexts. + + This is used to force multipart/form-data encoding in HTTP requests even when + the dictionary is empty, which would normally evaluate to False. + """ + + def __bool__(self) -> bool: + return True + + +FORCE_MULTIPART = ForceMultipartDict() diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_client.py new file mode 100644 index 000000000000..e4173f990f14 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_client.py @@ -0,0 +1,543 @@ +# This file was auto-generated by Fern from our API Definition. + +import asyncio +import email.utils +import re +import time +import typing +import urllib.parse +from contextlib import asynccontextmanager, contextmanager +from random import random + +import httpx +from .file import File, convert_file_dict_to_httpx_tuples +from .force_multipart import FORCE_MULTIPART +from .jsonable_encoder import jsonable_encoder +from .query_encoder import encode_query +from .remove_none_from_dict import remove_none_from_dict +from .request_options import RequestOptions +from httpx._types import RequestFiles + +INITIAL_RETRY_DELAY_SECONDS = 0.5 +MAX_RETRY_DELAY_SECONDS = 10 +MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30 + + +def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]: + """ + This function parses the `Retry-After` header in a HTTP response and returns the number of seconds to wait. + + Inspired by the urllib3 retry implementation. + """ + retry_after_ms = response_headers.get("retry-after-ms") + if retry_after_ms is not None: + try: + return int(retry_after_ms) / 1000 if retry_after_ms > 0 else 0 + except Exception: + pass + + retry_after = response_headers.get("retry-after") + if retry_after is None: + return None + + # Attempt to parse the header as an int. + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = float(retry_after) + # Fallback to parsing it as a date. + else: + retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + return None + if retry_date_tuple[9] is None: # Python 2 + # Assume UTC if no timezone was specified + # On Python2.7, parsedate_tz returns None for a timezone offset + # instead of 0 if no timezone is given, where mktime_tz treats + # a None timezone offset as local time. + retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:] + + retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + +def _retry_timeout(response: httpx.Response, retries: int) -> float: + """ + Determine the amount of time to wait before retrying a request. + This function begins by trying to parse a retry-after header from the response, and then proceeds to use exponential backoff + with a jitter to determine the number of seconds to wait. + """ + + # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. + retry_after = _parse_retry_after(response.headers) + if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER: + return retry_after + + # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS. + retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + + # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries. + timeout = retry_delay * (1 - 0.25 * random()) + return timeout if timeout >= 0 else 0 + + +def _should_retry(response: httpx.Response) -> bool: + retryable_400s = [429, 408, 409] + return response.status_code >= 500 or response.status_code in retryable_400s + + +def remove_omit_from_dict( + original: typing.Dict[str, typing.Optional[typing.Any]], + omit: typing.Optional[typing.Any], +) -> typing.Dict[str, typing.Any]: + if omit is None: + return original + new: typing.Dict[str, typing.Any] = {} + for key, value in original.items(): + if value is not omit: + new[key] = value + return new + + +def maybe_filter_request_body( + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Optional[typing.Any]: + if data is None: + return ( + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} + if request_options is not None + else None + ) + elif not isinstance(data, typing.Mapping): + data_content = jsonable_encoder(data) + else: + data_content = { + **(jsonable_encoder(remove_omit_from_dict(data, omit))), # type: ignore + **( + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} + if request_options is not None + else {} + ), + } + return data_content + + +# Abstracted out for testing purposes +def get_request_body( + *, + json: typing.Optional[typing.Any], + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Tuple[typing.Optional[typing.Any], typing.Optional[typing.Any]]: + json_body = None + data_body = None + if data is not None: + data_body = maybe_filter_request_body(data, request_options, omit) + else: + # If both data and json are None, we send json data in the event extra properties are specified + json_body = maybe_filter_request_body(json, request_options, omit) + + # If you have an empty JSON body, you should just send None + return (json_body if json_body != {} else None), data_body if data_body != {} else None + + +class HttpClient: + def __init__( + self, + *, + httpx_client: httpx.Client, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + response = self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + time.sleep(_retry_timeout(response=response, retries=retries)) + return self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + + return response + + @contextmanager + def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> typing.Iterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) as stream: + yield stream + + +class AsyncHttpClient: + def __init__( + self, + *, + httpx_client: httpx.AsyncClient, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + async def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + # Add the input to each of these and do None-safety checks + response = await self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + await asyncio.sleep(_retry_timeout(response=response, retries=retries)) + return await self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + return response + + @asynccontextmanager + async def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> typing.AsyncIterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + async with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit=omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) as stream: + yield stream diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_response.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_response.py new file mode 100644 index 000000000000..2479747e8bb0 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/http_response.py @@ -0,0 +1,55 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Dict, Generic, TypeVar + +import httpx + +# Generic to represent the underlying type of the data wrapped by the HTTP response. +T = TypeVar("T") + + +class BaseHttpResponse: + """Minimalist HTTP response wrapper that exposes response headers.""" + + _response: httpx.Response + + def __init__(self, response: httpx.Response): + self._response = response + + @property + def headers(self) -> Dict[str, str]: + return dict(self._response.headers) + + +class HttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + def close(self) -> None: + self._response.close() + + +class AsyncHttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + async def close(self) -> None: + await self._response.aclose() diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/jsonable_encoder.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/jsonable_encoder.py new file mode 100644 index 000000000000..afee3662d836 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/jsonable_encoder.py @@ -0,0 +1,100 @@ +# This file was auto-generated by Fern from our API Definition. + +""" +jsonable_encoder converts a Python object to a JSON-friendly dict +(e.g. datetimes to strings, Pydantic models to dicts). + +Taken from FastAPI, and made a bit simpler +https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py +""" + +import base64 +import dataclasses +import datetime as dt +from enum import Enum +from pathlib import PurePath +from types import GeneratorType +from typing import Any, Callable, Dict, List, Optional, Set, Union + +import pydantic +from .datetime_utils import serialize_datetime +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + encode_by_type, + to_jsonable_with_fallback, +) + +SetIntStr = Set[Union[int, str]] +DictIntStrAny = Dict[Union[int, str], Any] + + +def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: + custom_encoder = custom_encoder or {} + if custom_encoder: + if type(obj) in custom_encoder: + return custom_encoder[type(obj)](obj) + else: + for encoder_type, encoder_instance in custom_encoder.items(): + if isinstance(obj, encoder_type): + return encoder_instance(obj) + if isinstance(obj, pydantic.BaseModel): + if IS_PYDANTIC_V2: + encoder = getattr(obj.model_config, "json_encoders", {}) # type: ignore # Pydantic v2 + else: + encoder = getattr(obj.__config__, "json_encoders", {}) # type: ignore # Pydantic v1 + if custom_encoder: + encoder.update(custom_encoder) + obj_dict = obj.dict(by_alias=True) + if "__root__" in obj_dict: + obj_dict = obj_dict["__root__"] + if "root" in obj_dict: + obj_dict = obj_dict["root"] + return jsonable_encoder(obj_dict, custom_encoder=encoder) + if dataclasses.is_dataclass(obj): + obj_dict = dataclasses.asdict(obj) # type: ignore + return jsonable_encoder(obj_dict, custom_encoder=custom_encoder) + if isinstance(obj, bytes): + return base64.b64encode(obj).decode("utf-8") + if isinstance(obj, Enum): + return obj.value + if isinstance(obj, PurePath): + return str(obj) + if isinstance(obj, (str, int, float, type(None))): + return obj + if isinstance(obj, dt.datetime): + return serialize_datetime(obj) + if isinstance(obj, dt.date): + return str(obj) + if isinstance(obj, dict): + encoded_dict = {} + allowed_keys = set(obj.keys()) + for key, value in obj.items(): + if key in allowed_keys: + encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder) + encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder) + encoded_dict[encoded_key] = encoded_value + return encoded_dict + if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)): + encoded_list = [] + for item in obj: + encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) + return encoded_list + + def fallback_serializer(o: Any) -> Any: + attempt_encode = encode_by_type(o) + if attempt_encode is not None: + return attempt_encode + + try: + data = dict(o) + except Exception as e: + errors: List[Exception] = [] + errors.append(e) + try: + data = vars(o) + except Exception as e: + errors.append(e) + raise ValueError(errors) from e + return jsonable_encoder(data, custom_encoder=custom_encoder) + + return to_jsonable_with_fallback(obj, fallback_serializer) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/pydantic_utilities.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/pydantic_utilities.py new file mode 100644 index 000000000000..8906cdfa4217 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/pydantic_utilities.py @@ -0,0 +1,258 @@ +# This file was auto-generated by Fern from our API Definition. + +# nopycln: file +import datetime as dt +from collections import defaultdict +from typing import Any, Callable, ClassVar, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar, Union, cast + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + +if IS_PYDANTIC_V2: + from pydantic.v1.datetime_parse import parse_date as parse_date + from pydantic.v1.datetime_parse import parse_datetime as parse_datetime + from pydantic.v1.fields import ModelField as ModelField + from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] + from pydantic.v1.typing import get_args as get_args + from pydantic.v1.typing import get_origin as get_origin + from pydantic.v1.typing import is_literal_type as is_literal_type + from pydantic.v1.typing import is_union as is_union +else: + from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] + from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] + from pydantic.typing import get_args as get_args # type: ignore[no-redef] + from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_union as is_union # type: ignore[no-redef] + +from .datetime_utils import serialize_datetime +from .serialization import convert_and_respect_annotation_metadata +from typing_extensions import TypeAlias + +T = TypeVar("T") +Model = TypeVar("Model", bound=pydantic.BaseModel) + + +def parse_obj_as(type_: Type[T], object_: Any) -> T: + dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") + if IS_PYDANTIC_V2: + adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined] + return adapter.validate_python(dealiased_object) + return pydantic.parse_obj_as(type_, dealiased_object) + + +def to_jsonable_with_fallback(obj: Any, fallback_serializer: Callable[[Any], Any]) -> Any: + if IS_PYDANTIC_V2: + from pydantic_core import to_jsonable_python + + return to_jsonable_python(obj, fallback=fallback_serializer) + return fallback_serializer(obj) + + +class UniversalBaseModel(pydantic.BaseModel): + if IS_PYDANTIC_V2: + model_config: ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( # type: ignore[typeddict-unknown-key] + # Allow fields beginning with `model_` to be used in the model + protected_namespaces=(), + ) + + @pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined] + def serialize_model(self) -> Any: # type: ignore[name-defined] + serialized = self.dict() # type: ignore[attr-defined] + data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()} + return data + + else: + + class Config: + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} + + @classmethod + def model_construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + return cls.construct(_fields_set, **dealiased_object) + + @classmethod + def construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + if IS_PYDANTIC_V2: + return super().model_construct(_fields_set, **dealiased_object) # type: ignore[misc] + return super().construct(_fields_set, **dealiased_object) + + def json(self, **kwargs: Any) -> str: + kwargs_with_defaults = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + if IS_PYDANTIC_V2: + return super().model_dump_json(**kwargs_with_defaults) # type: ignore[misc] + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: Any) -> Dict[str, Any]: + """ + Override the default dict method to `exclude_unset` by default. This function patches + `exclude_unset` to work include fields within non-None default values. + """ + # Note: the logic here is multiplexed given the levers exposed in Pydantic V1 vs V2 + # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. + # + # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models + # that we have less control over, and this is less intrusive than custom serializers for now. + if IS_PYDANTIC_V2: + kwargs_with_defaults_exclude_unset = { + **kwargs, + "by_alias": True, + "exclude_unset": True, + "exclude_none": False, + } + kwargs_with_defaults_exclude_none = { + **kwargs, + "by_alias": True, + "exclude_none": True, + "exclude_unset": False, + } + dict_dump = deep_union_pydantic_dicts( + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore[misc] + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore[misc] + ) + + else: + _fields_set = self.__fields_set__.copy() + + fields = _get_model_fields(self.__class__) + for name, field in fields.items(): + if name not in _fields_set: + default = _get_field_default(field) + + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default is not None or ("exclude_unset" in kwargs and not kwargs["exclude_unset"]): + _fields_set.add(name) + + if default is not None: + self.__fields_set__.add(name) + + kwargs_with_defaults_exclude_unset_include_fields = { + "by_alias": True, + "exclude_unset": True, + "include": _fields_set, + **kwargs, + } + + dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields) + + return cast( + Dict[str, Any], + convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write"), + ) + + +def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]: + converted_list: List[Any] = [] + for i, item in enumerate(source): + destination_value = destination[i] + if isinstance(item, dict): + converted_list.append(deep_union_pydantic_dicts(item, destination_value)) + elif isinstance(item, list): + converted_list.append(_union_list_of_pydantic_dicts(item, destination_value)) + else: + converted_list.append(item) + return converted_list + + +def deep_union_pydantic_dicts(source: Dict[str, Any], destination: Dict[str, Any]) -> Dict[str, Any]: + for key, value in source.items(): + node = destination.setdefault(key, {}) + if isinstance(value, dict): + deep_union_pydantic_dicts(value, node) + # Note: we do not do this same processing for sets given we do not have sets of models + # and given the sets are unordered, the processing of the set and matching objects would + # be non-trivial. + elif isinstance(value, list): + destination[key] = _union_list_of_pydantic_dicts(value, node) + else: + destination[key] = value + + return destination + + +if IS_PYDANTIC_V2: + + class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore[misc, name-defined, type-arg] + pass + + UniversalRootModel: TypeAlias = V2RootModel # type: ignore[misc] +else: + UniversalRootModel: TypeAlias = UniversalBaseModel # type: ignore[misc, no-redef] + + +def encode_by_type(o: Any) -> Any: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple) + for type_, encoder in encoders_by_type.items(): + encoders_by_class_tuples[encoder] += (type_,) + + if type(o) in encoders_by_type: + return encoders_by_type[type(o)](o) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(o, classes_tuple): + return encoder(o) + + +def update_forward_refs(model: Type["Model"], **localns: Any) -> None: + if IS_PYDANTIC_V2: + model.model_rebuild(raise_errors=False) # type: ignore[attr-defined] + else: + model.update_forward_refs(**localns) + + +# Mirrors Pydantic's internal typing +AnyCallable = Callable[..., Any] + + +def universal_root_validator( + pre: bool = False, +) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload] + + return decorator + + +def universal_field_validator(field_name: str, pre: bool = False) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.field_validator(field_name, mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.validator(field_name, pre=pre)(func)) + + return decorator + + +PydanticField = Union[ModelField, pydantic.fields.FieldInfo] + + +def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: + if IS_PYDANTIC_V2: + return cast(Mapping[str, PydanticField], model.model_fields) # type: ignore[attr-defined] + return cast(Mapping[str, PydanticField], model.__fields__) + + +def _get_field_default(field: PydanticField) -> Any: + try: + value = field.get_default() # type: ignore[union-attr] + except: + value = field.default + if IS_PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/query_encoder.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/query_encoder.py new file mode 100644 index 000000000000..3183001d4046 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/query_encoder.py @@ -0,0 +1,58 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, List, Optional, Tuple + +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) -> List[Tuple[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.extend(traverse_query_dict(v, key)) + elif isinstance(v, list): + for arr_v in v: + if isinstance(arr_v, dict): + result.extend(traverse_query_dict(arr_v, key)) + else: + result.append((key, arr_v)) + else: + result.append((key, v)) + return result + + +def single_query_encoder(query_key: str, query_value: Any) -> List[Tuple[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) + elif isinstance(query_value, list): + encoded_values: List[Tuple[str, Any]] = [] + for value in query_value: + if isinstance(value, pydantic.BaseModel) or isinstance(value, dict): + if isinstance(value, pydantic.BaseModel): + obj_dict = value.dict(by_alias=True) + elif isinstance(value, dict): + obj_dict = value + + encoded_values.extend(single_query_encoder(query_key, obj_dict)) + else: + encoded_values.append((query_key, value)) + + return encoded_values + + return [(query_key, query_value)] + + +def encode_query(query: Optional[Dict[str, Any]]) -> Optional[List[Tuple[str, Any]]]: + if query is None: + return None + + encoded_query = [] + for k, v in query.items(): + encoded_query.extend(single_query_encoder(k, v)) + return encoded_query diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/remove_none_from_dict.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/remove_none_from_dict.py new file mode 100644 index 000000000000..c2298143f14a --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/remove_none_from_dict.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Mapping, Optional + + +def remove_none_from_dict(original: Mapping[str, Optional[Any]]) -> Dict[str, Any]: + new: Dict[str, Any] = {} + for key, value in original.items(): + if value is not None: + new[key] = value + return new diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/request_options.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/request_options.py new file mode 100644 index 000000000000..1b38804432ba --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/request_options.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +try: + from typing import NotRequired # type: ignore +except ImportError: + from typing_extensions import NotRequired + + +class RequestOptions(typing.TypedDict, total=False): + """ + Additional options for request-specific configuration when calling APIs via the SDK. + This is used primarily as an optional final parameter for service functions. + + Attributes: + - timeout_in_seconds: int. The number of seconds to await an API call before timing out. + + - max_retries: int. The max number of retries to attempt if the API call fails. + + - additional_headers: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's header dict + + - additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict + + - additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict + + - chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads. + """ + + timeout_in_seconds: NotRequired[int] + max_retries: NotRequired[int] + additional_headers: NotRequired[typing.Dict[str, typing.Any]] + additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]] + additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]] + chunk_size: NotRequired[int] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/serialization.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/serialization.py new file mode 100644 index 000000000000..c36e865cc729 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/core/serialization.py @@ -0,0 +1,276 @@ +# This file was auto-generated by Fern from our API Definition. + +import collections +import inspect +import typing + +import pydantic +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, + direction: typing.Literal["read", "write"], +) -> 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) + # Pydantic models + if ( + inspect.isclass(clean_type) + and issubclass(clean_type, pydantic.BaseModel) + and isinstance(object_, typing.Mapping) + ): + return _convert_mapping(object_, clean_type, direction) + # TypedDicts + if typing_extensions.is_typeddict(clean_type) and isinstance(object_, typing.Mapping): + return _convert_mapping(object_, clean_type, direction) + + if ( + typing_extensions.get_origin(clean_type) == typing.Dict + or typing_extensions.get_origin(clean_type) == dict + or clean_type == typing.Dict + ) and isinstance(object_, typing.Dict): + key_type = typing_extensions.get_args(clean_type)[0] + value_type = typing_extensions.get_args(clean_type)[1] + + return { + key: convert_and_respect_annotation_metadata( + object_=value, + annotation=annotation, + inner_type=value_type, + direction=direction, + ) + for key, value in object_.items() + } + + # If you're iterating on a string, do not bother to coerce it to a sequence. + if not isinstance(object_, str): + if ( + 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): + inner_type = typing_extensions.get_args(clean_type)[0] + return { + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + } + elif ( + ( + 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.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, + direction=direction, + ) + 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, + direction=direction, + ) + 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_mapping( + object_: typing.Mapping[str, object], + expected_type: typing.Any, + direction: typing.Literal["read", "write"], +) -> typing.Mapping[str, object]: + converted_object: typing.Dict[str, object] = {} + try: + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + except NameError: + # The TypedDict contains a circular reference, so + # we use the __annotations__ attribute directly. + annotations = getattr(expected_type, "__annotations__", {}) + aliases_to_field_names = _get_alias_to_field_name(annotations) + for key, value in object_.items(): + if direction == "read" and key in aliases_to_field_names: + dealiased_key = aliases_to_field_names.get(key) + if dealiased_key is not None: + type_ = annotations.get(dealiased_key) + else: + type_ = annotations.get(key) + # Note you can't get the annotation by the field name if you're in read mode, so you must check the aliases map + # + # So this is effectively saying if we're in write mode, and we don't have a type, or if we're in read mode and we don't have an alias + # then we can just pass the value through as is + if type_ is None: + converted_object[key] = value + elif direction == "read" and key not in aliases_to_field_names: + converted_object[key] = convert_and_respect_annotation_metadata( + object_=value, annotation=type_, direction=direction + ) + else: + converted_object[_alias_key(key, type_, direction, aliases_to_field_names)] = ( + convert_and_respect_annotation_metadata(object_=value, annotation=type_, direction=direction) + ) + 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 get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_alias_to_field_name(annotations) + + +def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_field_to_alias_name(annotations) + + +def _get_alias_to_field_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[maybe_alias] = field + return aliases + + +def _get_field_to_alias_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[field] = maybe_alias + return aliases + + +def _get_alias_from_type(type_: typing.Any) -> typing.Optional[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 None + + +def _alias_key( + key: str, + type_: typing.Any, + direction: typing.Literal["read", "write"], + aliases_to_field_names: typing.Dict[str, str], +) -> str: + if direction == "read": + return aliases_to_field_names.get(key, key) + return _get_alias_from_type(type_=type_) or key diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/__init__.py new file mode 100644 index 000000000000..f510610c7532 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/__init__.py @@ -0,0 +1,63 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import container, content_type, enum, http_methods, object, params, primitive, put, union, urls + from .put import Error, ErrorCategory, ErrorCode, PutResponse +_dynamic_imports: typing.Dict[str, str] = { + "Error": ".put", + "ErrorCategory": ".put", + "ErrorCode": ".put", + "PutResponse": ".put", + "container": ".", + "content_type": ".", + "enum": ".", + "http_methods": ".", + "object": ".", + "params": ".", + "primitive": ".", + "put": ".", + "union": ".", + "urls": ".", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "Error", + "ErrorCategory", + "ErrorCode", + "PutResponse", + "container", + "content_type", + "enum", + "http_methods", + "object", + "params", + "primitive", + "put", + "union", + "urls", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/client.py new file mode 100644 index 000000000000..57beb70fca5c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/client.py @@ -0,0 +1,234 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .raw_client import AsyncRawEndpointsClient, RawEndpointsClient + +if typing.TYPE_CHECKING: + from .container.client import AsyncContainerClient, ContainerClient + from .content_type.client import AsyncContentTypeClient, ContentTypeClient + from .enum.client import AsyncEnumClient, EnumClient + from .http_methods.client import AsyncHttpMethodsClient, HttpMethodsClient + from .object.client import AsyncObjectClient, ObjectClient + from .params.client import AsyncParamsClient, ParamsClient + from .primitive.client import AsyncPrimitiveClient, PrimitiveClient + from .put.client import AsyncPutClient, PutClient + from .union.client import AsyncUnionClient, UnionClient + from .urls.client import AsyncUrlsClient, UrlsClient + + +class EndpointsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawEndpointsClient(client_wrapper=client_wrapper) + self._client_wrapper = client_wrapper + self._container: typing.Optional[ContainerClient] = None + self._content_type: typing.Optional[ContentTypeClient] = None + self._enum: typing.Optional[EnumClient] = None + self._http_methods: typing.Optional[HttpMethodsClient] = None + self._object: typing.Optional[ObjectClient] = None + self._params: typing.Optional[ParamsClient] = None + self._primitive: typing.Optional[PrimitiveClient] = None + self._put: typing.Optional[PutClient] = None + self._union: typing.Optional[UnionClient] = None + self._urls: typing.Optional[UrlsClient] = None + + @property + def with_raw_response(self) -> RawEndpointsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawEndpointsClient + """ + return self._raw_client + + @property + def container(self): + if self._container is None: + from .container.client import ContainerClient # noqa: E402 + + self._container = ContainerClient(client_wrapper=self._client_wrapper) + return self._container + + @property + def content_type(self): + if self._content_type is None: + from .content_type.client import ContentTypeClient # noqa: E402 + + self._content_type = ContentTypeClient(client_wrapper=self._client_wrapper) + return self._content_type + + @property + def enum(self): + if self._enum is None: + from .enum.client import EnumClient # noqa: E402 + + self._enum = EnumClient(client_wrapper=self._client_wrapper) + return self._enum + + @property + def http_methods(self): + if self._http_methods is None: + from .http_methods.client import HttpMethodsClient # noqa: E402 + + self._http_methods = HttpMethodsClient(client_wrapper=self._client_wrapper) + return self._http_methods + + @property + def object(self): + if self._object is None: + from .object.client import ObjectClient # noqa: E402 + + self._object = ObjectClient(client_wrapper=self._client_wrapper) + return self._object + + @property + def params(self): + if self._params is None: + from .params.client import ParamsClient # noqa: E402 + + self._params = ParamsClient(client_wrapper=self._client_wrapper) + return self._params + + @property + def primitive(self): + if self._primitive is None: + from .primitive.client import PrimitiveClient # noqa: E402 + + self._primitive = PrimitiveClient(client_wrapper=self._client_wrapper) + return self._primitive + + @property + def put(self): + if self._put is None: + from .put.client import PutClient # noqa: E402 + + self._put = PutClient(client_wrapper=self._client_wrapper) + return self._put + + @property + def union(self): + if self._union is None: + from .union.client import UnionClient # noqa: E402 + + self._union = UnionClient(client_wrapper=self._client_wrapper) + return self._union + + @property + def urls(self): + if self._urls is None: + from .urls.client import UrlsClient # noqa: E402 + + self._urls = UrlsClient(client_wrapper=self._client_wrapper) + return self._urls + + +class AsyncEndpointsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawEndpointsClient(client_wrapper=client_wrapper) + self._client_wrapper = client_wrapper + self._container: typing.Optional[AsyncContainerClient] = None + self._content_type: typing.Optional[AsyncContentTypeClient] = None + self._enum: typing.Optional[AsyncEnumClient] = None + self._http_methods: typing.Optional[AsyncHttpMethodsClient] = None + self._object: typing.Optional[AsyncObjectClient] = None + self._params: typing.Optional[AsyncParamsClient] = None + self._primitive: typing.Optional[AsyncPrimitiveClient] = None + self._put: typing.Optional[AsyncPutClient] = None + self._union: typing.Optional[AsyncUnionClient] = None + self._urls: typing.Optional[AsyncUrlsClient] = None + + @property + def with_raw_response(self) -> AsyncRawEndpointsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawEndpointsClient + """ + return self._raw_client + + @property + def container(self): + if self._container is None: + from .container.client import AsyncContainerClient # noqa: E402 + + self._container = AsyncContainerClient(client_wrapper=self._client_wrapper) + return self._container + + @property + def content_type(self): + if self._content_type is None: + from .content_type.client import AsyncContentTypeClient # noqa: E402 + + self._content_type = AsyncContentTypeClient(client_wrapper=self._client_wrapper) + return self._content_type + + @property + def enum(self): + if self._enum is None: + from .enum.client import AsyncEnumClient # noqa: E402 + + self._enum = AsyncEnumClient(client_wrapper=self._client_wrapper) + return self._enum + + @property + def http_methods(self): + if self._http_methods is None: + from .http_methods.client import AsyncHttpMethodsClient # noqa: E402 + + self._http_methods = AsyncHttpMethodsClient(client_wrapper=self._client_wrapper) + return self._http_methods + + @property + def object(self): + if self._object is None: + from .object.client import AsyncObjectClient # noqa: E402 + + self._object = AsyncObjectClient(client_wrapper=self._client_wrapper) + return self._object + + @property + def params(self): + if self._params is None: + from .params.client import AsyncParamsClient # noqa: E402 + + self._params = AsyncParamsClient(client_wrapper=self._client_wrapper) + return self._params + + @property + def primitive(self): + if self._primitive is None: + from .primitive.client import AsyncPrimitiveClient # noqa: E402 + + self._primitive = AsyncPrimitiveClient(client_wrapper=self._client_wrapper) + return self._primitive + + @property + def put(self): + if self._put is None: + from .put.client import AsyncPutClient # noqa: E402 + + self._put = AsyncPutClient(client_wrapper=self._client_wrapper) + return self._put + + @property + def union(self): + if self._union is None: + from .union.client import AsyncUnionClient # noqa: E402 + + self._union = AsyncUnionClient(client_wrapper=self._client_wrapper) + return self._union + + @property + def urls(self): + if self._urls is None: + from .urls.client import AsyncUrlsClient # noqa: E402 + + self._urls = AsyncUrlsClient(client_wrapper=self._client_wrapper) + return self._urls diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/client.py new file mode 100644 index 000000000000..079e691d68e2 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/client.py @@ -0,0 +1,599 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.object.types.object_with_required_field import ObjectWithRequiredField +from .raw_client import AsyncRawContainerClient, RawContainerClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ContainerClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawContainerClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawContainerClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawContainerClient + """ + return self._raw_client + + def get_and_return_list_of_primitives( + self, *, request: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[str]: + """ + Parameters + ---------- + request : typing.Sequence[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[str] + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_list_of_primitives( + request=["string", "string"], + ) + """ + _response = self._raw_client.get_and_return_list_of_primitives(request=request, request_options=request_options) + return _response.data + + def get_and_return_list_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ObjectWithRequiredField] + + Examples + -------- + from seed import SeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_list_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ), + ObjectWithRequiredField( + string="string", + ), + ], + ) + """ + _response = self._raw_client.get_and_return_list_of_objects(request=request, request_options=request_options) + return _response.data + + def get_and_return_set_of_primitives( + self, *, request: typing.Set[str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.Set[str]: + """ + Parameters + ---------- + request : typing.Set[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Set[str] + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_set_of_primitives( + request={"string"}, + ) + """ + _response = self._raw_client.get_and_return_set_of_primitives(request=request, request_options=request_options) + return _response.data + + def get_and_return_set_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ObjectWithRequiredField] + + Examples + -------- + from seed import SeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_set_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ) + ], + ) + """ + _response = self._raw_client.get_and_return_set_of_objects(request=request, request_options=request_options) + return _response.data + + def get_and_return_map_prim_to_prim( + self, *, request: typing.Dict[str, str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, str]: + """ + Parameters + ---------- + request : typing.Dict[str, str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, str] + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_map_prim_to_prim( + request={"string": "string"}, + ) + """ + _response = self._raw_client.get_and_return_map_prim_to_prim(request=request, request_options=request_options) + return _response.data + + def get_and_return_map_of_prim_to_object( + self, + *, + request: typing.Dict[str, ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Dict[str, ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, ObjectWithRequiredField] + + Examples + -------- + from seed import SeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_map_of_prim_to_object( + request={ + "string": ObjectWithRequiredField( + string="string", + ) + }, + ) + """ + _response = self._raw_client.get_and_return_map_of_prim_to_object( + request=request, request_options=request_options + ) + return _response.data + + def get_and_return_optional( + self, + *, + request: typing.Optional[ObjectWithRequiredField] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Optional[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Optional[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[ObjectWithRequiredField] + + Examples + -------- + from seed import SeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.container.get_and_return_optional( + request=ObjectWithRequiredField( + string="string", + ), + ) + """ + _response = self._raw_client.get_and_return_optional(request=request, request_options=request_options) + return _response.data + + +class AsyncContainerClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawContainerClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawContainerClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawContainerClient + """ + return self._raw_client + + async def get_and_return_list_of_primitives( + self, *, request: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[str]: + """ + Parameters + ---------- + request : typing.Sequence[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[str] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_list_of_primitives( + request=["string", "string"], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_list_of_primitives( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_list_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ObjectWithRequiredField] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_list_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ), + ObjectWithRequiredField( + string="string", + ), + ], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_list_of_objects( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_set_of_primitives( + self, *, request: typing.Set[str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.Set[str]: + """ + Parameters + ---------- + request : typing.Set[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Set[str] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_set_of_primitives( + request={"string"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_set_of_primitives( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_set_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[ObjectWithRequiredField] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_set_of_objects( + request=[ + ObjectWithRequiredField( + string="string", + ) + ], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_set_of_objects( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_map_prim_to_prim( + self, *, request: typing.Dict[str, str], request_options: typing.Optional[RequestOptions] = None + ) -> typing.Dict[str, str]: + """ + Parameters + ---------- + request : typing.Dict[str, str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, str] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_map_prim_to_prim( + request={"string": "string"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_map_prim_to_prim( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_map_of_prim_to_object( + self, + *, + request: typing.Dict[str, ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Dict[str, ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, ObjectWithRequiredField] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_map_of_prim_to_object( + request={ + "string": ObjectWithRequiredField( + string="string", + ) + }, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_map_of_prim_to_object( + request=request, request_options=request_options + ) + return _response.data + + async def get_and_return_optional( + self, + *, + request: typing.Optional[ObjectWithRequiredField] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Optional[ObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Optional[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[ObjectWithRequiredField] + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithRequiredField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.container.get_and_return_optional( + request=ObjectWithRequiredField( + string="string", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_optional(request=request, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/raw_client.py new file mode 100644 index 000000000000..83074b096fa9 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/container/raw_client.py @@ -0,0 +1,587 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.object.types.object_with_required_field import ObjectWithRequiredField + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawContainerClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_and_return_list_of_primitives( + self, *, request: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.List[str]]: + """ + Parameters + ---------- + request : typing.Sequence[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.List[str]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/list-of-primitives", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[str], + parse_obj_as( + type_=typing.List[str], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_list_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.List[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.List[ObjectWithRequiredField]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/list-of-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[ObjectWithRequiredField], + parse_obj_as( + type_=typing.List[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_set_of_primitives( + self, *, request: typing.Set[str], request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Set[str]]: + """ + Parameters + ---------- + request : typing.Set[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Set[str]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/set-of-primitives", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Set[str], + parse_obj_as( + type_=typing.Set[str], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_set_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.List[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.List[ObjectWithRequiredField]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/set-of-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[ObjectWithRequiredField], + parse_obj_as( + type_=typing.List[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_map_prim_to_prim( + self, *, request: typing.Dict[str, str], request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[typing.Dict[str, str]]: + """ + Parameters + ---------- + request : typing.Dict[str, str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, str]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/map-prim-to-prim", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, str], + parse_obj_as( + type_=typing.Dict[str, str], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_map_of_prim_to_object( + self, + *, + request: typing.Dict[str, ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Dict[str, ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, ObjectWithRequiredField]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/map-prim-to-object", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Dict[str, ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, ObjectWithRequiredField], + parse_obj_as( + type_=typing.Dict[str, ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_optional( + self, + *, + request: typing.Optional[ObjectWithRequiredField] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Optional[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Optional[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Optional[ObjectWithRequiredField]] + """ + _response = self._client_wrapper.httpx_client.request( + "container/opt-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ObjectWithRequiredField, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if _response is None or not _response.text.strip(): + return HttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Optional[ObjectWithRequiredField], + parse_obj_as( + type_=typing.Optional[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawContainerClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_and_return_list_of_primitives( + self, *, request: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.List[str]]: + """ + Parameters + ---------- + request : typing.Sequence[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.List[str]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/list-of-primitives", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[str], + parse_obj_as( + type_=typing.List[str], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_list_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.List[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.List[ObjectWithRequiredField]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/list-of-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[ObjectWithRequiredField], + parse_obj_as( + type_=typing.List[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_set_of_primitives( + self, *, request: typing.Set[str], request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Set[str]]: + """ + Parameters + ---------- + request : typing.Set[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Set[str]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/set-of-primitives", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Set[str], + parse_obj_as( + type_=typing.Set[str], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_set_of_objects( + self, + *, + request: typing.Sequence[ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.List[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Sequence[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.List[ObjectWithRequiredField]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/set-of-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[ObjectWithRequiredField], + parse_obj_as( + type_=typing.List[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_map_prim_to_prim( + self, *, request: typing.Dict[str, str], request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[typing.Dict[str, str]]: + """ + Parameters + ---------- + request : typing.Dict[str, str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, str]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/map-prim-to-prim", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, str], + parse_obj_as( + type_=typing.Dict[str, str], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_map_of_prim_to_object( + self, + *, + request: typing.Dict[str, ObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Dict[str, ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, ObjectWithRequiredField]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/map-prim-to-object", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Dict[str, ObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, ObjectWithRequiredField], + parse_obj_as( + type_=typing.Dict[str, ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_optional( + self, + *, + request: typing.Optional[ObjectWithRequiredField] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Optional[ObjectWithRequiredField]]: + """ + Parameters + ---------- + request : typing.Optional[ObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Optional[ObjectWithRequiredField]] + """ + _response = await self._client_wrapper.httpx_client.request( + "container/opt-objects", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ObjectWithRequiredField, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if _response is None or not _response.text.strip(): + return AsyncHttpResponse(response=_response, data=None) + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Optional[ObjectWithRequiredField], + parse_obj_as( + type_=typing.Optional[ObjectWithRequiredField], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/client.py new file mode 100644 index 000000000000..8d1b852f5d4b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/client.py @@ -0,0 +1,482 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from .raw_client import AsyncRawContentTypeClient, RawContentTypeClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ContentTypeClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawContentTypeClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawContentTypeClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawContentTypeClient + """ + return self._raw_client + + def post_json_patch_content_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.content_type.post_json_patch_content_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + """ + _response = self._raw_client.post_json_patch_content_type( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + def post_json_patch_content_with_charset_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.content_type.post_json_patch_content_with_charset_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + """ + _response = self._raw_client.post_json_patch_content_with_charset_type( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + +class AsyncContentTypeClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawContentTypeClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawContentTypeClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawContentTypeClient + """ + return self._raw_client + + async def post_json_patch_content_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.content_type.post_json_patch_content_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.post_json_patch_content_type( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + async def post_json_patch_content_with_charset_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.content_type.post_json_patch_content_with_charset_type( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.post_json_patch_content_with_charset_type( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/raw_client.py new file mode 100644 index 000000000000..66e2642f57e2 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/content_type/raw_client.py @@ -0,0 +1,372 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawContentTypeClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def post_json_patch_content_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "foo/bar", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + headers={ + "content-type": "application/json-patch+json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def post_json_patch_content_with_charset_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "foo/baz", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + headers={ + "content-type": "application/json-patch+json; charset=utf-8", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawContentTypeClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def post_json_patch_content_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "foo/bar", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + headers={ + "content-type": "application/json-patch+json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def post_json_patch_content_with_charset_type( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "foo/baz", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + headers={ + "content-type": "application/json-patch+json; charset=utf-8", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/client.py new file mode 100644 index 000000000000..339460ec56ad --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/client.py @@ -0,0 +1,111 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.enum.types.weather_report import WeatherReport +from .raw_client import AsyncRawEnumClient, RawEnumClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class EnumClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawEnumClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawEnumClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawEnumClient + """ + return self._raw_client + + def get_and_return_enum( + self, *, request: WeatherReport, request_options: typing.Optional[RequestOptions] = None + ) -> WeatherReport: + """ + Parameters + ---------- + request : WeatherReport + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WeatherReport + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.enum.get_and_return_enum( + request="SUNNY", + ) + """ + _response = self._raw_client.get_and_return_enum(request=request, request_options=request_options) + return _response.data + + +class AsyncEnumClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawEnumClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawEnumClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawEnumClient + """ + return self._raw_client + + async def get_and_return_enum( + self, *, request: WeatherReport, request_options: typing.Optional[RequestOptions] = None + ) -> WeatherReport: + """ + Parameters + ---------- + request : WeatherReport + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WeatherReport + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.enum.get_and_return_enum( + request="SUNNY", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_enum(request=request, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/raw_client.py new file mode 100644 index 000000000000..2a83dd84de5b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/enum/raw_client.py @@ -0,0 +1,98 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...types.enum.types.weather_report import WeatherReport + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawEnumClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_and_return_enum( + self, *, request: WeatherReport, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[WeatherReport]: + """ + Parameters + ---------- + request : WeatherReport + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WeatherReport] + """ + _response = self._client_wrapper.httpx_client.request( + "enum", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WeatherReport, + parse_obj_as( + type_=WeatherReport, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawEnumClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_and_return_enum( + self, *, request: WeatherReport, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[WeatherReport]: + """ + Parameters + ---------- + request : WeatherReport + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WeatherReport] + """ + _response = await self._client_wrapper.httpx_client.request( + "enum", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WeatherReport, + parse_obj_as( + type_=WeatherReport, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/client.py new file mode 100644 index 000000000000..ad3dcecbeeec --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/client.py @@ -0,0 +1,544 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.object.types.object_with_optional_field import ObjectWithOptionalField +from .raw_client import AsyncRawHttpMethodsClient, RawHttpMethodsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class HttpMethodsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawHttpMethodsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawHttpMethodsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawHttpMethodsClient + """ + return self._raw_client + + def test_get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.http_methods.test_get( + id="id", + ) + """ + _response = self._raw_client.test_get(id, request_options=request_options) + return _response.data + + def test_post( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.http_methods.test_post( + string="string", + ) + """ + _response = self._raw_client.test_post(string=string, request_options=request_options) + return _response.data + + def test_put( + self, id: str, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + id : str + + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.http_methods.test_put( + id="id", + string="string", + ) + """ + _response = self._raw_client.test_put(id, string=string, request_options=request_options) + return _response.data + + def test_patch( + self, + id: str, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + id : str + + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.http_methods.test_patch( + id="id", + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + """ + _response = self._raw_client.test_patch( + id, + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + def test_delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> bool: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.http_methods.test_delete( + id="id", + ) + """ + _response = self._raw_client.test_delete(id, request_options=request_options) + return _response.data + + +class AsyncHttpMethodsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawHttpMethodsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawHttpMethodsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawHttpMethodsClient + """ + return self._raw_client + + async def test_get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.http_methods.test_get( + id="id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.test_get(id, request_options=request_options) + return _response.data + + async def test_post( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.http_methods.test_post( + string="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.test_post(string=string, request_options=request_options) + return _response.data + + async def test_put( + self, id: str, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + id : str + + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.http_methods.test_put( + id="id", + string="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.test_put(id, string=string, request_options=request_options) + return _response.data + + async def test_patch( + self, + id: str, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + id : str + + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.http_methods.test_patch( + id="id", + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.test_patch( + id, + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + async def test_delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> bool: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.http_methods.test_delete( + id="id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.test_delete(id, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/raw_client.py new file mode 100644 index 000000000000..ff94647dd9af --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/http_methods/raw_client.py @@ -0,0 +1,511 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...types.object.types.object_with_optional_field import ObjectWithOptionalField + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawHttpMethodsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def test_get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[str]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def test_post( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + "http-methods", + method="POST", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def test_put( + self, id: str, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + id : str + + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="PUT", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def test_patch( + self, + id: str, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + id : str + + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="PATCH", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def test_delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[bool]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[bool] + """ + _response = self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawHttpMethodsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def test_get( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def test_post( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + "http-methods", + method="POST", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def test_put( + self, id: str, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + id : str + + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="PUT", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def test_patch( + self, + id: str, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + id : str + + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="PATCH", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def test_delete( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[bool]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[bool] + """ + _response = await self._client_wrapper.httpx_client.request( + f"http-methods/{jsonable_encoder(id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/client.py new file mode 100644 index 000000000000..57bd6df98e50 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/client.py @@ -0,0 +1,869 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.object.types.nested_object_with_optional_field import NestedObjectWithOptionalField +from ...types.object.types.nested_object_with_required_field import NestedObjectWithRequiredField +from ...types.object.types.object_with_map_of_map import ObjectWithMapOfMap +from ...types.object.types.object_with_optional_field import ObjectWithOptionalField +from ...types.object.types.object_with_required_field import ObjectWithRequiredField +from .raw_client import AsyncRawObjectClient, RawObjectClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ObjectClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawObjectClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawObjectClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawObjectClient + """ + return self._raw_client + + def get_and_return_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_with_optional_field( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + """ + _response = self._raw_client.get_and_return_with_optional_field( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + def get_and_return_with_required_field( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithRequiredField: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithRequiredField + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_with_required_field( + string="string", + ) + """ + _response = self._raw_client.get_and_return_with_required_field(string=string, request_options=request_options) + return _response.data + + def get_and_return_with_map_of_map( + self, *, map_: typing.Dict[str, typing.Dict[str, str]], request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithMapOfMap: + """ + Parameters + ---------- + map_ : typing.Dict[str, typing.Dict[str, str]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithMapOfMap + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_with_map_of_map( + map_={"map": {"map": "map"}}, + ) + """ + _response = self._raw_client.get_and_return_with_map_of_map(map_=map_, request_options=request_options) + return _response.data + + def get_and_return_nested_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + nested_object: typing.Optional[ObjectWithOptionalField] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithOptionalField: + """ + Parameters + ---------- + string : typing.Optional[str] + + nested_object : typing.Optional[ObjectWithOptionalField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithOptionalField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_nested_with_optional_field( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + """ + _response = self._raw_client.get_and_return_nested_with_optional_field( + string=string, nested_object=nested_object, request_options=request_options + ) + return _response.data + + def get_and_return_nested_with_required_field( + self, + string_: str, + *, + string: str, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithRequiredField: + """ + Parameters + ---------- + string_ : str + + string : str + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithRequiredField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_nested_with_required_field( + string_="string", + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + """ + _response = self._raw_client.get_and_return_nested_with_required_field( + string_, string=string, nested_object=nested_object, request_options=request_options + ) + return _response.data + + def get_and_return_nested_with_required_field_as_list( + self, + *, + request: typing.Sequence[NestedObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithRequiredField: + """ + Parameters + ---------- + request : typing.Sequence[NestedObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithRequiredField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + from seed.types.object import ( + NestedObjectWithRequiredField, + ObjectWithOptionalField, + ) + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.object.get_and_return_nested_with_required_field_as_list( + request=[ + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + ], + ) + """ + _response = self._raw_client.get_and_return_nested_with_required_field_as_list( + request=request, request_options=request_options + ) + return _response.data + + +class AsyncObjectClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawObjectClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawObjectClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawObjectClient + """ + return self._raw_client + + async def get_and_return_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_with_optional_field( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_with_optional_field( + string=string, + integer=integer, + long_=long_, + double=double, + bool_=bool_, + datetime=datetime, + date=date, + uuid_=uuid_, + base_64=base_64, + list_=list_, + set_=set_, + map_=map_, + bigint=bigint, + request_options=request_options, + ) + return _response.data + + async def get_and_return_with_required_field( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithRequiredField: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithRequiredField + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_with_required_field( + string="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_with_required_field( + string=string, request_options=request_options + ) + return _response.data + + async def get_and_return_with_map_of_map( + self, *, map_: typing.Dict[str, typing.Dict[str, str]], request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithMapOfMap: + """ + Parameters + ---------- + map_ : typing.Dict[str, typing.Dict[str, str]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithMapOfMap + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_with_map_of_map( + map_={"map": {"map": "map"}}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_with_map_of_map(map_=map_, request_options=request_options) + return _response.data + + async def get_and_return_nested_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + nested_object: typing.Optional[ObjectWithOptionalField] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithOptionalField: + """ + Parameters + ---------- + string : typing.Optional[str] + + nested_object : typing.Optional[ObjectWithOptionalField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithOptionalField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_nested_with_optional_field( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_nested_with_optional_field( + string=string, nested_object=nested_object, request_options=request_options + ) + return _response.data + + async def get_and_return_nested_with_required_field( + self, + string_: str, + *, + string: str, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithRequiredField: + """ + Parameters + ---------- + string_ : str + + string : str + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithRequiredField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_nested_with_required_field( + string_="string", + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_nested_with_required_field( + string_, string=string, nested_object=nested_object, request_options=request_options + ) + return _response.data + + async def get_and_return_nested_with_required_field_as_list( + self, + *, + request: typing.Sequence[NestedObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> NestedObjectWithRequiredField: + """ + Parameters + ---------- + request : typing.Sequence[NestedObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + NestedObjectWithRequiredField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + from seed.types.object import ( + NestedObjectWithRequiredField, + ObjectWithOptionalField, + ) + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.object.get_and_return_nested_with_required_field_as_list( + request=[ + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + NestedObjectWithRequiredField( + string="string", + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ), + ], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_nested_with_required_field_as_list( + request=request, request_options=request_options + ) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/raw_client.py new file mode 100644 index 000000000000..af413f29b3bd --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/object/raw_client.py @@ -0,0 +1,652 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.object.types.nested_object_with_optional_field import NestedObjectWithOptionalField +from ...types.object.types.nested_object_with_required_field import NestedObjectWithRequiredField +from ...types.object.types.object_with_map_of_map import ObjectWithMapOfMap +from ...types.object.types.object_with_optional_field import ObjectWithOptionalField +from ...types.object.types.object_with_required_field import ObjectWithRequiredField + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawObjectClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_and_return_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + "object/get-and-return-with-optional-field", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_with_required_field( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ObjectWithRequiredField]: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithRequiredField] + """ + _response = self._client_wrapper.httpx_client.request( + "object/get-and-return-with-required-field", + method="POST", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithRequiredField, + parse_obj_as( + type_=ObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_with_map_of_map( + self, *, map_: typing.Dict[str, typing.Dict[str, str]], request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ObjectWithMapOfMap]: + """ + Parameters + ---------- + map_ : typing.Dict[str, typing.Dict[str, str]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithMapOfMap] + """ + _response = self._client_wrapper.httpx_client.request( + "object/get-and-return-with-map-of-map", + method="POST", + json={ + "map": map_, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithMapOfMap, + parse_obj_as( + type_=ObjectWithMapOfMap, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_nested_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + nested_object: typing.Optional[ObjectWithOptionalField] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[NestedObjectWithOptionalField]: + """ + Parameters + ---------- + string : typing.Optional[str] + + nested_object : typing.Optional[ObjectWithOptionalField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[NestedObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + "object/get-and-return-nested-with-optional-field", + method="POST", + json={ + "string": string, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithOptionalField, + parse_obj_as( + type_=NestedObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_nested_with_required_field( + self, + string_: str, + *, + string: str, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[NestedObjectWithRequiredField]: + """ + Parameters + ---------- + string_ : str + + string : str + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[NestedObjectWithRequiredField] + """ + _response = self._client_wrapper.httpx_client.request( + f"object/get-and-return-nested-with-required-field/{jsonable_encoder(string_)}", + method="POST", + json={ + "string": string, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithRequiredField, + parse_obj_as( + type_=NestedObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_nested_with_required_field_as_list( + self, + *, + request: typing.Sequence[NestedObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[NestedObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[NestedObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[NestedObjectWithRequiredField] + """ + _response = self._client_wrapper.httpx_client.request( + "object/get-and-return-nested-with-required-field-list", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[NestedObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithRequiredField, + parse_obj_as( + type_=NestedObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawObjectClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_and_return_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + integer: typing.Optional[int] = OMIT, + long_: typing.Optional[int] = OMIT, + double: typing.Optional[float] = OMIT, + bool_: typing.Optional[bool] = OMIT, + datetime: typing.Optional[dt.datetime] = OMIT, + date: typing.Optional[dt.date] = OMIT, + uuid_: typing.Optional[uuid.UUID] = OMIT, + base_64: typing.Optional[str] = OMIT, + list_: typing.Optional[typing.Sequence[str]] = OMIT, + set_: typing.Optional[typing.Set[str]] = OMIT, + map_: typing.Optional[typing.Dict[int, str]] = OMIT, + bigint: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + string : typing.Optional[str] + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + + integer : typing.Optional[int] + + long_ : typing.Optional[int] + + double : typing.Optional[float] + + bool_ : typing.Optional[bool] + + datetime : typing.Optional[dt.datetime] + + date : typing.Optional[dt.date] + + uuid_ : typing.Optional[uuid.UUID] + + base_64 : typing.Optional[str] + + list_ : typing.Optional[typing.Sequence[str]] + + set_ : typing.Optional[typing.Set[str]] + + map_ : typing.Optional[typing.Dict[int, str]] + + bigint : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + "object/get-and-return-with-optional-field", + method="POST", + json={ + "string": string, + "integer": integer, + "long": long_, + "double": double, + "bool": bool_, + "datetime": datetime, + "date": date, + "uuid": uuid_, + "base64": base_64, + "list": list_, + "set": set_, + "map": map_, + "bigint": bigint, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_with_required_field( + self, *, string: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ObjectWithRequiredField]: + """ + Parameters + ---------- + string : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithRequiredField] + """ + _response = await self._client_wrapper.httpx_client.request( + "object/get-and-return-with-required-field", + method="POST", + json={ + "string": string, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithRequiredField, + parse_obj_as( + type_=ObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_with_map_of_map( + self, *, map_: typing.Dict[str, typing.Dict[str, str]], request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ObjectWithMapOfMap]: + """ + Parameters + ---------- + map_ : typing.Dict[str, typing.Dict[str, str]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithMapOfMap] + """ + _response = await self._client_wrapper.httpx_client.request( + "object/get-and-return-with-map-of-map", + method="POST", + json={ + "map": map_, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithMapOfMap, + parse_obj_as( + type_=ObjectWithMapOfMap, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_nested_with_optional_field( + self, + *, + string: typing.Optional[str] = OMIT, + nested_object: typing.Optional[ObjectWithOptionalField] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[NestedObjectWithOptionalField]: + """ + Parameters + ---------- + string : typing.Optional[str] + + nested_object : typing.Optional[ObjectWithOptionalField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[NestedObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + "object/get-and-return-nested-with-optional-field", + method="POST", + json={ + "string": string, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithOptionalField, + parse_obj_as( + type_=NestedObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_nested_with_required_field( + self, + string_: str, + *, + string: str, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[NestedObjectWithRequiredField]: + """ + Parameters + ---------- + string_ : str + + string : str + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[NestedObjectWithRequiredField] + """ + _response = await self._client_wrapper.httpx_client.request( + f"object/get-and-return-nested-with-required-field/{jsonable_encoder(string_)}", + method="POST", + json={ + "string": string, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithRequiredField, + parse_obj_as( + type_=NestedObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_nested_with_required_field_as_list( + self, + *, + request: typing.Sequence[NestedObjectWithRequiredField], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[NestedObjectWithRequiredField]: + """ + Parameters + ---------- + request : typing.Sequence[NestedObjectWithRequiredField] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[NestedObjectWithRequiredField] + """ + _response = await self._client_wrapper.httpx_client.request( + "object/get-and-return-nested-with-required-field-list", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[NestedObjectWithRequiredField], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + NestedObjectWithRequiredField, + parse_obj_as( + type_=NestedObjectWithRequiredField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/client.py new file mode 100644 index 000000000000..f8e235381b5b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/client.py @@ -0,0 +1,662 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from .raw_client import AsyncRawParamsClient, RawParamsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ParamsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawParamsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawParamsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawParamsClient + """ + return self._raw_client + + def get_with_path(self, param: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_path( + param="param", + ) + """ + _response = self._raw_client.get_with_path(param, request_options=request_options) + return _response.data + + def get_with_inline_path(self, param: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_inline_path( + param="param", + ) + """ + _response = self._raw_client.get_with_inline_path(param, request_options=request_options) + return _response.data + + def get_with_query( + self, *, query: str, number: int, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with query param + + Parameters + ---------- + query : str + + number : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_query( + query="query", + number=1, + ) + """ + _response = self._raw_client.get_with_query(query=query, number=number, request_options=request_options) + return _response.data + + def get_with_allow_multiple_query( + self, + *, + query: typing.Union[str, typing.Sequence[str]], + number: typing.Union[int, typing.Sequence[int]], + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + GET with multiple of same query param + + Parameters + ---------- + query : typing.Union[str, typing.Sequence[str]] + + number : typing.Union[int, typing.Sequence[int]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_allow_multiple_query( + query="query", + number=1, + ) + """ + _response = self._raw_client.get_with_allow_multiple_query( + query=query, number=number, request_options=request_options + ) + return _response.data + + def get_with_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_path_and_query( + param="param", + query="query", + ) + """ + _response = self._raw_client.get_with_path_and_query(param, query=query, request_options=request_options) + return _response.data + + def get_with_inline_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.get_with_inline_path_and_query( + param="param", + query="query", + ) + """ + _response = self._raw_client.get_with_inline_path_and_query(param, query=query, request_options=request_options) + return _response.data + + def modify_with_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.modify_with_path( + param="param", + request="string", + ) + """ + _response = self._raw_client.modify_with_path(param, request=request, request_options=request_options) + return _response.data + + def modify_with_inline_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.params.modify_with_inline_path( + param="param", + request="string", + ) + """ + _response = self._raw_client.modify_with_inline_path(param, request=request, request_options=request_options) + return _response.data + + +class AsyncParamsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawParamsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawParamsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawParamsClient + """ + return self._raw_client + + async def get_with_path(self, param: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_path( + param="param", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_path(param, request_options=request_options) + return _response.data + + async def get_with_inline_path(self, param: str, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_inline_path( + param="param", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_inline_path(param, request_options=request_options) + return _response.data + + async def get_with_query( + self, *, query: str, number: int, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with query param + + Parameters + ---------- + query : str + + number : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_query( + query="query", + number=1, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_query(query=query, number=number, request_options=request_options) + return _response.data + + async def get_with_allow_multiple_query( + self, + *, + query: typing.Union[str, typing.Sequence[str]], + number: typing.Union[int, typing.Sequence[int]], + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + GET with multiple of same query param + + Parameters + ---------- + query : typing.Union[str, typing.Sequence[str]] + + number : typing.Union[int, typing.Sequence[int]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_allow_multiple_query( + query="query", + number=1, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_allow_multiple_query( + query=query, number=number, request_options=request_options + ) + return _response.data + + async def get_with_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_path_and_query( + param="param", + query="query", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_path_and_query(param, query=query, request_options=request_options) + return _response.data + + async def get_with_inline_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.get_with_inline_path_and_query( + param="param", + query="query", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_inline_path_and_query( + param, query=query, request_options=request_options + ) + return _response.data + + async def modify_with_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.modify_with_path( + param="param", + request="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.modify_with_path(param, request=request, request_options=request_options) + return _response.data + + async def modify_with_inline_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.params.modify_with_inline_path( + param="param", + request="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.modify_with_inline_path( + param, request=request, request_options=request_options + ) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/raw_client.py new file mode 100644 index 000000000000..9328189418af --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/params/raw_client.py @@ -0,0 +1,628 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawParamsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_with_path( + self, param: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_with_inline_path( + self, param: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_with_query( + self, *, query: str, number: int, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + GET with query param + + Parameters + ---------- + query : str + + number : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "params", + method="GET", + params={ + "query": query, + "number": number, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_with_allow_multiple_query( + self, + *, + query: typing.Union[str, typing.Sequence[str]], + number: typing.Union[int, typing.Sequence[int]], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + GET with multiple of same query param + + Parameters + ---------- + query : typing.Union[str, typing.Sequence[str]] + + number : typing.Union[int, typing.Sequence[int]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "params", + method="GET", + params={ + "query": query, + "number": number, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_with_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path-query/{jsonable_encoder(param)}", + method="GET", + params={ + "query": query, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_with_inline_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path-query/{jsonable_encoder(param)}", + method="GET", + params={ + "query": query, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def modify_with_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="PUT", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def modify_with_inline_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="PUT", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawParamsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_with_path( + self, param: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_with_inline_path( + self, param: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + GET with path param + + Parameters + ---------- + param : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_with_query( + self, *, query: str, number: int, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + GET with query param + + Parameters + ---------- + query : str + + number : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "params", + method="GET", + params={ + "query": query, + "number": number, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_with_allow_multiple_query( + self, + *, + query: typing.Union[str, typing.Sequence[str]], + number: typing.Union[int, typing.Sequence[int]], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + GET with multiple of same query param + + Parameters + ---------- + query : typing.Union[str, typing.Sequence[str]] + + number : typing.Union[int, typing.Sequence[int]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "params", + method="GET", + params={ + "query": query, + "number": number, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_with_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path-query/{jsonable_encoder(param)}", + method="GET", + params={ + "query": query, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_with_inline_path_and_query( + self, param: str, *, query: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + GET with path and query params + + Parameters + ---------- + param : str + + query : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path-query/{jsonable_encoder(param)}", + method="GET", + params={ + "query": query, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def modify_with_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="PUT", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def modify_with_inline_path( + self, param: str, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + PUT to update with path param + + Parameters + ---------- + param : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + f"params/path/{jsonable_encoder(param)}", + method="PUT", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/client.py new file mode 100644 index 000000000000..6a67a8dc662b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/client.py @@ -0,0 +1,665 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from .raw_client import AsyncRawPrimitiveClient, RawPrimitiveClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class PrimitiveClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawPrimitiveClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPrimitiveClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPrimitiveClient + """ + return self._raw_client + + def get_and_return_string(self, *, request: str, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_string( + request="string", + ) + """ + _response = self._raw_client.get_and_return_string(request=request, request_options=request_options) + return _response.data + + def get_and_return_int(self, *, request: int, request_options: typing.Optional[RequestOptions] = None) -> int: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + int + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_int( + request=1, + ) + """ + _response = self._raw_client.get_and_return_int(request=request, request_options=request_options) + return _response.data + + def get_and_return_long(self, *, request: int, request_options: typing.Optional[RequestOptions] = None) -> int: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + int + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_long( + request=1000000, + ) + """ + _response = self._raw_client.get_and_return_long(request=request, request_options=request_options) + return _response.data + + def get_and_return_double( + self, *, request: float, request_options: typing.Optional[RequestOptions] = None + ) -> float: + """ + Parameters + ---------- + request : float + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + float + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_double( + request=1.1, + ) + """ + _response = self._raw_client.get_and_return_double(request=request, request_options=request_options) + return _response.data + + def get_and_return_bool(self, *, request: bool, request_options: typing.Optional[RequestOptions] = None) -> bool: + """ + Parameters + ---------- + request : bool + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_bool( + request=True, + ) + """ + _response = self._raw_client.get_and_return_bool(request=request, request_options=request_options) + return _response.data + + def get_and_return_datetime( + self, *, request: dt.datetime, request_options: typing.Optional[RequestOptions] = None + ) -> dt.datetime: + """ + Parameters + ---------- + request : dt.datetime + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + dt.datetime + + Examples + -------- + import datetime + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_datetime( + request=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + ) + """ + _response = self._raw_client.get_and_return_datetime(request=request, request_options=request_options) + return _response.data + + def get_and_return_date( + self, *, request: dt.date, request_options: typing.Optional[RequestOptions] = None + ) -> dt.date: + """ + Parameters + ---------- + request : dt.date + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + dt.date + + Examples + -------- + import datetime + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_date( + request=datetime.date.fromisoformat( + "2023-01-15", + ), + ) + """ + _response = self._raw_client.get_and_return_date(request=request, request_options=request_options) + return _response.data + + def get_and_return_uuid( + self, *, request: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> uuid.UUID: + """ + Parameters + ---------- + request : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + uuid.UUID + + Examples + -------- + import uuid + + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_uuid( + request=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + ) + """ + _response = self._raw_client.get_and_return_uuid(request=request, request_options=request_options) + return _response.data + + def get_and_return_base_64(self, *, request: str, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.primitive.get_and_return_base_64( + request="SGVsbG8gd29ybGQh", + ) + """ + _response = self._raw_client.get_and_return_base_64(request=request, request_options=request_options) + return _response.data + + +class AsyncPrimitiveClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawPrimitiveClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPrimitiveClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPrimitiveClient + """ + return self._raw_client + + async def get_and_return_string( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_string( + request="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_string(request=request, request_options=request_options) + return _response.data + + async def get_and_return_int(self, *, request: int, request_options: typing.Optional[RequestOptions] = None) -> int: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + int + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_int( + request=1, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_int(request=request, request_options=request_options) + return _response.data + + async def get_and_return_long( + self, *, request: int, request_options: typing.Optional[RequestOptions] = None + ) -> int: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + int + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_long( + request=1000000, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_long(request=request, request_options=request_options) + return _response.data + + async def get_and_return_double( + self, *, request: float, request_options: typing.Optional[RequestOptions] = None + ) -> float: + """ + Parameters + ---------- + request : float + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + float + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_double( + request=1.1, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_double(request=request, request_options=request_options) + return _response.data + + async def get_and_return_bool( + self, *, request: bool, request_options: typing.Optional[RequestOptions] = None + ) -> bool: + """ + Parameters + ---------- + request : bool + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_bool( + request=True, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_bool(request=request, request_options=request_options) + return _response.data + + async def get_and_return_datetime( + self, *, request: dt.datetime, request_options: typing.Optional[RequestOptions] = None + ) -> dt.datetime: + """ + Parameters + ---------- + request : dt.datetime + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + dt.datetime + + Examples + -------- + import asyncio + import datetime + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_datetime( + request=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_datetime(request=request, request_options=request_options) + return _response.data + + async def get_and_return_date( + self, *, request: dt.date, request_options: typing.Optional[RequestOptions] = None + ) -> dt.date: + """ + Parameters + ---------- + request : dt.date + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + dt.date + + Examples + -------- + import asyncio + import datetime + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_date( + request=datetime.date.fromisoformat( + "2023-01-15", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_date(request=request, request_options=request_options) + return _response.data + + async def get_and_return_uuid( + self, *, request: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> uuid.UUID: + """ + Parameters + ---------- + request : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + uuid.UUID + + Examples + -------- + import asyncio + import uuid + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_uuid( + request=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_uuid(request=request, request_options=request_options) + return _response.data + + async def get_and_return_base_64( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> str: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.primitive.get_and_return_base_64( + request="SGVsbG8gd29ybGQh", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_base_64(request=request, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/raw_client.py new file mode 100644 index 000000000000..f0dad324321f --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/primitive/raw_client.py @@ -0,0 +1,691 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawPrimitiveClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_and_return_string( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/string", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_int( + self, *, request: int, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[int]: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[int] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/integer", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + int, + parse_obj_as( + type_=int, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_long( + self, *, request: int, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[int]: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[int] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/long", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + int, + parse_obj_as( + type_=int, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_double( + self, *, request: float, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[float]: + """ + Parameters + ---------- + request : float + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[float] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/double", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + float, + parse_obj_as( + type_=float, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_bool( + self, *, request: bool, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[bool]: + """ + Parameters + ---------- + request : bool + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[bool] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/boolean", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_datetime( + self, *, request: dt.datetime, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[dt.datetime]: + """ + Parameters + ---------- + request : dt.datetime + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[dt.datetime] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/datetime", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + dt.datetime, + parse_obj_as( + type_=dt.datetime, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_date( + self, *, request: dt.date, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[dt.date]: + """ + Parameters + ---------- + request : dt.date + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[dt.date] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/date", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + dt.date, + parse_obj_as( + type_=dt.date, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_uuid( + self, *, request: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[uuid.UUID]: + """ + Parameters + ---------- + request : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[uuid.UUID] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/uuid", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + uuid.UUID, + parse_obj_as( + type_=uuid.UUID, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_and_return_base_64( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "primitive/base64", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPrimitiveClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_and_return_string( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/string", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_int( + self, *, request: int, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[int]: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[int] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/integer", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + int, + parse_obj_as( + type_=int, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_long( + self, *, request: int, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[int]: + """ + Parameters + ---------- + request : int + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[int] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/long", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + int, + parse_obj_as( + type_=int, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_double( + self, *, request: float, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[float]: + """ + Parameters + ---------- + request : float + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[float] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/double", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + float, + parse_obj_as( + type_=float, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_bool( + self, *, request: bool, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[bool]: + """ + Parameters + ---------- + request : bool + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[bool] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/boolean", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_datetime( + self, *, request: dt.datetime, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[dt.datetime]: + """ + Parameters + ---------- + request : dt.datetime + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[dt.datetime] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/datetime", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + dt.datetime, + parse_obj_as( + type_=dt.datetime, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_date( + self, *, request: dt.date, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[dt.date]: + """ + Parameters + ---------- + request : dt.date + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[dt.date] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/date", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + dt.date, + parse_obj_as( + type_=dt.date, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_uuid( + self, *, request: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[uuid.UUID]: + """ + Parameters + ---------- + request : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[uuid.UUID] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/uuid", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + uuid.UUID, + parse_obj_as( + type_=uuid.UUID, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_and_return_base_64( + self, *, request: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "primitive/base64", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/__init__.py new file mode 100644 index 000000000000..adef89178b17 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/__init__.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import Error, ErrorCategory, ErrorCode, PutResponse +_dynamic_imports: typing.Dict[str, str] = { + "Error": ".types", + "ErrorCategory": ".types", + "ErrorCode": ".types", + "PutResponse": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/client.py new file mode 100644 index 000000000000..2fbec47f0220 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/client.py @@ -0,0 +1,104 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from .raw_client import AsyncRawPutClient, RawPutClient +from .types.put_response import PutResponse + + +class PutClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawPutClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPutClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPutClient + """ + return self._raw_client + + def add(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> PutResponse: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PutResponse + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.put.add( + id="id", + ) + """ + _response = self._raw_client.add(id, request_options=request_options) + return _response.data + + +class AsyncPutClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawPutClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPutClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPutClient + """ + return self._raw_client + + async def add(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> PutResponse: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PutResponse + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.put.add( + id="id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.add(id, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/raw_client.py new file mode 100644 index 000000000000..82072e62efdc --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/raw_client.py @@ -0,0 +1,90 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from .types.put_response import PutResponse + + +class RawPutClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def add(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[PutResponse]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[PutResponse] + """ + _response = self._client_wrapper.httpx_client.request( + f"{jsonable_encoder(id)}", + method="PUT", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + PutResponse, + parse_obj_as( + type_=PutResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPutClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def add( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[PutResponse]: + """ + Parameters + ---------- + id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[PutResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + f"{jsonable_encoder(id)}", + method="PUT", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + PutResponse, + parse_obj_as( + type_=PutResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/__init__.py new file mode 100644 index 000000000000..c65555532630 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/__init__.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .error import Error + from .error_category import ErrorCategory + from .error_code import ErrorCode + from .put_response import PutResponse +_dynamic_imports: typing.Dict[str, str] = { + "Error": ".error", + "ErrorCategory": ".error_category", + "ErrorCode": ".error_code", + "PutResponse": ".put_response", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["Error", "ErrorCategory", "ErrorCode", "PutResponse"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error.py new file mode 100644 index 000000000000..9b825f43e1f0 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel +from .error_category import ErrorCategory +from .error_code import ErrorCode + + +class Error(UniversalBaseModel): + category: ErrorCategory + code: ErrorCode + detail: typing.Optional[str] = None + field: typing.Optional[str] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_category.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_category.py new file mode 100644 index 000000000000..c55a5411babf --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_category.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ErrorCategory = typing.Union[typing.Literal["API_ERROR", "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR"], typing.Any] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_code.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_code.py new file mode 100644 index 000000000000..0883052a98b2 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/error_code.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ErrorCode = typing.Union[ + typing.Literal[ + "INTERNAL_SERVER_ERROR", + "UNAUTHORIZED", + "FORBIDDEN", + "BAD_REQUEST", + "CONFLICT", + "GONE", + "UNPROCESSABLE_ENTITY", + "NOT_IMPLEMENTED", + "BAD_GATEWAY", + "SERVICE_UNAVAILABLE", + "Unknown", + ], + typing.Any, +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/put_response.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/put_response.py new file mode 100644 index 000000000000..eca4bd8efebb --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/put/types/put_response.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel +from .error import Error + + +class PutResponse(UniversalBaseModel): + errors: typing.Optional[typing.List[Error]] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/raw_client.py new file mode 100644 index 000000000000..0b3eac091457 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/raw_client.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper + + +class RawEndpointsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + +class AsyncRawEndpointsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/client.py new file mode 100644 index 000000000000..952370981ac6 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/client.py @@ -0,0 +1,119 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.union.types.animal import Animal +from .raw_client import AsyncRawUnionClient, RawUnionClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class UnionClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawUnionClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawUnionClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawUnionClient + """ + return self._raw_client + + def get_and_return_union( + self, *, request: Animal, request_options: typing.Optional[RequestOptions] = None + ) -> Animal: + """ + Parameters + ---------- + request : Animal + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Animal + + Examples + -------- + from seed import SeedExhaustive + from seed.types.union import Animal_Dog + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.union.get_and_return_union( + request=Animal_Dog( + name="name", + likes_to_woof=True, + ), + ) + """ + _response = self._raw_client.get_and_return_union(request=request, request_options=request_options) + return _response.data + + +class AsyncUnionClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawUnionClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawUnionClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawUnionClient + """ + return self._raw_client + + async def get_and_return_union( + self, *, request: Animal, request_options: typing.Optional[RequestOptions] = None + ) -> Animal: + """ + Parameters + ---------- + request : Animal + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Animal + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + from seed.types.union import Animal_Dog + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.union.get_and_return_union( + request=Animal_Dog( + name="name", + likes_to_woof=True, + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_and_return_union(request=request, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/raw_client.py new file mode 100644 index 000000000000..2884ce478e2d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/union/raw_client.py @@ -0,0 +1,99 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.union.types.animal import Animal + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawUnionClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_and_return_union( + self, *, request: Animal, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Animal]: + """ + Parameters + ---------- + request : Animal + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Animal] + """ + _response = self._client_wrapper.httpx_client.request( + "union", + method="POST", + json=convert_and_respect_annotation_metadata(object_=request, annotation=Animal, direction="write"), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Animal, + parse_obj_as( + type_=Animal, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawUnionClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_and_return_union( + self, *, request: Animal, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Animal]: + """ + Parameters + ---------- + request : Animal + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Animal] + """ + _response = await self._client_wrapper.httpx_client.request( + "union", + method="POST", + json=convert_and_respect_annotation_metadata(object_=request, annotation=Animal, direction="write"), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Animal, + parse_obj_as( + type_=Animal, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/client.py new file mode 100644 index 000000000000..4d385b9c5607 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/client.py @@ -0,0 +1,263 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.request_options import RequestOptions +from .raw_client import AsyncRawUrlsClient, RawUrlsClient + + +class UrlsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawUrlsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawUrlsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawUrlsClient + """ + return self._raw_client + + def with_mixed_case(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.urls.with_mixed_case() + """ + _response = self._raw_client.with_mixed_case(request_options=request_options) + return _response.data + + def no_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.urls.no_ending_slash() + """ + _response = self._raw_client.no_ending_slash(request_options=request_options) + return _response.data + + def with_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.urls.with_ending_slash() + """ + _response = self._raw_client.with_ending_slash(request_options=request_options) + return _response.data + + def with_underscores(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.endpoints.urls.with_underscores() + """ + _response = self._raw_client.with_underscores(request_options=request_options) + return _response.data + + +class AsyncUrlsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawUrlsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawUrlsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawUrlsClient + """ + return self._raw_client + + async def with_mixed_case(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.urls.with_mixed_case() + + + asyncio.run(main()) + """ + _response = await self._raw_client.with_mixed_case(request_options=request_options) + return _response.data + + async def no_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.urls.no_ending_slash() + + + asyncio.run(main()) + """ + _response = await self._raw_client.no_ending_slash(request_options=request_options) + return _response.data + + async def with_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.urls.with_ending_slash() + + + asyncio.run(main()) + """ + _response = await self._raw_client.with_ending_slash(request_options=request_options) + return _response.data + + async def with_underscores(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.endpoints.urls.with_underscores() + + + asyncio.run(main()) + """ + _response = await self._raw_client.with_underscores(request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/raw_client.py new file mode 100644 index 000000000000..16ac7765bf53 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/endpoints/urls/raw_client.py @@ -0,0 +1,276 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions + + +class RawUrlsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def with_mixed_case(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "urls/MixedCase", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def no_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "urls/no-ending-slash", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def with_ending_slash(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "urls/with-ending-slash/", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def with_underscores(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "urls/with_underscores", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawUrlsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def with_mixed_case( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "urls/MixedCase", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def no_ending_slash( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "urls/no-ending-slash", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def with_ending_slash( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "urls/with-ending-slash/", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def with_underscores( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "urls/with_underscores", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/__init__.py new file mode 100644 index 000000000000..577a6a5b9b31 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/__init__.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import BadObjectRequestInfo + from .errors import BadRequestBody +_dynamic_imports: typing.Dict[str, str] = {"BadObjectRequestInfo": ".types", "BadRequestBody": ".errors"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["BadObjectRequestInfo", "BadRequestBody"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/__init__.py new file mode 100644 index 000000000000..834d9ade09b4 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .bad_request_body import BadRequestBody +_dynamic_imports: typing.Dict[str, str] = {"BadRequestBody": ".bad_request_body"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["BadRequestBody"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/bad_request_body.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/bad_request_body.py new file mode 100644 index 000000000000..bc4bffa84d59 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/errors/bad_request_body.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ...core.api_error import ApiError +from ..types.bad_object_request_info import BadObjectRequestInfo + + +class BadRequestBody(ApiError): + def __init__(self, body: BadObjectRequestInfo, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/__init__.py new file mode 100644 index 000000000000..eca962f371e3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .bad_object_request_info import BadObjectRequestInfo +_dynamic_imports: typing.Dict[str, str] = {"BadObjectRequestInfo": ".bad_object_request_info"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["BadObjectRequestInfo"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/bad_object_request_info.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/bad_object_request_info.py new file mode 100644 index 000000000000..6a3bd5c31e68 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/general_errors/types/bad_object_request_info.py @@ -0,0 +1,12 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ...core.pydantic_utilities import UniversalBaseModel + + +class BadObjectRequestInfo(UniversalBaseModel): + message: str + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/client.py new file mode 100644 index 000000000000..385d2def0b5a --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/client.py @@ -0,0 +1,188 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.object.types.object_with_optional_field import ObjectWithOptionalField +from .raw_client import AsyncRawInlinedRequestsClient, RawInlinedRequestsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class InlinedRequestsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawInlinedRequestsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawInlinedRequestsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawInlinedRequestsClient + """ + return self._raw_client + + def post_with_object_bodyand_response( + self, + *, + string: str, + integer: int, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + POST with custom object in request body, response is an object + + Parameters + ---------- + string : str + + integer : int + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import datetime + import uuid + + from seed import SeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.inlined_requests.post_with_object_bodyand_response( + string="string", + integer=1, + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + """ + _response = self._raw_client.post_with_object_bodyand_response( + string=string, integer=integer, nested_object=nested_object, request_options=request_options + ) + return _response.data + + +class AsyncInlinedRequestsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawInlinedRequestsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawInlinedRequestsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawInlinedRequestsClient + """ + return self._raw_client + + async def post_with_object_bodyand_response( + self, + *, + string: str, + integer: int, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> ObjectWithOptionalField: + """ + POST with custom object in request body, response is an object + + Parameters + ---------- + string : str + + integer : int + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + import datetime + import uuid + + from seed import AsyncSeedExhaustive + from seed.types.object import ObjectWithOptionalField + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.inlined_requests.post_with_object_bodyand_response( + string="string", + integer=1, + nested_object=ObjectWithOptionalField( + string="string", + integer=1, + long_=1000000, + double=1.1, + bool_=True, + datetime=datetime.datetime.fromisoformat( + "2024-01-15 09:30:00+00:00", + ), + date=datetime.date.fromisoformat( + "2023-01-15", + ), + uuid_=uuid.UUID( + "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32", + ), + base_64="SGVsbG8gd29ybGQh", + list_=["list", "list"], + set_={"set"}, + map_={1: "map"}, + bigint=1000000, + ), + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.post_with_object_bodyand_response( + string=string, integer=integer, nested_object=nested_object, request_options=request_options + ) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/raw_client.py new file mode 100644 index 000000000000..d1edbed872ca --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/inlined_requests/raw_client.py @@ -0,0 +1,157 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..core.serialization import convert_and_respect_annotation_metadata +from ..general_errors.errors.bad_request_body import BadRequestBody +from ..general_errors.types.bad_object_request_info import BadObjectRequestInfo +from ..types.object.types.object_with_optional_field import ObjectWithOptionalField + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawInlinedRequestsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def post_with_object_bodyand_response( + self, + *, + string: str, + integer: int, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ObjectWithOptionalField]: + """ + POST with custom object in request body, response is an object + + Parameters + ---------- + string : str + + integer : int + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + "req-bodies/object", + method="POST", + json={ + "string": string, + "integer": integer, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestBody( + headers=dict(_response.headers), + body=typing.cast( + BadObjectRequestInfo, + parse_obj_as( + type_=BadObjectRequestInfo, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawInlinedRequestsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def post_with_object_bodyand_response( + self, + *, + string: str, + integer: int, + nested_object: ObjectWithOptionalField, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + POST with custom object in request body, response is an object + + Parameters + ---------- + string : str + + integer : int + + nested_object : ObjectWithOptionalField + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + "req-bodies/object", + method="POST", + json={ + "string": string, + "integer": integer, + "NestedObject": convert_and_respect_annotation_metadata( + object_=nested_object, annotation=ObjectWithOptionalField, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestBody( + headers=dict(_response.headers), + body=typing.cast( + BadObjectRequestInfo, + parse_obj_as( + type_=BadObjectRequestInfo, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/client.py new file mode 100644 index 000000000000..b44a0ad37136 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/client.py @@ -0,0 +1,114 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawNoAuthClient, RawNoAuthClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class NoAuthClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawNoAuthClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawNoAuthClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawNoAuthClient + """ + return self._raw_client + + def post_with_no_auth( + self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None + ) -> bool: + """ + POST request with no auth + + Parameters + ---------- + request : typing.Optional[typing.Any] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.no_auth.post_with_no_auth( + request={"key": "value"}, + ) + """ + _response = self._raw_client.post_with_no_auth(request=request, request_options=request_options) + return _response.data + + +class AsyncNoAuthClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawNoAuthClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawNoAuthClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawNoAuthClient + """ + return self._raw_client + + async def post_with_no_auth( + self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None + ) -> bool: + """ + POST request with no auth + + Parameters + ---------- + request : typing.Optional[typing.Any] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + bool + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.no_auth.post_with_no_auth( + request={"key": "value"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.post_with_no_auth(request=request, request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/raw_client.py new file mode 100644 index 000000000000..66aa202e139d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_auth/raw_client.py @@ -0,0 +1,125 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..general_errors.errors.bad_request_body import BadRequestBody +from ..general_errors.types.bad_object_request_info import BadObjectRequestInfo + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawNoAuthClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def post_with_no_auth( + self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[bool]: + """ + POST request with no auth + + Parameters + ---------- + request : typing.Optional[typing.Any] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[bool] + """ + _response = self._client_wrapper.httpx_client.request( + "no-auth", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestBody( + headers=dict(_response.headers), + body=typing.cast( + BadObjectRequestInfo, + parse_obj_as( + type_=BadObjectRequestInfo, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawNoAuthClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def post_with_no_auth( + self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[bool]: + """ + POST request with no auth + + Parameters + ---------- + request : typing.Optional[typing.Any] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[bool] + """ + _response = await self._client_wrapper.httpx_client.request( + "no-auth", + method="POST", + json=request, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + bool, + parse_obj_as( + type_=bool, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestBody( + headers=dict(_response.headers), + body=typing.cast( + BadObjectRequestInfo, + parse_obj_as( + type_=BadObjectRequestInfo, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/client.py new file mode 100644 index 000000000000..23007e672acc --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/client.py @@ -0,0 +1,156 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.object.types.object_with_optional_field import ObjectWithOptionalField +from .raw_client import AsyncRawNoReqBodyClient, RawNoReqBodyClient + + +class NoReqBodyClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawNoReqBodyClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawNoReqBodyClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawNoReqBodyClient + """ + return self._raw_client + + def get_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.no_req_body.get_with_no_request_body() + """ + _response = self._raw_client.get_with_no_request_body(request_options=request_options) + return _response.data + + def post_with_no_request_body(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.no_req_body.post_with_no_request_body() + """ + _response = self._raw_client.post_with_no_request_body(request_options=request_options) + return _response.data + + +class AsyncNoReqBodyClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawNoReqBodyClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawNoReqBodyClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawNoReqBodyClient + """ + return self._raw_client + + async def get_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> ObjectWithOptionalField: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ObjectWithOptionalField + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.no_req_body.get_with_no_request_body() + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_no_request_body(request_options=request_options) + return _response.data + + async def post_with_no_request_body(self, *, request_options: typing.Optional[RequestOptions] = None) -> str: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + str + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.no_req_body.post_with_no_request_body() + + + asyncio.run(main()) + """ + _response = await self._raw_client.post_with_no_request_body(request_options=request_options) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/raw_client.py new file mode 100644 index 000000000000..f48dcc828ce3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/no_req_body/raw_client.py @@ -0,0 +1,153 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.object.types.object_with_optional_field import ObjectWithOptionalField + + +class RawNoReqBodyClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ObjectWithOptionalField] + """ + _response = self._client_wrapper.httpx_client.request( + "no-req-body", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def post_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[str] + """ + _response = self._client_wrapper.httpx_client.request( + "no-req-body", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawNoReqBodyClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ObjectWithOptionalField]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ObjectWithOptionalField] + """ + _response = await self._client_wrapper.httpx_client.request( + "no-req-body", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ObjectWithOptionalField, + parse_obj_as( + type_=ObjectWithOptionalField, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def post_with_no_request_body( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[str]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[str] + """ + _response = await self._client_wrapper.httpx_client.request( + "no-req-body", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + str, + parse_obj_as( + type_=str, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/py.typed b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/__init__.py new file mode 100644 index 000000000000..5cde0202dcf3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/client.py new file mode 100644 index 000000000000..a94ba5e68b9c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/client.py @@ -0,0 +1,142 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawReqWithHeadersClient, RawReqWithHeadersClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ReqWithHeadersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawReqWithHeadersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawReqWithHeadersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawReqWithHeadersClient + """ + return self._raw_client + + def get_with_custom_header( + self, + *, + x_test_service_header: str, + x_test_endpoint_header: str, + request: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + x_test_service_header : str + + x_test_endpoint_header : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from seed import SeedExhaustive + + client = SeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + client.req_with_headers.get_with_custom_header( + x_test_service_header="X-TEST-SERVICE-HEADER", + x_test_endpoint_header="X-TEST-ENDPOINT-HEADER", + request="string", + ) + """ + _response = self._raw_client.get_with_custom_header( + x_test_service_header=x_test_service_header, + x_test_endpoint_header=x_test_endpoint_header, + request=request, + request_options=request_options, + ) + return _response.data + + +class AsyncReqWithHeadersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawReqWithHeadersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawReqWithHeadersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawReqWithHeadersClient + """ + return self._raw_client + + async def get_with_custom_header( + self, + *, + x_test_service_header: str, + x_test_endpoint_header: str, + request: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + x_test_service_header : str + + x_test_endpoint_header : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from seed import AsyncSeedExhaustive + + client = AsyncSeedExhaustive( + token="YOUR_TOKEN", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.req_with_headers.get_with_custom_header( + x_test_service_header="X-TEST-SERVICE-HEADER", + x_test_endpoint_header="X-TEST-ENDPOINT-HEADER", + request="string", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_with_custom_header( + x_test_service_header=x_test_service_header, + x_test_endpoint_header=x_test_endpoint_header, + request=request, + request_options=request_options, + ) + return _response.data diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/raw_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/raw_client.py new file mode 100644 index 000000000000..c023ef576e0c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/req_with_headers/raw_client.py @@ -0,0 +1,108 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawReqWithHeadersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_with_custom_header( + self, + *, + x_test_service_header: str, + x_test_endpoint_header: str, + request: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Parameters + ---------- + x_test_service_header : str + + x_test_endpoint_header : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "test-headers/custom-header", + method="POST", + json=request, + headers={ + "X-TEST-SERVICE-HEADER": str(x_test_service_header) if x_test_service_header is not None else None, + "X-TEST-ENDPOINT-HEADER": str(x_test_endpoint_header) if x_test_endpoint_header is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawReqWithHeadersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_with_custom_header( + self, + *, + x_test_service_header: str, + x_test_endpoint_header: str, + request: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + x_test_service_header : str + + x_test_endpoint_header : str + + request : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "test-headers/custom-header", + method="POST", + json=request, + headers={ + "X-TEST-SERVICE-HEADER": str(x_test_service_header) if x_test_service_header is not None else None, + "X-TEST-ENDPOINT-HEADER": str(x_test_endpoint_header) if x_test_endpoint_header is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/__init__.py new file mode 100644 index 000000000000..408462d41f24 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/__init__.py @@ -0,0 +1,98 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import docs, enum, object, union + from .docs import ObjectWithDocs + from .enum import ErrorWithEnumBody, WeatherReport + from .object import ( + DoubleOptional, + NestedObjectWithOptionalField, + NestedObjectWithOptionalFieldError, + NestedObjectWithRequiredField, + NestedObjectWithRequiredFieldError, + ObjectWithMapOfMap, + ObjectWithOptionalField, + ObjectWithOptionalFieldError, + ObjectWithRequiredField, + ObjectWithRequiredFieldError, + OptionalAlias, + ) + from .union import Animal, Animal_Cat, Animal_Dog, Cat, Dog, ErrorWithUnionBody +_dynamic_imports: typing.Dict[str, str] = { + "Animal": ".union", + "Animal_Cat": ".union", + "Animal_Dog": ".union", + "Cat": ".union", + "Dog": ".union", + "DoubleOptional": ".object", + "ErrorWithEnumBody": ".enum", + "ErrorWithUnionBody": ".union", + "NestedObjectWithOptionalField": ".object", + "NestedObjectWithOptionalFieldError": ".object", + "NestedObjectWithRequiredField": ".object", + "NestedObjectWithRequiredFieldError": ".object", + "ObjectWithDocs": ".docs", + "ObjectWithMapOfMap": ".object", + "ObjectWithOptionalField": ".object", + "ObjectWithOptionalFieldError": ".object", + "ObjectWithRequiredField": ".object", + "ObjectWithRequiredFieldError": ".object", + "OptionalAlias": ".object", + "WeatherReport": ".enum", + "docs": ".", + "enum": ".", + "object": ".", + "union": ".", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "Animal", + "Animal_Cat", + "Animal_Dog", + "Cat", + "Dog", + "DoubleOptional", + "ErrorWithEnumBody", + "ErrorWithUnionBody", + "NestedObjectWithOptionalField", + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredField", + "NestedObjectWithRequiredFieldError", + "ObjectWithDocs", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredField", + "ObjectWithRequiredFieldError", + "OptionalAlias", + "WeatherReport", + "docs", + "enum", + "object", + "union", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/__init__.py new file mode 100644 index 000000000000..fed14b8370d1 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ObjectWithDocs +_dynamic_imports: typing.Dict[str, str] = {"ObjectWithDocs": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ObjectWithDocs"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/__init__.py new file mode 100644 index 000000000000..76ffda26b6ec --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .object_with_docs import ObjectWithDocs +_dynamic_imports: typing.Dict[str, str] = {"ObjectWithDocs": ".object_with_docs"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ObjectWithDocs"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/object_with_docs.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/object_with_docs.py new file mode 100644 index 000000000000..d9fe48e63409 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/docs/types/object_with_docs.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithDocs(UniversalBaseModel): + string: str = pydantic.Field() + """ + Characters that could lead to broken generated SDKs: + + JSDoc (JavaScript/TypeScript): + - @: Used for JSDoc tags + - {: }: Used for type definitions + - <: >: HTML tags + - *: Can interfere with comment blocks + - /**: JSDoc comment start + - ** /: JSDoc comment end + - &: HTML entities + + XMLDoc (C#): + - <: >: XML tags + - &: ': ": <: >: XML special characters + - {: }: Used for interpolated strings + - ///: Comment marker + - /**: Block comment start + - ** /: Block comment end + + Javadoc (Java): + - @: Used for Javadoc tags + - <: >: HTML tags + - &: HTML entities + - *: Can interfere with comment blocks + - /**: Javadoc comment start + - ** /: Javadoc comment end + + Doxygen (C++): + - \: Used for Doxygen commands + - @: Alternative command prefix + - <: >: XML/HTML tags + - &: HTML entities + - /**: C-style comment start + - ** /: C-style comment end + + RDoc (Ruby): + - :: Used in symbol notation + - =: Section markers + - #: Comment marker + - =begin: Block comment start + - =end: Block comment end + - @: Instance variable prefix + - $: Global variable prefix + - %: String literal delimiter + - #{: String interpolation start + - }: String interpolation end + + PHPDoc (PHP): + - @: Used for PHPDoc tags + - {: }: Used for type definitions + - $: Variable prefix + - /**: PHPDoc comment start + - ** /: PHPDoc comment end + - *: Can interfere with comment blocks + - &: HTML entities + """ + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/__init__.py new file mode 100644 index 000000000000..26fb6842f8db --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/__init__.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import WeatherReport + from .errors import ErrorWithEnumBody +_dynamic_imports: typing.Dict[str, str] = {"ErrorWithEnumBody": ".errors", "WeatherReport": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ErrorWithEnumBody", "WeatherReport"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/__init__.py new file mode 100644 index 000000000000..535bf1e80665 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .error_with_enum_body import ErrorWithEnumBody +_dynamic_imports: typing.Dict[str, str] = {"ErrorWithEnumBody": ".error_with_enum_body"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ErrorWithEnumBody"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/error_with_enum_body.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/error_with_enum_body.py new file mode 100644 index 000000000000..094a97f43d4a --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/errors/error_with_enum_body.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.weather_report import WeatherReport + + +class ErrorWithEnumBody(ApiError): + def __init__(self, body: WeatherReport, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/__init__.py new file mode 100644 index 000000000000..418a02acf8bb --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .weather_report import WeatherReport +_dynamic_imports: typing.Dict[str, str] = {"WeatherReport": ".weather_report"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["WeatherReport"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/weather_report.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/weather_report.py new file mode 100644 index 000000000000..2d54965dc223 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/enum/types/weather_report.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WeatherReport = typing.Union[typing.Literal["SUNNY", "CLOUDY", "RAINING", "SNOWING"], typing.Any] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/__init__.py new file mode 100644 index 000000000000..732326c6cf5b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/__init__.py @@ -0,0 +1,70 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + DoubleOptional, + NestedObjectWithOptionalField, + NestedObjectWithRequiredField, + ObjectWithMapOfMap, + ObjectWithOptionalField, + ObjectWithRequiredField, + OptionalAlias, + ) + from .errors import ( + NestedObjectWithOptionalFieldError, + NestedObjectWithRequiredFieldError, + ObjectWithOptionalFieldError, + ObjectWithRequiredFieldError, + ) +_dynamic_imports: typing.Dict[str, str] = { + "DoubleOptional": ".types", + "NestedObjectWithOptionalField": ".types", + "NestedObjectWithOptionalFieldError": ".errors", + "NestedObjectWithRequiredField": ".types", + "NestedObjectWithRequiredFieldError": ".errors", + "ObjectWithMapOfMap": ".types", + "ObjectWithOptionalField": ".types", + "ObjectWithOptionalFieldError": ".errors", + "ObjectWithRequiredField": ".types", + "ObjectWithRequiredFieldError": ".errors", + "OptionalAlias": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "DoubleOptional", + "NestedObjectWithOptionalField", + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredField", + "NestedObjectWithRequiredFieldError", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredField", + "ObjectWithRequiredFieldError", + "OptionalAlias", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/__init__.py new file mode 100644 index 000000000000..4178a60fed48 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/__init__.py @@ -0,0 +1,45 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .nested_object_with_optional_field_error import NestedObjectWithOptionalFieldError + from .nested_object_with_required_field_error import NestedObjectWithRequiredFieldError + from .object_with_optional_field_error import ObjectWithOptionalFieldError + from .object_with_required_field_error import ObjectWithRequiredFieldError +_dynamic_imports: typing.Dict[str, str] = { + "NestedObjectWithOptionalFieldError": ".nested_object_with_optional_field_error", + "NestedObjectWithRequiredFieldError": ".nested_object_with_required_field_error", + "ObjectWithOptionalFieldError": ".object_with_optional_field_error", + "ObjectWithRequiredFieldError": ".object_with_required_field_error", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "NestedObjectWithOptionalFieldError", + "NestedObjectWithRequiredFieldError", + "ObjectWithOptionalFieldError", + "ObjectWithRequiredFieldError", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_optional_field_error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_optional_field_error.py new file mode 100644 index 000000000000..17e095f6934b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_optional_field_error.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.nested_object_with_optional_field import NestedObjectWithOptionalField + + +class NestedObjectWithOptionalFieldError(ApiError): + def __init__(self, body: NestedObjectWithOptionalField, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_required_field_error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_required_field_error.py new file mode 100644 index 000000000000..728f61c5931d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/nested_object_with_required_field_error.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.nested_object_with_required_field import NestedObjectWithRequiredField + + +class NestedObjectWithRequiredFieldError(ApiError): + def __init__(self, body: NestedObjectWithRequiredField, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_optional_field_error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_optional_field_error.py new file mode 100644 index 000000000000..5c18566f0a30 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_optional_field_error.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.object_with_optional_field import ObjectWithOptionalField + + +class ObjectWithOptionalFieldError(ApiError): + def __init__(self, body: ObjectWithOptionalField, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_required_field_error.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_required_field_error.py new file mode 100644 index 000000000000..d59264d61a26 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/errors/object_with_required_field_error.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.object_with_required_field import ObjectWithRequiredField + + +class ObjectWithRequiredFieldError(ApiError): + def __init__(self, body: ObjectWithRequiredField, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/__init__.py new file mode 100644 index 000000000000..fb24f8b258e5 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/__init__.py @@ -0,0 +1,54 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .double_optional import DoubleOptional + from .nested_object_with_optional_field import NestedObjectWithOptionalField + from .nested_object_with_required_field import NestedObjectWithRequiredField + from .object_with_map_of_map import ObjectWithMapOfMap + from .object_with_optional_field import ObjectWithOptionalField + from .object_with_required_field import ObjectWithRequiredField + from .optional_alias import OptionalAlias +_dynamic_imports: typing.Dict[str, str] = { + "DoubleOptional": ".double_optional", + "NestedObjectWithOptionalField": ".nested_object_with_optional_field", + "NestedObjectWithRequiredField": ".nested_object_with_required_field", + "ObjectWithMapOfMap": ".object_with_map_of_map", + "ObjectWithOptionalField": ".object_with_optional_field", + "ObjectWithRequiredField": ".object_with_required_field", + "OptionalAlias": ".optional_alias", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = [ + "DoubleOptional", + "NestedObjectWithOptionalField", + "NestedObjectWithRequiredField", + "ObjectWithMapOfMap", + "ObjectWithOptionalField", + "ObjectWithRequiredField", + "OptionalAlias", +] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/double_optional.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/double_optional.py new file mode 100644 index 000000000000..5c840ce2921e --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/double_optional.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel +from .optional_alias import OptionalAlias + + +class DoubleOptional(UniversalBaseModel): + optional_alias: typing_extensions.Annotated[ + typing.Optional[OptionalAlias], pydantic.Field(alias="optionalAlias") + ] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_optional_field.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_optional_field.py new file mode 100644 index 000000000000..09c6a4a69218 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_optional_field.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel +from .object_with_optional_field import ObjectWithOptionalField + + +class NestedObjectWithOptionalField(UniversalBaseModel): + string: typing.Optional[str] = None + nested_object: typing_extensions.Annotated[ + typing.Optional[ObjectWithOptionalField], pydantic.Field(alias="NestedObject") + ] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_required_field.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_required_field.py new file mode 100644 index 000000000000..2f83b7eae040 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/nested_object_with_required_field.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel +from .object_with_optional_field import ObjectWithOptionalField + + +class NestedObjectWithRequiredField(UniversalBaseModel): + string: str + nested_object: typing_extensions.Annotated[ObjectWithOptionalField, pydantic.Field(alias="NestedObject")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_map_of_map.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_map_of_map.py new file mode 100644 index 000000000000..f9f2eb7e3615 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_map_of_map.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithMapOfMap(UniversalBaseModel): + map_: typing_extensions.Annotated[typing.Dict[str, typing.Dict[str, str]], pydantic.Field(alias="map")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_optional_field.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_optional_field.py new file mode 100644 index 000000000000..b4f92d406128 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_optional_field.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithOptionalField(UniversalBaseModel): + string: typing.Optional[str] = pydantic.Field(default=None) + """ + This is a rather long descriptor of this single field in a more complex type. If you ask me I think this is a pretty good description for this field all things considered. + """ + + integer: typing.Optional[int] = None + long_: typing_extensions.Annotated[typing.Optional[int], pydantic.Field(alias="long")] = None + double: typing.Optional[float] = None + bool_: typing_extensions.Annotated[typing.Optional[bool], pydantic.Field(alias="bool")] = None + datetime: typing.Optional[dt.datetime] = None + date: typing.Optional[dt.date] = None + uuid_: typing_extensions.Annotated[typing.Optional[uuid.UUID], pydantic.Field(alias="uuid")] = None + base_64: typing_extensions.Annotated[typing.Optional[str], pydantic.Field(alias="base64")] = None + list_: typing_extensions.Annotated[typing.Optional[typing.List[str]], pydantic.Field(alias="list")] = None + set_: typing_extensions.Annotated[typing.Optional[typing.Set[str]], pydantic.Field(alias="set")] = None + map_: typing_extensions.Annotated[typing.Optional[typing.Dict[int, str]], pydantic.Field(alias="map")] = None + bigint: typing.Optional[str] = None + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_required_field.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_required_field.py new file mode 100644 index 000000000000..868c9aa78bb4 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/object_with_required_field.py @@ -0,0 +1,12 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel + + +class ObjectWithRequiredField(UniversalBaseModel): + string: str + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/optional_alias.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/optional_alias.py new file mode 100644 index 000000000000..fa09e3be001c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/object/types/optional_alias.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OptionalAlias = typing.Optional[str] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/__init__.py new file mode 100644 index 000000000000..efcd42bd58a8 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/__init__.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import Animal, Animal_Cat, Animal_Dog, Cat, Dog + from .errors import ErrorWithUnionBody +_dynamic_imports: typing.Dict[str, str] = { + "Animal": ".types", + "Animal_Cat": ".types", + "Animal_Dog": ".types", + "Cat": ".types", + "Dog": ".types", + "ErrorWithUnionBody": ".errors", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["Animal", "Animal_Cat", "Animal_Dog", "Cat", "Dog", "ErrorWithUnionBody"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/__init__.py new file mode 100644 index 000000000000..08f93a252d1b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/__init__.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .error_with_union_body import ErrorWithUnionBody +_dynamic_imports: typing.Dict[str, str] = {"ErrorWithUnionBody": ".error_with_union_body"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ErrorWithUnionBody"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/error_with_union_body.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/error_with_union_body.py new file mode 100644 index 000000000000..be8388070ad3 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/errors/error_with_union_body.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ....core.api_error import ApiError +from ..types.animal import Animal + + +class ErrorWithUnionBody(ApiError): + def __init__(self, body: Animal, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/__init__.py new file mode 100644 index 000000000000..0db46d2121c0 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/__init__.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .animal import Animal, Animal_Cat, Animal_Dog + from .cat import Cat + from .dog import Dog +_dynamic_imports: typing.Dict[str, str] = { + "Animal": ".animal", + "Animal_Cat": ".animal", + "Animal_Dog": ".animal", + "Cat": ".cat", + "Dog": ".dog", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["Animal", "Animal_Cat", "Animal_Dog", "Cat", "Dog"] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/animal.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/animal.py new file mode 100644 index 000000000000..bed97830c266 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/animal.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel + + +class Animal_Dog(UniversalBaseModel): + animal: typing.Literal["dog"] = "dog" + name: str + likes_to_woof: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToWoof")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + + +class Animal_Cat(UniversalBaseModel): + animal: typing.Literal["cat"] = "cat" + name: str + likes_to_meow: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToMeow")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + + +Animal = typing.Union[Animal_Dog, Animal_Cat] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/cat.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/cat.py new file mode 100644 index 000000000000..1a73db996179 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/cat.py @@ -0,0 +1,14 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel + + +class Cat(UniversalBaseModel): + name: str + likes_to_meow: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToMeow")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/dog.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/dog.py new file mode 100644 index 000000000000..686b683b2b17 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/types/union/types/dog.py @@ -0,0 +1,14 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import UniversalBaseModel + + +class Dog(UniversalBaseModel): + name: str + likes_to_woof: typing_extensions.Annotated[bool, pydantic.Field(alias="likesToWoof")] + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/version.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/version.py new file mode 100644 index 000000000000..ac44536abdbe --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/src/seed/version.py @@ -0,0 +1,3 @@ +from importlib import metadata + +__version__ = metadata.version("fern_exhaustive") diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/custom/test_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/custom/test_client.py new file mode 100644 index 000000000000..ab04ce6393ef --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/custom/test_client.py @@ -0,0 +1,7 @@ +import pytest + + +# Get started with writing tests with pytest at https://docs.pytest.org +@pytest.mark.skip(reason="Unimplemented") +def test_client() -> None: + assert True diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/__init__.py new file mode 100644 index 000000000000..f3ea2659bb1c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/__init__.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/__init__.py new file mode 100644 index 000000000000..2cf01263529d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/circle.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/circle.py new file mode 100644 index 000000000000..74ecf38c308b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/circle.py @@ -0,0 +1,11 @@ +# 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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/color.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/color.py new file mode 100644 index 000000000000..2aa2c4c52f0c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_defaults.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_defaults.py new file mode 100644 index 000000000000..a977b1d2aa1c --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_optional_field.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/object_with_optional_field.py new file mode 100644 index 000000000000..6b5608bc05b6 --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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 .color import Color +from .shape import ShapeParams +from .undiscriminated_shape import UndiscriminatedShapeParams + +from seed.core.serialization import FieldMetadata + + +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.Optional[typing.Any] diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/shape.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/shape.py new file mode 100644 index 000000000000..7e70010a251f --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/shape.py @@ -0,0 +1,28 @@ +# 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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/square.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/square.py new file mode 100644 index 000000000000..71c7d25fd4ad --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/square.py @@ -0,0 +1,11 @@ +# 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/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/undiscriminated_shape.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/assets/models/undiscriminated_shape.py new file mode 100644 index 000000000000..99f12b300d1d --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/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/exhaustive/use-annotated-field-aliases/tests/utils/test_http_client.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_http_client.py new file mode 100644 index 000000000000..a541bae6531e --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_http_client.py @@ -0,0 +1,61 @@ +# 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 + + +def test_get_empty_json_request_body() -> None: + unrelated_request_options: RequestOptions = {"max_retries": 3} + json_body, data_body = get_request_body(json=None, data=None, request_options=unrelated_request_options, omit=None) + assert json_body is None + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={}, data=None, request_options=unrelated_request_options, omit=None + ) + + assert json_body_extras is None + assert data_body_extras is None diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_query_encoding.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_query_encoding.py new file mode 100644 index 000000000000..ef5fd7094f9b --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_query_encoding.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from seed.core.query_encoder import encode_query + + +def test_query_encoding_deep_objects() -> 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_query_encoding_deep_object_arrays() -> None: + assert encode_query({"objects": [{"key": "hello", "value": "world"}, {"key": "foo", "value": "bar"}]}) == [ + ("objects[key]", "hello"), + ("objects[value]", "world"), + ("objects[key]", "foo"), + ("objects[value]", "bar"), + ] + assert encode_query( + {"users": [{"name": "string", "tags": ["string"]}, {"name": "string2", "tags": ["string2", "string3"]}]} + ) == [ + ("users[name]", "string"), + ("users[tags]", "string"), + ("users[name]", "string2"), + ("users[tags]", "string2"), + ("users[tags]", "string3"), + ] + + +def test_encode_query_with_none() -> None: + encoded = encode_query(None) + assert encoded is None diff --git a/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_serialization.py b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_serialization.py new file mode 100644 index 000000000000..b298db89c4bd --- /dev/null +++ b/seed/python-sdk/exhaustive/use-annotated-field-aliases/tests/utils/test_serialization.py @@ -0,0 +1,72 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, List + +from .assets.models import ObjectWithOptionalFieldParams, ShapeParams + +from seed.core.serialization import convert_and_respect_annotation_metadata + +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, direction="write" + ) + 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], direction="write" + ) + + 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, direction="write" + ) + + 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, direction="write") + + 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, direction="write") + assert converted == data diff --git a/seed/python-sdk/seed.yml b/seed/python-sdk/seed.yml index 725c04b36dd7..9ae8a8f81026 100644 --- a/seed/python-sdk/seed.yml +++ b/seed/python-sdk/seed.yml @@ -235,6 +235,11 @@ fixtures: - customConfig: lazy_imports: false outputFolder: eager-imports + - customConfig: + pydantic_config: + version: v2 + use_annotated_field_aliases: true + outputFolder: use-annotated-field-aliases file-upload: - customConfig: null outputFolder: no-custom-config