python-package-folder 3.0.1__py3-none-any.whl → 3.1.0__py3-none-any.whl

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.
@@ -339,6 +339,13 @@ class BuildManager:
339
339
  shutil.copy2(source, target)
340
340
  self.copied_files.append(target)
341
341
  print(f"Copied external file: {source} -> {target}")
342
+ # If copying a Python file, ensure parent directory has __init__.py
343
+ # This helps type checkers resolve imports correctly
344
+ if source.suffix == ".py" and target.parent != self.src_dir:
345
+ init_file = target.parent / "__init__.py"
346
+ if not init_file.exists():
347
+ init_file.write_text("", encoding="utf-8")
348
+ self.copied_files.append(init_file)
342
349
  elif source.is_dir():
343
350
  if target.exists():
344
351
  shutil.rmtree(target)
@@ -354,6 +361,8 @@ class BuildManager:
354
361
  Copy a directory tree, excluding certain patterns.
355
362
 
356
363
  Excludes directories matching patterns like _SS, __SS, _sandbox, etc.
364
+ Ensures __init__.py files exist in directories containing Python files
365
+ so that type checkers can resolve imports correctly.
357
366
 
358
367
  Args:
359
368
  src: Source directory
@@ -385,6 +394,9 @@ class BuildManager:
385
394
  # Create destination directory
386
395
  dst.mkdir(parents=True, exist_ok=True)
387
396
 
397
+ has_python_files = False
398
+ copied_python_files = []
399
+
388
400
  # Copy files and subdirectories, excluding patterns
389
401
  for item in src.iterdir():
390
402
  if should_exclude(item):
@@ -395,8 +407,39 @@ class BuildManager:
395
407
 
396
408
  if src_item.is_file():
397
409
  shutil.copy2(src_item, dst_item)
410
+ if src_item.suffix == ".py":
411
+ has_python_files = True
412
+ copied_python_files.append(dst_item)
398
413
  elif src_item.is_dir():
399
414
  self._copytree_excluding(src_item, dst_item)
415
+ # Check if the subdirectory has Python files
416
+ if any(dst_item.rglob("*.py")):
417
+ has_python_files = True
418
+
419
+ # Ensure __init__.py exists in directories containing Python files
420
+ # This is needed for type checkers to resolve imports correctly
421
+ # Also ensure all parent directories in the path have __init__.py
422
+ if has_python_files:
423
+ init_file = dst / "__init__.py"
424
+ if not init_file.exists():
425
+ # Create an empty __init__.py file
426
+ init_file.write_text("", encoding="utf-8")
427
+ self.copied_files.append(init_file)
428
+
429
+ # Ensure all parent directories up to src_dir also have __init__.py
430
+ # This helps type checkers resolve nested imports like:
431
+ # from empty_drawing_detection.models.Information_extraction._shared_ie.ie_enums import ...
432
+ current = dst
433
+ while current != self.src_dir and current.is_relative_to(self.src_dir):
434
+ parent_init = current.parent / "__init__.py"
435
+ if (
436
+ parent_init.parent != self.src_dir
437
+ and not parent_init.exists()
438
+ and any(current.parent.rglob("*.py"))
439
+ ):
440
+ parent_init.write_text("", encoding="utf-8")
441
+ self.copied_files.append(parent_init)
442
+ current = current.parent
400
443
 
401
444
  def _get_package_name_from_import(self, module_name: str) -> str | None:
402
445
  """
@@ -140,7 +140,9 @@ class SubfolderBuildConfig:
140
140
  lines = content.split("\n")
141
141
  result = []
142
142
  in_hatch_build = False
143
+ in_hatch_build_section = False
143
144
  packages_set = False
145
+ paths_exclude_set = False
144
146
 
145
147
  for line in lines:
146
148
  # Detect hatch build section
@@ -148,6 +150,10 @@ class SubfolderBuildConfig:
148
150
  in_hatch_build = True
149
151
  result.append(line)
150
152
  continue
153
+ elif line.strip().startswith("[tool.hatch.build]"):
154
+ in_hatch_build_section = True
155
+ result.append(line)
156
+ continue
151
157
  elif line.strip().startswith("[") and in_hatch_build:
152
158
  # End of hatch build section, add packages if not set
153
159
  if not packages_set and correct_packages_path:
@@ -155,6 +161,15 @@ class SubfolderBuildConfig:
155
161
  result.append(f"packages = [{packages_str}]")
156
162
  in_hatch_build = False
157
163
  result.append(line)
164
+ elif line.strip().startswith("[") and in_hatch_build_section:
165
+ # End of hatch build section
166
+ in_hatch_build_section = False
167
+ result.append(line)
168
+ elif in_hatch_build_section:
169
+ # Track if paths-exclude already exists
170
+ if re.match(r"^\s*paths-exclude\s*=", line):
171
+ paths_exclude_set = True
172
+ result.append(line)
158
173
  elif in_hatch_build:
159
174
  # Modify packages path if found
160
175
  if re.match(r"^\s*packages\s*=", line):
@@ -194,6 +209,43 @@ class SubfolderBuildConfig:
194
209
  packages_str = f'"{correct_packages_path}"'
195
210
  result.append(f"packages = [{packages_str}]")
196
211
 
212
+ # Add file exclusion patterns to prevent including non-package files
213
+ # Only add if paths-exclude wasn't already set (we merged it above)
214
+ if not paths_exclude_set:
215
+ result.append("")
216
+ result.append("[tool.hatch.build]")
217
+ result.append("paths-exclude = [")
218
+ result.append(' ".cursor/**",')
219
+ result.append(' ".github/**",')
220
+ result.append(' ".vscode/**",')
221
+ result.append(' ".idea/**",')
222
+ result.append(' "data/**",')
223
+ result.append(' "docs/**",')
224
+ result.append(' "references/**",')
225
+ result.append(' "reports/**",')
226
+ result.append(' "scripts/**",')
227
+ result.append(' "tests/**",')
228
+ result.append(' "test/**",')
229
+ result.append(' "dist/**",')
230
+ result.append(' "build/**",')
231
+ result.append(' "*.egg-info/**",')
232
+ result.append(' "__pycache__/**",')
233
+ result.append(' ".pytest_cache/**",')
234
+ result.append(' ".mypy_cache/**",')
235
+ result.append(' ".venv/**",')
236
+ result.append(' "venv/**",')
237
+ result.append(' ".git/**",')
238
+ result.append(' ".gitignore",')
239
+ result.append(' ".gitattributes",')
240
+ result.append(' "Dockerfile",')
241
+ result.append(' ".dockerignore",')
242
+ result.append(' ".pylintrc",')
243
+ result.append(' "pyrightconfig.json",')
244
+ result.append(' "git-filter-repo",')
245
+ result.append(' "pyproject.toml.original",')
246
+ result.append(' "README.md.backup",')
247
+ result.append("]")
248
+
197
249
  return "\n".join(result)
198
250
 
199
251
  def create_temp_pyproject(self) -> Path | None:
@@ -532,6 +584,42 @@ class SubfolderBuildConfig:
532
584
  packages_str = ", ".join(f'"{p}"' for p in package_dirs)
533
585
  result.append(f"packages = [{packages_str}]")
534
586
 
587
+ # Add file exclusion patterns to prevent including non-package files
588
+ # This ensures only the subfolder code is included, not project root files
589
+ result.append("")
590
+ result.append("[tool.hatch.build]")
591
+ result.append("paths-exclude = [")
592
+ result.append(' ".cursor/**",')
593
+ result.append(' ".github/**",')
594
+ result.append(' ".vscode/**",')
595
+ result.append(' ".idea/**",')
596
+ result.append(' "data/**",')
597
+ result.append(' "docs/**",')
598
+ result.append(' "references/**",')
599
+ result.append(' "reports/**",')
600
+ result.append(' "scripts/**",')
601
+ result.append(' "tests/**",')
602
+ result.append(' "test/**",')
603
+ result.append(' "dist/**",')
604
+ result.append(' "build/**",')
605
+ result.append(' "*.egg-info/**",')
606
+ result.append(' "__pycache__/**",')
607
+ result.append(' ".pytest_cache/**",')
608
+ result.append(' ".mypy_cache/**",')
609
+ result.append(' ".venv/**",')
610
+ result.append(' "venv/**",')
611
+ result.append(' ".git/**",')
612
+ result.append(' ".gitignore",')
613
+ result.append(' ".gitattributes",')
614
+ result.append(' "Dockerfile",')
615
+ result.append(' ".dockerignore",')
616
+ result.append(' ".pylintrc",')
617
+ result.append(' "pyrightconfig.json",')
618
+ result.append(' "git-filter-repo",')
619
+ result.append(' "pyproject.toml.original",')
620
+ result.append(' "README.md.backup",')
621
+ result.append("]")
622
+
535
623
  # Add dependency group if specified
536
624
  if dependency_group:
537
625
  # Find where to insert dependency-groups section
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-package-folder
3
- Version: 3.0.1
3
+ Version: 3.1.0
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>
@@ -2,16 +2,16 @@ python_package_folder/__init__.py,sha256=DQt-uldOEKfh0MUqCvKdeNKOnpuOvpb7blYvXMy
2
2
  python_package_folder/__main__.py,sha256=a-__-VLhYw-J7S7CsHdhtEvQr3RiAZxiYDvKhKTgMX4,291
3
3
  python_package_folder/analyzer.py,sha256=cmTNUDCWBIh3XZ_mShlQVG1P9NN_oe3FUBTirVtYfTQ,16709
4
4
  python_package_folder/finder.py,sha256=RPidZ7LKCFuQ_KgCFIZdHWPXsZIDor3M4C0hKeYW7EI,11799
5
- python_package_folder/manager.py,sha256=L-NRTUd0q-qhhEXUCPcddRyR736-GpPf2gwznmnMWDs,41268
5
+ python_package_folder/manager.py,sha256=kyULmS948uW3yWUcabc2EVK_Nic3wrWMj8qCs18jj2Q,43526
6
6
  python_package_folder/publisher.py,sha256=TSjdOvxvnWLbJCnduTK_xZBRfvsrq9kpEH-sfebeWkU,13507
7
7
  python_package_folder/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  python_package_folder/python_package_folder.py,sha256=RPsqRcIy_LjzzTHdp4qdtFJ4-4xhtR_0YLIC0RlUxFo,8841
9
- python_package_folder/subfolder_build.py,sha256=VDWgrXgUa7qTXl2Sjbn7vEqbo8vP_aHtHPiUIGfqvug,35862
9
+ python_package_folder/subfolder_build.py,sha256=m9a7exvDEwtz_tuNlPF_bagXtcwNq9PHiJswVkbn2PM,39866
10
10
  python_package_folder/types.py,sha256=3yeSRR5p_3PDKEAaehW_RJ7NwJHexOIeA08bGaT1iSY,2368
11
11
  python_package_folder/utils.py,sha256=lIkWsFKeAYAJ9TDUM99T4pUBHJVbUvCdUgkWQN-LUho,3111
12
12
  python_package_folder/version.py,sha256=kIDP6S9trEfs9gj7lBYGxrWm4RPssRla24UtlO9Jkh4,9111
13
- python_package_folder-3.0.1.dist-info/METADATA,sha256=8vHC065eFngdamxOli4Ss6n2ydvAalypii38vxdeYf8,33282
14
- python_package_folder-3.0.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
- python_package_folder-3.0.1.dist-info/entry_points.txt,sha256=ttu4wAhoYSHGhWQNercLz9IVTTpXxhVlRA9vSTvaLe0,91
16
- python_package_folder-3.0.1.dist-info/licenses/LICENSE,sha256=vNgRJh8YiecqZoZld7TtwPI5I72HIymKD9g32fiJjCE,1073
17
- python_package_folder-3.0.1.dist-info/RECORD,,
13
+ python_package_folder-3.1.0.dist-info/METADATA,sha256=qNQ9k_yP2w7Tyxo6F8btfZRCckzheWU4HN78ETtGpaY,33282
14
+ python_package_folder-3.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
+ python_package_folder-3.1.0.dist-info/entry_points.txt,sha256=ttu4wAhoYSHGhWQNercLz9IVTTpXxhVlRA9vSTvaLe0,91
16
+ python_package_folder-3.1.0.dist-info/licenses/LICENSE,sha256=vNgRJh8YiecqZoZld7TtwPI5I72HIymKD9g32fiJjCE,1073
17
+ python_package_folder-3.1.0.dist-info/RECORD,,