dub 0.33.0__py3-none-any.whl → 0.34.0__py3-none-any.whl
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.
- dub/_version.py +3 -3
- dub/analytics.py +2 -0
- dub/basesdk.py +6 -0
- dub/commissions.py +4 -0
- dub/customers.py +8 -0
- dub/domains.py +12 -0
- dub/embed_tokens.py +2 -0
- dub/events.py +2 -0
- dub/folders.py +8 -0
- dub/links.py +20 -0
- dub/models/components/__init__.py +49 -149
- dub/models/components/leadcreatedevent.py +8 -8
- dub/models/components/linkclickedevent.py +12 -12
- dub/models/components/linkerrorschema.py +12 -12
- dub/models/components/linkschema.py +3 -3
- dub/models/components/linktagschema.py +3 -3
- dub/models/components/linktagschemaoutput.py +38 -0
- dub/models/components/linkwebhookevent.py +8 -10
- dub/models/components/partnerenrolledevent.py +4 -4
- dub/models/components/salecreatedevent.py +8 -8
- dub/models/operations/__init__.py +130 -22
- dub/models/operations/createpartner.py +4 -55
- dub/models/operations/createpartnerlink.py +0 -51
- dub/models/operations/createreferralsembedtoken.py +0 -51
- dub/models/operations/getcustomers.py +18 -0
- dub/models/operations/getlinkinfo.py +0 -2
- dub/models/operations/getlinks.py +2 -2
- dub/models/operations/getlinkscount.py +2 -2
- dub/models/operations/getqrcode.py +1 -1
- dub/models/operations/listdomains.py +1 -1
- dub/models/operations/listevents.py +2016 -21
- dub/models/operations/listpartners.py +4 -4
- dub/models/operations/retrieveanalytics.py +16 -5
- dub/models/operations/retrievelinks.py +2 -2
- dub/models/operations/tracklead.py +4 -4
- dub/models/operations/updatecustomer.py +23 -11
- dub/models/operations/updatelink.py +0 -2
- dub/models/operations/updateworkspace.py +3 -3
- dub/models/operations/upsertpartnerlink.py +0 -51
- dub/partners.py +22 -4
- dub/qr_codes.py +2 -0
- dub/tags.py +24 -12
- dub/track.py +4 -0
- dub/types/basemodel.py +41 -3
- dub/utils/__init__.py +0 -3
- dub/utils/enums.py +60 -0
- dub/utils/forms.py +21 -10
- dub/utils/queryparams.py +14 -2
- dub/utils/requestbodies.py +3 -3
- dub/utils/serializers.py +0 -20
- dub/workspaces.py +4 -0
- {dub-0.33.0.dist-info → dub-0.34.0.dist-info}/METADATA +14 -14
- {dub-0.33.0.dist-info → dub-0.34.0.dist-info}/RECORD +55 -58
- dub/models/components/clickevent.py +0 -557
- dub/models/components/continentcode.py +0 -16
- dub/models/components/leadevent.py +0 -681
- dub/models/components/saleevent.py +0 -780
- {dub-0.33.0.dist-info → dub-0.34.0.dist-info}/WHEEL +0 -0
- {dub-0.33.0.dist-info → dub-0.34.0.dist-info}/licenses/LICENSE +0 -0
dub/tags.py
CHANGED
|
@@ -23,7 +23,7 @@ class Tags(BaseSDK):
|
|
|
23
23
|
server_url: Optional[str] = None,
|
|
24
24
|
timeout_ms: Optional[int] = None,
|
|
25
25
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
26
|
-
) -> components.
|
|
26
|
+
) -> components.LinkTagSchemaOutput:
|
|
27
27
|
r"""Create a tag
|
|
28
28
|
|
|
29
29
|
Create a tag for the authenticated workspace.
|
|
@@ -66,6 +66,7 @@ class Tags(BaseSDK):
|
|
|
66
66
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
67
67
|
request, False, True, "json", Optional[operations.CreateTagRequestBody]
|
|
68
68
|
),
|
|
69
|
+
allow_empty_value=None,
|
|
69
70
|
timeout_ms=timeout_ms,
|
|
70
71
|
)
|
|
71
72
|
|
|
@@ -104,7 +105,7 @@ class Tags(BaseSDK):
|
|
|
104
105
|
|
|
105
106
|
response_data: Any = None
|
|
106
107
|
if utils.match_response(http_res, "201", "application/json"):
|
|
107
|
-
return unmarshal_json_response(components.
|
|
108
|
+
return unmarshal_json_response(components.LinkTagSchemaOutput, http_res)
|
|
108
109
|
if utils.match_response(http_res, "400", "application/json"):
|
|
109
110
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
110
111
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -160,7 +161,7 @@ class Tags(BaseSDK):
|
|
|
160
161
|
server_url: Optional[str] = None,
|
|
161
162
|
timeout_ms: Optional[int] = None,
|
|
162
163
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
163
|
-
) -> components.
|
|
164
|
+
) -> components.LinkTagSchemaOutput:
|
|
164
165
|
r"""Create a tag
|
|
165
166
|
|
|
166
167
|
Create a tag for the authenticated workspace.
|
|
@@ -203,6 +204,7 @@ class Tags(BaseSDK):
|
|
|
203
204
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
204
205
|
request, False, True, "json", Optional[operations.CreateTagRequestBody]
|
|
205
206
|
),
|
|
207
|
+
allow_empty_value=None,
|
|
206
208
|
timeout_ms=timeout_ms,
|
|
207
209
|
)
|
|
208
210
|
|
|
@@ -241,7 +243,7 @@ class Tags(BaseSDK):
|
|
|
241
243
|
|
|
242
244
|
response_data: Any = None
|
|
243
245
|
if utils.match_response(http_res, "201", "application/json"):
|
|
244
|
-
return unmarshal_json_response(components.
|
|
246
|
+
return unmarshal_json_response(components.LinkTagSchemaOutput, http_res)
|
|
245
247
|
if utils.match_response(http_res, "400", "application/json"):
|
|
246
248
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
247
249
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -292,7 +294,7 @@ class Tags(BaseSDK):
|
|
|
292
294
|
server_url: Optional[str] = None,
|
|
293
295
|
timeout_ms: Optional[int] = None,
|
|
294
296
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
295
|
-
) -> List[components.
|
|
297
|
+
) -> List[components.LinkTagSchemaOutput]:
|
|
296
298
|
r"""Retrieve a list of tags
|
|
297
299
|
|
|
298
300
|
Retrieve a list of tags for the authenticated workspace.
|
|
@@ -330,6 +332,7 @@ class Tags(BaseSDK):
|
|
|
330
332
|
accept_header_value="application/json",
|
|
331
333
|
http_headers=http_headers,
|
|
332
334
|
security=self.sdk_configuration.security,
|
|
335
|
+
allow_empty_value=None,
|
|
333
336
|
timeout_ms=timeout_ms,
|
|
334
337
|
)
|
|
335
338
|
|
|
@@ -368,7 +371,9 @@ class Tags(BaseSDK):
|
|
|
368
371
|
|
|
369
372
|
response_data: Any = None
|
|
370
373
|
if utils.match_response(http_res, "200", "application/json"):
|
|
371
|
-
return unmarshal_json_response(
|
|
374
|
+
return unmarshal_json_response(
|
|
375
|
+
List[components.LinkTagSchemaOutput], http_res
|
|
376
|
+
)
|
|
372
377
|
if utils.match_response(http_res, "400", "application/json"):
|
|
373
378
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
374
379
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -419,7 +424,7 @@ class Tags(BaseSDK):
|
|
|
419
424
|
server_url: Optional[str] = None,
|
|
420
425
|
timeout_ms: Optional[int] = None,
|
|
421
426
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
422
|
-
) -> List[components.
|
|
427
|
+
) -> List[components.LinkTagSchemaOutput]:
|
|
423
428
|
r"""Retrieve a list of tags
|
|
424
429
|
|
|
425
430
|
Retrieve a list of tags for the authenticated workspace.
|
|
@@ -457,6 +462,7 @@ class Tags(BaseSDK):
|
|
|
457
462
|
accept_header_value="application/json",
|
|
458
463
|
http_headers=http_headers,
|
|
459
464
|
security=self.sdk_configuration.security,
|
|
465
|
+
allow_empty_value=None,
|
|
460
466
|
timeout_ms=timeout_ms,
|
|
461
467
|
)
|
|
462
468
|
|
|
@@ -495,7 +501,9 @@ class Tags(BaseSDK):
|
|
|
495
501
|
|
|
496
502
|
response_data: Any = None
|
|
497
503
|
if utils.match_response(http_res, "200", "application/json"):
|
|
498
|
-
return unmarshal_json_response(
|
|
504
|
+
return unmarshal_json_response(
|
|
505
|
+
List[components.LinkTagSchemaOutput], http_res
|
|
506
|
+
)
|
|
499
507
|
if utils.match_response(http_res, "400", "application/json"):
|
|
500
508
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
501
509
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -552,7 +560,7 @@ class Tags(BaseSDK):
|
|
|
552
560
|
server_url: Optional[str] = None,
|
|
553
561
|
timeout_ms: Optional[int] = None,
|
|
554
562
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
555
|
-
) -> components.
|
|
563
|
+
) -> components.LinkTagSchemaOutput:
|
|
556
564
|
r"""Update a tag
|
|
557
565
|
|
|
558
566
|
Update a tag in the workspace.
|
|
@@ -601,6 +609,7 @@ class Tags(BaseSDK):
|
|
|
601
609
|
"json",
|
|
602
610
|
Optional[operations.UpdateTagRequestBody],
|
|
603
611
|
),
|
|
612
|
+
allow_empty_value=None,
|
|
604
613
|
timeout_ms=timeout_ms,
|
|
605
614
|
)
|
|
606
615
|
|
|
@@ -639,7 +648,7 @@ class Tags(BaseSDK):
|
|
|
639
648
|
|
|
640
649
|
response_data: Any = None
|
|
641
650
|
if utils.match_response(http_res, "200", "application/json"):
|
|
642
|
-
return unmarshal_json_response(components.
|
|
651
|
+
return unmarshal_json_response(components.LinkTagSchemaOutput, http_res)
|
|
643
652
|
if utils.match_response(http_res, "400", "application/json"):
|
|
644
653
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
645
654
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -696,7 +705,7 @@ class Tags(BaseSDK):
|
|
|
696
705
|
server_url: Optional[str] = None,
|
|
697
706
|
timeout_ms: Optional[int] = None,
|
|
698
707
|
http_headers: Optional[Mapping[str, str]] = None,
|
|
699
|
-
) -> components.
|
|
708
|
+
) -> components.LinkTagSchemaOutput:
|
|
700
709
|
r"""Update a tag
|
|
701
710
|
|
|
702
711
|
Update a tag in the workspace.
|
|
@@ -745,6 +754,7 @@ class Tags(BaseSDK):
|
|
|
745
754
|
"json",
|
|
746
755
|
Optional[operations.UpdateTagRequestBody],
|
|
747
756
|
),
|
|
757
|
+
allow_empty_value=None,
|
|
748
758
|
timeout_ms=timeout_ms,
|
|
749
759
|
)
|
|
750
760
|
|
|
@@ -783,7 +793,7 @@ class Tags(BaseSDK):
|
|
|
783
793
|
|
|
784
794
|
response_data: Any = None
|
|
785
795
|
if utils.match_response(http_res, "200", "application/json"):
|
|
786
|
-
return unmarshal_json_response(components.
|
|
796
|
+
return unmarshal_json_response(components.LinkTagSchemaOutput, http_res)
|
|
787
797
|
if utils.match_response(http_res, "400", "application/json"):
|
|
788
798
|
response_data = unmarshal_json_response(errors.BadRequestData, http_res)
|
|
789
799
|
raise errors.BadRequest(response_data, http_res)
|
|
@@ -872,6 +882,7 @@ class Tags(BaseSDK):
|
|
|
872
882
|
accept_header_value="application/json",
|
|
873
883
|
http_headers=http_headers,
|
|
874
884
|
security=self.sdk_configuration.security,
|
|
885
|
+
allow_empty_value=None,
|
|
875
886
|
timeout_ms=timeout_ms,
|
|
876
887
|
)
|
|
877
888
|
|
|
@@ -999,6 +1010,7 @@ class Tags(BaseSDK):
|
|
|
999
1010
|
accept_header_value="application/json",
|
|
1000
1011
|
http_headers=http_headers,
|
|
1001
1012
|
security=self.sdk_configuration.security,
|
|
1013
|
+
allow_empty_value=None,
|
|
1002
1014
|
timeout_ms=timeout_ms,
|
|
1003
1015
|
)
|
|
1004
1016
|
|
dub/track.py
CHANGED
|
@@ -66,6 +66,7 @@ class Track(BaseSDK):
|
|
|
66
66
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
67
67
|
request, False, True, "json", Optional[operations.TrackLeadRequestBody]
|
|
68
68
|
),
|
|
69
|
+
allow_empty_value=None,
|
|
69
70
|
timeout_ms=timeout_ms,
|
|
70
71
|
)
|
|
71
72
|
|
|
@@ -203,6 +204,7 @@ class Track(BaseSDK):
|
|
|
203
204
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
204
205
|
request, False, True, "json", Optional[operations.TrackLeadRequestBody]
|
|
205
206
|
),
|
|
207
|
+
allow_empty_value=None,
|
|
206
208
|
timeout_ms=timeout_ms,
|
|
207
209
|
)
|
|
208
210
|
|
|
@@ -340,6 +342,7 @@ class Track(BaseSDK):
|
|
|
340
342
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
341
343
|
request, False, True, "json", Optional[operations.TrackSaleRequestBody]
|
|
342
344
|
),
|
|
345
|
+
allow_empty_value=None,
|
|
343
346
|
timeout_ms=timeout_ms,
|
|
344
347
|
)
|
|
345
348
|
|
|
@@ -477,6 +480,7 @@ class Track(BaseSDK):
|
|
|
477
480
|
get_serialized_body=lambda: utils.serialize_request_body(
|
|
478
481
|
request, False, True, "json", Optional[operations.TrackSaleRequestBody]
|
|
479
482
|
),
|
|
483
|
+
allow_empty_value=None,
|
|
480
484
|
timeout_ms=timeout_ms,
|
|
481
485
|
)
|
|
482
486
|
|
dub/types/basemodel.py
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from pydantic import ConfigDict, model_serializer
|
|
4
4
|
from pydantic import BaseModel as PydanticBaseModel
|
|
5
|
-
from
|
|
5
|
+
from pydantic_core import core_schema
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
|
|
6
7
|
from typing_extensions import TypeAliasType, TypeAlias
|
|
7
8
|
|
|
8
9
|
|
|
@@ -35,5 +36,42 @@ else:
|
|
|
35
36
|
"OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
|
|
36
37
|
)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
UnrecognizedStr:
|
|
39
|
+
|
|
40
|
+
class UnrecognizedStr(str):
|
|
41
|
+
@classmethod
|
|
42
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
43
|
+
# Make UnrecognizedStr only work in lax mode, not strict mode
|
|
44
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
45
|
+
def validate_lax(v: Any) -> 'UnrecognizedStr':
|
|
46
|
+
if isinstance(v, cls):
|
|
47
|
+
return v
|
|
48
|
+
return cls(str(v))
|
|
49
|
+
|
|
50
|
+
# Use lax_or_strict_schema where strict always fails
|
|
51
|
+
# This forces Pydantic to prefer other union members in strict mode
|
|
52
|
+
# and only fall back to UnrecognizedStr in lax mode
|
|
53
|
+
return core_schema.lax_or_strict_schema(
|
|
54
|
+
lax_schema=core_schema.chain_schema([
|
|
55
|
+
core_schema.str_schema(),
|
|
56
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
57
|
+
]),
|
|
58
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class UnrecognizedInt(int):
|
|
63
|
+
@classmethod
|
|
64
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
65
|
+
# Make UnrecognizedInt only work in lax mode, not strict mode
|
|
66
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
67
|
+
def validate_lax(v: Any) -> 'UnrecognizedInt':
|
|
68
|
+
if isinstance(v, cls):
|
|
69
|
+
return v
|
|
70
|
+
return cls(int(v))
|
|
71
|
+
return core_schema.lax_or_strict_schema(
|
|
72
|
+
lax_schema=core_schema.chain_schema([
|
|
73
|
+
core_schema.int_schema(),
|
|
74
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
75
|
+
]),
|
|
76
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
77
|
+
)
|
dub/utils/__init__.py
CHANGED
|
@@ -41,7 +41,6 @@ if TYPE_CHECKING:
|
|
|
41
41
|
validate_decimal,
|
|
42
42
|
validate_float,
|
|
43
43
|
validate_int,
|
|
44
|
-
validate_open_enum,
|
|
45
44
|
)
|
|
46
45
|
from .url import generate_url, template_url, remove_suffix
|
|
47
46
|
from .values import (
|
|
@@ -102,7 +101,6 @@ __all__ = [
|
|
|
102
101
|
"validate_const",
|
|
103
102
|
"validate_float",
|
|
104
103
|
"validate_int",
|
|
105
|
-
"validate_open_enum",
|
|
106
104
|
"cast_partial",
|
|
107
105
|
]
|
|
108
106
|
|
|
@@ -155,7 +153,6 @@ _dynamic_imports: dict[str, str] = {
|
|
|
155
153
|
"validate_const": ".serializers",
|
|
156
154
|
"validate_float": ".serializers",
|
|
157
155
|
"validate_int": ".serializers",
|
|
158
|
-
"validate_open_enum": ".serializers",
|
|
159
156
|
"cast_partial": ".values",
|
|
160
157
|
}
|
|
161
158
|
|
dub/utils/enums.py
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
4
|
import sys
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic_core import core_schema
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class OpenEnumMeta(enum.EnumMeta):
|
|
7
11
|
# The __call__ method `boundary` kwarg was added in 3.11 and must be present
|
|
@@ -72,3 +76,59 @@ class OpenEnumMeta(enum.EnumMeta):
|
|
|
72
76
|
)
|
|
73
77
|
except ValueError:
|
|
74
78
|
return value
|
|
79
|
+
|
|
80
|
+
def __new__(mcs, name, bases, namespace, **kwargs):
|
|
81
|
+
cls = super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
82
|
+
|
|
83
|
+
# Add __get_pydantic_core_schema__ to make open enums work correctly
|
|
84
|
+
# in union discrimination. In strict mode (used by Pydantic for unions),
|
|
85
|
+
# only known enum values match. In lax mode, unknown values are accepted.
|
|
86
|
+
def __get_pydantic_core_schema__(
|
|
87
|
+
cls_inner: Any, _source_type: Any, _handler: Any
|
|
88
|
+
) -> core_schema.CoreSchema:
|
|
89
|
+
# Create a validator that only accepts known enum values (for strict mode)
|
|
90
|
+
def validate_strict(v: Any) -> Any:
|
|
91
|
+
if isinstance(v, cls_inner):
|
|
92
|
+
return v
|
|
93
|
+
# Use the parent EnumMeta's __call__ which raises ValueError for unknown values
|
|
94
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
95
|
+
|
|
96
|
+
# Create a lax validator that accepts unknown values
|
|
97
|
+
def validate_lax(v: Any) -> Any:
|
|
98
|
+
if isinstance(v, cls_inner):
|
|
99
|
+
return v
|
|
100
|
+
try:
|
|
101
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
102
|
+
except ValueError:
|
|
103
|
+
# Return the raw value for unknown enum values
|
|
104
|
+
return v
|
|
105
|
+
|
|
106
|
+
# Determine the base type schema (str or int)
|
|
107
|
+
is_int_enum = False
|
|
108
|
+
for base in cls_inner.__mro__:
|
|
109
|
+
if base is int:
|
|
110
|
+
is_int_enum = True
|
|
111
|
+
break
|
|
112
|
+
if base is str:
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
base_schema = (
|
|
116
|
+
core_schema.int_schema()
|
|
117
|
+
if is_int_enum
|
|
118
|
+
else core_schema.str_schema()
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Use lax_or_strict_schema:
|
|
122
|
+
# - strict mode: only known enum values match (raises ValueError for unknown)
|
|
123
|
+
# - lax mode: accept any value, return enum member or raw value
|
|
124
|
+
return core_schema.lax_or_strict_schema(
|
|
125
|
+
lax_schema=core_schema.chain_schema(
|
|
126
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_lax)]
|
|
127
|
+
),
|
|
128
|
+
strict_schema=core_schema.chain_schema(
|
|
129
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_strict)]
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
setattr(cls, "__get_pydantic_core_schema__", classmethod(__get_pydantic_core_schema__))
|
|
134
|
+
return cls
|
dub/utils/forms.py
CHANGED
|
@@ -142,16 +142,21 @@ def serialize_multipart_form(
|
|
|
142
142
|
if field_metadata.file:
|
|
143
143
|
if isinstance(val, List):
|
|
144
144
|
# Handle array of files
|
|
145
|
+
array_field_name = f_name + "[]"
|
|
145
146
|
for file_obj in val:
|
|
146
147
|
if not _is_set(file_obj):
|
|
147
148
|
continue
|
|
148
|
-
|
|
149
|
-
file_name, content, content_type = _extract_file_properties(
|
|
149
|
+
|
|
150
|
+
file_name, content, content_type = _extract_file_properties(
|
|
151
|
+
file_obj
|
|
152
|
+
)
|
|
150
153
|
|
|
151
154
|
if content_type is not None:
|
|
152
|
-
files.append(
|
|
155
|
+
files.append(
|
|
156
|
+
(array_field_name, (file_name, content, content_type))
|
|
157
|
+
)
|
|
153
158
|
else:
|
|
154
|
-
files.append((
|
|
159
|
+
files.append((array_field_name, (file_name, content)))
|
|
155
160
|
else:
|
|
156
161
|
# Handle single file
|
|
157
162
|
file_name, content, content_type = _extract_file_properties(val)
|
|
@@ -161,11 +166,16 @@ def serialize_multipart_form(
|
|
|
161
166
|
else:
|
|
162
167
|
files.append((f_name, (file_name, content)))
|
|
163
168
|
elif field_metadata.json:
|
|
164
|
-
files.append(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
files.append(
|
|
170
|
+
(
|
|
171
|
+
f_name,
|
|
172
|
+
(
|
|
173
|
+
None,
|
|
174
|
+
marshal_json(val, request_field_types[name]),
|
|
175
|
+
"application/json",
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
)
|
|
169
179
|
else:
|
|
170
180
|
if isinstance(val, List):
|
|
171
181
|
values = []
|
|
@@ -175,7 +185,8 @@ def serialize_multipart_form(
|
|
|
175
185
|
continue
|
|
176
186
|
values.append(_val_to_string(value))
|
|
177
187
|
|
|
178
|
-
|
|
188
|
+
array_field_name = f_name + "[]"
|
|
189
|
+
form[array_field_name] = values
|
|
179
190
|
else:
|
|
180
191
|
form[f_name] = _val_to_string(val)
|
|
181
192
|
return media_type, form, files
|
dub/utils/queryparams.py
CHANGED
|
@@ -27,12 +27,13 @@ from .forms import _populate_form
|
|
|
27
27
|
def get_query_params(
|
|
28
28
|
query_params: Any,
|
|
29
29
|
gbls: Optional[Any] = None,
|
|
30
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
30
31
|
) -> Dict[str, List[str]]:
|
|
31
32
|
params: Dict[str, List[str]] = {}
|
|
32
33
|
|
|
33
|
-
globals_already_populated = _populate_query_params(query_params, gbls, params, [])
|
|
34
|
+
globals_already_populated = _populate_query_params(query_params, gbls, params, [], allow_empty_value)
|
|
34
35
|
if _is_set(gbls):
|
|
35
|
-
_populate_query_params(gbls, None, params, globals_already_populated)
|
|
36
|
+
_populate_query_params(gbls, None, params, globals_already_populated, allow_empty_value)
|
|
36
37
|
|
|
37
38
|
return params
|
|
38
39
|
|
|
@@ -42,6 +43,7 @@ def _populate_query_params(
|
|
|
42
43
|
gbls: Any,
|
|
43
44
|
query_param_values: Dict[str, List[str]],
|
|
44
45
|
skip_fields: List[str],
|
|
46
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
45
47
|
) -> List[str]:
|
|
46
48
|
globals_already_populated: List[str] = []
|
|
47
49
|
|
|
@@ -69,6 +71,16 @@ def _populate_query_params(
|
|
|
69
71
|
globals_already_populated.append(name)
|
|
70
72
|
|
|
71
73
|
f_name = field.alias if field.alias is not None else name
|
|
74
|
+
|
|
75
|
+
allow_empty_set = set(allow_empty_value or [])
|
|
76
|
+
should_include_empty = f_name in allow_empty_set and (
|
|
77
|
+
value is None or value == [] or value == ""
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if should_include_empty:
|
|
81
|
+
query_param_values[f_name] = [""]
|
|
82
|
+
continue
|
|
83
|
+
|
|
72
84
|
serialization = metadata.serialization
|
|
73
85
|
if serialization is not None:
|
|
74
86
|
serialized_parms = _get_serialized_params(
|
dub/utils/requestbodies.py
CHANGED
|
@@ -44,15 +44,15 @@ def serialize_request_body(
|
|
|
44
44
|
|
|
45
45
|
serialized_request_body = SerializedRequestBody(media_type)
|
|
46
46
|
|
|
47
|
-
if re.match(r"(application|text)
|
|
47
|
+
if re.match(r"^(application|text)\/([^+]+\+)*json.*", media_type) is not None:
|
|
48
48
|
serialized_request_body.content = marshal_json(request_body, request_body_type)
|
|
49
|
-
elif re.match(r"multipart\/.*", media_type) is not None:
|
|
49
|
+
elif re.match(r"^multipart\/.*", media_type) is not None:
|
|
50
50
|
(
|
|
51
51
|
serialized_request_body.media_type,
|
|
52
52
|
serialized_request_body.data,
|
|
53
53
|
serialized_request_body.files,
|
|
54
54
|
) = serialize_multipart_form(media_type, request_body)
|
|
55
|
-
elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None:
|
|
55
|
+
elif re.match(r"^application\/x-www-form-urlencoded.*", media_type) is not None:
|
|
56
56
|
serialized_request_body.data = serialize_form_data(request_body)
|
|
57
57
|
elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)):
|
|
58
58
|
serialized_request_body.content = request_body
|
dub/utils/serializers.py
CHANGED
|
@@ -102,26 +102,6 @@ def validate_int(b):
|
|
|
102
102
|
return int(b)
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
def validate_open_enum(is_int: bool):
|
|
106
|
-
def validate(e):
|
|
107
|
-
if e is None:
|
|
108
|
-
return None
|
|
109
|
-
|
|
110
|
-
if isinstance(e, Unset):
|
|
111
|
-
return e
|
|
112
|
-
|
|
113
|
-
if is_int:
|
|
114
|
-
if not isinstance(e, int):
|
|
115
|
-
raise ValueError("Expected int")
|
|
116
|
-
else:
|
|
117
|
-
if not isinstance(e, str):
|
|
118
|
-
raise ValueError("Expected string")
|
|
119
|
-
|
|
120
|
-
return e
|
|
121
|
-
|
|
122
|
-
return validate
|
|
123
|
-
|
|
124
|
-
|
|
125
105
|
def validate_const(v):
|
|
126
106
|
def validate(c):
|
|
127
107
|
# Optional[T] is a Union[T, None]
|
dub/workspaces.py
CHANGED
|
@@ -58,6 +58,7 @@ class Workspaces(BaseSDK):
|
|
|
58
58
|
accept_header_value="application/json",
|
|
59
59
|
http_headers=http_headers,
|
|
60
60
|
security=self.sdk_configuration.security,
|
|
61
|
+
allow_empty_value=None,
|
|
61
62
|
timeout_ms=timeout_ms,
|
|
62
63
|
)
|
|
63
64
|
|
|
@@ -187,6 +188,7 @@ class Workspaces(BaseSDK):
|
|
|
187
188
|
accept_header_value="application/json",
|
|
188
189
|
http_headers=http_headers,
|
|
189
190
|
security=self.sdk_configuration.security,
|
|
191
|
+
allow_empty_value=None,
|
|
190
192
|
timeout_ms=timeout_ms,
|
|
191
193
|
)
|
|
192
194
|
|
|
@@ -331,6 +333,7 @@ class Workspaces(BaseSDK):
|
|
|
331
333
|
"json",
|
|
332
334
|
Optional[operations.UpdateWorkspaceRequestBody],
|
|
333
335
|
),
|
|
336
|
+
allow_empty_value=None,
|
|
334
337
|
timeout_ms=timeout_ms,
|
|
335
338
|
)
|
|
336
339
|
|
|
@@ -475,6 +478,7 @@ class Workspaces(BaseSDK):
|
|
|
475
478
|
"json",
|
|
476
479
|
Optional[operations.UpdateWorkspaceRequestBody],
|
|
477
480
|
),
|
|
481
|
+
allow_empty_value=None,
|
|
478
482
|
timeout_ms=timeout_ms,
|
|
479
483
|
)
|
|
480
484
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dub
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.34.0
|
|
4
4
|
Summary: Python Client SDK Generated by Speakeasy
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: Speakeasy
|
|
@@ -277,23 +277,23 @@ asyncio.run(main())
|
|
|
277
277
|
<details open>
|
|
278
278
|
<summary>Available methods</summary>
|
|
279
279
|
|
|
280
|
-
### [
|
|
280
|
+
### [Analytics](https://github.com/dubinc/dub-python/blob/master/docs/sdks/analytics/README.md)
|
|
281
281
|
|
|
282
282
|
* [retrieve](https://github.com/dubinc/dub-python/blob/master/docs/sdks/analytics/README.md#retrieve) - Retrieve analytics for a link, a domain, or the authenticated workspace.
|
|
283
283
|
|
|
284
|
-
### [
|
|
284
|
+
### [Commissions](https://github.com/dubinc/dub-python/blob/master/docs/sdks/commissions/README.md)
|
|
285
285
|
|
|
286
286
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/commissions/README.md#list) - Get commissions for a program.
|
|
287
287
|
* [update](https://github.com/dubinc/dub-python/blob/master/docs/sdks/commissions/README.md#update) - Update a commission.
|
|
288
288
|
|
|
289
|
-
### [
|
|
289
|
+
### [Customers](https://github.com/dubinc/dub-python/blob/master/docs/sdks/customers/README.md)
|
|
290
290
|
|
|
291
291
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/customers/README.md#list) - Retrieve a list of customers
|
|
292
292
|
* [get](https://github.com/dubinc/dub-python/blob/master/docs/sdks/customers/README.md#get) - Retrieve a customer
|
|
293
293
|
* [update](https://github.com/dubinc/dub-python/blob/master/docs/sdks/customers/README.md#update) - Update a customer
|
|
294
294
|
* [delete](https://github.com/dubinc/dub-python/blob/master/docs/sdks/customers/README.md#delete) - Delete a customer
|
|
295
295
|
|
|
296
|
-
### [
|
|
296
|
+
### [Domains](https://github.com/dubinc/dub-python/blob/master/docs/sdks/domains/README.md)
|
|
297
297
|
|
|
298
298
|
* [create](https://github.com/dubinc/dub-python/blob/master/docs/sdks/domains/README.md#create) - Create a domain
|
|
299
299
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/domains/README.md#list) - Retrieve a list of domains
|
|
@@ -302,22 +302,22 @@ asyncio.run(main())
|
|
|
302
302
|
* [register](https://github.com/dubinc/dub-python/blob/master/docs/sdks/domains/README.md#register) - Register a domain
|
|
303
303
|
* [check_status](https://github.com/dubinc/dub-python/blob/master/docs/sdks/domains/README.md#check_status) - Check the availability of one or more domains
|
|
304
304
|
|
|
305
|
-
### [
|
|
305
|
+
### [EmbedTokens](https://github.com/dubinc/dub-python/blob/master/docs/sdks/embedtokens/README.md)
|
|
306
306
|
|
|
307
307
|
* [referrals](https://github.com/dubinc/dub-python/blob/master/docs/sdks/embedtokens/README.md#referrals) - Create a referrals embed token
|
|
308
308
|
|
|
309
|
-
### [
|
|
309
|
+
### [Events](https://github.com/dubinc/dub-python/blob/master/docs/sdks/events/README.md)
|
|
310
310
|
|
|
311
311
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/events/README.md#list) - Retrieve a list of events
|
|
312
312
|
|
|
313
|
-
### [
|
|
313
|
+
### [Folders](https://github.com/dubinc/dub-python/blob/master/docs/sdks/folders/README.md)
|
|
314
314
|
|
|
315
315
|
* [create](https://github.com/dubinc/dub-python/blob/master/docs/sdks/folders/README.md#create) - Create a folder
|
|
316
316
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/folders/README.md#list) - Retrieve a list of folders
|
|
317
317
|
* [update](https://github.com/dubinc/dub-python/blob/master/docs/sdks/folders/README.md#update) - Update a folder
|
|
318
318
|
* [delete](https://github.com/dubinc/dub-python/blob/master/docs/sdks/folders/README.md#delete) - Delete a folder
|
|
319
319
|
|
|
320
|
-
### [
|
|
320
|
+
### [Links](https://github.com/dubinc/dub-python/blob/master/docs/sdks/links/README.md)
|
|
321
321
|
|
|
322
322
|
* [create](https://github.com/dubinc/dub-python/blob/master/docs/sdks/links/README.md#create) - Create a link
|
|
323
323
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/links/README.md#list) - Retrieve a list of links
|
|
@@ -330,7 +330,7 @@ asyncio.run(main())
|
|
|
330
330
|
* [delete_many](https://github.com/dubinc/dub-python/blob/master/docs/sdks/links/README.md#delete_many) - Bulk delete links
|
|
331
331
|
* [upsert](https://github.com/dubinc/dub-python/blob/master/docs/sdks/links/README.md#upsert) - Upsert a link
|
|
332
332
|
|
|
333
|
-
### [
|
|
333
|
+
### [Partners](https://github.com/dubinc/dub-python/blob/master/docs/sdks/partners/README.md)
|
|
334
334
|
|
|
335
335
|
* [create](https://github.com/dubinc/dub-python/blob/master/docs/sdks/partners/README.md#create) - Create or update a partner
|
|
336
336
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/partners/README.md#list) - List all partners
|
|
@@ -340,23 +340,23 @@ asyncio.run(main())
|
|
|
340
340
|
* [analytics](https://github.com/dubinc/dub-python/blob/master/docs/sdks/partners/README.md#analytics) - Retrieve analytics for a partner
|
|
341
341
|
* [ban](https://github.com/dubinc/dub-python/blob/master/docs/sdks/partners/README.md#ban) - Ban a partner
|
|
342
342
|
|
|
343
|
-
### [
|
|
343
|
+
### [QRCodes](https://github.com/dubinc/dub-python/blob/master/docs/sdks/qrcodes/README.md)
|
|
344
344
|
|
|
345
345
|
* [get](https://github.com/dubinc/dub-python/blob/master/docs/sdks/qrcodes/README.md#get) - Retrieve a QR code
|
|
346
346
|
|
|
347
|
-
### [
|
|
347
|
+
### [Tags](https://github.com/dubinc/dub-python/blob/master/docs/sdks/tags/README.md)
|
|
348
348
|
|
|
349
349
|
* [create](https://github.com/dubinc/dub-python/blob/master/docs/sdks/tags/README.md#create) - Create a tag
|
|
350
350
|
* [list](https://github.com/dubinc/dub-python/blob/master/docs/sdks/tags/README.md#list) - Retrieve a list of tags
|
|
351
351
|
* [update](https://github.com/dubinc/dub-python/blob/master/docs/sdks/tags/README.md#update) - Update a tag
|
|
352
352
|
* [delete](https://github.com/dubinc/dub-python/blob/master/docs/sdks/tags/README.md#delete) - Delete a tag
|
|
353
353
|
|
|
354
|
-
### [
|
|
354
|
+
### [Track](https://github.com/dubinc/dub-python/blob/master/docs/sdks/track/README.md)
|
|
355
355
|
|
|
356
356
|
* [lead](https://github.com/dubinc/dub-python/blob/master/docs/sdks/track/README.md#lead) - Track a lead
|
|
357
357
|
* [sale](https://github.com/dubinc/dub-python/blob/master/docs/sdks/track/README.md#sale) - Track a sale
|
|
358
358
|
|
|
359
|
-
### [
|
|
359
|
+
### [Workspaces](https://github.com/dubinc/dub-python/blob/master/docs/sdks/workspaces/README.md)
|
|
360
360
|
|
|
361
361
|
* [get](https://github.com/dubinc/dub-python/blob/master/docs/sdks/workspaces/README.md#get) - Retrieve a workspace
|
|
362
362
|
* [update](https://github.com/dubinc/dub-python/blob/master/docs/sdks/workspaces/README.md#update) - Update a workspace
|