Skip to content

Consider accepting both snake_case and camelCase values for dicts and Literals #756

@vdusek

Description

@vdusek

Context

Spun out of a review discussion on #738: #738 (comment)

I think there is a case for accepting camelCase here instead - it is exactly what the API accepts. On the other hand, snake_case fits in better with the rest of the Python code and works better for the "I just don't want to look up what model I need to import" use case for TypedDicts.

The same tension already exists today for Literal values used in resource-client methods, e.g.:

sort_by: Literal['created_at', 'last_run_started_at'] | None = 'created_at'

The Apify API expects these as camelCase (createdAt, lastRunStartedAt), while the Python client exposes them in snake_case to match Python conventions. The same question now arises for the newly generated input-side TypedDicts from #738 (field names in dicts passed to client methods).

Proposal

Consider — and, if agreed, implement — accepting both snake_case and camelCase values in:

  1. TypedDict inputs introduced in feat: generate TypedDict types for input-side models #738 (_typeddicts_generated.py, _typeddicts.py) — allow users to pass either naming style as keys.
  2. Literal arguments already present across resource clients (e.g. sort_by, pricing-model literals, webhook event-type literals, etc.) — accept both forms.

Trade-offs to weigh

  • Pro snake_case only: consistent with Pydantic models and the rest of the Python code; idiomatic for Python users.
  • Pro camelCase only: matches the API 1:1 — users who already know the API don't need a translation table, which is especially valuable for the "I don't want to import the Pydantic model, just pass a dict" use case.
  • Pro accepting both: maximum ergonomics, no wrong answer for the user; cost is implementation complexity (normalization layer) and documentation/typing clarity (both forms must be reflected in the type hints so the type checker accepts them).

Scope

  • Decide on the policy (one style only vs. both accepted).
  • If accepting both: define normalization boundary (input translation to API payload), update generation scripts (scripts/postprocess_generated_models.py) and the hand-written literals in resource clients, and ensure type checkers (ty) see both forms.
  • Update docs/examples accordingly.

cc @janbuchar

Metadata

Metadata

Assignees

Labels

t-toolingIssues with this label are in the ownership of the tooling team.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions