Skip to content

Commit a3988b7

Browse files
authored
docs: Improve API doc groups (#509)
### Description - Improve API doc groups (as was done in apify/crawlee-python#1309). - `Actor` and `ChargingManager` class docstrings were updated. - Missing symbols from Crawlee were exposed here. - Usage of `ignore_docs` was removed, as it's no longer needed. <img width="2104" height="2992" alt="image" src="https://github.com/user-attachments/assets/5bfbf9cb-b9d5-4a3a-9ce1-8ae4580557da" /> ### Issue - Closes: #508
1 parent c75520a commit a3988b7

File tree

12 files changed

+217
-56
lines changed

12 files changed

+217
-56
lines changed

src/apify/_actor.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from apify_client import ApifyClientAsync
1515
from apify_shared.consts import ActorEnvVars, ActorExitCodes, ApifyEnvVars
16-
from apify_shared.utils import ignore_docs, maybe_extract_enum_member_value
16+
from apify_shared.utils import maybe_extract_enum_member_value
1717
from crawlee import service_locator
1818
from crawlee.events import (
1919
Event,
@@ -54,9 +54,46 @@
5454

5555

5656
@docs_name('Actor')
57-
@docs_group('Classes')
57+
@docs_group('Actor')
5858
class _ActorType:
59-
"""The class of `Actor`. Only make a new instance if you're absolutely sure you need to."""
59+
"""The core class for building Actors on the Apify platform.
60+
61+
Actors are serverless programs running in the cloud that can perform anything from simple actions
62+
(such as filling out a web form or sending an email) to complex operations (such as crawling an
63+
entire website or removing duplicates from a large dataset). They are packaged as Docker containers
64+
which accept well-defined JSON input, perform an action, and optionally produce well-defined output.
65+
66+
### References
67+
68+
- Apify platform documentation: https://docs.apify.com/platform/actors
69+
- Actor whitepaper: https://whitepaper.actor/
70+
71+
### Usage
72+
73+
```python
74+
import asyncio
75+
76+
import httpx
77+
from apify import Actor
78+
from bs4 import BeautifulSoup
79+
80+
81+
async def main() -> None:
82+
async with Actor:
83+
actor_input = await Actor.get_input()
84+
async with httpx.AsyncClient() as client:
85+
response = await client.get(actor_input['url'])
86+
soup = BeautifulSoup(response.content, 'html.parser')
87+
data = {
88+
'url': actor_input['url'],
89+
'title': soup.title.string if soup.title else None,
90+
}
91+
await Actor.push_data(data)
92+
93+
if __name__ == '__main__':
94+
asyncio.run(main())
95+
```
96+
"""
6097

6198
_is_rebooting = False
6299
_is_any_instance_initialized = False
@@ -108,7 +145,6 @@ def __init__(
108145

109146
self._is_initialized = False
110147

111-
@ignore_docs
112148
async def __aenter__(self) -> Self:
113149
"""Initialize the Actor.
114150
@@ -120,7 +156,6 @@ async def __aenter__(self) -> Self:
120156
await self.init()
121157
return self
122158

123-
@ignore_docs
124159
async def __aexit__(
125160
self,
126161
_exc_type: type[BaseException] | None,

src/apify/_charging.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from pydantic import TypeAdapter
1010

11-
from apify_shared.utils import ignore_docs
1211
from crawlee._utils.context import ensure_context
1312

1413
from apify._models import ActorRun, PricingModel
@@ -26,9 +25,18 @@
2625
run_validator = TypeAdapter[ActorRun | None](ActorRun | None)
2726

2827

29-
@docs_group('Interfaces')
28+
@docs_group('Charging')
3029
class ChargingManager(Protocol):
31-
"""Provides fine-grained access to pay-per-event functionality."""
30+
"""Provides fine-grained access to pay-per-event functionality.
31+
32+
The ChargingManager allows you to charge for specific events in your Actor when using
33+
the pay-per-event pricing model. This enables precise cost control and transparent
34+
billing for different operations within your Actor.
35+
36+
### References
37+
38+
- Apify platform documentation: https://docs.apify.com/platform/actors/publishing/monetize
39+
"""
3240

3341
async def charge(self, event_name: str, count: int = 1) -> ChargeResult:
3442
"""Charge for a specified number of events - sub-operations of the Actor.
@@ -57,7 +65,7 @@ def get_pricing_info(self) -> ActorPricingInfo:
5765
"""
5866

5967

60-
@docs_group('Data structures')
68+
@docs_group('Charging')
6169
@dataclass(frozen=True)
6270
class ChargeResult:
6371
"""Result of the `ChargingManager.charge` method."""
@@ -72,7 +80,7 @@ class ChargeResult:
7280
"""How many events of each known type can still be charged within the limit."""
7381

7482

75-
@docs_group('Data structures')
83+
@docs_group('Charging')
7684
@dataclass
7785
class ActorPricingInfo:
7886
"""Result of the `ChargingManager.get_pricing_info` method."""
@@ -90,7 +98,6 @@ class ActorPricingInfo:
9098
"""Price of every known event type."""
9199

92100

93-
@ignore_docs
94101
class ChargingManagerImplementation(ChargingManager):
95102
"""Implementation of the `ChargingManager` Protocol - this is only meant to be instantiated internally."""
96103

src/apify/_configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def _transform_to_list(value: Any) -> list[str] | None:
2525
return value if isinstance(value, list) else str(value).split(',')
2626

2727

28-
@docs_group('Classes')
28+
@docs_group('Configuration')
2929
class Configuration(CrawleeConfiguration):
3030
"""A class for specifying the configuration of an Actor.
3131

src/apify/_crypto.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from cryptography.hazmat.primitives.asymmetric import padding, rsa
1313
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
1414

15-
from apify_shared.utils import ignore_docs
1615
from crawlee._utils.crypto import crypto_random_object_id
1716

1817
from apify._consts import ENCRYPTED_INPUT_VALUE_REGEXP, ENCRYPTED_JSON_VALUE_PREFIX, ENCRYPTED_STRING_VALUE_PREFIX
@@ -22,7 +21,6 @@
2221
ENCRYPTION_AUTH_TAG_LENGTH = 16
2322

2423

25-
@ignore_docs
2624
def public_encrypt(value: str, *, public_key: rsa.RSAPublicKey) -> dict:
2725
"""Encrypts the given value using AES cipher and the password for encryption using the public key.
2826
@@ -66,7 +64,6 @@ def public_encrypt(value: str, *, public_key: rsa.RSAPublicKey) -> dict:
6664
}
6765

6866

69-
@ignore_docs
7067
def private_decrypt(
7168
encrypted_password: str,
7269
encrypted_value: str,
@@ -118,7 +115,6 @@ def private_decrypt(
118115
return decipher_bytes.decode('utf-8')
119116

120117

121-
@ignore_docs
122118
def load_private_key(private_key_file_base64: str, private_key_password: str) -> rsa.RSAPrivateKey:
123119
private_key = serialization.load_pem_private_key(
124120
base64.b64decode(private_key_file_base64.encode('utf-8')),
@@ -138,7 +134,6 @@ def _load_public_key(public_key_file_base64: str) -> rsa.RSAPublicKey:
138134
return public_key
139135

140136

141-
@ignore_docs
142137
def decrypt_input_secrets(private_key: rsa.RSAPrivateKey, input_data: Any) -> Any:
143138
"""Decrypt input secrets."""
144139
if not isinstance(input_data, dict):
@@ -180,7 +175,6 @@ def encode_base62(num: int) -> str:
180175
return res
181176

182177

183-
@ignore_docs
184178
def create_hmac_signature(secret_key: str, message: str) -> str:
185179
"""Generate an HMAC signature and encodes it using Base62. Base62 encoding reduces the signature length.
186180

src/apify/_models.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from typing import TypeAlias
1717

1818

19-
@docs_group('Data structures')
19+
@docs_group('Actor')
2020
class Webhook(BaseModel):
2121
__model_config__ = ConfigDict(populate_by_name=True)
2222

@@ -35,14 +35,14 @@ class Webhook(BaseModel):
3535
] = None
3636

3737

38-
@docs_group('Data structures')
38+
@docs_group('Actor')
3939
class ActorRunMeta(BaseModel):
4040
__model_config__ = ConfigDict(populate_by_name=True)
4141

4242
origin: Annotated[MetaOrigin, Field()]
4343

4444

45-
@docs_group('Data structures')
45+
@docs_group('Actor')
4646
class ActorRunStats(BaseModel):
4747
__model_config__ = ConfigDict(populate_by_name=True)
4848

@@ -63,7 +63,7 @@ class ActorRunStats(BaseModel):
6363
compute_units: Annotated[float, Field(alias='computeUnits')]
6464

6565

66-
@docs_group('Data structures')
66+
@docs_group('Actor')
6767
class ActorRunOptions(BaseModel):
6868
__model_config__ = ConfigDict(populate_by_name=True)
6969

@@ -74,7 +74,7 @@ class ActorRunOptions(BaseModel):
7474
max_total_charge_usd: Annotated[Decimal | None, Field(alias='maxTotalChargeUsd')] = None
7575

7676

77-
@docs_group('Data structures')
77+
@docs_group('Actor')
7878
class ActorRunUsage(BaseModel):
7979
__model_config__ = ConfigDict(populate_by_name=True)
8080

@@ -92,7 +92,7 @@ class ActorRunUsage(BaseModel):
9292
proxy_serps: Annotated[float | None, Field(alias='PROXY_SERPS')] = None
9393

9494

95-
@docs_group('Data structures')
95+
@docs_group('Actor')
9696
class ActorRun(BaseModel):
9797
__model_config__ = ConfigDict(populate_by_name=True)
9898

src/apify/_platform_event_manager.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,10 @@
2727

2828
from apify._configuration import Configuration
2929

30-
3130
__all__ = ['EventManager', 'LocalEventManager', 'PlatformEventManager']
3231

3332

34-
@docs_group('Data structures')
35-
class PersistStateEvent(BaseModel):
36-
name: Literal[Event.PERSIST_STATE]
37-
data: Annotated[EventPersistStateData, Field(default_factory=lambda: EventPersistStateData(is_migrating=False))]
38-
39-
40-
@docs_group('Data structures')
33+
@docs_group('Event data')
4134
class SystemInfoEventData(BaseModel):
4235
mem_avg_bytes: Annotated[float, Field(alias='memAvgBytes')]
4336
mem_current_bytes: Annotated[float, Field(alias='memCurrentBytes')]
@@ -64,31 +57,37 @@ def to_crawlee_format(self, dedicated_cpus: float) -> EventSystemInfoData:
6457
)
6558

6659

67-
@docs_group('Data structures')
60+
@docs_group('Events')
61+
class PersistStateEvent(BaseModel):
62+
name: Literal[Event.PERSIST_STATE]
63+
data: Annotated[EventPersistStateData, Field(default_factory=lambda: EventPersistStateData(is_migrating=False))]
64+
65+
66+
@docs_group('Events')
6867
class SystemInfoEvent(BaseModel):
6968
name: Literal[Event.SYSTEM_INFO]
7069
data: SystemInfoEventData
7170

7271

73-
@docs_group('Data structures')
72+
@docs_group('Events')
7473
class MigratingEvent(BaseModel):
7574
name: Literal[Event.MIGRATING]
7675
data: Annotated[EventMigratingData, Field(default_factory=EventMigratingData)]
7776

7877

79-
@docs_group('Data structures')
78+
@docs_group('Events')
8079
class AbortingEvent(BaseModel):
8180
name: Literal[Event.ABORTING]
8281
data: Annotated[EventAbortingData, Field(default_factory=EventAbortingData)]
8382

8483

85-
@docs_group('Data structures')
84+
@docs_group('Events')
8685
class ExitEvent(BaseModel):
8786
name: Literal[Event.EXIT]
8887
data: Annotated[EventExitData, Field(default_factory=EventExitData)]
8988

9089

91-
@docs_group('Data structures')
90+
@docs_group('Events')
9291
class EventWithoutData(BaseModel):
9392
name: Literal[
9493
Event.SESSION_RETIRED,
@@ -101,13 +100,13 @@ class EventWithoutData(BaseModel):
101100
data: Any = None
102101

103102

104-
@docs_group('Data structures')
103+
@docs_group('Events')
105104
class DeprecatedEvent(BaseModel):
106105
name: Literal['cpuInfo']
107106
data: Annotated[dict[str, Any], Field(default_factory=dict)]
108107

109108

110-
@docs_group('Data structures')
109+
@docs_group('Events')
111110
class UnknownEvent(BaseModel):
112111
name: str
113112
data: Annotated[dict[str, Any], Field(default_factory=dict)]
@@ -120,7 +119,7 @@ class UnknownEvent(BaseModel):
120119
)
121120

122121

123-
@docs_group('Classes')
122+
@docs_group('Event managers')
124123
class PlatformEventManager(EventManager):
125124
"""A class for managing Actor events.
126125

src/apify/_proxy_configuration.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import httpx
1111

1212
from apify_shared.consts import ApifyEnvVars
13-
from apify_shared.utils import ignore_docs
1413
from crawlee.proxy_configuration import ProxyConfiguration as CrawleeProxyConfiguration
1514
from crawlee.proxy_configuration import ProxyInfo as CrawleeProxyInfo
1615
from crawlee.proxy_configuration import _NewUrlFunction
@@ -28,7 +27,6 @@
2827
SESSION_ID_MAX_LENGTH = 50
2928

3029

31-
@ignore_docs
3230
def is_url(url: str) -> bool:
3331
"""Check if the given string is a valid URL."""
3432
try:
@@ -69,7 +67,7 @@ def _check(
6967
raise ValueError(f'{error_str} does not match pattern {pattern.pattern!r}')
7068

7169

72-
@docs_group('Classes')
70+
@docs_group('Configuration')
7371
@dataclass
7472
class ProxyInfo(CrawleeProxyInfo):
7573
"""Provides information about a proxy connection that is used for requests."""
@@ -89,7 +87,7 @@ class ProxyInfo(CrawleeProxyInfo):
8987
"""
9088

9189

92-
@docs_group('Classes')
90+
@docs_group('Configuration')
9391
class ProxyConfiguration(CrawleeProxyConfiguration):
9492
"""Configures a connection to a proxy server with the provided options.
9593
@@ -104,7 +102,6 @@ class ProxyConfiguration(CrawleeProxyConfiguration):
104102

105103
_configuration: Configuration
106104

107-
@ignore_docs
108105
def __init__(
109106
self,
110107
*,

src/apify/_utils.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,19 @@ def is_running_in_ipython() -> bool:
3030
return getattr(builtins, '__IPYTHON__', False)
3131

3232

33-
GroupName = Literal['Classes', 'Abstract classes', 'Interfaces', 'Data structures', 'Errors', 'Functions']
33+
# The order of the rendered API groups is defined in the website/docusaurus.config.js file.
34+
GroupName = Literal[
35+
'Actor',
36+
'Charging',
37+
'Configuration',
38+
'Event data',
39+
'Event managers',
40+
'Events',
41+
'Request loaders',
42+
'Storage clients',
43+
'Storage data',
44+
'Storages',
45+
]
3446

3547

3648
def docs_group(group_name: GroupName) -> Callable: # noqa: ARG001

src/apify/apify_storage_client/_apify_storage_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from apify._configuration import Configuration
2121

2222

23-
@docs_group('Classes')
23+
@docs_group('Storage clients')
2424
class ApifyStorageClient(StorageClient):
2525
"""A storage client implementation based on the Apify platform storage."""
2626

0 commit comments

Comments
 (0)