Skip to content

[VPEX][4/8] Add local-env formatting-preserving pyproject.toml merge#5827

Open
rugpanov wants to merge 4 commits into
dbconnect/03-constraintsfrom
dbconnect/04-merge
Open

[VPEX][4/8] Add local-env formatting-preserving pyproject.toml merge#5827
rugpanov wants to merge 4 commits into
dbconnect/03-constraintsfrom
dbconnect/04-merge

Conversation

@rugpanov

@rugpanov rugpanov commented Jul 3, 2026

Copy link
Copy Markdown

Context

PR 4 of 8 in the stacked databricks local-env python sync series (see #5823 for the full plan). Stacked on #5826 — review #5823, #5824, #5826 first; this PR's diff is only merge.go + its test.

This is the trickiest self-contained logic in the feature, which is why it gets its own PR.

What this PR contains

merge.go — a formatting-preserving pyproject.toml merge. It rewrites only the env-owned sections and preserves every other byte (comments, ordering, whitespace, CRLF). It updates requires-python and the databricks-connect pin in place and maintains a marker-bracketed managed [tool.uv] constraint block. The merge is idempotent — feeding its own output back in is byte-identical. RenderFreshPyproject produces a complete managed file for a greenfield project.

Two properties worth close review

Both are covered by tests that parse the result as TOML rather than asserting on substrings:

  1. No duplicate table header. When the user's pyproject.toml already has a [tool.uv] table with a non-constraint key, the managed constraint-dependencies nests header-less inside that table rather than emitting a second [tool.uv] header — two headers for one table is invalid TOML that uv rejects.
  2. Robust single- vs multi-line array detection. Detection tracks real bracket depth outside strings and comments (bracketDepthDelta), so an opening line containing a ] inside an element (e.g. "requests[security]~=2.0") or a trailing comment is not misread as single-line and mis-stripped.

Dependencies & surface

Depends on the constraints PR (#5826) for the Constraints type. Still dormant — nothing imports the package yet.

This pull request and its description were written by Isaac.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

Could not determine reviewers from git history.
Round-robin suggestion: @renaudhartert-db

Eligible reviewers: @andrewnester, @anton-107, @denik, @janniklasrose, @pietern, @renaudhartert-db, @shreyas-goenka, @simonfaltum

Suggestions based on git history. See OWNERS for ownership rules.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 79113e4

Run: 28679377607

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 7 14 230 1045 4:15
💚​ aws windows 7 14 232 1043 3:59
💚​ aws-ucws linux 7 14 314 963 5:23
💚​ aws-ucws windows 7 14 316 961 4:04
💚​ azure linux 4 15 230 1044 4:08
💚​ azure windows 4 15 232 1042 4:02
💚​ azure-ucws linux 4 15 316 960 5:14
💚​ azure-ucws windows 4 15 318 958 4:03
💚​ gcp linux 4 15 229 1046 4:04
💚​ gcp windows 4 15 231 1044 3:56
21 interesting tests: 14 SKIP, 7 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 💚​R 💚​R 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/replace_existing 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_projects/update_display_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 5 slowest tests (at least 2 minutes):
duration env testname
3:09 gcp windows TestAccept
3:06 azure-ucws windows TestAccept
3:06 azure windows TestAccept
3:04 aws windows TestAccept
3:00 aws-ucws windows TestAccept

@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from d867d1f to 64d8996 Compare July 3, 2026 13:20
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from ccc19f1 to 92f1dda Compare July 3, 2026 13:20
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 13:21 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 13:21 — with GitHub Actions Inactive
@rugpanov rugpanov changed the title Add dbconnect formatting-preserving pyproject.toml merge [VPEX][4/8] Add local-env formatting-preserving pyproject.toml merge Jul 3, 2026
@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from 64d8996 to 3fd0bfe Compare July 3, 2026 15:26
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from 92f1dda to b96bf8b Compare July 3, 2026 15:26
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:27 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:27 — with GitHub Actions Inactive
@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from 3fd0bfe to ce01647 Compare July 3, 2026 15:31
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from b96bf8b to 6477a4c Compare July 3, 2026 15:31
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:31 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:31 — with GitHub Actions Inactive
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from 6477a4c to f4cc1c7 Compare July 3, 2026 15:41
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:42 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 15:42 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 17:55 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 17:55 — with GitHub Actions Inactive
@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from 797c4ac to 03b4a2b Compare July 3, 2026 18:15
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from 56b496d to 7b23583 Compare July 3, 2026 18:15
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:15 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:15 — with GitHub Actions Inactive
@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from 03b4a2b to 7eaf270 Compare July 3, 2026 18:27
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from 7b23583 to a1644d9 Compare July 3, 2026 18:27
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:27 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 18:27 — with GitHub Actions Inactive
rugpanov added 4 commits July 3, 2026 21:13
Fourth in the stacked local-env series.

merge.go rewrites only the env-owned sections of a pyproject.toml and
preserves every other byte (comments, ordering, whitespace, CRLF). It
updates requires-python and the databricks-connect pin in place, and
maintains a marker-bracketed managed [tool.uv] constraint block. The
operation is idempotent: feeding its own output back in is byte-identical.
RenderFreshPyproject produces a complete managed file for a greenfield
project.

Two correctness properties this file has to get right, both covered by
tests that parse the result as TOML rather than asserting on strings:

- When the user's pyproject.toml already has a [tool.uv] table with a
  non-constraint key, the managed constraint-dependencies nests header-less
  inside that table instead of emitting a second [tool.uv] header (two
  headers for one table is invalid TOML that uv rejects).
- Single- vs multi-line constraint-dependencies detection tracks real
  bracket depth outside strings and comments, so an opening line that
  contains a "]" inside an element (e.g. "requests[security]~=2.0") or a
  trailing comment is not misread as single-line and mis-stripped.

Depends on the constraints PR for the Constraints type. Still dormant.

Co-authored-by: Isaac
Review of the merge layer found the databricks-connect rewrite was not scoped
to [dependency-groups].dev:

- It walked every line of [dependency-groups] and rewrote the first
  databricks-connect element found, so a pin in a sibling group (docs/test)
  was clobbered instead of the dev entry. It now locates the dev assignment
  and edits only within that array's line span.

- The single-line branch replaced the databricks-connect token anywhere on
  the dev line, including inside a trailing comment (user content). Replacement
  is now confined to the array portion (through its closing "]"); the trailing
  comment is preserved byte-for-byte.

- mergeRequiresPython replaced the whole line, dropping an inline comment such
  as `requires-python = ">=3.10" # maintained by platform team`. It now
  reattaches the trailing comment, honoring the byte-preservation contract for
  everything outside the managed value.

Adds tests for each: sibling-group untouched, comment not clobbered, inline
comment preserved.

Co-authored-by: Isaac
Round-2 review found the merge did not tolerate a trailing comment on a table
header line (e.g. "[project] # note"). Two consequences: mergeRequiresPython
could not find a commented [project] header (managed value silently not
updated), and worse, the [dependency-groups] end bound could run past a
commented sibling header, so a dev key in a following table was mistaken for
[dependency-groups].dev and rewritten.

tableHeaderRe now allows a trailing comment and a new headerName helper matches
a header by its bracketed name ignoring the comment; both the table lookup and
the [tool.uv] attachment check use it. Also documents that line endings are a
whole-file property (a CRLF-anywhere file is emitted entirely as CRLF), which
is faithful for real single-ending pyproject.toml files.

Co-authored-by: Isaac
…ldren

Round-3 review found tableHeaderRe did not match TOML array-of-tables headers
like "[[tool.uv.index]]". A [tool.uv] table's end bound therefore ran through
its [[tool.uv.index]] children, and the header-less managed constraint block
could be inserted inside the last index item instead of under [tool.uv],
producing wrong or invalid uv config.

tableHeaderRe now matches both "[...]" and "[[...]]"; headerName returns the
full "[[...]]" token so an array-of-tables header is never treated as the same
table as its "[...]" parent. Adds a merge test with a [[tool.uv.index]] child.

Co-authored-by: Isaac
@rugpanov rugpanov force-pushed the dbconnect/03-constraints branch from 7eaf270 to 79890ca Compare July 3, 2026 19:14
@rugpanov rugpanov force-pushed the dbconnect/04-merge branch from a1644d9 to 79113e4 Compare July 3, 2026 19:14
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 19:15 — with GitHub Actions Inactive
@rugpanov rugpanov temporarily deployed to test-trigger-is July 3, 2026 19:15 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants