use_cases: add generic CRUD base classes and build-time generator#122
Merged
Conversation
absoludity
commented
Mar 25, 2026
Comment on lines
+200
to
+206
| def _imported_class_names(directory: Path) -> set[str]: | ||
| """Return names imported into any non-private file in directory. | ||
|
|
||
| Scans import statements (not class definitions) so that re-exported | ||
| Request/Response classes satisfy doctrine checks even when they are | ||
| defined outside the use_cases directory (e.g. in _generated/). | ||
| """ |
Collaborator
Author
There was a problem hiding this comment.
This change to the doctrine test was required as, once we have the generated classes, the actual call-sites were no longer needing to define the class but rather are just importing the generated one. With this change, the doctrine is satisfied if it's imported.
The introspector previously only detected Request/Response classes via AST class definitions. With build-time code generation, these classes may be defined in _generated/ and imported (with or without aliasing) into the use_cases files that re-export them. Augment _parse_bounded_context_cached to also scan import statements in use_cases files, collecting locally-bound names ending with Request or Response that are not already found as class definitions. UseCase imports are intentionally excluded — they appear as injected dependencies, not as definitions, so they must remain class-definition-only.
total_count is always len(entities) and is a near-universal convention in REST list responses. Including it in the generated base removes the need for hand-rolled subclasses solely to add this field.
8c1a0dd to
1ed5f91
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the generator infrastructure described in ADR 008 (revised in #121), with two small changes:
generic_crud.pyprovides four base classes —GetUseCase,ListUseCase,CreateUseCase,UpdateUseCase— plusEntityNotFoundError. Each base class holds the repository and implements the core logic (_get_by_id,_list_all,_create,_update_by_id). Generated subclasses are thin wrappers that declare typed Request/Response and call through.Change 1: I've added a
total_countto the response of the ListUseCase as it seemed generic enough and a downstream project was having to override the class to add it, which seemed superfluous.Change 2: Not related to the generator infrastructure, but rather updating a doctrine test - I'll comment inline.
generate_crud.pyis a CLI script that takes entity/repo metadata and emits acrud_{entity_snake}.pyfile into a specified.generated/directory. Uses f-string templates andruff format. Downstream projects add amake generate-crudtarget that invokes it; julee itself has no CRUD use cases to generate.Also fixes the remaining
pytestcalls in the Makefile that were missinguv run(same issue as theblack/rufffix on the previous branch).Closes #91 (partially — the generate step wiring is in downstream uses)