Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/pre_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
uses: apify/workflows/.github/workflows/python_integration_tests.yaml@main
secrets: inherit
with:
python-versions: '["3.10", "3.11", "3.12", "3.13", "3.14"]'
python-versions: '["3.10", "3.14"]'

update_changelog:
name: Update changelog
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
uses: apify/workflows/.github/workflows/python_integration_tests.yaml@main
secrets: inherit
with:
python-versions: '["3.10", "3.11", "3.12", "3.13", "3.14"]'
python-versions: '["3.10", "3.14"]'

update_changelog:
name: Update changelog
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/run_code_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ jobs:

integration_tests:
name: Integration tests
needs: [lint_check, type_check, unit_tests]
uses: apify/workflows/.github/workflows/python_integration_tests.yaml@main
with:
python-versions: '["3.10", "3.11", "3.12", "3.13", "3.14"]'
python-versions: '["3.10", "3.14"]'
secrets: inherit
2 changes: 1 addition & 1 deletion docs/01_overview/code/01_usage_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ async def main() -> None:
return

# Fetch results from the Actor run's default dataset.
dataset_client = apify_client.dataset(call_result['defaultDatasetId'])
dataset_client = apify_client.dataset(call_result.default_dataset_id)
list_items_result = await dataset_client.list_items()
print(f'Dataset: {list_items_result}')
2 changes: 1 addition & 1 deletion docs/01_overview/code/01_usage_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ def main() -> None:
return

# Fetch results from the Actor run's default dataset.
dataset_client = apify_client.dataset(call_result['defaultDatasetId'])
dataset_client = apify_client.dataset(call_result.default_dataset_id)
list_items_result = dataset_client.list_items()
print(f'Dataset: {list_items_result}')
2 changes: 1 addition & 1 deletion docs/02_concepts/code/01_async_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async def main() -> None:

# Start the Actor and get the run ID
run_result = await actor_client.start()
run_client = apify_client.run(run_result['id'])
run_client = apify_client.run(run_result.id)
log_client = run_client.log()

# Stream the logs
Expand Down
12 changes: 6 additions & 6 deletions docs/03_examples/code/02_tasks_async.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import asyncio

from apify_client import ApifyClientAsync
from apify_client.clients.resource_clients import TaskClientAsync
from apify_client._models import Run, Task
from apify_client._resource_clients import TaskClientAsync

TOKEN = 'MY-APIFY-TOKEN'
HASHTAGS = ['zebra', 'lion', 'hippo']


async def run_apify_task(client: TaskClientAsync) -> dict:
result = await client.call()
return result or {}
async def run_apify_task(client: TaskClientAsync) -> Run | None:
return await client.call()


async def main() -> None:
apify_client = ApifyClientAsync(token=TOKEN)

# Create Apify tasks
apify_tasks = list[dict]()
apify_tasks = list[Task]()
apify_tasks_client = apify_client.tasks()

for hashtag in HASHTAGS:
Expand All @@ -34,7 +34,7 @@ async def main() -> None:
apify_task_clients = list[TaskClientAsync]()

for apify_task in apify_tasks:
task_id = apify_task['id']
task_id = apify_task.id
apify_task_client = apify_client.task(task_id)
apify_task_clients.append(apify_task_client)

Expand Down
17 changes: 9 additions & 8 deletions docs/03_examples/code/02_tasks_sync.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
from apify_client import ApifyClient
from apify_client.clients.resource_clients import TaskClient
from apify_client._models import Run, Task
from apify_client._resource_clients import TaskClient

TOKEN = 'MY-APIFY-TOKEN'
HASHTAGS = ['zebra', 'lion', 'hippo']


def run_apify_task(client: TaskClient) -> dict:
result = client.call()
return result or {}
def run_apify_task(client: TaskClient) -> Run | None:
return client.call()


def main() -> None:
apify_client = ApifyClient(token=TOKEN)

# Create Apify tasks
apify_tasks = list[dict]()
apify_tasks = list[Task]()
apify_tasks_client = apify_client.tasks()

for hashtag in HASHTAGS:
Expand All @@ -32,18 +32,19 @@ def main() -> None:
apify_task_clients = list[TaskClient]()

for apify_task in apify_tasks:
task_id = apify_task['id']
task_id = apify_task.id
apify_task_client = apify_client.task(task_id)
apify_task_clients.append(apify_task_client)

print('Task clients created:', apify_task_clients)

# Execute Apify tasks
task_run_results = list[dict]()
task_run_results = list[Run]()

for client in apify_task_clients:
result = run_apify_task(client)
task_run_results.append(result)
if result is not None:
task_run_results.append(result)

print('Task results:', task_run_results)

Expand Down
4 changes: 2 additions & 2 deletions docs/03_examples/code/03_retrieve_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ async def main() -> None:

for dataset_item in actor_datasets.items:
# Dataset items can be handled here. Dataset items can be paginated
dataset_client = apify_client.dataset(dataset_item['id'])
dataset_client = apify_client.dataset(dataset_item.id)
dataset_items = await dataset_client.list_items(limit=1000)

# Items can be pushed to single dataset
merging_dataset_client = apify_client.dataset(merging_dataset['id'])
merging_dataset_client = apify_client.dataset(merging_dataset.id)
await merging_dataset_client.push_items(dataset_items.items)

# ...
Expand Down
4 changes: 2 additions & 2 deletions docs/03_examples/code/03_retrieve_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ def main() -> None:

