Skip to content

Fix pyproject.toml formatting when appending alembic config #1684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kernmod
Copy link

@kernmod kernmod commented Jun 15, 2025

Description

This PR fixes issue #1679 where alembic init --template pyproject would concatenate sections without proper spacing when appending to an existing pyproject.toml file.

Problem: The [tool.alembic] section was appended directly after the last line of the existing content, resulting in invalid TOML:
[tool.mypy]
python_version = "3.10"[tool.alembic]

Solution: Modified _append_template method in ScriptDirectory to detect TOML files and ensure proper spacing (2 newlines) between top-level sections.

Result: Proper TOML formatting is maintained:

[tool.mypy]
python_version = "3.10"

[tool.alembic]
script_location = "%(here)s/alembic"


### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [ ] A documentation / typographical error fix
	- Good to go, no issue or tests are needed
- [ x] A short code fix
	- please include the issue number, and create an issue if none exists, which
	  must include a complete example of the issue.  one line code fixes without an
	  issue and demonstration will not be accepted.
	- Please include: `Fixes: #<issue number>` in the commit message
	- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
	- please include the issue number, and create an issue if none exists, which must
	  include a complete example of how the feature would look.
	- Please include: `Fixes: #<issue number>` in the commit message
	- please include tests.

**Have a nice day!**

- Modified _append_template to ensure proper TOML section spacing
- Added special handling for .toml files to insert two newlines between sections
- Added tests to prevent regression
- Fixes sqlalchemy#1679
Copy link
Member

@zzzeek zzzeek left a comment

Choose a reason for hiding this comment

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

we were ready to merge a quick one liner for this over at #1680 , which started out as more like this PR. I like that this PR has tests. If we are really going to try to check for a .toml file that already has trailing whitespace, vs. one that does not, it would need to be done non-intrusively and the append of the whitespace should be down with the template write.

# TOML convention: ensure 2 newlines between top-level sections
# The template should start with [tool.alembic], so we need proper spacing
if existing_content:
f.write('\n\n')
Copy link
Member

@zzzeek zzzeek Jun 16, 2025

Choose a reason for hiding this comment

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

OK but what if the template_to_file command fails? now we have two newlines that will keep getting bumped each time (although I guess the strip() and rewrite-the-whole-file approach fixes that, but I dont want to rewrite the whole file). Id rather this be all within one file.open() and once we have the output from the template

in #1680 we add the two newlines in the single open

existing_content = f.read()

# Check if we need to add newlines before appending
existing_content = existing_content.rstrip()
Copy link
Member

Choose a reason for hiding this comment

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

this is not really a "check", this just truncates what was there so that it can add two newlines unconditionally

if output_path.suffix.lower() == '.toml' and output_path.exists():
# Read existing content
with open(output_path, 'r', encoding=self.output_encoding) as f:
existing_content = f.read()
Copy link
Member

Choose a reason for hiding this comment

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

we've read the content here. Can we just look to see if it already ends with "\n\n" ? that's what we did originally at #1680 why rewrite the file


# TOML convention: ensure 2 newlines between top-level sections
# The template should start with [tool.alembic], so we need proper spacing
if existing_content:
Copy link
Member

Choose a reason for hiding this comment

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

why did we open and rewrite the file if no existing content?

from alembic.testing import TestBase


class TestPyprojectTemplate(TestBase):
Copy link
Member

Choose a reason for hiding this comment

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

good test but this should be in tests/test_command.py->CommandLineTest->test_init_file_pyproject_formatting , it should have four cases: one where there's no pyproject.toml, one where there's an empty pyproject.toml, one where there's an existing pyproject.toml with no trailing whitespace (maybe even a fifth test, where there's one trailing newline, not two), one where there's a pyproject.toml with existing trailing whitespace.

@zzzeek
Copy link
Member

zzzeek commented Jun 16, 2025

we already had #1680 in progress so I added a test and in its final form in d00e854 , since we were under pressure to get a fix out for this. up to you if you want to add a "conditional" element to it re: the newlines, or otherwise we can close this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

alembic init with pyproject template, and existing pyproject.toml, does not have a newline
2 participants