dub 0.26.6__tar.gz → 0.26.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. {dub-0.26.6 → dub-0.26.8}/PKG-INFO +1 -1
  2. {dub-0.26.6 → dub-0.26.8}/pyproject.toml +3 -1
  3. {dub-0.26.6 → dub-0.26.8}/src/dub/_version.py +3 -3
  4. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/__init__.py +5 -2
  5. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/listcommissions.py +2 -0
  6. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/listevents.py +4 -4
  7. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/retrieveanalytics.py +14 -0
  8. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatecommission.py +1 -0
  9. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/forms.py +49 -28
  10. {dub-0.26.6 → dub-0.26.8}/LICENSE +0 -0
  11. {dub-0.26.6 → dub-0.26.8}/README-PYPI.md +0 -0
  12. {dub-0.26.6 → dub-0.26.8}/py.typed +0 -0
  13. {dub-0.26.6 → dub-0.26.8}/src/dub/__init__.py +0 -0
  14. {dub-0.26.6 → dub-0.26.8}/src/dub/_hooks/__init__.py +0 -0
  15. {dub-0.26.6 → dub-0.26.8}/src/dub/_hooks/registration.py +0 -0
  16. {dub-0.26.6 → dub-0.26.8}/src/dub/_hooks/sdkhooks.py +0 -0
  17. {dub-0.26.6 → dub-0.26.8}/src/dub/_hooks/types.py +0 -0
  18. {dub-0.26.6 → dub-0.26.8}/src/dub/analytics.py +0 -0
  19. {dub-0.26.6 → dub-0.26.8}/src/dub/basesdk.py +0 -0
  20. {dub-0.26.6 → dub-0.26.8}/src/dub/commissions.py +0 -0
  21. {dub-0.26.6 → dub-0.26.8}/src/dub/customers.py +0 -0
  22. {dub-0.26.6 → dub-0.26.8}/src/dub/domains.py +0 -0
  23. {dub-0.26.6 → dub-0.26.8}/src/dub/embed_tokens.py +0 -0
  24. {dub-0.26.6 → dub-0.26.8}/src/dub/events.py +0 -0
  25. {dub-0.26.6 → dub-0.26.8}/src/dub/folders.py +0 -0
  26. {dub-0.26.6 → dub-0.26.8}/src/dub/httpclient.py +0 -0
  27. {dub-0.26.6 → dub-0.26.8}/src/dub/links.py +0 -0
  28. {dub-0.26.6 → dub-0.26.8}/src/dub/models/__init__.py +0 -0
  29. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/__init__.py +0 -0
  30. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsbrowsers.py +0 -0
  31. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticscities.py +0 -0
  32. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticscontinents.py +0 -0
  33. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticscount.py +0 -0
  34. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticscountries.py +0 -0
  35. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsdevices.py +0 -0
  36. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsos.py +0 -0
  37. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsreferers.py +0 -0
  38. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsrefererurls.py +0 -0
  39. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticsregions.py +0 -0
  40. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticstimeseries.py +0 -0
  41. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticstoplinks.py +0 -0
  42. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticstopurls.py +0 -0
  43. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/analyticstriggers.py +0 -0
  44. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/clickevent.py +0 -0
  45. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/continentcode.py +0 -0
  46. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/countrycode.py +0 -0
  47. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/domainschema.py +0 -0
  48. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/folderschema.py +0 -0
  49. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/leadcreatedevent.py +0 -0
  50. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/leadevent.py +0 -0
  51. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/linkclickedevent.py +0 -0
  52. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/linkerrorschema.py +0 -0
  53. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/linkgeotargeting.py +0 -0
  54. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/linkschema.py +0 -0
  55. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/linkwebhookevent.py +0 -0
  56. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/partneranalyticscount.py +0 -0
  57. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/partneranalyticstimeseries.py +0 -0
  58. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/partneranalyticstoplinks.py +0 -0
  59. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/partnerenrolledevent.py +0 -0
  60. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/salecreatedevent.py +0 -0
  61. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/saleevent.py +0 -0
  62. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/security.py +0 -0
  63. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/tagschema.py +0 -0
  64. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/webhookevent.py +0 -0
  65. {dub-0.26.6 → dub-0.26.8}/src/dub/models/components/workspaceschema.py +0 -0
  66. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/__init__.py +0 -0
  67. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/badrequest.py +0 -0
  68. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/conflict.py +0 -0
  69. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/forbidden.py +0 -0
  70. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/internalservererror.py +0 -0
  71. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/inviteexpired.py +0 -0
  72. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/notfound.py +0 -0
  73. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/ratelimitexceeded.py +0 -0
  74. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/sdkerror.py +0 -0
  75. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/unauthorized.py +0 -0
  76. {dub-0.26.6 → dub-0.26.8}/src/dub/models/errors/unprocessableentity.py +0 -0
  77. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/bulkcreatelinks.py +0 -0
  78. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/bulkdeletelinks.py +0 -0
  79. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/bulkupdatelinks.py +0 -0
  80. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/checkdomainstatus.py +0 -0
  81. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createcustomer.py +0 -0
  82. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createdomain.py +0 -0
  83. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createfolder.py +0 -0
  84. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createlink.py +0 -0
  85. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createpartner.py +0 -0
  86. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createpartnerlink.py +0 -0
  87. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createreferralsembedtoken.py +0 -0
  88. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/createtag.py +0 -0
  89. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/deletecustomer.py +0 -0
  90. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/deletedomain.py +0 -0
  91. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/deletefolder.py +0 -0
  92. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/deletelink.py +0 -0
  93. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/deletetag.py +0 -0
  94. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getcustomer.py +0 -0
  95. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getcustomers.py +0 -0
  96. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getlinkinfo.py +0 -0
  97. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getlinks.py +0 -0
  98. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getlinkscount.py +0 -0
  99. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getqrcode.py +0 -0
  100. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/gettags.py +0 -0
  101. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/getworkspace.py +0 -0
  102. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/listdomains.py +0 -0
  103. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/listfolders.py +0 -0
  104. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/registerdomain.py +0 -0
  105. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/retrievelinks.py +0 -0
  106. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/retrievepartneranalytics.py +0 -0
  107. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/tracklead.py +0 -0
  108. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/tracksale.py +0 -0
  109. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatecustomer.py +0 -0
  110. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatedomain.py +0 -0
  111. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatefolder.py +0 -0
  112. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatelink.py +0 -0
  113. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updatetag.py +0 -0
  114. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/updateworkspace.py +0 -0
  115. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/upsertlink.py +0 -0
  116. {dub-0.26.6 → dub-0.26.8}/src/dub/models/operations/upsertpartnerlink.py +0 -0
  117. {dub-0.26.6 → dub-0.26.8}/src/dub/partners.py +0 -0
  118. {dub-0.26.6 → dub-0.26.8}/src/dub/py.typed +0 -0
  119. {dub-0.26.6 → dub-0.26.8}/src/dub/qr_codes.py +0 -0
  120. {dub-0.26.6 → dub-0.26.8}/src/dub/sdk.py +0 -0
  121. {dub-0.26.6 → dub-0.26.8}/src/dub/sdkconfiguration.py +0 -0
  122. {dub-0.26.6 → dub-0.26.8}/src/dub/tags.py +0 -0
  123. {dub-0.26.6 → dub-0.26.8}/src/dub/track.py +0 -0
  124. {dub-0.26.6 → dub-0.26.8}/src/dub/types/__init__.py +0 -0
  125. {dub-0.26.6 → dub-0.26.8}/src/dub/types/basemodel.py +0 -0
  126. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/__init__.py +0 -0
  127. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/annotations.py +0 -0
  128. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/datetimes.py +0 -0
  129. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/enums.py +0 -0
  130. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/eventstreaming.py +0 -0
  131. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/headers.py +0 -0
  132. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/logger.py +0 -0
  133. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/metadata.py +0 -0
  134. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/queryparams.py +0 -0
  135. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/requestbodies.py +0 -0
  136. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/retries.py +0 -0
  137. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/security.py +0 -0
  138. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/serializers.py +0 -0
  139. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/url.py +0 -0
  140. {dub-0.26.6 → dub-0.26.8}/src/dub/utils/values.py +0 -0
  141. {dub-0.26.6 → dub-0.26.8}/src/dub/workspaces.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dub
3
- Version: 0.26.6
3
+ Version: 0.26.8
4
4
  Summary: Python Client SDK Generated by Speakeasy
5
5
  Author: Speakeasy
6
6
  Requires-Python: >=3.9.2
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dub"
3
- version = "0.26.6"
3
+ version = "0.26.8"
4
4
  description = "Python Client SDK Generated by Speakeasy"
5
5
  authors = [{ name = "Speakeasy" },]
6
6
  readme = "README-PYPI.md"
@@ -39,6 +39,8 @@ pythonpath = ["src"]
39
39
 
40
40
  [tool.mypy]
41
41
  disable_error_code = "misc"
42
+ explicit_package_bases = true
43
+ mypy_path = "src"
42
44
 
43
45
  [[tool.mypy.overrides]]
44
46
  module = "typing_inspect"
@@ -3,10 +3,10 @@
3
3
  import importlib.metadata
4
4
 
5
5
  __title__: str = "dub"
6
- __version__: str = "0.26.6"
6
+ __version__: str = "0.26.8"
7
7
  __openapi_doc_version__: str = "0.0.1"
8
- __gen_version__: str = "2.623.0"
9
- __user_agent__: str = "speakeasy-sdk/python 0.26.6 2.623.0 0.0.1 dub"
8
+ __gen_version__: str = "2.630.6"
9
+ __user_agent__: str = "speakeasy-sdk/python 0.26.8 2.630.6 0.0.1 dub"
10
10
 
