-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy path_utils.py
More file actions
127 lines (88 loc) · 3.87 KB
/
Copy path_utils.py
File metadata and controls
127 lines (88 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from __future__ import annotations
import asyncio
import secrets
import string
import time
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, TypeVar, overload
import pytest
if TYPE_CHECKING:
from collections.abc import Coroutine
# Environment variable names for test configuration
TOKEN_ENV_VAR = 'APIFY_TEST_USER_API_TOKEN'
TOKEN_ENV_VAR_2 = 'APIFY_TEST_USER_2_API_TOKEN'
API_URL_ENV_VAR = 'APIFY_INTEGRATION_TESTS_API_URL'
T = TypeVar('T')
# ============================================================================
# Data classes for test fixtures
# ============================================================================
@dataclass
class StorageFixture:
"""Base storage fixture with ID and signature."""
id: str
signature: str
@dataclass
class DatasetFixture(StorageFixture):
"""Dataset fixture with expected content."""
expected_content: list
@dataclass
class KvsFixture(StorageFixture):
"""Key-value store fixture with expected content and key signatures."""
expected_content: dict[str, Any]
keys_signature: dict[str, str]
# ============================================================================
# Helper functions
# ============================================================================
def get_crypto_random_object_id(length: int = 17) -> str:
"""Generate a cryptographically secure random object ID."""
chars = 'abcdefghijklmnopqrstuvwxyzABCEDFGHIJKLMNOPQRSTUVWXYZ0123456789'
return ''.join(secrets.choice(chars) for _ in range(length))
def get_random_string(length: int = 10) -> str:
"""Generate a random alphabetic string."""
return ''.join(secrets.choice(string.ascii_letters) for _ in range(length))
def get_random_resource_name(label: str) -> str:
"""Generate a unique resource name containing the given label.
Ensures the generated name does not exceed the API limit of 63 characters.
"""
name_template = 'python-client-test-{}-{}'
template_length = len(name_template.format('', ''))
api_name_limit = 63
random_id_length = 8
label_length_limit = api_name_limit - template_length - random_id_length
label = label.replace('_', '-')
assert len(label) <= label_length_limit, f'Max label length is {label_length_limit}, but got {len(label)}'
return name_template.format(label, get_crypto_random_object_id(random_id_length))
@overload
async def maybe_await(value: Coroutine[Any, Any, T]) -> T: ...
@overload
async def maybe_await(value: T) -> T: ...
async def maybe_await(value: T | Coroutine[Any, Any, T]) -> T:
"""Await coroutines, pass through other values.
Enables unified test code for both sync and async clients:
result = await maybe_await(client.datasets().list())
"""
if hasattr(value, '__await__'):
return await value # ty: ignore[invalid-await]
return value
async def maybe_sleep(seconds: float, *, is_async: bool) -> None:
"""Sleep using asyncio or time.sleep based on client type."""
if is_async:
await asyncio.sleep(seconds)
else:
time.sleep(seconds) # noqa: ASYNC251
# ============================================================================
# Pytest markers and parametrization
# ============================================================================
parametrized_api_urls = pytest.mark.parametrize(
('api_url', 'api_public_url'),
[
('https://api.apify.com', 'https://api.apify.com'),
('https://api.apify.com', None),
('https://api.apify.com', 'https://custom-public-url.com'),
('https://api.apify.com', 'https://custom-public-url.com/with/custom/path'),
('https://api.apify.com', 'https://custom-public-url.com/with/custom/path/'),
('http://10.0.88.214:8010', 'https://api.apify.com'),
('http://10.0.88.214:8010', None),
],
)
"""Parametrize decorator for testing various API URL and public URL combinations."""