python-package-folder 3.0.2__tar.gz → 3.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/PKG-INFO +1 -1
  2. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/subfolder_build.py +58 -0
  3. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_subfolder_build.py +105 -0
  4. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.copier-answers.yml +0 -0
  5. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.cursor/rules/general.mdc +0 -0
  6. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.cursor/rules/python.mdc +0 -0
  7. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.github/workflows/ci.yml +0 -0
  8. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.github/workflows/publish.yml +0 -0
  9. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.gitignore +0 -0
  10. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/.vscode/settings.json +0 -0
  11. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/LICENSE +0 -0
  12. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/Makefile +0 -0
  13. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/README.md +0 -0
  14. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/coverage.svg +0 -0
  15. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/development.md +0 -0
  16. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/installation.md +0 -0
  17. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/publishing.md +0 -0
  18. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/pyproject.toml +0 -0
  19. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/__init__.py +0 -0
  20. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/__main__.py +0 -0
  21. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/analyzer.py +0 -0
  22. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/finder.py +0 -0
  23. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/manager.py +0 -0
  24. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/publisher.py +0 -0
  25. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/py.typed +0 -0
  26. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/python_package_folder.py +0 -0
  27. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/types.py +0 -0
  28. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/utils.py +0 -0
  29. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/src/python_package_folder/version.py +0 -0
  30. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/conftest.py +0 -0
  31. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/some_globals.py +0 -0
  32. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/subfolder_to_build/README.md +0 -0
  33. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/subfolder_to_build/__init__.py +0 -0
  34. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/subfolder_to_build/some_function.py +0 -0
  35. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/subfolder_to_build/some_globals.py +0 -0
  36. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/utility_folder/_SS/some_superseded_file.py +0 -0
  37. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/folder_structure/utility_folder/some_utility.py +0 -0
  38. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_build_with_external_deps.py +0 -0
  39. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_linting.py +0 -0
  40. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_preserve_directory_structure.py +0 -0
  41. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_publisher.py +0 -0
  42. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_shared_subdirectory_imports.py +0 -0
  43. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_spreadsheet_creation_imports.py +0 -0
  44. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_third_party_dependencies.py +0 -0
  45. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_utils.py +0 -0
  46. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/test_version_manager.py +0 -0
  47. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/tests/tests.py +0 -0
  48. {python_package_folder-3.0.2 → python_package_folder-3.1.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-package-folder
3
- Version: 3.0.2
3
+ Version: 3.1.1
4
4
  Summary: Python package to automatically package and build a folder, fetching all relevant dependencies.
5
5
  Project-URL: Repository, https://github.com/alelom/python-package-folder
6
6
  Author-email: Alessio Lombardi <work@alelom.com>
@@ -140,7 +140,10 @@ class SubfolderBuildConfig:
140
140
  lines = content.split("\n")
141
141
  result = []
142
142
  in_hatch_build = False
143
+ in_hatch_build_section = False
144
+ in_sdist_section = False
143
145
  packages_set = False
146
+ only_include_set = False
144
147
 
145
148
  for line in lines:
146
149
  # Detect hatch build section
@@ -148,6 +151,10 @@ class SubfolderBuildConfig:
148
151
  in_hatch_build = True
149
152
  result.append(line)
150
153
  continue
154
+ elif line.strip().startswith("[tool.hatch.build]"):
155
+ in_hatch_build_section = True
156
+ result.append(line)
157
+ continue
151
158
  elif line.strip().startswith("[") and in_hatch_build:
152
159
  # End of hatch build section, add packages if not set
153
160
  if not packages_set and correct_packages_path:
@@ -155,6 +162,25 @@ class SubfolderBuildConfig:
155
162
  result.append(f"packages = [{packages_str}]")
156
163
  in_hatch_build = False
157
164
  result.append(line)
165
+ elif line.strip().startswith("[") and in_hatch_build_section:
166
+ # End of hatch build section
167
+ in_hatch_build_section = False
168
+ result.append(line)
169
+ elif line.strip().startswith("[tool.hatch.build.targets.sdist]"):
170
+ in_sdist_section = True
171
+ result.append(line)
172
+ continue
173
+ elif line.strip().startswith("[") and in_sdist_section:
174
+ # End of sdist section
175
+ in_sdist_section = False
176
+ result.append(line)
177
+ elif in_sdist_section:
178
+ # Track if only-include already exists
179
+ if re.match(r"^\s*only-include\s*=", line):
180
+ only_include_set = True
181
+ result.append(line)
182
+ elif in_hatch_build_section:
183
+ result.append(line)
158
184
  elif in_hatch_build:
159
185
  # Modify packages path if found
160
186
  if re.match(r"^\s*packages\s*=", line):
@@ -194,6 +220,22 @@ class SubfolderBuildConfig:
194
220
  packages_str = f'"{correct_packages_path}"'
195
221
  result.append(f"packages = [{packages_str}]")
196
222
 
223
+ # Use only-include for source distributions to ensure only the subfolder is included
224
+ # This prevents including files from the project root
225
+ if correct_packages_path and not only_include_set:
226
+ result.append("")
227
+ result.append("[tool.hatch.build.targets.sdist]")
228
+ # Include only the subfolder directory and necessary files
229
+ only_include_paths = [correct_packages_path]
230
+ # Also include pyproject.toml and README if they exist
231
+ only_include_paths.append("pyproject.toml")
232
+ only_include_paths.append("README.md")
233
+ only_include_paths.append("README.rst")
234
+ only_include_paths.append("README.txt")
235
+ only_include_paths.append("README")
236
+ only_include_str = ", ".join(f'"{p}"' for p in only_include_paths)
237
+ result.append(f"only-include = [{only_include_str}]")
238
+
197
239
  return "\n".join(result)
198
240
 
199
241
  def create_temp_pyproject(self) -> Path | None:
@@ -532,6 +574,22 @@ class SubfolderBuildConfig:
532
574
  packages_str = ", ".join(f'"{p}"' for p in package_dirs)
533
575
  result.append(f"packages = [{packages_str}]")
534
576
 
577
+ # Use only-include for source distributions to ensure only the subfolder is included
578
+ # This prevents including files from the project root
579
+ if package_dirs:
580
+ result.append("")
581
+ result.append("[tool.hatch.build.targets.sdist]")
582
+ # Include only the subfolder directory and necessary files
583
+ only_include_paths = [package_dirs[0]]
584
+ # Also include pyproject.toml and README if they exist
585
+ only_include_paths.append("pyproject.toml")
586
+ only_include_paths.append("README.md")
587
+ only_include_paths.append("README.rst")
588
+ only_include_paths.append("README.txt")
589
+ only_include_paths.append("README")
590
+ only_include_str = ", ".join(f'"{p}"' for p in only_include_paths)
591
+ result.append(f"only-include = [{only_include_str}]")
592
+
535
593
  # Add dependency group if specified
536
594
  if dependency_group:
537
595
  # Find where to insert dependency-groups section
@@ -675,6 +675,111 @@ class TestSubfolderBuildTemporaryPyprojectCreation:
675
675
  # Cleanup
676
676
  config.restore()
677
677
 
678
+ def test_file_exclusion_patterns_added(self, test_project_with_pyproject: Path) -> None:
679
+ """Test that file exclusion patterns are added to temporary pyproject.toml."""
680
+ project_root = test_project_with_pyproject
681
+ subfolder = project_root / "subfolder"
682
+
683
+ # Create various non-package files and directories that should be excluded
684
+ (project_root / ".cursor").mkdir()
685
+ (project_root / ".github").mkdir()
686
+ (project_root / ".vscode").mkdir()
687
+ (project_root / "data").mkdir()
688
+ (project_root / "docs").mkdir()
689
+ (project_root / "references").mkdir()
690
+ (project_root / "reports").mkdir()
691
+ (project_root / "scripts").mkdir()
692
+ (project_root / "tests").mkdir()
693
+ (project_root / "Dockerfile").write_text("# Dockerfile")
694
+ (project_root / ".gitignore").write_text("*.pyc")
695
+
696
+ # Ensure no pyproject.toml in subfolder
697
+ subfolder_pyproject = subfolder / "pyproject.toml"
698
+ if subfolder_pyproject.exists():
699
+ subfolder_pyproject.unlink()
700
+
701
+ config = SubfolderBuildConfig(
702
+ project_root=project_root,
703
+ src_dir=subfolder,
704
+ version="1.0.0",
705
+ package_name="test-package",
706
+ )
707
+
708
+ pyproject_path = config.create_temp_pyproject()
709
+
710
+ assert pyproject_path is not None
711
+ assert pyproject_path.exists()
712
+ content = pyproject_path.read_text()
713
+
714
+ # Verify [tool.hatch.build.targets.sdist] section exists
715
+ assert "[tool.hatch.build.targets.sdist]" in content
716
+
717
+ # Verify only-include is present
718
+ assert "only-include = [" in content
719
+
720
+ # Verify the subfolder is included
721
+ assert '"subfolder"' in content
722
+
723
+ # Verify necessary files are included
724
+ assert '"pyproject.toml"' in content
725
+ assert '"README.md"' in content
726
+
727
+ # Verify non-package directories are NOT explicitly included
728
+ assert '".cursor"' not in content or '".cursor"' not in content.split("only-include")[1]
729
+ assert '".github"' not in content or '".github"' not in content.split("only-include")[1]
730
+ assert '"data"' not in content or '"data"' not in content.split("only-include")[1]
731
+ assert '"docs"' not in content or '"docs"' not in content.split("only-include")[1]
732
+
733
+ # Cleanup
734
+ config.restore()
735
+
736
+ def test_file_exclusion_patterns_with_subfolder_pyproject(
737
+ self, test_project_with_pyproject: Path
738
+ ) -> None:
739
+ """Test that file exclusion patterns are added when subfolder has its own pyproject.toml."""
740
+ project_root = test_project_with_pyproject
741
+ subfolder = project_root / "subfolder"
742
+
743
+ # Create various non-package files that should be excluded
744
+ (project_root / ".cursor").mkdir()
745
+ (project_root / "data").mkdir()
746
+ (project_root / "docs").mkdir()
747
+
748
+ # Create pyproject.toml in subfolder
749
+ subfolder_pyproject_content = """[project]
750
+ name = "subfolder-package"
751
+ version = "1.0.0"
752
+ description = "Subfolder package"
753
+ """
754
+ (subfolder / "pyproject.toml").write_text(subfolder_pyproject_content)
755
+
756
+ config = SubfolderBuildConfig(
757
+ project_root=project_root,
758
+ src_dir=subfolder,
759
+ version="2.0.0", # Should be ignored since subfolder has its own
760
+ )
761
+
762
+ pyproject_path = config.create_temp_pyproject()
763
+
764
+ assert pyproject_path is not None
765
+ assert pyproject_path.exists()
766
+ content = pyproject_path.read_text()
767
+
768
+ # Verify [tool.hatch.build.targets.sdist] section exists
769
+ assert "[tool.hatch.build.targets.sdist]" in content
770
+
771
+ # Verify only-include is present
772
+ assert "only-include = [" in content
773
+
774
+ # Verify the subfolder is included
775
+ assert '"subfolder-package"' in content or '"subfolder"' in content
776
+
777
+ # Verify necessary files are included
778
+ assert '"pyproject.toml"' in content
779
+
780
+ # Cleanup
781
+ config.restore()
782
+
678
783
  def test_third_party_dependencies_added(self, test_project_with_pyproject: Path) -> None:
679
784
  """Test that third-party dependencies are added to temporary pyproject.toml."""
680
785
  project_root = test_project_with_pyproject