Skip to content

Add a parameter create to resolve() to create the directory/file if it doesn't exist. #2751

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions arcade/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,19 @@ def resolve_resource_path(path: str | Path) -> Path:
return resolve(path)


def resolve(path: str | Path) -> Path:
def create_path(path: Path) -> None:
"""
Create a file or directory at the given path.
If the path has a suffix, it's treated as a file, otherwise, as a directory.
"""
if path.suffix:
path.parent.mkdir(parents=True, exist_ok=True)
path.touch(exist_ok=True)
else:
path.mkdir(parents=True, exist_ok=True)


def resolve(path: str | Path, *, create: bool = False) -> Path:
"""
Attempts to resolve a path to a resource including resource handles.

Expand All @@ -67,6 +79,7 @@ def resolve(path: str | Path) -> Path:

Args:
path: A Path or string
create: If True, create the path if it doesn't exist.
"""
# Convert to a Path object and resolve resource handle
if isinstance(path, str):
Expand All @@ -87,22 +100,30 @@ def resolve(path: str | Path) -> Path:
# match. This allows for overriding of resources.
paths = get_resource_handle_paths(handle)
for handle_path in reversed(paths):
path = handle_path / resource
if path.exists():
candidate_path = handle_path / resource
if candidate_path.exists():
path = candidate_path
break
else:
searched_paths = "\n".join(f"-> {p}" for p in reversed(paths))
raise FileNotFoundError(
f"Cannot locate resource '{resource}' using handle "
f"'{handle}' in any of the following paths:\n"
f"{searched_paths}"
)
if create:
path = paths[-1] / resource
create_path(path)
else:
searched_paths = "\n".join(f"-> {p}" for p in reversed(paths))
raise FileNotFoundError(
f"Cannot locate resource '{resource}' using handle "
f"'{handle}' in any of the following paths:\n"
f"{searched_paths}"
)

# Always convert into a Path object
path = Path(handle_path / resource)
path = Path(path)
else:
path = Path(path)

if create:
create_path(path)

try:
path = Path(path.resolve(strict=True))
except AttributeError:
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/resources/test_handles.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,36 @@ def test_default_handles():
resources.resolve(":system:images/cards/cardBack_blue1.png")


def test_resolve_create(tmp_path):
"""Test if we can create directories and files using the resolve."""
# Test directory creation
new_dir = tmp_path / "created_dir"
assert not new_dir.exists()
result_dir = resources.resolve(new_dir, create=True)
assert result_dir == new_dir.resolve()
assert new_dir.exists() and new_dir.is_dir()

# Test file creation
new_file = tmp_path / "created_file.txt"
assert not new_file.exists()
result_file = resources.resolve(new_file, create=True)
assert result_file == new_file.resolve()
assert new_file.exists() and new_file.is_file()


def test_default_handle_create():
"""Test if we can create directories and files using the default handle."""
handle_dir = ":resources:new_dir"
with pytest.raises(FileNotFoundError):
resources.resolve(handle_dir)
result_dir = resources.resolve(handle_dir, create=True)
assert result_dir.exists() and result_dir.is_dir()
for base_path in resources.get_resource_handle_paths("resources"):
dir_path = base_path / "new_dir"
if dir_path.exists() and dir_path.is_dir():
dir_path.rmdir()


def test_add_handles(monkeypatch):
monkeypatch.setattr(resources, "handles", {})

Expand Down
Loading