python-fsutil 0.12.0__py3-none-any.whl → 0.13.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.
fsutil/__init__.py CHANGED
@@ -80,6 +80,7 @@ __all__ = [
80
80
  "get_file_size_formatted",
81
81
  "get_filename",
82
82
  "get_parent_dir",
83
+ "get_permissions",
83
84
  "get_unique_name",
84
85
  "is_dir",
85
86
  "is_empty",
@@ -113,6 +114,7 @@ __all__ = [
113
114
  "replace_file",
114
115
  "search_dirs",
115
116
  "search_files",
117
+ "set_permissions",
116
118
  "split_filename",
117
119
  "split_filepath",
118
120
  "split_path",
@@ -788,6 +790,17 @@ def get_parent_dir(path: PathIn, *, levels: int = 1) -> str:
788
790
  return join_path(path, *([os.pardir] * max(1, levels)))
789
791
 
790
792
 
793
+ def get_permissions(path: PathIn) -> int:
794
+ """
795
+ Get the file/directory permissions.
796
+ """
797
+ path = _get_path(path)
798
+ assert_exists(path)
799
+ st_mode = os.stat(path).st_mode
800
+ permissions = int(str(oct(st_mode & 0o777))[2:])
801
+ return permissions
802
+
803
+
791
804
  def get_unique_name(
792
805
  path: PathIn,
793
806
  *,
@@ -797,7 +810,7 @@ def get_unique_name(
797
810
  separator: str = "-",
798
811
  ) -> str:
799
812
  """
800
- Gets a unique name for a directory/file ath the given directory path.
813
+ Get a unique name for a directory/file ath the given directory path.
801
814
  """
802
815
  path = _get_path(path)
803
816
  assert_dir(path)
@@ -1282,6 +1295,16 @@ def search_files(path: PathIn, pattern: str = "**/*.*") -> list[str]:
1282
1295
  return _filter_paths(path, _search_paths(path, pattern), predicate=is_file)
1283
1296
 
1284
1297
 
1298
+ def set_permissions(path: PathIn, value: int) -> None:
1299
+ """
1300
+ Set the file/directory permissions.
1301
+ """
1302
+ path = _get_path(path)
1303
+ assert_exists(path)
1304
+ permissions = int(str(value), 8) & 0o777
1305
+ os.chmod(path, permissions)
1306
+
1307
+
1285
1308
  def split_filename(path: PathIn) -> tuple[str, str]:
1286
1309
  """
1287
1310
  Split a filename and returns its basename and extension.
@@ -1321,22 +1344,30 @@ def _write_file_atomic(
1321
1344
  append: bool = False,
1322
1345
  encoding: str = "utf-8",
1323
1346
  ) -> None:
1347
+ path = _get_path(path)
1324
1348
  mode = "a" if append else "w"
1325
1349
  if append:
1326
1350
  content = read_file(path, encoding=encoding) + content
1327
1351
  dirpath, _ = split_filepath(path)
1328
- with tempfile.NamedTemporaryFile(
1329
- mode=mode,
1330
- dir=dirpath,
1331
- delete=False,
1332
- encoding=encoding,
1333
- ) as file:
1334
- file.write(content)
1335
- file.flush()
1336
- os.fsync(file.fileno())
1337
- temp_path = file.name
1338
- os.replace(temp_path, path)
1339
- remove_file(temp_path)
1352
+ try:
1353
+ with tempfile.NamedTemporaryFile(
1354
+ mode=mode,
1355
+ dir=dirpath,
1356
+ delete=True,
1357
+ encoding=encoding,
1358
+ ) as file:
1359
+ file.write(content)
1360
+ file.flush()
1361
+ os.fsync(file.fileno())
1362
+ temp_path = file.name
1363
+ if exists(path):
1364
+ set_permissions(temp_path, get_permissions(path))
1365
+ os.replace(temp_path, path)
1366
+ except FileNotFoundError:
1367
+ # success - the NamedTemporaryFile has not been able
1368
+ # to remove the temp file on __exit__ because the temp file
1369
+ # has replaced atomically the file at path.
1370
+ pass
1340
1371
 
1341
1372
 
1342
1373
  def _write_file_non_atomic(
fsutil/metadata.py CHANGED
@@ -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.12.0"
7
+ __version__ = "0.13.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fsutil
3
- Version: 0.12.0
3
+ Version: 0.13.0
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>
@@ -132,6 +132,7 @@ import fsutil
132
132
  - [`get_file_size_formatted`](#get_file_size_formatted)
133
133
  - [`get_filename`](#get_filename)
134
134
  - [`get_parent_dir`](#get_parent_dir)
135
+ - [`get_permissions`](#get_permissions)
135
136
  - [`get_unique_name`](#get_unique_name)
136
137
  - [`is_dir`](#is_dir)
137
138
  - [`is_empty`](#is_empty)
@@ -165,6 +166,7 @@ import fsutil
165
166
  - [`replace_file`](#replace_file)
166
167
  - [`search_dirs`](#search_dirs)
167
168
  - [`search_files`](#search_files)
169
+ - [`set_permissions`](#set_permissions)
168
170
  - [`split_filename`](#split_filename)
169
171
  - [`split_filepath`](#split_filepath)
170
172
  - [`split_path`](#split_path)
@@ -494,10 +496,17 @@ filename = fsutil.get_filename(path)
494
496
  parent_dir = fsutil.get_parent_dir(path, levels=1)
495
497
  ```
496
498
 
499
+ #### `get_permissions`
500
+
501
+ ```python
502
+ # Get the file/directory permissions.
503
+ permissions = fsutil.get_permissions(path)
504
+ ```
505
+
497
506
  #### `get_unique_name`
498
507
 
499
508
  ```python
500
- # Gets a unique name for a directory/file ath the given directory path.
509
+ # Get a unique name for a directory/file ath the given directory path.
501
510
  unique_name = fsutil.get_unique_name(path, prefix="", suffix="", extension="", separator="-")
502
511
  ```
503
512
 
@@ -747,6 +756,13 @@ dirs = fsutil.search_dirs(path, pattern="**/*")
747
756
  files = fsutil.search_files(path, pattern="**/*.*")
748
757
  ```
749
758
 
759
+ #### `set_permissions`
760
+
761
+ ```python
762
+ # Set the file/directory permissions.
763
+ fsutil.set_permissions(path, 700)
764
+ ```
765
+
750
766
  #### `split_filename`
751
767
 
752
768
  ```python
@@ -0,0 +1,8 @@
1
+ fsutil/__init__.py,sha256=IpqVSsROxOpfRTEpHEgmB8Y0Ig0OwLcOEOvl_xNRlCg,39444
2
+ fsutil/metadata.py,sha256=K36K01JFKjpV25tf7qT9WchCaxT2E7DfEJ2Dx-3OQjk,266
3
+ fsutil/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_fsutil-0.13.0.dist-info/LICENSE.txt,sha256=IcPfOD_lonKcLMnPRhiWdQUPW_LYW-5TTDljwi3UXQg,1078
5
+ python_fsutil-0.13.0.dist-info/METADATA,sha256=AKjGMjwCxQkDP5gbvq-q2XUow99v_FL53oHh5ewS3vs,24628
6
+ python_fsutil-0.13.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
7
+ python_fsutil-0.13.0.dist-info/top_level.txt,sha256=KGTSjNLPWmxnZt8BFMZQrpnhkO7DsKrYWoXK-Sf3wBQ,7
8
+ python_fsutil-0.13.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- fsutil/__init__.py,sha256=YIHGlEZd6monzxGLsw07X5ZYWqfg_otx-FQPLdeE4YA,38516
2
- fsutil/metadata.py,sha256=0ftqc9BXPYtOpU-J9EhK0S7c34Rc96Tsx7eQSpabXtk,266
3
- fsutil/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_fsutil-0.12.0.dist-info/LICENSE.txt,sha256=IcPfOD_lonKcLMnPRhiWdQUPW_LYW-5TTDljwi3UXQg,1078
5
- python_fsutil-0.12.0.dist-info/METADATA,sha256=QBGWF_HGwjgkCyllklBAkGwVwO3lf-Lxkqs1j3yLneo,24314
6
- python_fsutil-0.12.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
7
- python_fsutil-0.12.0.dist-info/top_level.txt,sha256=KGTSjNLPWmxnZt8BFMZQrpnhkO7DsKrYWoXK-Sf3wBQ,7
8
- python_fsutil-0.12.0.dist-info/RECORD,,