monkeyfs 0.2.1__tar.gz → 0.2.2__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 (46) hide show
  1. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/PKG-INFO +1 -1
  2. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/conformance.py +10 -1
  3. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/mount.py +2 -1
  4. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/virtual.py +10 -5
  5. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs.egg-info/PKG-INFO +1 -1
  6. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/pyproject.toml +1 -1
  7. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_directory_ops.py +48 -0
  8. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_open_optional.py +1 -1
  9. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/LICENSE +0 -0
  10. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/README.md +0 -0
  11. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/__init__.py +0 -0
  12. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/base.py +0 -0
  13. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/context.py +0 -0
  14. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/isolated.py +0 -0
  15. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/patching/__init__.py +0 -0
  16. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/patching/core.py +0 -0
  17. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/patching/fdtable.py +0 -0
  18. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/patching/install.py +0 -0
  19. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/patching/patches.py +0 -0
  20. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/py.typed +0 -0
  21. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/readonly.py +0 -0
  22. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs/virtualfile.py +0 -0
  23. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs.egg-info/SOURCES.txt +0 -0
  24. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs.egg-info/dependency_links.txt +0 -0
  25. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs.egg-info/requires.txt +0 -0
  26. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/monkeyfs.egg-info/top_level.txt +0 -0
  27. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/setup.cfg +0 -0
  28. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_bulk_operations.py +0 -0
  29. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_conformance.py +0 -0
  30. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_expanduser.py +0 -0
  31. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_fd_emulation.py +0 -0
  32. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_finalization_and_invalidate.py +0 -0
  33. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_isolated.py +0 -0
  34. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_lazy_binary_read.py +0 -0
  35. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_metadata.py +0 -0
  36. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_mount.py +0 -0
  37. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_patching.py +0 -0
  38. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_patching_pathlib.py +0 -0
  39. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_patching_safe_paths.py +0 -0
  40. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_protocol.py +0 -0
  41. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_ranged_read.py +0 -0
  42. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_readonly.py +0 -0
  43. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_symlink_entries.py +0 -0
  44. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_vfs_optional.py +0 -0
  45. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_vfs_size_limit.py +0 -0
  46. {monkeyfs-0.2.1 → monkeyfs-0.2.2}/tests/test_virtual.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monkeyfs
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Transparent filesystem interception via monkey-patching.
5
5
  Author: ashenfad
6
6
  License-Expression: MIT
@@ -212,12 +212,21 @@ def _check_listing_paths(fs: Any, scratch: str) -> None:
212
212
  f"{absolute.get('probe.bin')!r}",
213
213
  )
214
214
 
215
- deep = [info.path for info in fs.list_detailed(scratch, True)]
215
+ entries = fs.list_detailed(scratch, True)
216
+ deep = [info.path for info in entries]
216
217
  _require(
217
218
  f"{scratch}/nested/leaf.bin" in deep,
218
219
  f"a recursive list_detailed({scratch!r}) must name a nested entry "
219
220
  f"{scratch + '/nested/leaf.bin'!r}, got {deep!r}",
220
221
  )
222
+ for info in entries:
223
+ _require(
224
+ info.name == info.path.rsplit("/", 1)[-1],
225
+ f"list_detailed(...).name is the entry's own name, the last "
226
+ f"component of its path, at every depth: for path "
227
+ f"{info.path!r} expected {info.path.rsplit('/', 1)[-1]!r}, "
228
+ f"got {info.name!r}",
229
+ )
221
230
 
222
231
  start = fs.getcwd()
223
232
  fs.chdir(scratch)
@@ -285,10 +285,11 @@ class MountFS:
285
285
  for name in names:
286
286
  full_abs = f"{norm}/{name}" if norm else f"/{name}"
287
287
  display = f"{user_prefix}/{name}" if user_prefix != "." else name
288
+ basename = name.rsplit("/", 1)[-1]
288
289
  meta = self.stat(full_abs)
289
290
  result.append(
290
291
  FileInfo(
291
- name=name,
292
+ name=basename,
292
293
  path=display,
293
294
  size=meta.size,
294
295
  created_at=meta.created_at,
@@ -1325,7 +1325,10 @@ class VirtualFS:
1325
1325
  recursive: If True, list all nested files and directories.
1326
1326
 
1327
1327
  Returns:
1328
- List of FileInfo objects sorted by name.
1328
+ List of FileInfo objects sorted by path relative to the queried
1329
+ directory, so a directory precedes its contents. ``name`` is the
1330
+ entry's own name, the last component of ``path``, at every depth;
1331
+ it is not what the list is ordered by.
1329
1332
 
1330
1333
  Example:
1331
1334
  >>> files = vfs.list_detailed("/shared")
@@ -1350,7 +1353,9 @@ class VirtualFS:
1350
1353
  internal_path = f"{base}/{name}" if base else name
1351
1354
  absolute = "/" + internal_path
1352
1355
 
1353
- # Display path preserves the user's queried prefix
1356
+ # Display path preserves the user's queried prefix; the name
1357
+ # is the last component alone, whatever depth the entry sits at.
1358
+ basename = name.rsplit("/", 1)[-1]
1354
1359
  display = f"{user_prefix}/{name}" if user_prefix != "." else name
1355
1360
 
1356
1361
  meta = self._meta_at(internal_path)
@@ -1360,7 +1365,7 @@ class VirtualFS:
1360
1365
  now = self._now_iso()
1361
1366
  result.append(
1362
1367
  FileInfo(
1363
- name=name,
1368
+ name=basename,
1364
1369
  path=display,
1365
1370
  size=0,
1366
1371
  created_at=meta.created_at if meta is not None else now,
@@ -1371,7 +1376,7 @@ class VirtualFS:
1371
1376
  elif meta is not None:
1372
1377
  result.append(
1373
1378
  FileInfo(
1374
- name=name,
1379
+ name=basename,
1375
1380
  path=display,
1376
1381
  size=meta.size,
1377
1382
  created_at=meta.created_at,
@@ -1385,7 +1390,7 @@ class VirtualFS:
1385
1390
  now = self._now_iso()
1386
1391
  result.append(
1387
1392
  FileInfo(
1388
- name=name,
1393
+ name=basename,
1389
1394
  path=display,
1390
1395
  size=len(content),
1391
1396
  created_at=now,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monkeyfs
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Transparent filesystem interception via monkey-patching.
5
5
  Author: ashenfad
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "monkeyfs"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  description = "Transparent filesystem interception via monkey-patching."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -466,3 +466,51 @@ class TestImplicitDirectories:
466
466
  assert vfs.list("/") == ["pkg", "top.py"]
467
467
  assert vfs.list("pkg") == ["__init__.py", "sub", "utils.py"]
468
468
  assert vfs.list("pkg/sub") == ["mod.py"]
469
+
470
+
471
+ # -- list_detailed().name is the entry's own name at every depth ---------------
472
+
473
+
474
+ def _nested_tree(fs):
475
+ fs.makedirs("/probe/sub")
476
+ fs.write("/probe/one.txt", b"1")
477
+ fs.write("/probe/sub/two.txt", b"2")
478
+ return fs
479
+
480
+
481
+ def _names_and_paths(fs):
482
+ # The sequence as returned, not a sorted copy: every backend orders a
483
+ # recursive listing by path relative to the queried directory, so a
484
+ # directory precedes its contents, and a backend that drifts from
485
+ # that order fails here rather than being tidied into agreement.
486
+ return [(i.name, i.path) for i in fs.list_detailed("/probe", recursive=True)]
487
+
488
+
489
+ def test_virtualfs_recursive_listing_names_are_basenames():
490
+ from monkeyfs import VirtualFS
491
+
492
+ assert _names_and_paths(_nested_tree(VirtualFS({}))) == [
493
+ ("one.txt", "/probe/one.txt"),
494
+ ("sub", "/probe/sub"),
495
+ ("two.txt", "/probe/sub/two.txt"),
496
+ ]
497
+
498
+
499
+ def test_mountfs_recursive_listing_names_are_basenames():
500
+ from monkeyfs import MountFS, VirtualFS
501
+
502
+ assert _names_and_paths(_nested_tree(MountFS(VirtualFS({})))) == [
503
+ ("one.txt", "/probe/one.txt"),
504
+ ("sub", "/probe/sub"),
505
+ ("two.txt", "/probe/sub/two.txt"),
506
+ ]
507
+
508
+
509
+ def test_isolatedfs_recursive_listing_names_are_basenames(tmp_path):
510
+ from monkeyfs import IsolatedFS
511
+
512
+ assert _names_and_paths(_nested_tree(IsolatedFS(str(tmp_path)))) == [
513
+ ("one.txt", "/probe/one.txt"),
514
+ ("sub", "/probe/sub"),
515
+ ("two.txt", "/probe/sub/two.txt"),
516
+ ]
@@ -190,7 +190,7 @@ class TermishFS:
190
190
  meta = self.stat(full)
191
191
  entries.append(
192
192
  FileInfo(
193
- name=name,
193
+ name=posixpath.basename(name),
194
194
  path=display,
195
195
  size=meta.size,
196
196
  created_at=meta.created_at,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes