Skip to content

Commit 21704dd

Browse files
authored
Merge pull request #108 from ArcanaFramework/forward-ref-in-mime
Forward-ref-in-mime and additional logging
2 parents 9f45ec4 + 29ded74 commit 21704dd

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

fileformats/core/fileset.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,15 +1452,22 @@ def copy(
14521452
dest_dir = Path(dest_dir)
14531453
# Logic to determine the laziest mode to use
14541454
mode = self.CopyMode[mode] if isinstance(mode, str) else mode
1455+
logger.debug("Requested '%s' for the copy operation", mode)
14551456
if len(self.fspaths) == 1:
14561457
# If there is only one path to copy, then collation isn't meaningful
14571458
collation = self.CopyCollation.any
1459+
logger.debug(
1460+
"Collation mode is set to 'any' as there is only one path in the fileset"
1461+
)
14581462
else:
14591463
collation = (
14601464
self.CopyCollation[collation]
14611465
if isinstance(collation, str)
14621466
else collation
14631467
)
1468+
logger.debug(
1469+
"Collation mode is set to '%s' for the copy operation", collation
1470+
)
14641471
# Rule out any copy modes that are not supported given the collation mode
14651472
# and file-system mounts the paths and destination directory reside on
14661473
constraints = []
@@ -1473,7 +1480,9 @@ def copy(
14731480
f"Destination directory is on CIFS mount ({dest_dir}) "
14741481
"and we therefore cannot create a symlink"
14751482
)
1476-
logger.debug(constraint)
1483+
logger.debug(
1484+
constraint + ", supported modes restricted to %s", supported_modes
1485+
)
14771486
constraints.append(constraint)
14781487
not_on_same_mount = [
14791488
p for p in self.fspaths if not FsMountIdentifier.on_same_mount(p, dest_dir)
@@ -1485,7 +1494,9 @@ def copy(
14851494
f"not on same file-system mount as the destination directory {dest_dir}"
14861495
"and therefore cannot be hard-linked"
14871496
)
1488-
logger.debug(constraint)
1497+
logger.debug(
1498+
constraint + ", supported modes restricted to %s", supported_modes
1499+
)
14891500
constraints.append(constraint)
14901501
if (
14911502
new_stem
@@ -1497,9 +1508,19 @@ def copy(
14971508
)
14981509
):
14991510
supported_modes -= self.CopyMode.leave
1511+
logger.debug(
1512+
"Collation mode is set to '%s' or new_stem/prefix/stem_suffix is set, "
1513+
"therefore we cannot leave the files where they are",
1514+
collation,
1515+
)
15001516

15011517
# Get the intersection of copy modes that are supported and have been requested
15021518
selected_mode = mode & supported_modes
1519+
logger.debug(
1520+
"Selected copy mode is '%s' for the copy operation (requested %s)",
1521+
selected_mode,
1522+
mode,
1523+
)
15031524
if not selected_mode:
15041525
msg = (
15051526
f"Cannot copy {self} using '{mode}' mode as it is not supported by "
@@ -1509,15 +1530,20 @@ def copy(
15091530
msg += ", and the following constraints:\n" + "\n".join(constraints)
15101531
raise UnsatisfiableCopyModeError(msg)
15111532
if selected_mode & self.CopyMode.leave:
1533+
logger.debug(
1534+
"Selected copy mode is set to 'leave', therefore we are not copying anything"
1535+
)
15121536
return self # Don't need to do anything
15131537

15141538
copy_file: ty.Callable[[Path, Path], None]
15151539
copy_dir: ty.Callable[[Path, Path], None]
15161540

15171541
# Select inner copy/link methods
15181542
if selected_mode & self.CopyMode.symlink:
1543+
logger.debug('Using symbolic links for the "copy" operation')
15191544
copy_dir = copy_file = os.symlink
15201545
elif selected_mode & self.CopyMode.hardlink:
1546+
logger.debug('Using hard links for the "copy" operation')
15211547
copy_file = os.link
15221548

15231549
def hardlink_dir(src: Path, dest: Path) -> None:
@@ -1530,6 +1556,7 @@ def hardlink_dir(src: Path, dest: Path) -> None:
15301556

15311557
copy_dir = hardlink_dir
15321558
else:
1559+
logger.debug('Using full copy for the "copy" operation')
15331560
assert selected_mode & self.CopyMode.copy
15341561
copy_dir = shutil.copytree
15351562
copy_file = shutil.copyfile # type: ignore
@@ -1737,10 +1764,15 @@ def _src_dest_pairs(
17371764
exts = [d[-1] for d in decomposed_fspaths]
17381765
duplicate_exts = [n for n, c in Counter(exts).items() if c > 1]
17391766
if duplicate_exts:
1767+
reason = ""
1768+
if new_stem:
1769+
reason += f"with a new stem, {new_stem!r}, "
1770+
if collation == self.CopyCollation.adjacent:
1771+
reason += f"with collation mode '{collation}', "
17401772
raise UnsatisfiableCopyModeError(
1741-
f"Cannot copy/move {self} with collation mode "
1742-
f'"{collation}", as there are duplicate extensions, {duplicate_exts}, '
1743-
f"in file paths: " + "\n".join(str(p) for p in self.fspaths)
1773+
f"Cannot copy/move {self} {reason} as there are duplicate "
1774+
f"extensions, {duplicate_exts}, in file paths: "
1775+
+ "\n".join(str(p) for p in self.fspaths)
17441776
)
17451777
# Set default for new_stem if not provided and collating file-set to be adjacent
17461778
if new_stem is None:

fileformats/core/identification.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import operator
22
from pathlib import Path
3+
import inspect
34
import typing as ty
45
import re
56
from fileformats.core.exceptions import (
@@ -128,8 +129,15 @@ def to_mime(
128129
namespace scheme instead of putting all non-standard types into the 'application'
129130
registry if not
130131
"""
132+
# Handle forward references
133+
if isinstance(datatype, ty.ForwardRef):
134+
datatype = datatype.__forward_arg__
131135
origin = ty.get_origin(datatype)
132-
if origin is None and not issubclass(datatype, fileformats.core.DataType):
136+
if (
137+
origin is None
138+
and inspect.isclass(datatype)
139+
and not issubclass(datatype, fileformats.core.DataType)
140+
):
133141
raise TypeError(
134142
f"Cannot convert {datatype} to mime-type as it is not a file-set class"
135143
)
@@ -146,9 +154,6 @@ def to_mime(
146154
return item_mime
147155
if origin is ty.Union:
148156
return ",".join(to_mime(t, official=official) for t in ty.get_args(datatype))
149-
# Handle case
150-
if isinstance(datatype, ty.ForwardRef):
151-
datatype = datatype.__forward_arg__
152157
if (
153158
isinstance(datatype, str)
154159
and datatype.startswith("fileformats.")

fileformats/core/tests/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ def test_copy_symlink_with_unrequired_fallback(fsobject: FsObject, dest_dir: Pat
101101

102102

103103
def test_copy_hardlink(fsobject: FsObject, dest_dir: Path):
104-
cpy = fsobject.copy(dest_dir, mode=File.CopyMode.symlink)
104+
cpy = fsobject.copy(dest_dir, mode=File.CopyMode.hardlink_or_copy)
105105
assert all(p.parent == dest_dir for p in cpy.fspaths)
106106
assert set(p.name for p in cpy.fspaths) == set(p.name for p in fsobject.fspaths)
107107
assert all(
108-
os.path.samefile(c, o)
108+
c != o and os.path.samefile(c, o)
109109
for c, o in zip(sorted(cpy.fspaths), sorted(fsobject.fspaths))
110110
if o.is_file()
111111
)

fileformats/field/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class Array(
190190
] = (Singular,)
191191
item_type: ty.Optional[ty.Type[Singular[ItemType, ty.Any]]] = None
192192

193-
primitive = tuple
193+
primitive = tuple # type: ignore[assignment]
194194

195195
value: ty.Tuple[ItemType, ...]
196196

0 commit comments

Comments
 (0)