Skip to content

Commit 540c650

Browse files
committed
Refactor handling of [tool.python-package-folder] section in SubfolderBuildConfig
This commit enhances the logic for managing the [tool.python-package-folder] section in the configuration. It ensures that the section is correctly inserted or updated without creating duplicates. Additionally, new tests are added to verify the absence of duplicate sections and the presence of exclude-patterns, improving the robustness of the build configuration.
1 parent 84b0034 commit 540c650

File tree

2 files changed

+94
-27
lines changed

2 files changed

+94
-27
lines changed

src/python_package_folder/subfolder_build.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -694,44 +694,55 @@ def _modify_pyproject_string(
694694
# Usually after [dependency-groups] or at the end
695695
insert_index = len(result)
696696
tool_section_exists = False
697+
tool_section_start = -1
698+
tool_section_end = -1
699+
700+
# First, search specifically for [tool.python-package-folder]
697701
for i, line in enumerate(result):
698702
if line.strip() == "[tool.python-package-folder]":
699703
tool_section_exists = True
700-
insert_index = i
701-
break
702-
elif line.strip().startswith("[tool.") and i > 0:
703-
# Insert before other tool sections
704-
insert_index = i
704+
tool_section_start = i
705+
# Find end of section (next [section] or end of file)
706+
for j in range(i + 1, len(result)):
707+
if result[j].strip().startswith("["):
708+
tool_section_end = j
709+
break
710+
if tool_section_end == -1:
711+
tool_section_end = len(result)
705712
break
713+
714+
# If not found, find a good insertion point before other [tool.*] sections
715+
if not tool_section_exists:
716+
for i, line in enumerate(result):
717+
if line.strip().startswith("[tool.") and i > 0:
718+
# Insert before other tool sections
719+
insert_index = i
720+
break
706721

707722
# Format exclude patterns
708723
patterns_str = ", ".join(f'"{p}"' for p in exclude_patterns)
709-
exclude_lines = [
710-
"",
711-
"[tool.python-package-folder]",
712-
f'exclude-patterns = [{patterns_str}]',
713-
]
714724

715725
if tool_section_exists:
716-
# Replace or update existing section
717-
end_index = insert_index + 1
718-
while end_index < len(result) and not result[end_index].strip().startswith("["):
719-
end_index += 1
720-
# Check if exclude-patterns already exists
721-
has_exclude_patterns = any(
722-
"exclude-patterns" in result[i] for i in range(insert_index, end_index)
723-
)
724-
if has_exclude_patterns:
725-
# Update existing exclude-patterns line
726-
for i in range(insert_index, end_index):
727-
if "exclude-patterns" in result[i]:
728-
result[i] = f'exclude-patterns = [{patterns_str}]'
729-
break
730-
else:
731-
# Add exclude-patterns to existing section
732-
result.insert(end_index - 1, f'exclude-patterns = [{patterns_str}]')
726+
# Update existing section
727+
# Check if exclude-patterns already exists in the section
728+
has_exclude_patterns = False
729+
for i in range(tool_section_start + 1, tool_section_end):
730+
if "exclude-patterns" in result[i]:
731+
has_exclude_patterns = True
732+
# Update the existing line
733+
result[i] = f'exclude-patterns = [{patterns_str}]'
734+
break
735+
736+
if not has_exclude_patterns:
737+
# Add exclude-patterns to existing section (before the next section)
738+
result.insert(tool_section_end, f'exclude-patterns = [{patterns_str}]')
733739
else:
734740
# Insert new section
741+
exclude_lines = [
742+
"",
743+
"[tool.python-package-folder]",
744+
f'exclude-patterns = [{patterns_str}]',
745+
]
735746
result[insert_index:insert_index] = exclude_lines
736747

737748
return "\n".join(result)

tests/test_exclude_patterns.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,60 @@ def test_exclude_patterns_no_subfolder_toml(self, test_project_with_exclude_patt
211211
assert ".*_test.*" in content
212212
assert "sandbox" in content
213213

214+
# Verify there's only ONE [tool.python-package-folder] section (no duplicates)
215+
sections = [line for line in content.split("\n") if line.strip() == "[tool.python-package-folder]"]
216+
assert len(sections) == 1, f"Found {len(sections)} duplicate [tool.python-package-folder] sections"
217+
218+
config.restore()
219+
220+
def test_exclude_patterns_no_duplicate_section(self, tmp_path: Path) -> None:
221+
"""Test that exclude patterns don't create duplicate sections when original already has it."""
222+
project_root = tmp_path / "test_project"
223+
project_root.mkdir()
224+
225+
# Create pyproject.toml with existing [tool.python-package-folder] section
226+
pyproject_content = """[project]
227+
name = "test-package"
228+
version = "0.1.0"
229+
230+
[build-system]
231+
requires = ["hatchling"]
232+
build-backend = "hatchling.build"
233+
234+
[tool.hatch.build.targets.wheel]
235+
packages = ["src/test_package"]
236+
237+
[tool.python-package-folder]
238+
exclude-patterns = ["_SS", ".*_test.*"]
239+
240+
[tool.pylint.'TYPECHECK']
241+
generated-members = ["networkx.*"]
242+
"""
243+
(project_root / "pyproject.toml").write_text(pyproject_content)
244+
245+
# Create source directory
246+
src_dir = project_root / "src" / "test_package"
247+
src_dir.mkdir(parents=True)
248+
(src_dir / "__init__.py").write_text("")
249+
250+
config = SubfolderBuildConfig(
251+
project_root=project_root,
252+
src_dir=src_dir,
253+
package_name="test-package",
254+
version="1.0.0",
255+
)
256+
257+
# Create temporary pyproject.toml
258+
temp_pyproject = config.create_temp_pyproject()
259+
assert temp_pyproject is not None
260+
261+
# Check that there's only ONE [tool.python-package-folder] section
262+
content = temp_pyproject.read_text()
263+
sections = [line for line in content.split("\n") if line.strip() == "[tool.python-package-folder]"]
264+
assert len(sections) == 1, f"Found {len(sections)} duplicate [tool.python-package-folder] sections: {sections}"
265+
266+
# Verify exclude-patterns is present
267+
assert "exclude-patterns" in content
268+
assert "_SS" in content
269+
214270
config.restore()

0 commit comments

Comments
 (0)