Skip to content

feat: generate Literal type aliases instead of StrEnum classes#759

Draft
vdusek wants to merge 3 commits intomasterfrom
feat/literals-instead-of-enums
Draft

feat: generate Literal type aliases instead of StrEnum classes#759
vdusek wants to merge 3 commits intomasterfrom
feat/literals-instead-of-enums

Conversation

@vdusek
Copy link
Copy Markdown
Contributor

@vdusek vdusek commented Apr 23, 2026

Summary

Closes #576.

Rewrites every generated class X(StrEnum) in _models_generated.py into a reusable X: TypeAlias = Literal[...]. Users can now pass plain strings (status='RUNNING') instead of importing enum members, and the aliases can be reused across resource-client method signatures — matching how Crawlee and the Apify SDK already model these values, and avoiding footguns like #575 where mixing enum and string values caused subtle issues.

Approach

  • New convert_enums_to_literals step in scripts/postprocess_generated_models.py, slotted between deduplicate_error_type_enum and add_docs_group_decorators. AST-based: finds every top-level ClassDef whose bases include StrEnum, extracts string values in declaration order, replaces the class block with Name: TypeAlias = Literal[...]. Docstrings are preserved as trailing bare-strings.
  • Injects TypeAlias into from typing import ... if missing. from enum import StrEnum becomes unused and is removed by the existing ruff check --fix pass.
  • Two small refactors shared by the post-processing pipeline: _collapse_blank_lines (was duplicated in 4 places) and _ensure_typing_import (was duplicated in 2 places).
  • All 11 enums are now aliases: ActorJobStatus, ActorPermissionLevel, ErrorType, GeneralAccess, HttpMethod, RunOrigin, SourceCodeFileFormat, StorageOwnership, VersionSourceType, WebhookDispatchStatus, WebhookEventType.
  • Updated all internal consumers (_consts.py, _status_message_watcher.py, _resource_clients/actor.py) and tests that previously accessed enum members (.MEMBER / .MEMBER.value) to use the string literal values directly.
  • Docstrings in _resource_clients/actor_version*.py updated to reference 'SOURCE_FILES' etc. rather than VersionSourceType.SOURCE_FILES.

Breaking change

This is a deliberate breaking change tracked under the v3 milestone on #576. ActorJobStatus.RUNNING and similar enum-member access no longer exists — pass the plain string instead.

Rewrite every generated `class X(StrEnum)` into a reusable
`X: TypeAlias = Literal[...]` so users can pass plain strings and type
aliases can be shared across resource-client method signatures. Closes #576.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vdusek vdusek added adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. labels Apr 23, 2026
@vdusek vdusek self-assigned this Apr 23, 2026
@github-actions github-actions Bot added this to the 139th sprint - Tooling team milestone Apr 23, 2026
@github-actions github-actions Bot added the tested Temporary label used only programatically for some analytics. label Apr 23, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.41%. Comparing base (2fd66d0) to head (36b6927).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #759      +/-   ##
==========================================
- Coverage   95.66%   95.41%   -0.26%     
==========================================
  Files          48       49       +1     
  Lines        5218     4779     -439     
==========================================
- Hits         4992     4560     -432     
+ Misses        226      219       -7     
Flag Coverage Δ
integration 95.41% <100.00%> (-0.26%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

vdusek and others added 2 commits April 23, 2026 15:17
…_case API values

Split the 11 generated `Literal` type aliases out of `_models_generated.py`
into a new `_literals_generated.py` so downstream code can depend on the
literals without pulling in every Pydantic model. Rename the hand-maintained
`_types.py` to `_literals.py` to match. Convert camelCase literal values
(`'ownedByMe'`, `'sharedWithMe'`) to snake_case and emit a wire-format mapping
so the API still receives the camelCase form it expects.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`X = Literal[...]` is already recognized as a type alias by every Python
type checker, so the `: TypeAlias` annotation adds noise without adding
any semantic value. Drop it from the postprocess-generated aliases and
from the hand-maintained `TerminalActorJobStatus`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prefer using literal types over enums

2 participants