growsurf-python 0.0.2__tar.gz → 0.1.0__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.
- growsurf_python-0.1.0/.release-please-manifest.json +3 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/CHANGELOG.md +19 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/PKG-INFO +1 -1
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/api.md +2 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/bin/check-release-environment +4 -0
- growsurf_python-0.1.0/bin/publish-pypi +7 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/pyproject.toml +1 -1
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_files.py +1 -1
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_models.py +80 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_version.py +1 -1
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/participant.py +101 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/__init__.py +3 -0
- growsurf_python-0.1.0/src/growsurf/types/campaign/participant_create_mobile_token_response.py +15 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/test_participant.py +109 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_models.py +57 -3
- growsurf_python-0.0.2/.release-please-manifest.json +0 -3
- growsurf_python-0.0.2/bin/publish-pypi +0 -11
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/.gitignore +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/CONTRIBUTING.md +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/LICENSE +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/README.md +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/SECURITY.md +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/examples/.keep +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/release-please-config.json +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/requirements-dev.lock +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_base_client.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_client.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_compat.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_constants.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_exceptions.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_qs.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_resource.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_streaming.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_types.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_compat.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_datetime_parse.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_json.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_logs.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_path.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_proxy.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_reflection.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_resources_proxy.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_streams.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_sync.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_transform.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_typing.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/_utils/_utils.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/lib/.keep +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/py.typed +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/campaign.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/commission.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/reward.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/campaign.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/commission_approve_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/commission_delete_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/fraud_risk_level.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_add_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_delete_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_list_commissions_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_list_payouts_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_list_referrals_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_list_rewards_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_list_rewards_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_record_transaction_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_record_transaction_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_reward.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_send_invites_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_send_invites_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_trigger_referral_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_update_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/referral_source.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/referral_status.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/reward_approve_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/reward_approve_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/reward_delete_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/reward_fulfill_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_commissions_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_leaderboard_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_participants_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_payouts_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_referrals_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_retrieve_analytics_params.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_retrieve_analytics_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/commission_structure.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/participant_commission_list.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/participant_list.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/participant_payout_list.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/referral_list.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/__init__.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/test_commission.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/test_reward.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/test_campaign.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/conftest.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/sample_file.txt +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_client.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_extract_files.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_files.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_qs.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_required_args.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_response.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_streaming.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_transform.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_utils/test_datetime_parse.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_utils/test_json.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_utils/test_path.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_utils/test_proxy.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/test_utils/test_typing.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/utils.py +0 -0
- {growsurf_python-0.0.2 → growsurf_python-0.1.0}/uv.lock +0 -0
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0 (2026-05-12)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v0.0.2...v0.1.0](https://github.com/growsurf/growsurf-python/compare/v0.0.2...v0.1.0)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **api:** manual updates ([31c14cf](https://github.com/growsurf/growsurf-python/commit/31c14cfba6611cc5c974230e9e2584e6f6b3a7a3))
|
|
10
|
+
* **internal/types:** support eagerly validating pydantic iterators ([c6cd14c](https://github.com/growsurf/growsurf-python/commit/c6cd14c45e8a652f511ca9c31de194c4cd140d2d))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **client:** add missing f-string prefix in file type error message ([7a3c356](https://github.com/growsurf/growsurf-python/commit/7a3c356587c6b2ea311c1f28723fd86a946db5db))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Chores
|
|
19
|
+
|
|
20
|
+
* update SDK settings ([434e9ce](https://github.com/growsurf/growsurf-python/commit/434e9cec74d6101510ca7f45261e981b8362121f))
|
|
21
|
+
|
|
3
22
|
## 0.0.2 (2026-05-08)
|
|
4
23
|
|
|
5
24
|
Full Changelog: [v0.0.1...v0.0.2](https://github.com/growsurf/growsurf-python/compare/v0.0.1...v0.0.2)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: growsurf-python
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: The official Python library for the growsurf API
|
|
5
5
|
Project-URL: Homepage, https://github.com/growsurf/growsurf-python
|
|
6
6
|
Project-URL: Repository, https://github.com/growsurf/growsurf-python
|
|
@@ -38,6 +38,7 @@ from growsurf.types.campaign import (
|
|
|
38
38
|
ReferralSource,
|
|
39
39
|
ReferralStatus,
|
|
40
40
|
ParticipantDeleteResponse,
|
|
41
|
+
ParticipantCreateMobileTokenResponse,
|
|
41
42
|
ParticipantListRewardsResponse,
|
|
42
43
|
ParticipantRecordTransactionResponse,
|
|
43
44
|
ParticipantSendInvitesResponse,
|
|
@@ -51,6 +52,7 @@ Methods:
|
|
|
51
52
|
- <code title="post /campaign/{id}/participant/{participantIdOrEmail}">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">update</a>(participant_id_or_email, \*, id, \*\*<a href="src/growsurf/types/campaign/participant_update_params.py">params</a>) -> <a href="./src/growsurf/types/campaign/participant.py">Participant</a></code>
|
|
52
53
|
- <code title="delete /campaign/{id}/participant/{participantIdOrEmail}">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">delete</a>(participant_id_or_email, \*, id) -> <a href="./src/growsurf/types/campaign/participant_delete_response.py">ParticipantDeleteResponse</a></code>
|
|
53
54
|
- <code title="post /campaign/{id}/participant">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">add</a>(id, \*\*<a href="src/growsurf/types/campaign/participant_add_params.py">params</a>) -> <a href="./src/growsurf/types/campaign/participant.py">Participant</a></code>
|
|
55
|
+
- <code title="post /campaign/{id}/participant/{participantIdOrEmail}/mobile-token">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">create_mobile_token</a>(participant_id_or_email, \*, id) -> <a href="./src/growsurf/types/campaign/participant_create_mobile_token_response.py">ParticipantCreateMobileTokenResponse</a></code>
|
|
54
56
|
- <code title="get /campaign/{id}/participant/{participantIdOrEmail}/commissions">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">list_commissions</a>(participant_id_or_email, \*, id, \*\*<a href="src/growsurf/types/campaign/participant_list_commissions_params.py">params</a>) -> <a href="./src/growsurf/types/participant_commission_list.py">ParticipantCommissionList</a></code>
|
|
55
57
|
- <code title="get /campaign/{id}/participant/{participantIdOrEmail}/payouts">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">list_payouts</a>(participant_id_or_email, \*, id, \*\*<a href="src/growsurf/types/campaign/participant_list_payouts_params.py">params</a>) -> <a href="./src/growsurf/types/participant_payout_list.py">ParticipantPayoutList</a></code>
|
|
56
58
|
- <code title="get /campaign/{id}/participant/{participantIdOrEmail}/referrals">client.campaign.participant.<a href="./src/growsurf/resources/campaign/participant.py">list_referrals</a>(participant_id_or_email, \*, id, \*\*<a href="src/growsurf/types/campaign/participant_list_referrals_params.py">params</a>) -> <a href="./src/growsurf/types/referral_list.py">ReferralList</a></code>
|
|
@@ -99,7 +99,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles
|
|
|
99
99
|
elif is_sequence_t(files):
|
|
100
100
|
files = [(key, await _async_transform_file(file)) for key, file in files]
|
|
101
101
|
else:
|
|
102
|
-
raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence")
|
|
102
|
+
raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence")
|
|
103
103
|
|
|
104
104
|
return files
|
|
105
105
|
|
|
@@ -25,7 +25,9 @@ from typing_extensions import (
|
|
|
25
25
|
ClassVar,
|
|
26
26
|
Protocol,
|
|
27
27
|
Required,
|
|
28
|
+
Annotated,
|
|
28
29
|
ParamSpec,
|
|
30
|
+
TypeAlias,
|
|
29
31
|
TypedDict,
|
|
30
32
|
TypeGuard,
|
|
31
33
|
final,
|
|
@@ -79,7 +81,15 @@ from ._compat import (
|
|
|
79
81
|
from ._constants import RAW_RESPONSE_HEADER
|
|
80
82
|
|
|
81
83
|
if TYPE_CHECKING:
|
|
84
|
+
from pydantic import GetCoreSchemaHandler, ValidatorFunctionWrapHandler
|
|
85
|
+
from pydantic_core import CoreSchema, core_schema
|
|
82
86
|
from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema
|
|
87
|
+
else:
|
|
88
|
+
try:
|
|
89
|
+
from pydantic_core import CoreSchema, core_schema
|
|
90
|
+
except ImportError:
|
|
91
|
+
CoreSchema = None
|
|
92
|
+
core_schema = None
|
|
83
93
|
|
|
84
94
|
__all__ = ["BaseModel", "GenericModel"]
|
|
85
95
|
|
|
@@ -396,6 +406,76 @@ class BaseModel(pydantic.BaseModel):
|
|
|
396
406
|
)
|
|
397
407
|
|
|
398
408
|
|
|
409
|
+
class _EagerIterable(list[_T], Generic[_T]):
|
|
410
|
+
"""
|
|
411
|
+
Accepts any Iterable[T] input (including generators), consumes it
|
|
412
|
+
eagerly, and validates all items upfront.
|
|
413
|
+
|
|
414
|
+
Validation preserves the original container type where possible
|
|
415
|
+
(e.g. a set[T] stays a set[T]). Serialization (model_dump / JSON)
|
|
416
|
+
always emits a list — round-tripping through model_dump() will not
|
|
417
|
+
restore the original container type.
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
@classmethod
|
|
421
|
+
def __get_pydantic_core_schema__(
|
|
422
|
+
cls,
|
|
423
|
+
source_type: Any,
|
|
424
|
+
handler: GetCoreSchemaHandler,
|
|
425
|
+
) -> CoreSchema:
|
|
426
|
+
(item_type,) = get_args(source_type) or (Any,)
|
|
427
|
+
item_schema: CoreSchema = handler.generate_schema(item_type)
|
|
428
|
+
list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema)
|
|
429
|
+
|
|
430
|
+
return core_schema.no_info_wrap_validator_function(
|
|
431
|
+
cls._validate,
|
|
432
|
+
list_of_items_schema,
|
|
433
|
+
serialization=core_schema.plain_serializer_function_ser_schema(
|
|
434
|
+
cls._serialize,
|
|
435
|
+
info_arg=False,
|
|
436
|
+
),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
@staticmethod
|
|
440
|
+
def _validate(v: Iterable[_T], handler: "ValidatorFunctionWrapHandler") -> Any:
|
|
441
|
+
original_type: type[Any] = type(v)
|
|
442
|
+
|
|
443
|
+
# Normalize to list so list_schema can validate each item
|
|
444
|
+
if isinstance(v, list):
|
|
445
|
+
items: list[_T] = v
|
|
446
|
+
else:
|
|
447
|
+
try:
|
|
448
|
+
items = list(v)
|
|
449
|
+
except TypeError as e:
|
|
450
|
+
raise TypeError("Value is not iterable") from e
|
|
451
|
+
|
|
452
|
+
# Validate items against the inner schema
|
|
453
|
+
validated: list[_T] = handler(items)
|
|
454
|
+
|
|
455
|
+
# Reconstruct original container type
|
|
456
|
+
if original_type is list:
|
|
457
|
+
return validated
|
|
458
|
+
# str(list) produces the list's repr, not a string built from items,
|
|
459
|
+
# so skip reconstruction for str and its subclasses.
|
|
460
|
+
if issubclass(original_type, str):
|
|
461
|
+
return validated
|
|
462
|
+
try:
|
|
463
|
+
return original_type(validated)
|
|
464
|
+
except (TypeError, ValueError):
|
|
465
|
+
# If the type cannot be reconstructed, just return the validated list
|
|
466
|
+
return validated
|
|
467
|
+
|
|
468
|
+
@staticmethod
|
|
469
|
+
def _serialize(v: Iterable[_T]) -> list[_T]:
|
|
470
|
+
"""Always serialize as a list so Pydantic's JSON encoder is happy."""
|
|
471
|
+
if isinstance(v, list):
|
|
472
|
+
return v
|
|
473
|
+
return list(v)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable]
|
|
477
|
+
|
|
478
|
+
|
|
399
479
|
def _construct_field(value: object, field: FieldInfo, key: str) -> object:
|
|
400
480
|
if value is None:
|
|
401
481
|
return field_get_default(field)
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/participant.py
RENAMED
|
@@ -39,6 +39,7 @@ from ...types.campaign.participant_list_rewards_response import ParticipantListR
|
|
|
39
39
|
from ...types.campaign.participant_send_invites_response import ParticipantSendInvitesResponse
|
|
40
40
|
from ...types.campaign.participant_trigger_referral_response import ParticipantTriggerReferralResponse
|
|
41
41
|
from ...types.campaign.participant_record_transaction_response import ParticipantRecordTransactionResponse
|
|
42
|
+
from ...types.campaign.participant_create_mobile_token_response import ParticipantCreateMobileTokenResponse
|
|
42
43
|
|
|
43
44
|
__all__ = ["ParticipantResource", "AsyncParticipantResource"]
|
|
44
45
|
|
|
@@ -272,6 +273,50 @@ class ParticipantResource(SyncAPIResource):
|
|
|
272
273
|
cast_to=Participant,
|
|
273
274
|
)
|
|
274
275
|
|
|
276
|
+
def create_mobile_token(
|
|
277
|
+
self,
|
|
278
|
+
participant_id_or_email: str,
|
|
279
|
+
*,
|
|
280
|
+
id: str,
|
|
281
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
282
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
283
|
+
extra_headers: Headers | None = None,
|
|
284
|
+
extra_query: Query | None = None,
|
|
285
|
+
extra_body: Body | None = None,
|
|
286
|
+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
|
|
287
|
+
) -> ParticipantCreateMobileTokenResponse:
|
|
288
|
+
"""Creates a participant-scoped token for GrowSurf mobile SDK participant
|
|
289
|
+
endpoints.
|
|
290
|
+
|
|
291
|
+
The program must have mobile SDK access enabled.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
extra_headers: Send extra headers
|
|
295
|
+
|
|
296
|
+
extra_query: Add additional query parameters to the request
|
|
297
|
+
|
|
298
|
+
extra_body: Add additional JSON properties to the request
|
|
299
|
+
|
|
300
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
301
|
+
"""
|
|
302
|
+
if not id:
|
|
303
|
+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
|
|
304
|
+
if not participant_id_or_email:
|
|
305
|
+
raise ValueError(
|
|
306
|
+
f"Expected a non-empty value for `participant_id_or_email` but received {participant_id_or_email!r}"
|
|
307
|
+
)
|
|
308
|
+
return self._post(
|
|
309
|
+
path_template(
|
|
310
|
+
"/campaign/{id}/participant/{participant_id_or_email}/mobile-token",
|
|
311
|
+
id=id,
|
|
312
|
+
participant_id_or_email=participant_id_or_email,
|
|
313
|
+
),
|
|
314
|
+
options=make_request_options(
|
|
315
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
316
|
+
),
|
|
317
|
+
cast_to=ParticipantCreateMobileTokenResponse,
|
|
318
|
+
)
|
|
319
|
+
|
|
275
320
|
def list_commissions(
|
|
276
321
|
self,
|
|
277
322
|
participant_id_or_email: str,
|
|
@@ -966,6 +1011,50 @@ class AsyncParticipantResource(AsyncAPIResource):
|
|
|
966
1011
|
cast_to=Participant,
|
|
967
1012
|
)
|
|
968
1013
|
|
|
1014
|
+
async def create_mobile_token(
|
|
1015
|
+
self,
|
|
1016
|
+
participant_id_or_email: str,
|
|
1017
|
+
*,
|
|
1018
|
+
id: str,
|
|
1019
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
1020
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
1021
|
+
extra_headers: Headers | None = None,
|
|
1022
|
+
extra_query: Query | None = None,
|
|
1023
|
+
extra_body: Body | None = None,
|
|
1024
|
+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
|
|
1025
|
+
) -> ParticipantCreateMobileTokenResponse:
|
|
1026
|
+
"""Creates a participant-scoped token for GrowSurf mobile SDK participant
|
|
1027
|
+
endpoints.
|
|
1028
|
+
|
|
1029
|
+
The program must have mobile SDK access enabled.
|
|
1030
|
+
|
|
1031
|
+
Args:
|
|
1032
|
+
extra_headers: Send extra headers
|
|
1033
|
+
|
|
1034
|
+
extra_query: Add additional query parameters to the request
|
|
1035
|
+
|
|
1036
|
+
extra_body: Add additional JSON properties to the request
|
|
1037
|
+
|
|
1038
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
1039
|
+
"""
|
|
1040
|
+
if not id:
|
|
1041
|
+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
|
|
1042
|
+
if not participant_id_or_email:
|
|
1043
|
+
raise ValueError(
|
|
1044
|
+
f"Expected a non-empty value for `participant_id_or_email` but received {participant_id_or_email!r}"
|
|
1045
|
+
)
|
|
1046
|
+
return await self._post(
|
|
1047
|
+
path_template(
|
|
1048
|
+
"/campaign/{id}/participant/{participant_id_or_email}/mobile-token",
|
|
1049
|
+
id=id,
|
|
1050
|
+
participant_id_or_email=participant_id_or_email,
|
|
1051
|
+
),
|
|
1052
|
+
options=make_request_options(
|
|
1053
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
1054
|
+
),
|
|
1055
|
+
cast_to=ParticipantCreateMobileTokenResponse,
|
|
1056
|
+
)
|
|
1057
|
+
|
|
969
1058
|
async def list_commissions(
|
|
970
1059
|
self,
|
|
971
1060
|
participant_id_or_email: str,
|
|
@@ -1447,6 +1536,9 @@ class ParticipantResourceWithRawResponse:
|
|
|
1447
1536
|
self.add = to_raw_response_wrapper(
|
|
1448
1537
|
participant.add,
|
|
1449
1538
|
)
|
|
1539
|
+
self.create_mobile_token = to_raw_response_wrapper(
|
|
1540
|
+
participant.create_mobile_token,
|
|
1541
|
+
)
|
|
1450
1542
|
self.list_commissions = to_raw_response_wrapper(
|
|
1451
1543
|
participant.list_commissions,
|
|
1452
1544
|
)
|
|
@@ -1486,6 +1578,9 @@ class AsyncParticipantResourceWithRawResponse:
|
|
|
1486
1578
|
self.add = async_to_raw_response_wrapper(
|
|
1487
1579
|
participant.add,
|
|
1488
1580
|
)
|
|
1581
|
+
self.create_mobile_token = async_to_raw_response_wrapper(
|
|
1582
|
+
participant.create_mobile_token,
|
|
1583
|
+
)
|
|
1489
1584
|
self.list_commissions = async_to_raw_response_wrapper(
|
|
1490
1585
|
participant.list_commissions,
|
|
1491
1586
|
)
|
|
@@ -1525,6 +1620,9 @@ class ParticipantResourceWithStreamingResponse:
|
|
|
1525
1620
|
self.add = to_streamed_response_wrapper(
|
|
1526
1621
|
participant.add,
|
|
1527
1622
|
)
|
|
1623
|
+
self.create_mobile_token = to_streamed_response_wrapper(
|
|
1624
|
+
participant.create_mobile_token,
|
|
1625
|
+
)
|
|
1528
1626
|
self.list_commissions = to_streamed_response_wrapper(
|
|
1529
1627
|
participant.list_commissions,
|
|
1530
1628
|
)
|
|
@@ -1564,6 +1662,9 @@ class AsyncParticipantResourceWithStreamingResponse:
|
|
|
1564
1662
|
self.add = async_to_streamed_response_wrapper(
|
|
1565
1663
|
participant.add,
|
|
1566
1664
|
)
|
|
1665
|
+
self.create_mobile_token = async_to_streamed_response_wrapper(
|
|
1666
|
+
participant.create_mobile_token,
|
|
1667
|
+
)
|
|
1567
1668
|
self.list_commissions = async_to_streamed_response_wrapper(
|
|
1568
1669
|
participant.list_commissions,
|
|
1569
1670
|
)
|
|
@@ -33,3 +33,6 @@ from .participant_trigger_referral_response import (
|
|
|
33
33
|
from .participant_record_transaction_response import (
|
|
34
34
|
ParticipantRecordTransactionResponse as ParticipantRecordTransactionResponse,
|
|
35
35
|
)
|
|
36
|
+
from .participant_create_mobile_token_response import (
|
|
37
|
+
ParticipantCreateMobileTokenResponse as ParticipantCreateMobileTokenResponse,
|
|
38
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
+
|
|
3
|
+
from pydantic import Field as FieldInfo
|
|
4
|
+
|
|
5
|
+
from ..._models import BaseModel
|
|
6
|
+
|
|
7
|
+
__all__ = ["ParticipantCreateMobileTokenResponse"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ParticipantCreateMobileTokenResponse(BaseModel):
|
|
11
|
+
expires_in: int = FieldInfo(alias="expiresIn")
|
|
12
|
+
"""Token lifetime in seconds."""
|
|
13
|
+
|
|
14
|
+
participant_token: str = FieldInfo(alias="participantToken")
|
|
15
|
+
"""Participant-scoped bearer token for GrowSurf mobile SDK participant endpoints."""
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/test_participant.py
RENAMED
|
@@ -16,6 +16,7 @@ from growsurf.types.campaign import (
|
|
|
16
16
|
ParticipantListRewardsResponse,
|
|
17
17
|
ParticipantSendInvitesResponse,
|
|
18
18
|
ParticipantTriggerReferralResponse,
|
|
19
|
+
ParticipantCreateMobileTokenResponse,
|
|
19
20
|
ParticipantRecordTransactionResponse,
|
|
20
21
|
)
|
|
21
22
|
|
|
@@ -269,6 +270,60 @@ class TestParticipant:
|
|
|
269
270
|
email="gavin@hooli.com",
|
|
270
271
|
)
|
|
271
272
|
|
|
273
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
274
|
+
@parametrize
|
|
275
|
+
def test_method_create_mobile_token(self, client: Growsurf) -> None:
|
|
276
|
+
participant = client.campaign.participant.create_mobile_token(
|
|
277
|
+
participant_id_or_email="participantIdOrEmail",
|
|
278
|
+
id="id",
|
|
279
|
+
)
|
|
280
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
281
|
+
|
|
282
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
283
|
+
@parametrize
|
|
284
|
+
def test_raw_response_create_mobile_token(self, client: Growsurf) -> None:
|
|
285
|
+
response = client.campaign.participant.with_raw_response.create_mobile_token(
|
|
286
|
+
participant_id_or_email="participantIdOrEmail",
|
|
287
|
+
id="id",
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
assert response.is_closed is True
|
|
291
|
+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
292
|
+
participant = response.parse()
|
|
293
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
294
|
+
|
|
295
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
296
|
+
@parametrize
|
|
297
|
+
def test_streaming_response_create_mobile_token(self, client: Growsurf) -> None:
|
|
298
|
+
with client.campaign.participant.with_streaming_response.create_mobile_token(
|
|
299
|
+
participant_id_or_email="participantIdOrEmail",
|
|
300
|
+
id="id",
|
|
301
|
+
) as response:
|
|
302
|
+
assert not response.is_closed
|
|
303
|
+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
304
|
+
|
|
305
|
+
participant = response.parse()
|
|
306
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
307
|
+
|
|
308
|
+
assert cast(Any, response.is_closed) is True
|
|
309
|
+
|
|
310
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
311
|
+
@parametrize
|
|
312
|
+
def test_path_params_create_mobile_token(self, client: Growsurf) -> None:
|
|
313
|
+
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
|
|
314
|
+
client.campaign.participant.with_raw_response.create_mobile_token(
|
|
315
|
+
participant_id_or_email="participantIdOrEmail",
|
|
316
|
+
id="",
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
with pytest.raises(
|
|
320
|
+
ValueError, match=r"Expected a non-empty value for `participant_id_or_email` but received ''"
|
|
321
|
+
):
|
|
322
|
+
client.campaign.participant.with_raw_response.create_mobile_token(
|
|
323
|
+
participant_id_or_email="",
|
|
324
|
+
id="id",
|
|
325
|
+
)
|
|
326
|
+
|
|
272
327
|
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
273
328
|
@parametrize
|
|
274
329
|
def test_method_list_commissions(self, client: Growsurf) -> None:
|
|
@@ -1007,6 +1062,60 @@ class TestAsyncParticipant:
|
|
|
1007
1062
|
email="gavin@hooli.com",
|
|
1008
1063
|
)
|
|
1009
1064
|
|
|
1065
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
1066
|
+
@parametrize
|
|
1067
|
+
async def test_method_create_mobile_token(self, async_client: AsyncGrowsurf) -> None:
|
|
1068
|
+
participant = await async_client.campaign.participant.create_mobile_token(
|
|
1069
|
+
participant_id_or_email="participantIdOrEmail",
|
|
1070
|
+
id="id",
|
|
1071
|
+
)
|
|
1072
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
1073
|
+
|
|
1074
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
1075
|
+
@parametrize
|
|
1076
|
+
async def test_raw_response_create_mobile_token(self, async_client: AsyncGrowsurf) -> None:
|
|
1077
|
+
response = await async_client.campaign.participant.with_raw_response.create_mobile_token(
|
|
1078
|
+
participant_id_or_email="participantIdOrEmail",
|
|
1079
|
+
id="id",
|
|
1080
|
+
)
|
|
1081
|
+
|
|
1082
|
+
assert response.is_closed is True
|
|
1083
|
+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
1084
|
+
participant = await response.parse()
|
|
1085
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
1086
|
+
|
|
1087
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
1088
|
+
@parametrize
|
|
1089
|
+
async def test_streaming_response_create_mobile_token(self, async_client: AsyncGrowsurf) -> None:
|
|
1090
|
+
async with async_client.campaign.participant.with_streaming_response.create_mobile_token(
|
|
1091
|
+
participant_id_or_email="participantIdOrEmail",
|
|
1092
|
+
id="id",
|
|
1093
|
+
) as response:
|
|
1094
|
+
assert not response.is_closed
|
|
1095
|
+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
|
|
1096
|
+
|
|
1097
|
+
participant = await response.parse()
|
|
1098
|
+
assert_matches_type(ParticipantCreateMobileTokenResponse, participant, path=["response"])
|
|
1099
|
+
|
|
1100
|
+
assert cast(Any, response.is_closed) is True
|
|
1101
|
+
|
|
1102
|
+
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
1103
|
+
@parametrize
|
|
1104
|
+
async def test_path_params_create_mobile_token(self, async_client: AsyncGrowsurf) -> None:
|
|
1105
|
+
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
|
|
1106
|
+
await async_client.campaign.participant.with_raw_response.create_mobile_token(
|
|
1107
|
+
participant_id_or_email="participantIdOrEmail",
|
|
1108
|
+
id="",
|
|
1109
|
+
)
|
|
1110
|
+
|
|
1111
|
+
with pytest.raises(
|
|
1112
|
+
ValueError, match=r"Expected a non-empty value for `participant_id_or_email` but received ''"
|
|
1113
|
+
):
|
|
1114
|
+
await async_client.campaign.participant.with_raw_response.create_mobile_token(
|
|
1115
|
+
participant_id_or_email="",
|
|
1116
|
+
id="id",
|
|
1117
|
+
)
|
|
1118
|
+
|
|
1010
1119
|
@pytest.mark.skip(reason="Mock server tests are disabled")
|
|
1011
1120
|
@parametrize
|
|
1012
1121
|
async def test_method_list_commissions(self, async_client: AsyncGrowsurf) -> None:
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast
|
|
3
3
|
from datetime import datetime, timezone
|
|
4
|
-
from
|
|
4
|
+
from collections import deque
|
|
5
|
+
from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
7
8
|
import pydantic
|
|
@@ -9,7 +10,7 @@ from pydantic import Field
|
|
|
9
10
|
|
|
10
11
|
from growsurf._utils import PropertyInfo
|
|
11
12
|
from growsurf._compat import PYDANTIC_V1, parse_obj, model_dump, model_json
|
|
12
|
-
from growsurf._models import DISCRIMINATOR_CACHE, BaseModel, construct_type
|
|
13
|
+
from growsurf._models import DISCRIMINATOR_CACHE, BaseModel, EagerIterable, construct_type
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class BasicModel(BaseModel):
|
|
@@ -961,3 +962,56 @@ def test_extra_properties() -> None:
|
|
|
961
962
|
assert model.a.prop == 1
|
|
962
963
|
assert isinstance(model.a, Item)
|
|
963
964
|
assert model.other == "foo"
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
# NOTE: Workaround for Pydantic Iterable behavior.
|
|
968
|
+
# Iterable fields are replaced with a ValidatorIterator and may be consumed
|
|
969
|
+
# during serialization, which can cause subsequent dumps to return empty data.
|
|
970
|
+
# See: https://github.com/pydantic/pydantic/issues/9541
|
|
971
|
+
@pytest.mark.parametrize(
|
|
972
|
+
"data, expected_validated",
|
|
973
|
+
[
|
|
974
|
+
([1, 2, 3], [1, 2, 3]),
|
|
975
|
+
((1, 2, 3), (1, 2, 3)),
|
|
976
|
+
(set([1, 2, 3]), set([1, 2, 3])),
|
|
977
|
+
(iter([1, 2, 3]), [1, 2, 3]),
|
|
978
|
+
([], []),
|
|
979
|
+
((x for x in [1, 2, 3]), [1, 2, 3]),
|
|
980
|
+
(map(lambda x: x, [1, 2, 3]), [1, 2, 3]),
|
|
981
|
+
(frozenset([1, 2, 3]), frozenset([1, 2, 3])),
|
|
982
|
+
(deque([1, 2, 3]), deque([1, 2, 3])),
|
|
983
|
+
],
|
|
984
|
+
ids=["list", "tuple", "set", "iterator", "empty", "generator", "map", "frozenset", "deque"],
|
|
985
|
+
)
|
|
986
|
+
@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2")
|
|
987
|
+
def test_iterable_construction(data: Iterable[int], expected_validated: Iterable[int]) -> None:
|
|
988
|
+
class TypeWithIterable(TypedDict):
|
|
989
|
+
items: EagerIterable[int]
|
|
990
|
+
|
|
991
|
+
class Model(BaseModel):
|
|
992
|
+
data: TypeWithIterable
|
|
993
|
+
|
|
994
|
+
m = Model.model_validate({"data": {"items": data}})
|
|
995
|
+
assert m.data["items"] == expected_validated
|
|
996
|
+
|
|
997
|
+
# Verify repeated dumps don't lose data (the original bug)
|
|
998
|
+
assert m.model_dump()["data"]["items"] == list(expected_validated)
|
|
999
|
+
assert m.model_dump()["data"]["items"] == list(expected_validated)
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2")
|
|
1003
|
+
def test_iterable_construction_str_falls_back_to_list() -> None:
|
|
1004
|
+
# str is iterable (over chars), but str(list_of_chars) produces the list's repr
|
|
1005
|
+
# rather than reconstructing a string from items. We special-case str to fall
|
|
1006
|
+
# back to list instead of attempting reconstruction.
|
|
1007
|
+
class TypeWithIterable(TypedDict):
|
|
1008
|
+
items: EagerIterable[str]
|
|
1009
|
+
|
|
1010
|
+
class Model(BaseModel):
|
|
1011
|
+
data: TypeWithIterable
|
|
1012
|
+
|
|
1013
|
+
m = Model.model_validate({"data": {"items": "hello"}})
|
|
1014
|
+
|
|
1015
|
+
# falls back to list of chars rather than calling str(["h", "e", "l", "l", "o"])
|
|
1016
|
+
assert m.data["items"] == ["h", "e", "l", "l", "o"]
|
|
1017
|
+
assert m.model_dump()["data"]["items"] == ["h", "e", "l", "l", "o"]
|
|
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
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/resources/campaign/commission.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/fraud_risk_level.py
RENAMED
|
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
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/participant_reward.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/referral_source.py
RENAMED
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/referral_status.py
RENAMED
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign/reward_approve_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_payouts_params.py
RENAMED
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_referrals_params.py
RENAMED
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/campaign_list_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/participant_commission_list.py
RENAMED
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/src/growsurf/types/participant_payout_list.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{growsurf_python-0.0.2 → growsurf_python-0.1.0}/tests/api_resources/campaign/test_commission.py
RENAMED
|
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
|