for dataset_item in actor_datasets.items:
# Dataset items can be handled here. Dataset items can be paginated
dataset_client = apify_client.dataset(dataset_item['id'])
dataset_client = apify_client.dataset(dataset_item.id)
dataset_items = dataset_client.list_items(limit=1000)

# Items can be pushed to single dataset
merging_dataset_client = apify_client.dataset(merging_dataset['id'])
merging_dataset_client = apify_client.dataset(merging_dataset.id)
merging_dataset_client.push_items(dataset_items.items)

# ...
Expand Down
23 changes: 23 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dev = [
"setuptools", # setuptools are used by pytest but not explicitly required
"types-colorama<0.5.0",
"werkzeug<4.0.0", # Werkzeug is used by pytest-httpserver
"datamodel-code-generator[http,ruff]<1.0.0",
]

[tool.hatch.build.targets.wheel]
Expand Down Expand Up @@ -138,6 +139,10 @@ indent-style = "space"
"N999", # Invalid module name
"T201", # print found
]
"src/apify_client/_models.py" = [
"D", # Everything from the pydocstyle
"E501", # Line too long
]

[tool.ruff.lint.flake8-quotes]
docstring-quotes = "double"
Expand Down Expand Up @@ -187,3 +192,21 @@ exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:", "assert_never()"]

[tool.ipdb]
context = 7

# https://koxudaxi.github.io/datamodel-code-generator/
[tool.datamodel-codegen]
url = "https://docs.apify.com/api/openapi.json"
input_file_type = "openapi"
output = "src/apify_client/_models.py"
target_python_version = "3.10"
output_model_type = "pydantic_v2.BaseModel"
use_schema_description = true
use_field_description = true
use_union_operator = true
capitalise_enum_members = true
collapse_root_models = true
set_default_enum_member = true
use_annotated = true
wrap_string_literal = true
snake_case_field = true
formatters = ["ruff-check", "ruff-format"]
2 changes: 1 addition & 1 deletion scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_current_package_version() -> str:
# It replaces the version number on the line with the format `version = "1.2.3"`
def set_current_package_version(version: str) -> None:
with open(PYPROJECT_TOML_FILE_PATH, 'r+', encoding='utf-8') as pyproject_toml_file:
updated_pyproject_toml_file_lines = []
updated_pyproject_toml_file_lines = list[str]()
version_string_found = False
for line in pyproject_toml_file:
line_processed = line
Expand Down
2 changes: 1 addition & 1 deletion src/apify_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from importlib import metadata

from .client import ApifyClient, ApifyClientAsync
from ._client import ApifyClient, ApifyClientAsync

__version__ = metadata.version('apify-client')

Expand Down
4 changes: 2 additions & 2 deletions src/apify_client/client.py → src/apify_client/_client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import annotations

from apify_client._http_client import HTTPClient, HTTPClientAsync
from apify_client._statistics import Statistics
from apify_client.clients import (
from apify_client._resource_clients import (
ActorClient,
ActorClientAsync,
ActorCollectionClient,
Expand Down Expand Up @@ -50,6 +49,7 @@
WebhookDispatchCollectionClient,
WebhookDispatchCollectionClientAsync,
)
from apify_client._types import Statistics

DEFAULT_API_URL = 'https://api.apify.com'
DEFAULT_TIMEOUT = 360
Expand Down
12 changes: 6 additions & 6 deletions src/apify_client/_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
import impit

from apify_client._logging import log_context, logger_name
from apify_client._statistics import Statistics
from apify_client._types import Statistics
from apify_client._utils import is_retryable_error, retry_with_exp_backoff, retry_with_exp_backoff_async
from apify_client.errors import ApifyApiError

if TYPE_CHECKING:
from collections.abc import Callable

from apify_client._types import JSONSerializable
from apify_client._types import JsonSerializable

DEFAULT_BACKOFF_EXPONENTIAL_FACTOR = 2
DEFAULT_BACKOFF_RANDOM_FACTOR = 1
Expand Down Expand Up @@ -96,7 +96,7 @@ def _prepare_request_call(
headers: dict | None = None,
params: dict | None = None,
data: Any = None,
json: JSONSerializable | None = None,
json: JsonSerializable | None = None,
) -> tuple[dict, dict | None, Any]:
if json and data:
raise ValueError('Cannot pass both "json" and "data" parameters at the same time!')
Expand Down Expand Up @@ -125,7 +125,7 @@ def _build_url_with_params(self, url: str, params: dict | None = None) -> str:
if not params:
return url

param_pairs: list[tuple[str, str]] = []
param_pairs = list[tuple[str, str]]()
for key, value in params.items():
if isinstance(value, list):
param_pairs.extend((key, str(v)) for v in value)
Expand All @@ -146,7 +146,7 @@ def call(
headers: dict | None = None,
params: dict | None = None,
data: Any = None,
json: JSONSerializable | None = None,
json: JsonSerializable | None = None,
stream: bool | None = None,
timeout_secs: int | None = None,
) -> impit.Response:
Expand Down Expand Up @@ -225,7 +225,7 @@ async def call(
headers: dict | None = None,
params: dict | None = None,
data: Any = None,
json: JSONSerializable | None = None,
json: JsonSerializable | None = None,
stream: bool | None = None,
timeout_secs: int | None = None,
) -> impit.Response:
Expand Down
Loading
Loading