python-fsutil 0.15.0__tar.gz → 0.16.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 (39) hide show
  1. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/MANIFEST.in +2 -1
  2. {python_fsutil-0.15.0/python_fsutil.egg-info → python_fsutil-0.16.1}/PKG-INFO +7 -6
  3. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/README.md +3 -4
  4. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/pyproject.toml +10 -3
  5. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/io.py +7 -7
  6. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/metadata.py +1 -1
  7. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/operations.py +4 -0
  8. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src/python_fsutil.egg-info}/PKG-INFO +7 -6
  9. python_fsutil-0.16.1/src/python_fsutil.egg-info/SOURCES.txt +36 -0
  10. python_fsutil-0.16.1/tests/__init__.py +0 -0
  11. python_fsutil-0.16.1/tests/conftest.py +15 -0
  12. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_operations.py +18 -0
  13. python_fsutil-0.15.0/python_fsutil.egg-info/SOURCES.txt +0 -34
  14. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/LICENSE.txt +0 -0
  15. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/setup.cfg +0 -0
  16. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/setup.py +0 -0
  17. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/__init__.py +0 -0
  18. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/archives.py +0 -0
  19. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/args.py +0 -0
  20. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/checks.py +0 -0
  21. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/converters.py +0 -0
  22. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/deps.py +0 -0
  23. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/info.py +0 -0
  24. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/paths.py +0 -0
  25. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/perms.py +0 -0
  26. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/py.typed +0 -0
  27. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/fsutil/types.py +0 -0
  28. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/python_fsutil.egg-info/dependency_links.txt +0 -0
  29. {python_fsutil-0.15.0 → python_fsutil-0.16.1/src}/python_fsutil.egg-info/top_level.txt +0 -0
  30. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_archives.py +0 -0
  31. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_args.py +0 -0
  32. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_checks.py +0 -0
  33. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_converters.py +0 -0
  34. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_deps.py +0 -0
  35. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_info.py +0 -0
  36. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_io.py +0 -0
  37. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_metadata.py +0 -0
  38. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_paths.py +0 -0
  39. {python_fsutil-0.15.0 → python_fsutil-0.16.1}/tests/test_perms.py +0 -0
@@ -1,4 +1,5 @@
1
1
  include LICENSE.txt
2
2
  include README.md
3
- recursive-include fsutil *
3
+ recursive-include src *
4
+ recursive-include tests *
4
5
  recursive-exclude * *.pyc __pycache__ .DS_Store
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: python-fsutil
3
- Version: 0.15.0
3
+ Version: 0.16.1
4
4
  Summary: high-level file-system operations for lazy devs.
5
5
  Author-email: Fabio Caccamo <fabio.caccamo@gmail.com>
6
6
  Maintainer-email: Fabio Caccamo <fabio.caccamo@gmail.com>
@@ -46,6 +46,7 @@ Classifier: Programming Language :: Python :: 3.10
46
46
  Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
48
  Classifier: Programming Language :: Python :: 3.13
49
+ Classifier: Programming Language :: Python :: 3.14
49
50
  Classifier: Programming Language :: Python :: Implementation :: PyPy
50
51
  Classifier: Topic :: Desktop Environment :: File Managers
51
52
  Classifier: Topic :: Software Development :: Build Tools
@@ -54,6 +55,7 @@ Classifier: Topic :: System :: Filesystems
54
55
  Classifier: Topic :: Utilities
55
56
  Description-Content-Type: text/markdown
56
57
  License-File: LICENSE.txt
58
+ Dynamic: license-file
57
59
 
