@planqk/planqk-service-sdk 1.9.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/.devcontainer/devcontainer.json +32 -0
  2. package/.devcontainer/post-create.sh +7 -0
  3. package/.env.template +4 -0
  4. package/.gitlab-ci.yml +103 -0
  5. package/.python-version +1 -0
  6. package/.releaserc.json +45 -0
  7. package/LICENSE +201 -0
  8. package/README-node.md +41 -0
  9. package/README-python.md +52 -0
  10. package/README.md +42 -21
  11. package/dist/auth.js +12 -19
  12. package/dist/client.d.ts +2 -12
  13. package/dist/client.js +5 -76
  14. package/dist/sdk/Client.d.ts +4 -3
  15. package/dist/sdk/Client.js +4 -8
  16. package/dist/sdk/api/errors/BadRequestError.d.ts +1 -1
  17. package/dist/sdk/api/errors/BadRequestError.js +18 -8
  18. package/dist/sdk/api/errors/ForbiddenError.d.ts +1 -1
  19. package/dist/sdk/api/errors/ForbiddenError.js +18 -8
  20. package/dist/sdk/api/errors/InternalServerError.d.ts +1 -1
  21. package/dist/sdk/api/errors/InternalServerError.js +18 -8
  22. package/dist/sdk/api/errors/NotFoundError.d.ts +1 -1
  23. package/dist/sdk/api/errors/NotFoundError.js +18 -8
  24. package/dist/sdk/api/errors/UnauthorizedError.d.ts +1 -1
  25. package/dist/sdk/api/errors/UnauthorizedError.js +18 -8
  26. package/dist/sdk/api/resources/index.d.ts +0 -3
  27. package/dist/sdk/api/resources/index.js +18 -11
  28. package/dist/sdk/api/resources/serviceApi/client/Client.d.ts +65 -12
  29. package/dist/sdk/api/resources/serviceApi/client/Client.js +405 -261
  30. package/dist/sdk/api/resources/serviceApi/client/index.d.ts +1 -1
  31. package/dist/sdk/api/resources/serviceApi/client/index.js +0 -15
  32. package/dist/sdk/api/resources/serviceApi/types/GetResultResponse.d.ts +4 -1
  33. package/dist/sdk/api/resources/serviceApi/types/{GetInterimResultsResponse.d.ts → GetResultResponseEmbedded.d.ts} +3 -1
  34. package/dist/sdk/api/resources/serviceApi/types/GetResultResponseLinks.d.ts +7 -0
  35. package/dist/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.d.ts +1 -0
  36. package/dist/sdk/api/resources/serviceApi/types/index.d.ts +3 -1
  37. package/dist/sdk/api/resources/serviceApi/types/index.js +3 -1
  38. package/dist/sdk/api/types/HalLink.d.ts +21 -0
  39. package/dist/sdk/api/types/InputData.d.ts +1 -1
  40. package/dist/sdk/api/types/{InputRef.d.ts → InputDataRef.d.ts} +1 -1
  41. package/dist/sdk/api/types/InputParams.d.ts +1 -1
  42. package/dist/sdk/api/types/{Job.d.ts → ServiceExecution.d.ts} +2 -2
  43. package/dist/sdk/api/types/{JobStatus.d.ts → ServiceExecutionStatus.d.ts} +2 -2
  44. package/dist/sdk/api/types/{JobStatus.js → ServiceExecutionStatus.js} +2 -2
  45. package/dist/sdk/api/types/index.d.ts +4 -8
  46. package/dist/sdk/api/types/index.js +4 -8
  47. package/dist/sdk/core/fetcher/APIResponse.d.ts +1 -0
  48. package/dist/sdk/core/fetcher/Fetcher.d.ts +6 -5
  49. package/dist/sdk/core/fetcher/Fetcher.js +68 -112
  50. package/dist/sdk/core/fetcher/Supplier.js +2 -11
  51. package/dist/sdk/core/fetcher/createRequestUrl.d.ts +1 -0
  52. package/dist/sdk/core/fetcher/createRequestUrl.js +12 -0
  53. package/dist/sdk/core/fetcher/getFetchFn.d.ts +4 -0
  54. package/dist/sdk/core/fetcher/getFetchFn.js +57 -0
  55. package/dist/sdk/core/fetcher/getHeader.d.ts +1 -0
  56. package/dist/sdk/core/fetcher/getHeader.js +11 -0
  57. package/dist/sdk/core/fetcher/getRequestBody.d.ts +7 -0
  58. package/dist/sdk/core/fetcher/getRequestBody.js +11 -0
  59. package/dist/sdk/core/fetcher/getResponseBody.d.ts +1 -0
  60. package/dist/sdk/core/fetcher/getResponseBody.js +40 -0
  61. package/dist/sdk/core/fetcher/index.d.ts +1 -0
  62. package/dist/sdk/core/fetcher/index.js +3 -1
  63. package/dist/sdk/core/fetcher/makeRequest.d.ts +1 -0
  64. package/dist/sdk/core/fetcher/makeRequest.js +33 -0
  65. package/dist/sdk/core/fetcher/requestWithRetries.d.ts +1 -0
  66. package/dist/sdk/core/fetcher/requestWithRetries.js +20 -0
  67. package/dist/sdk/core/fetcher/signals.d.ts +11 -0
  68. package/dist/sdk/core/fetcher/signals.js +36 -0
  69. package/dist/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.d.ts +30 -0
  70. package/dist/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.js +232 -0
  71. package/dist/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.d.ts +21 -0
  72. package/dist/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.js +91 -0
  73. package/dist/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.d.ts +31 -0
  74. package/dist/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.js +214 -0
  75. package/dist/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.d.ts +18 -0
  76. package/dist/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.js +48 -0
  77. package/dist/sdk/core/index.d.ts +1 -0
  78. package/dist/sdk/core/index.js +1 -0
  79. package/dist/sdk/core/runtime/index.d.ts +1 -0
  80. package/dist/sdk/core/runtime/index.js +5 -0
  81. package/dist/sdk/core/runtime/runtime.d.ts +9 -0
  82. package/dist/sdk/core/runtime/runtime.js +92 -0
  83. package/dist/sdk/errors/PlanqkServiceApiError.js +2 -0
  84. package/dist/sdk/index.js +17 -7
  85. package/eslint.config.mjs +11 -0
  86. package/fern/fern.config.json +4 -0
  87. package/fern/generators.yml +25 -0
  88. package/fern/openapi/openapi.yml +342 -0
  89. package/notebooks/python-sdk.ipynb +280 -0
  90. package/package.json +27 -28
  91. package/planqk/__init__.py +0 -0
  92. package/planqk/service/__init__.py +1 -0
  93. package/planqk/service/_version.py +1 -0
  94. package/planqk/service/auth.py +30 -0
  95. package/planqk/service/client.py +151 -0
  96. package/planqk/service/sdk/__init__.py +48 -0
  97. package/planqk/service/sdk/client.py +152 -0
  98. package/planqk/service/sdk/core/__init__.py +47 -0
  99. package/planqk/service/sdk/core/api_error.py +17 -0
  100. package/planqk/service/sdk/core/client_wrapper.py +74 -0
  101. package/planqk/service/sdk/core/datetime_utils.py +30 -0
  102. package/planqk/service/sdk/core/file.py +70 -0
  103. package/planqk/service/sdk/core/http_client.py +575 -0
  104. package/planqk/service/sdk/core/jsonable_encoder.py +103 -0
  105. package/planqk/service/sdk/core/pydantic_utilities.py +323 -0
  106. package/planqk/service/sdk/core/query_encoder.py +60 -0
  107. package/planqk/service/sdk/core/remove_none_from_dict.py +11 -0
  108. package/planqk/service/sdk/core/request_options.py +35 -0
  109. package/planqk/service/sdk/core/serialization.py +276 -0
  110. package/planqk/service/sdk/environment.py +7 -0
  111. package/planqk/service/sdk/errors/__init__.py +15 -0
  112. package/planqk/service/sdk/errors/bad_request_error.py +9 -0
  113. package/planqk/service/sdk/errors/forbidden_error.py +9 -0
  114. package/planqk/service/sdk/errors/internal_server_error.py +9 -0
  115. package/planqk/service/sdk/errors/not_found_error.py +9 -0
  116. package/planqk/service/sdk/errors/unauthorized_error.py +9 -0
  117. package/planqk/service/sdk/service_api/__init__.py +15 -0
  118. package/planqk/service/sdk/service_api/client.py +1257 -0
  119. package/planqk/service/sdk/service_api/types/__init__.py +13 -0
  120. package/planqk/service/sdk/service_api/types/get_result_response.py +30 -0
  121. package/planqk/service/sdk/service_api/types/get_result_response_embedded.py +22 -0
  122. package/planqk/service/sdk/service_api/types/get_result_response_links.py +22 -0
  123. package/planqk/service/sdk/service_api/types/health_check_response.py +24 -0
  124. package/planqk/service/sdk/types/__init__.py +17 -0
  125. package/planqk/service/sdk/types/hal_link.py +59 -0
  126. package/planqk/service/sdk/types/input_data.py +5 -0
  127. package/planqk/service/sdk/types/input_data_ref.py +27 -0
  128. package/planqk/service/sdk/types/input_params.py +5 -0
  129. package/planqk/service/sdk/types/service_execution.py +34 -0
  130. package/planqk/service/sdk/types/service_execution_status.py +8 -0
  131. package/pyproject.toml +51 -0
  132. package/scripts/update-version.sh +6 -0
  133. package/src/client.ts +4 -78
  134. package/src/index.test.ts +43 -0
  135. package/src/sdk/Client.ts +4 -7
  136. package/src/sdk/api/errors/BadRequestError.ts +1 -1
  137. package/src/sdk/api/errors/ForbiddenError.ts +1 -1
  138. package/src/sdk/api/errors/InternalServerError.ts +1 -1
  139. package/src/sdk/api/errors/NotFoundError.ts +1 -1
  140. package/src/sdk/api/errors/UnauthorizedError.ts +1 -1
  141. package/src/sdk/api/resources/index.ts +0 -3
  142. package/src/sdk/api/resources/serviceApi/client/Client.ts +205 -32
  143. package/src/sdk/api/resources/serviceApi/client/index.ts +1 -1
  144. package/src/sdk/api/resources/serviceApi/types/GetResultResponse.ts +4 -5
  145. package/src/sdk/api/resources/serviceApi/types/GetResultResponseEmbedded.ts +9 -0
  146. package/src/sdk/api/resources/serviceApi/types/GetResultResponseLinks.ts +9 -0
  147. package/src/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.ts +1 -0
  148. package/src/sdk/api/resources/serviceApi/types/index.ts +3 -1
  149. package/src/sdk/api/types/HalLink.ts +22 -0
  150. package/src/sdk/api/types/InputData.ts +1 -1
  151. package/src/sdk/api/types/{InputRef.ts → InputDataRef.ts} +1 -1
  152. package/src/sdk/api/types/InputParams.ts +1 -1
  153. package/src/sdk/api/types/{Job.ts → ServiceExecution.ts} +2 -2
  154. package/src/sdk/api/types/{JobStatus.ts → ServiceExecutionStatus.ts} +2 -2
  155. package/src/sdk/api/types/index.ts +4 -8
  156. package/src/sdk/core/fetcher/APIResponse.ts +1 -0
  157. package/src/sdk/core/fetcher/Fetcher.ts +55 -72
  158. package/src/sdk/core/fetcher/createRequestUrl.ts +10 -0
  159. package/src/sdk/core/fetcher/getFetchFn.ts +25 -0
  160. package/src/sdk/core/fetcher/getHeader.ts +8 -0
  161. package/src/sdk/core/fetcher/getRequestBody.ts +14 -0
  162. package/src/sdk/core/fetcher/getResponseBody.ts +32 -0
  163. package/src/sdk/core/fetcher/index.ts +1 -0
  164. package/src/sdk/core/fetcher/makeRequest.ts +44 -0
  165. package/src/sdk/core/fetcher/requestWithRetries.ts +21 -0
  166. package/src/sdk/core/fetcher/signals.ts +38 -0
  167. package/src/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.ts +252 -0
  168. package/src/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.ts +106 -0
  169. package/src/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.ts +239 -0
  170. package/src/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.ts +33 -0
  171. package/src/sdk/core/index.ts +1 -0
  172. package/src/sdk/core/runtime/index.ts +1 -0
  173. package/src/sdk/core/runtime/runtime.ts +126 -0
  174. package/tsconfig.json +15 -107
  175. package/uv.lock +1109 -0
  176. package/.eslintignore +0 -3
  177. package/.eslintrc +0 -7
  178. package/dist/sdk/api/resources/serviceApi/client/requests/GetInterimResultsRequest.d.ts +0 -9
  179. package/dist/sdk/api/resources/serviceApi/client/requests/StartExecutionRequest.d.ts +0 -13
  180. package/dist/sdk/api/resources/serviceApi/client/requests/index.d.ts +0 -2
  181. package/dist/sdk/api/resources/serviceApi/client/requests/index.js +0 -2
  182. package/dist/sdk/api/resources/statusApi/client/Client.d.ts +0 -28
  183. package/dist/sdk/api/resources/statusApi/client/Client.js +0 -97
  184. package/dist/sdk/api/resources/statusApi/client/index.d.ts +0 -1
  185. package/dist/sdk/api/resources/statusApi/client/index.js +0 -2
  186. package/dist/sdk/api/resources/statusApi/index.d.ts +0 -2
  187. package/dist/sdk/api/resources/statusApi/index.js +0 -18
  188. package/dist/sdk/api/resources/statusApi/types/index.d.ts +0 -1
  189. package/dist/sdk/api/resources/statusApi/types/index.js +0 -17
  190. package/dist/sdk/api/types/ArrayResponse.d.ts +0 -4
  191. package/dist/sdk/api/types/InterimResultResponse.d.ts +0 -4
  192. package/dist/sdk/api/types/InterimResultResponse.js +0 -5
  193. package/dist/sdk/api/types/Job.js +0 -5
  194. package/dist/sdk/api/types/NumberResponse.d.ts +0 -4
  195. package/dist/sdk/api/types/NumberResponse.js +0 -5
  196. package/dist/sdk/api/types/ObjectResponse.d.ts +0 -4
  197. package/dist/sdk/api/types/ObjectResponse.js +0 -5
  198. package/dist/sdk/api/types/StringResponse.d.ts +0 -4
  199. package/dist/sdk/api/types/StringResponse.js +0 -5
  200. package/jest.config.js +0 -12
  201. package/src/sdk/api/resources/serviceApi/client/requests/GetInterimResultsRequest.ts +0 -10
  202. package/src/sdk/api/resources/serviceApi/client/requests/StartExecutionRequest.ts +0 -15
  203. package/src/sdk/api/resources/serviceApi/client/requests/index.ts +0 -2
  204. package/src/sdk/api/resources/serviceApi/types/GetInterimResultsResponse.ts +0 -9
  205. package/src/sdk/api/resources/statusApi/client/Client.ts +0 -75
  206. package/src/sdk/api/resources/statusApi/client/index.ts +0 -1
  207. package/src/sdk/api/resources/statusApi/index.ts +0 -2
  208. package/src/sdk/api/resources/statusApi/types/index.ts +0 -1
  209. package/src/sdk/api/types/ArrayResponse.ts +0 -5
  210. package/src/sdk/api/types/InterimResultResponse.ts +0 -5
  211. package/src/sdk/api/types/NumberResponse.ts +0 -5
  212. package/src/sdk/api/types/ObjectResponse.ts +0 -5
  213. package/src/sdk/api/types/StringResponse.ts +0 -5
  214. package/tests/fixtures/complex-input.ts +0 -477
  215. package/tests/integration.test.ts +0 -92
  216. /package/dist/sdk/api/resources/serviceApi/{client/requests/GetInterimResultsRequest.js → types/GetResultResponseEmbedded.js} +0 -0
  217. /package/dist/sdk/api/resources/serviceApi/{client/requests/StartExecutionRequest.js → types/GetResultResponseLinks.js} +0 -0
  218. /package/dist/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.js +0 -0
  219. /package/dist/sdk/api/{resources/serviceApi/types/GetInterimResultsResponse.js → types/HalLink.js} +0 -0
  220. /package/dist/sdk/api/types/{ArrayResponse.js → InputDataRef.js} +0 -0
  221. /package/dist/sdk/api/types/{InputRef.js → ServiceExecution.js} +0 -0
