Background
We're on Pydantic ≥2.11. Models in src/apify/_models.py and src/apify/storage_clients/_apify/_models.py map snake_case fields to the Apify API's camelCase, declaring each alias by hand:
actor_id: Annotated[str | None, Field(alias='actorId')] = None
actor_task_id: Annotated[str | None, Field(alias='actorTaskId')] = None
Proposal
Add alias_generator=to_camel to the shared config so aliases are derived:
from pydantic.alias_generators import to_camel
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
Fields then become actor_id: str | None = None and still bind to actorId. Currently 19 models repeat ConfigDict(populate_by_name=True, ...) while 11 (events in events/_types.py, the request-loader input models) have no config at all. A single base model carrying the config (including the generator) would cover both gaps.
Where it makes sense
- Apply to the API-response models that already use camelCase aliases.
- Keep explicit
Field(alias=...) where the generated key would differ.
- Subclasses of Crawlee storage models (
ApifyKeyValueStoreMetadata, ApifyRequestQueueMetadata) should follow whatever Crawlee adopts.
- Event models carry protocol-defined names, so check each before switching.
Scope
Refactor only. Generated aliases must match the current ones, guarded by tests.
Background
We're on Pydantic ≥2.11. Models in
src/apify/_models.pyandsrc/apify/storage_clients/_apify/_models.pymap snake_case fields to the Apify API's camelCase, declaring each alias by hand:Proposal
Add
alias_generator=to_camelto the shared config so aliases are derived:Fields then become
actor_id: str | None = Noneand still bind toactorId. Currently 19 models repeatConfigDict(populate_by_name=True, ...)while 11 (events inevents/_types.py, the request-loader input models) have no config at all. A single base model carrying the config (including the generator) would cover both gaps.Where it makes sense
Field(alias=...)where the generated key would differ.ApifyKeyValueStoreMetadata,ApifyRequestQueueMetadata) should follow whatever Crawlee adopts.Scope
Refactor only. Generated aliases must match the current ones, guarded by tests.