58
60
  [![](https://img.shields.io/pypi/pyversions/python-fsutil.svg?color=blue&logo=python&logoColor=white)](https://www.python.org/)
59
61
  [![](https://img.shields.io/pypi/v/python-fsutil.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/python-fsutil/)
@@ -65,7 +67,6 @@ License-File: LICENSE.txt
65
67
  [![](https://img.shields.io/github/actions/workflow/status/fabiocaccamo/python-fsutil/test-package.yml?branch=main&label=build&logo=github)](https://github.com/fabiocaccamo/python-fsutil)
66
68
  [![](https://img.shields.io/codecov/c/gh/fabiocaccamo/python-fsutil?logo=codecov)](https://codecov.io/gh/fabiocaccamo/python-fsutil)
67
69
  [![](https://img.shields.io/codacy/grade/fc40788ae7d74d1fb34a38934113c4e5?logo=codacy)](https://www.codacy.com/app/fabiocaccamo/python-fsutil)
68
- [![](https://img.shields.io/codeclimate/maintainability/fabiocaccamo/python-fsutil?logo=code-climate)](https://codeclimate.com/github/fabiocaccamo/python-fsutil/)
69
70
  [![](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&logoColor=black)](https://github.com/psf/black)
70
71
  [![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
71
72
 
@@ -825,8 +826,8 @@ pre-commit install --install-hooks
825
826
  # run tests using tox
826
827
  tox
827
828
 
828
- # or run tests using unittest
829
- python -m unittest
829
+ # or run tests using pytest
830
+ pytest
830
831
  ```
831
832
 
832
833
  ## License
@@ -838,7 +839,7 @@ Released under [MIT License](LICENSE.txt).
838
839
 
839
840
  - :star: Star this project on [GitHub](https://github.com/fabiocaccamo/python-fsutil)
840
841
  - :octocat: Follow me on [GitHub](https://github.com/fabiocaccamo)
841
- - :blue_heart: Follow me on [Twitter](https://twitter.com/fabiocaccamo)
842
+ - :blue_heart: Follow me on [Bluesky](https://bsky.app/profile/fabiocaccamo.bsky.social)
842
843
  - :moneybag: Sponsor me on [Github](https://github.com/sponsors/fabiocaccamo)
843
844
 
844
845
  ## See also
@@ -8,7 +8,6 @@
8
8
  [![](https://img.shields.io/github/actions/workflow/status/fabiocaccamo/python-fsutil/test-package.yml?branch=main&label=build&logo=github)](https://github.com/fabiocaccamo/python-fsutil)
9
9
  [![](https://img.shields.io/codecov/c/gh/fabiocaccamo/python-fsutil?logo=codecov)](https://codecov.io/gh/fabiocaccamo/python-fsutil)
10
10
  [![](https://img.shields.io/codacy/grade/fc40788ae7d74d1fb34a38934113c4e5?logo=codacy)](https://www.codacy.com/app/fabiocaccamo/python-fsutil)
11
- [![](https://img.shields.io/codeclimate/maintainability/fabiocaccamo/python-fsutil?logo=code-climate)](https://codeclimate.com/github/fabiocaccamo/python-fsutil/)
12
11
  [![](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&logoColor=black)](https://github.com/psf/black)
13
12
  [![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
14
13
 
@@ -768,8 +767,8 @@ pre-commit install --install-hooks
768
767
  # run tests using tox
769
768
  tox
770
769
 
771
- # or run tests using unittest
772
- python -m unittest
770
+ # or run tests using pytest
771
+ pytest
773
772
  ```
774
773
 
775
774
  ## License
@@ -781,7 +780,7 @@ Released under [MIT License](LICENSE.txt).
781
780
 
782
781
  - :star: Star this project on [GitHub](https://github.com/fabiocaccamo/python-fsutil)
783
782
  - :octocat: Follow me on [GitHub](https://github.com/fabiocaccamo)
784
- - :blue_heart: Follow me on [Twitter](https://twitter.com/fabiocaccamo)
783
+ - :blue_heart: Follow me on [Bluesky](https://bsky.app/profile/fabiocaccamo.bsky.social)
785
784
  - :moneybag: Sponsor me on [Github](https://github.com/sponsors/fabiocaccamo)
786
785
 
787
786
  ## See also
@@ -38,6 +38,7 @@ classifiers = [
38
38
  "Programming Language :: Python :: 3.11",
39
39
  "Programming Language :: Python :: 3.12",
40
40
  "Programming Language :: Python :: 3.13",
41
+ "Programming Language :: Python :: 3.14",
41
42
  "Programming Language :: Python :: Implementation :: PyPy",
42
43
  "Topic :: Desktop Environment :: File Managers",
43
44
  "Topic :: Software Development :: Build Tools",
@@ -85,13 +86,18 @@ exclude = '''
85
86
  '''
86
87
 
87
88
  [tool.mypy]
88
- files = ["fsutil"]
89
+ files = ["src"]
89
90
  disable_error_code = "import-untyped"
90
91
  ignore_missing_imports = true
91
92
  install_types = true
92
93
  non_interactive = true
93
94
  strict = true
94
95
 
96
+ [tool.pytest.ini_options]
97
+ pythonpath = "src"
98
+ addopts = "-v"
99
+ testpaths = ["tests"]
100
+
95
101
  [tool.ruff]
96
102
  line-length = 88
97
103
 
@@ -102,8 +108,9 @@ select = ["B", "B9", "C", "E", "F", "I", "W"]
102
108
  [tool.ruff.lint.mccabe]
103
109
  max-complexity = 10
104
110
 
105
- [tool.setuptools.packages.find]
106
- include = ["fsutil*"]
111
+ [tool.setuptools]
112
+ package-dir = {"" = "src"}
113
+ packages = ["fsutil"]
107
114
 
108
115
  [tool.setuptools.dynamic.version]
109
116
  attr = "fsutil.metadata.__version__"
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import os
5
- import platform
6
5
  import tempfile
7
6
  from collections.abc import Generator
8
7
  from datetime import datetime
@@ -137,12 +136,12 @@ def _write_file_atomic(
137
136
  if append:
138
137
  content = read_file(path, encoding=encoding) + content
139
138
  dirpath, _ = split_filepath(path)
140
- auto_delete_temp_file = False if platform.system() == "Windows" else True
139
+ temp_path = None
141
140
  try:
142
141
  with tempfile.NamedTemporaryFile(
143
142
  mode=mode,
144
143
  dir=dirpath,
145
- delete=auto_delete_temp_file,
144
+ delete=False,
146
145
  # delete_on_close=False, # supported since Python >= 3.12
147
146
  encoding=encoding,
148
147
  ) as file:
@@ -150,10 +149,11 @@ def _write_file_atomic(
150
149
  file.flush()
151
150
  os.fsync(file.fileno())
152
151
  temp_path = file.name
153
- permissions = get_permissions(path) if exists(path) else None
154
- os.replace(temp_path, path)
155
- if permissions:
156
- set_permissions(path, permissions)
152
+ # file is now closed, safe to replace on Windows
153
+ permissions = get_permissions(path) if exists(path) else None
154
+ os.replace(temp_path, path)
155
+ if permissions:
156
+ set_permissions(path, permissions)
157
157
  except FileNotFoundError:
158
158
  # success - the NamedTemporaryFile has not been able
159
159
  # to remove the temp file on __exit__ because the temp file
@@ -4,4 +4,4 @@ __description__ = "high-level file-system operations for lazy devs."
4
4
  __email__ = "fabio.caccamo@gmail.com"
5
5
  __license__ = "MIT"
6
6
  __title__ = "python-fsutil"
7
- __version__ = "0.15.0"
7
+ __version__ = "0.16.1"
@@ -517,6 +517,10 @@ def _search_paths(path: PathIn, pattern: str) -> list[str]:
517
517
  assert_dir(path)
518
518
  pathname = os.path.join(path, pattern)
519
519
  paths = glob.glob(pathname, recursive=True)
520
+ # normalize paths to use OS-specific separators
521
+ paths = [
522
+ os.path.relpath(os.path.normpath(path_result), path) for path_result in paths
523
+ ]
520
524
  return paths
521
525
 
522
526
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: python-fsutil
3
- Version: 0.15.0
3
+ Version: 0.16.1
4
4
  Summary: high-level file-system operations for lazy devs.
5
5
  Author-email: Fabio Caccamo <fabio.caccamo@gmail.com>
6
6
  Maintainer-email: Fabio Caccamo <fabio.caccamo@gmail.com>
@@ -46,6 +46,7 @@ Classifier: Programming Language :: Python :: 3.10
46
46
  Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
48
  Classifier: Programming Language :: Python :: 3.13
49
+ Classifier: Programming Language :: Python :: 3.14
49
50
  Classifier: Programming Language :: Python :: Implementation :: PyPy
50
51
  Classifier: Topic :: Desktop Environment :: File Managers
51
52
  Classifier: Topic :: Software Development :: Build Tools
@@ -54,6 +55,7 @@ Classifier: Topic :: System :: Filesystems
54
55
  Classifier: Topic :: Utilities
55
56
  Description-Content-Type: text/markdown
56
57
  License-File: LICENSE.txt
58
+ Dynamic: license-file
57
59
 
58
60
  [![](https://img.shields.io/pypi/pyversions/python-fsutil.svg?color=blue&logo=python&logoColor=white)](https://www.python.org/)
59
61
  [![](https://img.shields.io/pypi/v/python-fsutil.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/python-fsutil/)
@@ -65,7 +67,6 @@ License-File: LICENSE.txt
65
67
  [![](https://img.shields.io/github/actions/workflow/status/fabiocaccamo/python-fsutil/test-package.yml?branch=main&label=build&logo=github)](https://github.com/fabiocaccamo/python-fsutil)
66
68
  [![](https://img.shields.io/codecov/c/gh/fabiocaccamo/python-fsutil?logo=codecov)](https://codecov.io/gh/fabiocaccamo/python-fsutil)
67
69
  [![](https://img.shields.io/codacy/grade/fc40788ae7d74d1fb34a38934113c4e5?logo=codacy)](https://www.codacy.com/app/fabiocaccamo/python-fsutil)
68
- [![](https://img.shields.io/codeclimate/maintainability/fabiocaccamo/python-fsutil?logo=code-climate)](https://codeclimate.com/github/fabiocaccamo/python-fsutil/)
69
70
  [![](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&logoColor=black)](https://github.com/psf/black)
70
71
  [![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
71
72
 
@@ -825,8 +826,8 @@ pre-commit install --install-hooks
825
826
  # run tests using tox
826
827
  tox
827
828
 
828
- # or run tests using unittest
829
- python -m unittest
829
+ # or run tests using pytest
830
+ pytest
830
831
  ```
831
832
 
832
833
  ## License
@@ -838,7 +839,7 @@ Released under [MIT License](LICENSE.txt).
838
839
 
839
840
  - :star: Star this project on [GitHub](https://github.com/fabiocaccamo/python-fsutil)
840
841
  - :octocat: Follow me on [GitHub](https://github.com/fabiocaccamo)
841
- - :blue_heart: Follow me on [Twitter](https://twitter.com/fabiocaccamo)
842
+ - :blue_heart: Follow me on [Bluesky](https://bsky.app/profile/fabiocaccamo.bsky.social)
842
843
  - :moneybag: Sponsor me on [Github](https://github.com/sponsors/fabiocaccamo)
843
844
 
844
845
  ## See also
@@ -0,0 +1,36 @@
1
+ LICENSE.txt
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ src/fsutil/__init__.py
7
+ src/fsutil/archives.py
8
+ src/fsutil/args.py
9
+ src/fsutil/checks.py
10
+ src/fsutil/converters.py
11
+ src/fsutil/deps.py
12
+ src/fsutil/info.py
13
+ src/fsutil/io.py
14
+ src/fsutil/metadata.py
15
+ src/fsutil/operations.py
16
+ src/fsutil/paths.py
17
+ src/fsutil/perms.py
18
+ src/fsutil/py.typed
19
+ src/fsutil/types.py
20
+ src/python_fsutil.egg-info/PKG-INFO
21
+ src/python_fsutil.egg-info/SOURCES.txt
22
+ src/python_fsutil.egg-info/dependency_links.txt
23
+ src/python_fsutil.egg-info/top_level.txt
24
+ tests/__init__.py
25
+ tests/conftest.py
26
+ tests/test_archives.py
27
+ tests/test_args.py
28
+ tests/test_checks.py
29
+ tests/test_converters.py
30
+ tests/test_deps.py
31
+ tests/test_info.py
32
+ tests/test_io.py
33
+ tests/test_metadata.py
34
+ tests/test_operations.py
35
+ tests/test_paths.py
36
+ tests/test_perms.py
File without changes
@@ -0,0 +1,15 @@
1
+ import os
2
+ import tempfile
3
+
4
+ import pytest
5
+
6
+
7
+ @pytest.fixture
8
+ def temp_path():
9
+ with tempfile.TemporaryDirectory() as temp_dir:
10
+
11
+ def _temp_path(filepath=""):
12
+ # normalize path to use OS-specific separators
13
+ return os.path.normpath(os.path.join(temp_dir, filepath))
14
+
15
+ yield _temp_path
@@ -518,6 +518,24 @@ def test_search_files(temp_path):
518
518
  assert results == expected_results
519
519
 
520
520
 
521
+ def test_search_files_with_relative_path(temp_path, monkeypatch):
522
+ """
523
+ Regression test: search_files with a relative path must not return an empty
524
+ list due to the double-prefix bug in _filter_paths.
525
+ """
526
+ fsutil.create_file(temp_path("a/b/c/IMG_1002.png"))
527
+ fsutil.create_file(temp_path("a/x/c/IMG_1005.png"))
528
+ fsutil.create_file(temp_path("a/b/c/IMG_1000.jpg"))
529
+
530
+ # change cwd to the parent of "a/" so that the relative path is valid
531
+ monkeypatch.chdir(temp_path(""))
532
+
533
+ results = fsutil.search_files("./a/", "**/c/IMG_*.png")
534
+
535
+ assert len(results) == 2
536
+ assert all(fsutil.is_file(result) for result in results)
537
+
538
+
521
539
  def test_search_dirs(temp_path):
522
540
  fsutil.create_file(temp_path("a/b/c/IMG_1000.jpg"))
523
541
  fsutil.create_file(temp_path("x/y/z/c/IMG_1001.jpg"))
@@ -1,34 +0,0 @@
1
- LICENSE.txt
2
- MANIFEST.in
3
- README.md
4
- pyproject.toml
5
- setup.py
6
- fsutil/__init__.py
7
- fsutil/archives.py
8
- fsutil/args.py
9
- fsutil/checks.py
10
- fsutil/converters.py
11
- fsutil/deps.py
12
- fsutil/info.py
13
- fsutil/io.py
14
- fsutil/metadata.py
15
- fsutil/operations.py
16
- fsutil/paths.py
17
- fsutil/perms.py
18
- fsutil/py.typed
19
- fsutil/types.py
20
- python_fsutil.egg-info/PKG-INFO
21
- python_fsutil.egg-info/SOURCES.txt
22
- python_fsutil.egg-info/dependency_links.txt
23
- python_fsutil.egg-info/top_level.txt
24
- tests/test_archives.py
25
- tests/test_args.py
26
- tests/test_checks.py
27
- tests/test_converters.py
28
- tests/test_deps.py
29
- tests/test_info.py
30
- tests/test_io.py
31
- tests/test_metadata.py
32
- tests/test_operations.py
33
- tests/test_paths.py
34
- tests/test_perms.py
File without changes
File without changes