@@ -0,0 +1,323 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ # nopycln: file
4
+ import datetime as dt
5
+ import typing
6
+ from collections import defaultdict
7
+
8
+ import typing_extensions
9
+
10
+ import pydantic
11
+
12
+ from .datetime_utils import serialize_datetime
13
+ from .serialization import convert_and_respect_annotation_metadata
14
+
15
+ IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
16
+
17
+ if IS_PYDANTIC_V2:
18
+ # isort will try to reformat the comments on these imports, which breaks mypy
19
+ # isort: off
20
+ from pydantic.v1.datetime_parse import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
21
+ parse_date as parse_date,
22
+ )
23
+ from pydantic.v1.datetime_parse import ( # pyright: ignore[reportMissingImports] # Pydantic v2
24
+ parse_datetime as parse_datetime,
25
+ )
26
+ from pydantic.v1.json import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
27
+ ENCODERS_BY_TYPE as encoders_by_type,
28
+ )
29
+ from pydantic.v1.typing import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
30
+ get_args as get_args,
31
+ )
32
+ from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
33
+ get_origin as get_origin,
34
+ )
35
+ from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
36
+ is_literal_type as is_literal_type,
37
+ )
38
+ from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2
39
+ is_union as is_union,
40
+ )
41
+ from pydantic.v1.fields import ModelField as ModelField # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2
42
+ else:
43
+ from pydantic.datetime_parse import parse_date as parse_date # type: ignore # Pydantic v1
44
+ from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore # Pydantic v1
45
+ from pydantic.fields import ModelField as ModelField # type: ignore # Pydantic v1
46
+ from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore # Pydantic v1
47
+ from pydantic.typing import get_args as get_args # type: ignore # Pydantic v1
48
+ from pydantic.typing import get_origin as get_origin # type: ignore # Pydantic v1
49
+ from pydantic.typing import is_literal_type as is_literal_type # type: ignore # Pydantic v1
50
+ from pydantic.typing import is_union as is_union # type: ignore # Pydantic v1
51
+
52
+ # isort: on
53
+
54
+
55
+ T = typing.TypeVar("T")
56
+ Model = typing.TypeVar("Model", bound=pydantic.BaseModel)
57
+
58
+
59
+ def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T:
60
+ dealiased_object = convert_and_respect_annotation_metadata(
61
+ object_=object_, annotation=type_, direction="read"
62
+ )
63
+ if IS_PYDANTIC_V2:
64
+ adapter = pydantic.TypeAdapter(type_) # type: ignore # Pydantic v2
65
+ return adapter.validate_python(dealiased_object)
66
+ else:
67
+ return pydantic.parse_obj_as(type_, dealiased_object)
68
+
69
+
70
+ def to_jsonable_with_fallback(
71
+ obj: typing.Any, fallback_serializer: typing.Callable[[typing.Any], typing.Any]
72
+ ) -> typing.Any:
73
+ if IS_PYDANTIC_V2:
74
+ from pydantic_core import to_jsonable_python
75
+
76
+ return to_jsonable_python(obj, fallback=fallback_serializer)
77
+ else:
78
+ return fallback_serializer(obj)
79
+
80
+
81
+ class UniversalBaseModel(pydantic.BaseModel):
82
+ if IS_PYDANTIC_V2:
83
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(
84
+ # Allow fields beginning with `model_` to be used in the model
85
+ protected_namespaces=(),
86
+ ) # type: ignore # Pydantic v2
87
+
88
+ @pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2
89
+ def serialize_model(
90
+ self, handler: pydantic.SerializerFunctionWrapHandler
91
+ ) -> typing.Any: # type: ignore # Pydantic v2
92
+ serialized = handler(self)
93
+ data = {
94
+ k: serialize_datetime(v) if isinstance(v, dt.datetime) else v
95
+ for k, v in serialized.items()
96
+ }
97
+ return data
98
+
99
+ else:
100
+
101
+ class Config:
102
+ smart_union = True
103
+ json_encoders = {dt.datetime: serialize_datetime}
104
+
105
+ @classmethod
106
+ def model_construct(
107
+ cls: typing.Type["Model"],
108
+ _fields_set: typing.Optional[typing.Set[str]] = None,
109
+ **values: typing.Any,
110
+ ) -> "Model":
111
+ dealiased_object = convert_and_respect_annotation_metadata(
112
+ object_=values, annotation=cls, direction="read"
113
+ )
114
+ return cls.construct(_fields_set, **dealiased_object)
115
+
116
+ @classmethod
117
+ def construct(
118
+ cls: typing.Type["Model"],
119
+ _fields_set: typing.Optional[typing.Set[str]] = None,
120
+ **values: typing.Any,
121
+ ) -> "Model":
122
+ dealiased_object = convert_and_respect_annotation_metadata(
123
+ object_=values, annotation=cls, direction="read"
124
+ )
125
+ if IS_PYDANTIC_V2:
126
+ return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2
127
+ else:
128
+ return super().construct(_fields_set, **dealiased_object)
129
+
130
+ def json(self, **kwargs: typing.Any) -> str:
131
+ kwargs_with_defaults: typing.Any = {
132
+ "by_alias": True,
133
+ "exclude_unset": True,
134
+ **kwargs,
135
+ }
136
+ if IS_PYDANTIC_V2:
137
+ return super().model_dump_json(**kwargs_with_defaults) # type: ignore # Pydantic v2
138
+ else:
139
+ return super().json(**kwargs_with_defaults)
140
+
141
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
142
+ """
143
+ Override the default dict method to `exclude_unset` by default. This function patches
144
+ `exclude_unset` to work include fields within non-None default values.
145
+ """
146
+ # Note: the logic here is multiplexed given the levers exposed in Pydantic V1 vs V2
147
+ # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice.
148
+ #
149
+ # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models
150
+ # that we have less control over, and this is less intrusive than custom serializers for now.
151
+ if IS_PYDANTIC_V2:
152
+ kwargs_with_defaults_exclude_unset: typing.Any = {
153
+ **kwargs,
154
+ "by_alias": True,
155
+ "exclude_unset": True,
156
+ "exclude_none": False,
157
+ }
158
+ kwargs_with_defaults_exclude_none: typing.Any = {
159
+ **kwargs,
160
+ "by_alias": True,
161
+ "exclude_none": True,
162
+ "exclude_unset": False,
163
+ }
164
+ dict_dump = deep_union_pydantic_dicts(
165
+ super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2
166
+ super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2
167
+ )
168
+
169
+ else:
170
+ _fields_set = self.__fields_set__.copy()
171
+
172
+ fields = _get_model_fields(self.__class__)
173
+ for name, field in fields.items():
174
+ if name not in _fields_set:
175
+ default = _get_field_default(field)
176
+
177
+ # If the default values are non-null act like they've been set
178
+ # This effectively allows exclude_unset to work like exclude_none where
179
+ # the latter passes through intentionally set none values.
180
+ if default is not None or (
181
+ "exclude_unset" in kwargs and not kwargs["exclude_unset"]
182
+ ):
183
+ _fields_set.add(name)
184
+
185
+ if default is not None:
186
+ self.__fields_set__.add(name)
187
+
188
+ kwargs_with_defaults_exclude_unset_include_fields: typing.Any = {
189
+ "by_alias": True,
190
+ "exclude_unset": True,
191
+ "include": _fields_set,
192
+ **kwargs,
193
+ }
194
+
195
+ dict_dump = super().dict(
196
+ **kwargs_with_defaults_exclude_unset_include_fields
197
+ )
198
+
199
+ return convert_and_respect_annotation_metadata(
200
+ object_=dict_dump, annotation=self.__class__, direction="write"
201
+ )
202
+
203
+
204
+ def _union_list_of_pydantic_dicts(
205
+ source: typing.List[typing.Any], destination: typing.List[typing.Any]
206
+ ) -> typing.List[typing.Any]:
207
+ converted_list: typing.List[typing.Any] = []
208
+ for i, item in enumerate(source):
209
+ destination_value = destination[i] # type: ignore
210
+ if isinstance(item, dict):
211
+ converted_list.append(deep_union_pydantic_dicts(item, destination_value))
212
+ elif isinstance(item, list):
213
+ converted_list.append(
214
+ _union_list_of_pydantic_dicts(item, destination_value)
215
+ )
216
+ else:
217
+ converted_list.append(item)
218
+ return converted_list
219
+
220
+
221
+ def deep_union_pydantic_dicts(
222
+ source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any]
223
+ ) -> typing.Dict[str, typing.Any]:
224
+ for key, value in source.items():
225
+ node = destination.setdefault(key, {})
226
+ if isinstance(value, dict):
227
+ deep_union_pydantic_dicts(value, node)
228
+ # Note: we do not do this same processing for sets given we do not have sets of models
229
+ # and given the sets are unordered, the processing of the set and matching objects would
230
+ # be non-trivial.
231
+ elif isinstance(value, list):
232
+ destination[key] = _union_list_of_pydantic_dicts(value, node)
233
+ else:
234
+ destination[key] = value
235
+
236
+ return destination
237
+
238
+
239
+ if IS_PYDANTIC_V2:
240
+
241
+ class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore # Pydantic v2
242
+ pass
243
+
244
+ UniversalRootModel: typing_extensions.TypeAlias = V2RootModel # type: ignore
245
+ else:
246
+ UniversalRootModel: typing_extensions.TypeAlias = UniversalBaseModel # type: ignore
247
+
248
+
249
+ def encode_by_type(o: typing.Any) -> typing.Any:
250
+ encoders_by_class_tuples: typing.Dict[
251
+ typing.Callable[[typing.Any], typing.Any], typing.Tuple[typing.Any, ...]
252
+ ] = defaultdict(tuple)
253
+ for type_, encoder in encoders_by_type.items():
254
+ encoders_by_class_tuples[encoder] += (type_,)
255
+
256
+ if type(o) in encoders_by_type:
257
+ return encoders_by_type[type(o)](o)
258
+ for encoder, classes_tuple in encoders_by_class_tuples.items():
259
+ if isinstance(o, classes_tuple):
260
+ return encoder(o)
261
+
262
+
263
+ def update_forward_refs(model: typing.Type["Model"], **localns: typing.Any) -> None:
264
+ if IS_PYDANTIC_V2:
265
+ model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2
266
+ else:
267
+ model.update_forward_refs(**localns)
268
+
269
+
270
+ # Mirrors Pydantic's internal typing
271
+ AnyCallable = typing.Callable[..., typing.Any]
272
+
273
+
274
+ def universal_root_validator(
275
+ pre: bool = False,
276
+ ) -> typing.Callable[[AnyCallable], AnyCallable]:
277
+ def decorator(func: AnyCallable) -> AnyCallable:
278
+ if IS_PYDANTIC_V2:
279
+ return pydantic.model_validator(mode="before" if pre else "after")(func) # type: ignore # Pydantic v2
280
+ else:
281
+ return pydantic.root_validator(pre=pre)(func) # type: ignore # Pydantic v1
282
+
283
+ return decorator
284
+
285
+
286
+ def universal_field_validator(
287
+ field_name: str, pre: bool = False
288
+ ) -> typing.Callable[[AnyCallable], AnyCallable]:
289
+ def decorator(func: AnyCallable) -> AnyCallable:
290
+ if IS_PYDANTIC_V2:
291
+ return pydantic.field_validator(
292
+ field_name, mode="before" if pre else "after"
293
+ )(func) # type: ignore # Pydantic v2
294
+ else:
295
+ return pydantic.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1
296
+
297
+ return decorator
298
+
299
+
300
+ PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo]
301
+
302
+
303
+ def _get_model_fields(
304
+ model: typing.Type["Model"],
305
+ ) -> typing.Mapping[str, PydanticField]:
306
+ if IS_PYDANTIC_V2:
307
+ return model.model_fields # type: ignore # Pydantic v2
308
+ else:
309
+ return model.__fields__ # type: ignore # Pydantic v1
310
+
311
+
312
+ def _get_field_default(field: PydanticField) -> typing.Any:
313
+ try:
314
+ value = field.get_default() # type: ignore # Pydantic < v1.10.15
315
+ except:
316
+ value = field.default
317
+ if IS_PYDANTIC_V2:
318
+ from pydantic_core import PydanticUndefined
319
+
320
+ if value == PydanticUndefined:
321
+ return None
322
+ return value
323
+ return value
@@ -0,0 +1,60 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from typing import Any, Dict, List, Optional, Tuple
4
+
5
+ import pydantic
6
+
7
+
8
+ # Flattens dicts to be of the form {"key[subkey][subkey2]": value} where value is not a dict
9
+ def traverse_query_dict(
10
+ dict_flat: Dict[str, Any], key_prefix: Optional[str] = None
11
+ ) -> List[Tuple[str, Any]]:
12
+ result = []
13
+ for k, v in dict_flat.items():
14
+ key = f"{key_prefix}[{k}]" if key_prefix is not None else k
15
+ if isinstance(v, dict):
16
+ result.extend(traverse_query_dict(v, key))
17
+ elif isinstance(v, list):
18
+ for arr_v in v:
19
+ if isinstance(arr_v, dict):
20
+ result.extend(traverse_query_dict(arr_v, key))
21
+ else:
22
+ result.append((key, arr_v))
23
+ else:
24
+ result.append((key, v))
25
+ return result
26
+
27
+
28
+ def single_query_encoder(query_key: str, query_value: Any) -> List[Tuple[str, Any]]:
29
+ if isinstance(query_value, pydantic.BaseModel) or isinstance(query_value, dict):
30
+ if isinstance(query_value, pydantic.BaseModel):
31
+ obj_dict = query_value.dict(by_alias=True)
32
+ else:
33
+ obj_dict = query_value
34
+ return traverse_query_dict(obj_dict, query_key)
35
+ elif isinstance(query_value, list):
36
+ encoded_values: List[Tuple[str, Any]] = []
37
+ for value in query_value:
38
+ if isinstance(value, pydantic.BaseModel) or isinstance(value, dict):
39
+ if isinstance(value, pydantic.BaseModel):
40
+ obj_dict = value.dict(by_alias=True)
41
+ elif isinstance(value, dict):
42
+ obj_dict = value
43
+
44
+ encoded_values.extend(single_query_encoder(query_key, obj_dict))
45
+ else:
46
+ encoded_values.append((query_key, value))
47
+
48
+ return encoded_values
49
+
50
+ return [(query_key, query_value)]
51
+
52
+
53
+ def encode_query(query: Optional[Dict[str, Any]]) -> Optional[List[Tuple[str, Any]]]:
54
+ if query is None:
55
+ return None
56
+
57
+ encoded_query = []
58
+ for k, v in query.items():
59
+ encoded_query.extend(single_query_encoder(k, v))
60
+ return encoded_query
@@ -0,0 +1,11 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from typing import Any, Dict, Mapping, Optional
4
+
5
+
6
+ def remove_none_from_dict(original: Mapping[str, Optional[Any]]) -> Dict[str, Any]:
7
+ new: Dict[str, Any] = {}
8
+ for key, value in original.items():
9
+ if value is not None:
10
+ new[key] = value
11
+ return new
@@ -0,0 +1,35 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ try:
6
+ from typing import NotRequired # type: ignore
7
+ except ImportError:
8
+ from typing_extensions import NotRequired
9
+
10
+
11
+ class RequestOptions(typing.TypedDict, total=False):
12
+ """
13
+ Additional options for request-specific configuration when calling APIs via the SDK.
14
+ This is used primarily as an optional final parameter for service functions.
15
+
16
+ Attributes:
17
+ - timeout_in_seconds: int. The number of seconds to await an API call before timing out.
18
+
19
+ - max_retries: int. The max number of retries to attempt if the API call fails.
20
+
21
+ - additional_headers: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's header dict
22
+
23
+ - additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict
24
+
25
+ - additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict
26
+
27
+ - 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.
28
+ """
29
+
30
+ timeout_in_seconds: NotRequired[int]
31
+ max_retries: NotRequired[int]
32
+ additional_headers: NotRequired[typing.Dict[str, typing.Any]]
33
+ additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]]
34
+ additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]]
35
+ chunk_size: NotRequired[int]