Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Changelog

### Changed

- improved handling of `Enum` arguments
- improved support for storing more data types in key-value stores

### Fixed
Expand Down
9 changes: 8 additions & 1 deletion src/apify_client/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import time
from datetime import datetime, timezone
from enum import Enum
from http import HTTPStatus
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, cast

Expand Down Expand Up @@ -138,7 +139,7 @@ def _encode_webhook_list_to_base64(webhooks: List[Dict]) -> bytes:
data = []
for webhook in webhooks:
webhook_representation = {
'eventTypes': [event_type.value for event_type in webhook['event_types']],
'eventTypes': [_maybe_extract_enum_member_value(event_type) for event_type in webhook['event_types']],
'requestUrl': webhook['request_url'],
}
if 'payload_template' in webhook:
Expand Down Expand Up @@ -203,6 +204,12 @@ def _encode_key_value_store_record_value(value: Any, content_type: Optional[str]
return (value, content_type)


def _maybe_extract_enum_member_value(maybe_enum_member: Any) -> Any:
if isinstance(maybe_enum_member, Enum):
return maybe_enum_member.value
return maybe_enum_member


class ListPage:
"""A single page of items returned from a list() method."""

Expand Down
10 changes: 8 additions & 2 deletions src/apify_client/clients/resource_clients/actor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from typing import Any, Dict, List, Optional

from ..._utils import _encode_key_value_store_record_value, _encode_webhook_list_to_base64, _parse_date_fields, _pluck_data
from ..._utils import (
_encode_key_value_store_record_value,
_encode_webhook_list_to_base64,
_maybe_extract_enum_member_value,
_parse_date_fields,
_pluck_data,
)
from ...consts import ActorJobStatus
from ..base import ResourceClient
from .actor_version import ActorVersionClient
Expand Down Expand Up @@ -294,7 +300,7 @@ def last_run(self, *, status: Optional[ActorJobStatus] = None) -> RunClient:
return RunClient(**self._sub_resource_init_options(
resource_id='last',
resource_path='runs',
params=self._params(status=status.value if status is not None else None),
params=self._params(status=_maybe_extract_enum_member_value(status) if status is not None else None),
))

def versions(self) -> ActorVersionCollectionClient:
Expand Down
3 changes: 2 additions & 1 deletion src/apify_client/clients/resource_clients/actor_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Any, Dict, List, Optional

from ..._utils import _maybe_extract_enum_member_value
from ...consts import ActorSourceType
from ..base import ResourceClient

Expand Down Expand Up @@ -72,7 +73,7 @@ def update(
if apply_env_vars_to_build is not None:
version_fields['applyEnvVarsToBuild'] = apply_env_vars_to_build
if source_type is not None:
version_fields['sourceType'] = source_type.value
version_fields['sourceType'] = _maybe_extract_enum_member_value(source_type)
if source_code is not None:
version_fields['sourceCode'] = source_code
if base_docker_image is not None:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict, List, Optional

from ..._utils import ListPage
from ..._utils import ListPage, _maybe_extract_enum_member_value
from ...consts import ActorSourceType
from ..base import ResourceCollectionClient

Expand Down Expand Up @@ -77,7 +77,7 @@ def create(
if apply_env_vars_to_build is not None:
version_fields['applyEnvVarsToBuild'] = apply_env_vars_to_build
if source_type is not None:
version_fields['sourceType'] = source_type.value
version_fields['sourceType'] = _maybe_extract_enum_member_value(source_type)
if source_code is not None:
version_fields['sourceCode'] = source_code
if base_docker_image is not None:
Expand Down
4 changes: 2 additions & 2 deletions src/apify_client/clients/resource_clients/run_collection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Optional

from ..._utils import ListPage
from ..._utils import ListPage, _maybe_extract_enum_member_value
from ...consts import ActorJobStatus
from ..base import ResourceCollectionClient

Expand Down Expand Up @@ -39,5 +39,5 @@ def list(
limit=limit,
offset=offset,
desc=desc,
status=status.value if status is not None else None,
status=_maybe_extract_enum_member_value(status) if status is not None else None,
)
11 changes: 9 additions & 2 deletions src/apify_client/clients/resource_clients/task.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from typing import Any, Dict, List, Optional, cast

from ..._errors import ApifyApiError
from ..._utils import _catch_not_found_or_throw, _encode_webhook_list_to_base64, _filter_out_none_values_recursively, _parse_date_fields, _pluck_data
from ..._utils import (
_catch_not_found_or_throw,
_encode_webhook_list_to_base64,
_filter_out_none_values_recursively,
_maybe_extract_enum_member_value,
_parse_date_fields,
_pluck_data,
)
from ...consts import ActorJobStatus
from ..base import ResourceClient
from .run import RunClient
Expand Down Expand Up @@ -218,7 +225,7 @@ def last_run(self, *, status: Optional[ActorJobStatus] = None) -> RunClient:
return RunClient(**self._sub_resource_init_options(
resource_id='last',
resource_path='runs',
params=self._params(status=status.value if status is not None else None),
params=self._params(status=_maybe_extract_enum_member_value(status) if status is not None else None),
))

def webhooks(self) -> WebhookCollectionClient:
Expand Down
4 changes: 2 additions & 2 deletions src/apify_client/clients/resource_clients/webhook.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Dict, List, Optional

from ..._errors import ApifyApiError
from ..._utils import _catch_not_found_or_throw, _parse_date_fields, _pluck_data, _snake_case_to_camel_case
from ..._utils import _catch_not_found_or_throw, _maybe_extract_enum_member_value, _parse_date_fields, _pluck_data, _snake_case_to_camel_case
from ...consts import WebhookEventType
from ..base import ResourceClient
from .webhook_dispatch_collection import WebhookDispatchCollectionClient
Expand Down Expand Up @@ -40,7 +40,7 @@ def _prepare_webhook_representation(
webhook['condition'] = condition

if event_types is not None:
webhook['eventTypes'] = [event_type.value for event_type in event_types]
webhook['eventTypes'] = [_maybe_extract_enum_member_value(event_type) for event_type in event_types]

return webhook

Expand Down
6 changes: 3 additions & 3 deletions src/apify_client/consts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum


class ActorJobStatus(Enum):
class ActorJobStatus(str, Enum):
"""Available statuses for actor jobs (runs or builds)."""

#: Actor job initialized but not started yet
Expand All @@ -27,7 +27,7 @@ def _is_terminal(self) -> bool:
return self in (ActorJobStatus.SUCCEEDED, ActorJobStatus.FAILED, ActorJobStatus.TIMED_OUT, ActorJobStatus.ABORTED)


class ActorSourceType(Enum):
class ActorSourceType(str, Enum):
"""Available source types for actors."""

#: Actor source code is a single JavaScript/Node.js file
Expand All @@ -42,7 +42,7 @@ class ActorSourceType(Enum):
GITHUB_GIST = 'GITHUB_GIST'


class WebhookEventType(Enum):
class WebhookEventType(str, Enum):
"""Events that can trigger a webhook."""

#: The actor run was created
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import time
import unittest
from datetime import datetime, timezone
from enum import Enum
from typing import Any, Callable

from apify_client._utils import (
Expand All @@ -10,6 +11,7 @@
_is_content_type_text,
_is_content_type_xml,
_is_file_or_bytes,
_maybe_extract_enum_member_value,
_parse_date_fields,
_pluck_data,
_retry_with_exp_backoff,
Expand Down Expand Up @@ -167,3 +169,14 @@ def test__encode_webhook_list_to_base64(self) -> None:
]),
b'W3siZXZlbnRUeXBlcyI6IFsiQUNUT1IuUlVOLkNSRUFURUQiXSwgInJlcXVlc3RVcmwiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9ydW4tY3JlYXRlZCJ9LCB7ImV2ZW50VHlwZXMiOiBbIkFDVE9SLlJVTi5TVUNDRUVERUQiXSwgInJlcXVlc3RVcmwiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9ydW4tc3VjY2VlZGVkIiwgInBheWxvYWRUZW1wbGF0ZSI6ICJ7XCJoZWxsb1wiOiBcIndvcmxkXCIsIFwicmVzb3VyY2VcIjp7e3Jlc291cmNlfX19In1d', # noqa: E501
)

def test__maybe_extract_enum_member_value(self) -> None:
class TestEnum(Enum):
A = 'A'
B = 'B'

self.assertEqual(_maybe_extract_enum_member_value(TestEnum.A), 'A')
self.assertEqual(_maybe_extract_enum_member_value(TestEnum.B), 'B')
self.assertEqual(_maybe_extract_enum_member_value('C'), 'C')
self.assertEqual(_maybe_extract_enum_member_value(1), 1)
self.assertEqual(_maybe_extract_enum_member_value(None), None)