Skip to content

Fix specify-tags router filtering#558

Merged
koxudaxi merged 3 commits intomainfrom
issue-488-specify-tags
Apr 28, 2026
Merged

Fix specify-tags router filtering#558
koxudaxi merged 3 commits intomainfrom
issue-488-specify-tags

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Apr 28, 2026

Fixes: #488

Summary

  • Apply --specify-tags to modular router imports and generated router files for fresh output directories.
  • Preserve the existing partial router regeneration behavior when an existing main.py already has router includes.
  • Update CLI docs/prompt data and tests for filtered fresh generation.

Checks

  • tox -e py3.14
  • tox -e cli-docs -- --check
  • tox -e llms-txt -- --check
  • tox -e readme
  • tox -e fix
  • tox -e type
  • tox -e config-types
  • tox -e schema-docs -- --check

Summary by CodeRabbit

  • New Features

    • Enhanced the --specify-tags CLI option to generate or regenerate routers for a specified comma-separated tag list.
  • Bug Fixes

    • If no requested tags match available tags, the CLI exits with an error listing available tags and does not create the main output.
  • Documentation

    • Updated CLI docs/help to reflect the generate-or-regenerate wording for --specify-tags.
  • Tests

    • Added and refactored tests to validate tag-based generation, exclusion of non-selected tags, and the no-match error case.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b2824855-0b9c-415a-9216-84dad10f8cd6

📥 Commits

Reviewing files that changed from the base of the PR and between 51df2aa and 5c21673.

📒 Files selected for processing (2)
  • fastapi_code_generator/cli.py
  • tests/main/test_main.py

Walkthrough

CLI tag-filtering was implemented to select which routers are generated or regenerated based on a comma-separated --specify-tags list. The CLI now builds (router, tag) pairs, optionally filters them after inspecting output_dir/main.py, errors if no tags match, and related docs and tests were updated.

Changes

Cohort / File(s) Summary
Documentation & Prompt
docs/cli-reference.md, docs/llms-full.txt, fastapi_code_generator/prompt_data.py
Updated --specify-tags wording from “Regenerate only …” to “Generate or regenerate only …” to match actual behavior.
CLI Tag Filtering Logic
fastapi_code_generator/cli.py
Builds deduplicated, case-insensitive (router, tag) pairs from OpenAPI operation tags; parses --specify-tags to a set; reads output_dir/main.py for app.include_router presence; filters pairs when appropriate; raises a ClickException if no requested tags match available tags; uses filtered pairs for main.py and per-router template rendering.
Tests: tag selection & error paths
tests/main/test_main.py
Refactored tag-specific tests to assert exit codes and validate generated main.py imports, app.include_router(...) calls, presence/absence of router module files, and code validation. Added a negative test for “no matching tag” that asserts exit code 1 and exact error text.

Sequence Diagram(s)

sequenceDiagram
  participant User as User (CLI)
  participant CLI as fastapi_code_generator/cli.py
  participant FS as File System (output_dir)
  participant Templ as Template Renderer

  User->>CLI: invoke with --generate-routers --specify-tags "TagA,TagB"
  CLI->>FS: read OpenAPI spec (operation tags)
  CLI->>CLI: build deduplicated (router, tag) pairs
  CLI->>FS: read output_dir/main.py (check for "app.include_router")
  CLI->>CLI: parse specified_tags set
  alt main.py lacks includes and specified_tags present
    CLI->>CLI: filter (router, tag) pairs by specified_tags
    alt no matches
      CLI-->>User: raise ClickException (exit 1) with requested vs available tags
    end
  end
  CLI->>Templ: render main.py with selected routers/tags
  Templ->>FS: write main.py
  loop for each selected (router, tag)
    CLI->>Templ: render router module for tag
    Templ->>FS: write router module file
  end
  CLI-->>User: exit 0 (success)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through tags both near and far,
Paired routers with names like a tiny star,
Now you list a few and only they spring,
Quiet files bloom — tidy routing in spring.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix specify-tags router filtering' directly addresses the main change, which fixes the --specify-tags option to properly filter routers by tag.
Linked Issues check ✅ Passed The PR implements filtering of routers by tag when --specify-tags is used, ensuring only requested tags' routers are generated, which directly satisfies issue #488 requirements.
Out of Scope Changes check ✅ Passed All changes are focused on implementing the --specify-tags filtering functionality: CLI documentation updates, core filtering logic, and related test coverage are all in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-488-specify-tags

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

📚 Docs Preview: https://pr-558.fastapi-code-generator.pages.dev

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 28, 2026

Merging this PR will not alter performance

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

✅ 1 untouched benchmark


Comparing issue-488-specify-tags (5c21673) with main (e9f2965)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (e9f2965) to head (5c21673).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #558   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           17        17           
  Lines         1204      1231   +27     
  Branches       126       128    +2     
=========================================
+ Hits          1204      1231   +27     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fastapi_code_generator/cli.py (1)

278-283: ⚠️ Potential issue | 🟠 Major

Router/tag pairing can become incorrect due to independent sorting.

At Line 279 and Line 282, router names and tags are sorted separately and then zipped. If normalization changes ordering, routers can be paired with the wrong tags, causing wrong files to be regenerated for selected tags.

Suggested fix
-    sorted_tags = sorted(set(all_tags), key=lambda x: x.lower())
-    routers = sorted(
-        [re.sub(TITLE_PATTERN, '_', tag.strip()).lower() for tag in sorted_tags]
-    )
-    router_tag_pairs = list(zip(routers, sorted_tags))
+    sorted_tags = sorted(set(all_tags), key=lambda x: x.lower())
+    router_tag_pairs: list[tuple[str, str]] = []
+    seen_router_to_tag: dict[str, str] = {}
+    for tag in sorted_tags:
+        router = re.sub(TITLE_PATTERN, "_", tag.strip()).lower()
+        prev = seen_router_to_tag.get(router)
+        if prev is not None and prev != tag:
+            raise ClickException(
+                f"Tag name collision after router normalization: {prev!r} and {tag!r} -> {router!r}"
+            )
+        seen_router_to_tag[router] = tag
+        router_tag_pairs.append((router, tag))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fastapi_code_generator/cli.py` around lines 278 - 283, The current code sorts
tags into sorted_tags then independently computes and sorts routers, which can
change order and break the router_tag_pairs mapping; instead derive routers
directly from sorted_tags in the same order (use the normalized form via
TITLE_PATTERN on each tag in sorted_tags) and then zip those routers with
sorted_tags to build router_tag_pairs, removing the separate sorting of the
router list so the pairing remains correct.
🧹 Nitpick comments (1)
tests/main/test_main.py (1)

684-690: Add app.include_router(...) assertions in this scenario too.

This test currently verifies imports and files but not router inclusion calls. A missing include_router regression in main.py could slip through here.

Suggested assertion additions
     main_text = output_dir.joinpath("main.py").read_text(encoding="utf-8")
     assert "from .routers import fat_cats, wild_boars" in main_text
+    assert "app.include_router(fat_cats.router)" in main_text
+    assert "app.include_router(wild_boars.router)" in main_text
     assert "slim_dogs" not in main_text
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/main/test_main.py` around lines 684 - 690, The test reads main.py into
main_text and checks imports and existence of router files but not that those
routers are actually mounted; add assertions that main_text includes the
include_router calls (e.g., check for "app.include_router(fat_cats.router" and
"app.include_router(wild_boars.router" and that it does NOT include "slim_dogs"
include_router) so that main.py both imports and calls app.include_router for
fat_cats and wild_boars; place these assertions near the existing import/file
assertions that reference main_text and the routers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fastapi_code_generator/cli.py`:
- Around line 294-303: If specified_tags is provided but filtering yields an
empty main_router_tag_pairs, fail fast with a clear error instead of proceeding
to set routers/tags to empty and rendering invalid main.py; detect this after
computing main_router_tag_pairs (the tuple list produced from router_tag_pairs
when specified_tags and not existing_main_has_router_includes) and raise/exit
with a descriptive message referencing the provided specified_tags and that no
routers matched, so the caller can correct the tag list before template
rendering that uses template_vars["routers"] and template_vars["tags"].

---

Outside diff comments:
In `@fastapi_code_generator/cli.py`:
- Around line 278-283: The current code sorts tags into sorted_tags then
independently computes and sorts routers, which can change order and break the
router_tag_pairs mapping; instead derive routers directly from sorted_tags in
the same order (use the normalized form via TITLE_PATTERN on each tag in
sorted_tags) and then zip those routers with sorted_tags to build
router_tag_pairs, removing the separate sorting of the router list so the
pairing remains correct.

---

Nitpick comments:
In `@tests/main/test_main.py`:
- Around line 684-690: The test reads main.py into main_text and checks imports
and existence of router files but not that those routers are actually mounted;
add assertions that main_text includes the include_router calls (e.g., check for
"app.include_router(fat_cats.router" and "app.include_router(wild_boars.router"
and that it does NOT include "slim_dogs" include_router) so that main.py both
imports and calls app.include_router for fat_cats and wild_boars; place these
assertions near the existing import/file assertions that reference main_text and
the routers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cee315bd-06b3-4f7a-b74a-d57a80ba8187

📥 Commits

Reviewing files that changed from the base of the PR and between e9f2965 and cd286d9.

📒 Files selected for processing (5)
  • docs/cli-reference.md
  • docs/llms-full.txt
  • fastapi_code_generator/cli.py
  • fastapi_code_generator/prompt_data.py
  • tests/main/test_main.py

Comment thread fastapi_code_generator/cli.py
@koxudaxi koxudaxi marked this pull request as ready for review April 28, 2026 03:05
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/main/test_main.py (1)

643-651: Consider extracting repeated router-assertion checks into a helper.

These two blocks are effectively identical; factoring them into a shared assertion helper would reduce maintenance overhead for future message/import/order changes.

Also applies to: 684-692

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/main/test_main.py` around lines 643 - 651, The test repeats assertions
checking router imports/usage and file existence (main_text, app.include_router,
routers/fat_cats.py, routers/wild_boars.py, routers/slim_dogs.py,
validate_generated_code); extract those checks into a small helper (e.g.,
assert_routers_present(output_dir, main_text, expected_present,
expected_absent)) that asserts the import lines, include_router calls,
existence/non-existence of files, and calls validate_generated_code, then
replace both identical blocks with calls to this helper to reduce duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fastapi_code_generator/cli.py`:
- Line 280: The zip call that creates router_tag_pairs uses zip(routers,
sorted_tags) without the strict argument, which Ruff B905 flags; update the call
in the CLI code where router_tag_pairs is created (variable router_tag_pairs,
using inputs routers and sorted_tags) to use zip(..., strict=True) so mismatched
lengths would raise immediately.

---

Nitpick comments:
In `@tests/main/test_main.py`:
- Around line 643-651: The test repeats assertions checking router imports/usage
and file existence (main_text, app.include_router, routers/fat_cats.py,
routers/wild_boars.py, routers/slim_dogs.py, validate_generated_code); extract
those checks into a small helper (e.g., assert_routers_present(output_dir,
main_text, expected_present, expected_absent)) that asserts the import lines,
include_router calls, existence/non-existence of files, and calls
validate_generated_code, then replace both identical blocks with calls to this
helper to reduce duplication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9aa00851-6678-4304-95b6-ae00f8fc4925

📥 Commits

Reviewing files that changed from the base of the PR and between cd286d9 and 51df2aa.

📒 Files selected for processing (2)
  • fastapi_code_generator/cli.py
  • tests/main/test_main.py

Comment thread fastapi_code_generator/cli.py Outdated
@koxudaxi koxudaxi merged commit 2390c55 into main Apr 28, 2026
44 checks passed
@koxudaxi koxudaxi deleted the issue-488-specify-tags branch April 28, 2026 05:02
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: No breaking changes detected

Reasoning: The breaking-change label is absent, so this PR is treated as a non-breaking release update.


This analysis was performed by repository automation using PR labels and the ## Breaking Changes section.

@github-actions github-actions Bot added the breaking-change-analyzed PR has been checked for release draft updates label Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change-analyzed PR has been checked for release draft updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--specify-tags not working

1 participant