11
11
  try:
12
12
  if __package__ is not None:
@@ -235,6 +235,7 @@ if TYPE_CHECKING:
235
235
  ListDomainsResponseTypedDict,
236
236
  )
237
237
  from .listevents import (
238
+ ListEventsQueryParamSortBy,
238
239
  ListEventsQueryParamTagIds,
239
240
  ListEventsQueryParamTagIdsTypedDict,
240
241
  ListEventsRequest,
@@ -244,7 +245,6 @@ if TYPE_CHECKING:
244
245
  Order,
245
246
  QueryParamEvent,
246
247
  QueryParamInterval,
247
- QueryParamSortBy,
248
248
  QueryParamSortOrder,
249
249
  QueryParamTrigger,
250
250
  )
@@ -259,6 +259,7 @@ if TYPE_CHECKING:
259
259
  Event,
260
260
  Interval,
261
261
  QueryParamGroupBy,
262
+ QueryParamSortBy,
262
263
  RetrieveAnalyticsQueryParamTagIds,
263
264
  RetrieveAnalyticsQueryParamTagIdsTypedDict,
264
265
  RetrieveAnalyticsRequest,
@@ -568,6 +569,7 @@ __all__ = [
568
569
  "ListDomainsRequestTypedDict",
569
570
  "ListDomainsResponse",
570
571
  "ListDomainsResponseTypedDict",
572
+ "ListEventsQueryParamSortBy",
571
573
  "ListEventsQueryParamTagIds",
572
574
  "ListEventsQueryParamTagIdsTypedDict",
573
575
  "ListEventsRequest",
@@ -904,6 +906,7 @@ _dynamic_imports: dict[str, str] = {
904
906
  "ListDomainsRequestTypedDict": ".listdomains",
905
907
  "ListDomainsResponse": ".listdomains",
906
908
  "ListDomainsResponseTypedDict": ".listdomains",
909
+ "ListEventsQueryParamSortBy": ".listevents",
907
910
  "ListEventsQueryParamTagIds": ".listevents",
908
911
  "ListEventsQueryParamTagIdsTypedDict": ".listevents",
909
912
  "ListEventsRequest": ".listevents",
@@ -913,7 +916,6 @@ _dynamic_imports: dict[str, str] = {
913
916
  "Order": ".listevents",
914
917
  "QueryParamEvent": ".listevents",
915
918
  "QueryParamInterval": ".listevents",
916
- "QueryParamSortBy": ".listevents",
917
919
  "QueryParamSortOrder": ".listevents",
918
920
  "QueryParamTrigger": ".listevents",
919
921
  "ListFoldersRequest": ".listfolders",
@@ -925,6 +927,7 @@ _dynamic_imports: dict[str, str] = {
925
927
  "Event": ".retrieveanalytics",
926
928
  "Interval": ".retrieveanalytics",
927
929
  "QueryParamGroupBy": ".retrieveanalytics",
930
+ "QueryParamSortBy": ".retrieveanalytics",
928
931
  "RetrieveAnalyticsQueryParamTagIds": ".retrieveanalytics",
929
932
  "RetrieveAnalyticsQueryParamTagIdsTypedDict": ".retrieveanalytics",
930
933
  "RetrieveAnalyticsRequest": ".retrieveanalytics",
@@ -14,6 +14,7 @@ class Type(str, Enum):
14
14
  CLICK = "click"
15
15
  LEAD = "lead"
16
16
  SALE = "sale"
17
+ CUSTOM = "custom"
17
18
 
18
19
 
19
20
  class QueryParamStatus(str, Enum):
@@ -174,6 +175,7 @@ class ListCommissionsType(str, Enum):
174
175
  CLICK = "click"
175
176
  LEAD = "lead"
176
177
  SALE = "sale"
178
+ CUSTOM = "custom"
177
179
 
178
180
 
179
181
  class ListCommissionsStatus(str, Enum):
@@ -71,7 +71,7 @@ class QueryParamSortOrder(str, Enum):
71
71
  DESC = "desc"
72
72
 
73
73
 
74
- class QueryParamSortBy(str, Enum):
74
+ class ListEventsQueryParamSortBy(str, Enum):
75
75
  r"""The field to sort the events by. The default is `timestamp`."""
76
76
 
77
77
  TIMESTAMP = "timestamp"
@@ -160,7 +160,7 @@ class ListEventsRequestTypedDict(TypedDict):
160
160
  limit: NotRequired[float]
161
161
  sort_order: NotRequired[QueryParamSortOrder]
162
162
  r"""The sort order. The default is `desc`."""
163
- sort_by: NotRequired[QueryParamSortBy]
163
+ sort_by: NotRequired[ListEventsQueryParamSortBy]
164
164
  r"""The field to sort the events by. The default is `timestamp`."""
165
165
  order: NotRequired[Order]
166
166
  r"""DEPRECATED. Use `sortOrder` instead."""
@@ -399,10 +399,10 @@ class ListEventsRequest(BaseModel):
399
399
  r"""The sort order. The default is `desc`."""
400
400
 
401
401
  sort_by: Annotated[
402
- Optional[QueryParamSortBy],
402
+ Optional[ListEventsQueryParamSortBy],
403
403
  pydantic.Field(alias="sortBy"),
404
404
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
405
- ] = QueryParamSortBy.TIMESTAMP
405
+ ] = ListEventsQueryParamSortBy.TIMESTAMP
406
406
  r"""The field to sort the events by. The default is `timestamp`."""
407
407
 
408
408
  order: Annotated[
@@ -96,6 +96,12 @@ RetrieveAnalyticsQueryParamTagIds = TypeAliasType(
96
96
  r"""The tag IDs to retrieve analytics for."""
97
97
 
98
98
 
99
+ class QueryParamSortBy(str, Enum):
100
+ CLICKS = "clicks"
101
+ LEADS = "leads"
102
+ SALES = "sales"
103
+
104
+
99
105
  class RetrieveAnalyticsRequestTypedDict(TypedDict):
100
106
  event: NotRequired[Event]
101
107
  r"""The type of event to retrieve analytics for. Defaults to `clicks`."""
@@ -157,6 +163,7 @@ class RetrieveAnalyticsRequestTypedDict(TypedDict):
157
163
  r"""Deprecated. Use the `trigger` field instead. Filter for QR code scans. If true, filter for QR codes only. If false, filter for links only. If undefined, return both."""
158
164
  root: NotRequired[bool]
159
165
  r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
166
+ sort_by: NotRequired[QueryParamSortBy]
160
167
  utm_source: NotRequired[Nullable[str]]
161
168
  r"""The UTM source of the short link."""
162
169
  utm_medium: NotRequired[Nullable[str]]
@@ -361,6 +368,12 @@ class RetrieveAnalyticsRequest(BaseModel):
361
368
  ] = None
362
369
  r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
363
370
 
371
+ sort_by: Annotated[
372
+ Optional[QueryParamSortBy],
373
+ pydantic.Field(alias="sortBy"),
374
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
375
+ ] = None
376
+
364
377
  utm_source: Annotated[
365
378
  OptionalNullable[str],
366
379
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
@@ -424,6 +437,7 @@ class RetrieveAnalyticsRequest(BaseModel):
424
437
  "folderId",
425
438
  "qr",
426
439
  "root",
440
+ "sortBy",
427
441
  "utm_source",
428
442
  "utm_medium",
429
443
  "utm_campaign",
@@ -68,6 +68,7 @@ class UpdateCommissionType(str, Enum):
68
68
  CLICK = "click"
69
69
  LEAD = "lead"
70
70
  SALE = "sale"
71
+ CUSTOM = "custom"
71
72
 
72
73
 
73
74
  class UpdateCommissionStatus(str, Enum):
@@ -86,11 +86,39 @@ def _populate_form(
86
86
  return form
87
87
 
88
88
 
89
+ def _extract_file_properties(file_obj: Any) -> Tuple[str, Any, Any]:
90
+ """Extract file name, content, and content type from a file object."""
91
+ file_fields: Dict[str, FieldInfo] = file_obj.__class__.model_fields
92
+
93
+ file_name = ""
94
+ content = None
95
+ content_type = None
96
+
97
+ for file_field_name in file_fields:
98
+ file_field = file_fields[file_field_name]
99
+
100
+ file_metadata = find_field_metadata(file_field, MultipartFormMetadata)
101
+ if file_metadata is None:
102
+ continue
103
+
104
+ if file_metadata.content:
105
+ content = getattr(file_obj, file_field_name, None)
106
+ elif file_field_name == "content_type":
107
+ content_type = getattr(file_obj, file_field_name, None)
108
+ else:
109
+ file_name = getattr(file_obj, file_field_name)
110
+
111
+ if file_name == "" or content is None:
112
+ raise ValueError("invalid multipart/form-data file")
113
+
114
+ return file_name, content, content_type
115
+
116
+
89
117
  def serialize_multipart_form(
90
118
  media_type: str, request: Any
91
- ) -> Tuple[str, Dict[str, Any], Dict[str, Any]]:
119
+ ) -> Tuple[str, Dict[str, Any], List[Tuple[str, Any]]]:
92
120
  form: Dict[str, Any] = {}
93
- files: Dict[str, Any] = {}
121
+ files: List[Tuple[str, Any]] = []
94
122
 
95
123
  if not isinstance(request, BaseModel):
96
124
  raise TypeError("invalid request body type")
@@ -112,39 +140,32 @@ def serialize_multipart_form(
112
140
  f_name = field.alias if field.alias else name
113
141
 
114
142
  if field_metadata.file:
115
- file_fields: Dict[str, FieldInfo] = val.__class__.model_fields
116
-
117
- file_name = ""
118
- content = None
119
- content_type = None
120
-
121
- for file_field_name in file_fields:
122
- file_field = file_fields[file_field_name]
143
+ if isinstance(val, List):
144
+ # Handle array of files
145
+ for file_obj in val:
146
+ if not _is_set(file_obj):
147
+ continue
148
+
149
+ file_name, content, content_type = _extract_file_properties(file_obj)
123
150
 
124
- file_metadata = find_field_metadata(file_field, MultipartFormMetadata)
125
- if file_metadata is None:
126
- continue
151
+ if content_type is not None:
152
+ files.append((f_name + "[]", (file_name, content, content_type)))
153
+ else:
154
+ files.append((f_name + "[]", (file_name, content)))
155
+ else:
156
+ # Handle single file
157
+ file_name, content, content_type = _extract_file_properties(val)
127
158
 
128
- if file_metadata.content:
129
- content = getattr(val, file_field_name, None)
130
- elif file_field_name == "content_type":
131
- content_type = getattr(val, file_field_name, None)
159
+ if content_type is not None:
160
+ files.append((f_name, (file_name, content, content_type)))
132
161
  else:
133
- file_name = getattr(val, file_field_name)
134
-
135
- if file_name == "" or content is None:
136
- raise ValueError("invalid multipart/form-data file")
137
-
138
- if content_type is not None:
139
- files[f_name] = (file_name, content, content_type)
140
- else:
141
- files[f_name] = (file_name, content)
162
+ files.append((f_name, (file_name, content)))
142
163
  elif field_metadata.json:
143
- files[f_name] = (
164
+ files.append((f_name, (
144
165
  None,
145
166
  marshal_json(val, request_field_types[name]),
146
167
  "application/json",
147
- )
168
+ )))
148
169
  else:
149
170
  if isinstance(val, List):
150
171
  values = []
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes