Conversation
Teach the Python generator to account for existing source-group rules so custom targets keep ownership of their sources while stale files are pruned and dependencies are resolved.
Preserving existing py_library/py_test targets introduced three defects, each covered by a new testdata case. Sources listed by a preserved target were pruned unless Gazelle itself would have generated them, but that set excludes files hidden by python_ignore_files, gazelle:exclude, and subdirectories in per-package mode. Since srcs is mergeable, those sources were deleted from the user's BUILD file even though they exist on disk. Pruning now keys off whether the file exists; membership in the managed set only decides whether the rule is adopted at all, so a rule built entirely from ignored sources stays untouched as before. A preserved target with a single source does not claim it, so appendPyLibrary saw the same file twice and extracted its main module into two identical py_binary targets, which Gazelle rejected with "multiple rules found with label". Main modules are now extracted once per source file. Extracting a main module in per-file mode also removed __init__.py from the target, on the assumption that the caller had just added it via python_generation_mode_per_file_include_init. For a preserved target that had listed __init__.py by hand this emptied its srcs and deleted it. Whether __init__.py was auto-included is now passed explicitly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ests collectExistingPythonSourceRules never returns a rule with empty srcs, and nothing mutates a preserved py_test's srcs between collection and use, so the branch emitting an empty rule could not be reached. A preserved test whose sources have all disappeared is not collected in the first place, and getRulesWithInvalidSrcs already deletes it. Removing the branch leaves existingPythonSourceRule.kind unread. The field was also misleading: it held the canonical kind rather than the kind written in the BUILD file, so under map_kind the empty rule it built would not have matched the rule it was meant to delete. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…t mode The comment claimed the __init__ target matches the generated project package, but that target is named after the package. __init__ is preserved like any other hand-written target; it appears unchanged because project mode makes it claim __init__.py and regenerating it yields identical content. The old wording implied name-matching targets are left alone, which is the opposite of what happens: they are the ones excluded from preservation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records the review findings for the py_library/py_test preservation feature that are not addressed on this branch, with line references, the mechanism that makes each one reachable, and the decisions already taken so they are not relitigated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Preserved source targets could gain visibility, collide with generated targets, retain stale dependencies after main-module extraction, or be incorrectly claimed or deleted for edge-case source sets. Exclude targets Gazelle must generate itself and sources requiring dedicated handling. Base claiming on declared sources, preserve visibility, and recompute dependencies after source extraction. Document the management semantics and cover the edge cases with integration fixtures.
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
Co-authored-by: Alex Martani <alexandre.martani@benchling.com>
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.
Gazelle now regenerates eligible hand-written
py_libraryandpy_testtargets in place while retaining custom target structure and non-managed attributes. This supports package-mode split layouts with aggregate or explicit source ownership, as well as file-mode packages with dedicated__init__.pyand sibling module targets. It avoids duplicate source ownership, preserves visibility and excluded-only targets, prunes stale sources and dependencies, and prevents duplicate generated binaries.A target name is reserved only when Gazelle actually emits a target with it, so a test-only package no longer reserves the package library name. Previously a hand-written test carrying that name was skipped for preservation and its sources were duplicated into a generated test target. Package-named libraries whose live sources are all hidden by directory exclusions are also left intact rather than mistaken for empty generated targets.
Source-less package-named umbrella targets are removed as stale by default, allowing dependencies to resolve directly to concrete source owners. Intentional source-less re-exports can opt out with
# keep. File-mode package targets no longer absorb sibling modules during regeneration, and visibility directives are normalized so trailing commas and whitespace cannot emit invalid empty labels.include_pytest_conftestannotations on multi-source tests are merged deterministically. Unset annotations no longer overwrite explicit values based on concurrent parse order, and conflicting explicit values produce an error.Documentation, unit tests, and integration fixtures protect target eligibility, split-package layouts, excluded source trees, generated-name reservation, main-module extraction, stale umbrella cleanup, file-mode package initialization, visibility normalization, and annotation behavior.