Skip to content

Commit

Permalink
Add transform_filepath method. #12 #13
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiocaccamo committed Mar 19, 2024
1 parent c8c7301 commit 18f3ded
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import fsutil
- [`split_filename`](#split_filename)
- [`split_filepath`](#split_filepath)
- [`split_path`](#split_path)
- [`transform_filepath`](#transform_filepath)
- [`write_file`](#write_file)
- [`write_file_json`](#write_file_json)

Expand Down Expand Up @@ -726,6 +727,13 @@ dirpath, filename = fsutil.split_filepath(path)
path_names = fsutil.split_path(path)
```

#### `transform_filepath`

```python
# Trasform a filepath by applying the provided optional changes.
filepath = fsutil.transform_filepath(path, dirpath=None, basename=lambda b: slugify(b), extension="webp")
```

#### `write_file`

```python
Expand Down
57 changes: 57 additions & 0 deletions fsutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,63 @@ def split_path(path: PathIn) -> list[str]:
return names


def transform_filepath(
path: PathIn,
*,
dirpath: str | Callable[[str], str] | None = None,
basename: str | Callable[[str], str] | None = None,
extension: str | Callable[[str], str] | None = None,
) -> str:
"""
Trasform a filepath by applying the provided optional changes.
:param path: The path.
:type path: PathIn
:param dirpath: The new dirpath or a callable.
:type dirpath: str | Callable[[str], str] | None
:param basename: The new basename or a callable.
:type basename: str | Callable[[str], str] | None
:param extension: The new extension or a callable.
:type extension: str | Callable[[str], str] | None
:returns: The filepath with the applied changes.
:rtype: str
"""

def _get_value(
new_value: str | Callable[[str], str] | None,
old_value: str,
) -> str:
value = old_value
if new_value is not None:
if callable(new_value):
value = new_value(old_value)
elif isinstance(new_value, str):
value = new_value
else:
value = old_value
return value

if all([dirpath is None, basename is None, extension is None]):
raise ValueError(
"Invalid arguments: at least one of "
"'dirpath', 'basename' or 'extension' is required."
)
old_dirpath, old_filename = split_filepath(path)
old_basename, old_extension = split_filename(old_filename)
new_dirpath = _get_value(dirpath, old_dirpath)
new_basename = _get_value(basename, old_basename)
new_extension = _get_value(extension, old_extension)
if not any([new_dirpath, new_basename, new_extension]):
raise ValueError(
"Invalid arguments: at least one of "
"'dirpath', 'basename' or 'extension' is required."
)
new_filename = join_filename(new_basename, new_extension)
new_filepath = join_filepath(new_dirpath, new_filename)
return new_filepath


def _write_file_atomic(
path: PathIn,
content: str,
Expand Down
77 changes: 77 additions & 0 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,83 @@ def test_split_path(self):
s = "/root/a/b/c/Document.txt"
self.assertEqual(fsutil.split_path(s), ["root", "a", "b", "c", "Document.txt"])

def test_transform_filepath_without_args(self):
s = "/root/a/b/c/Document.txt"
with self.assertRaises(ValueError):
(fsutil.transform_filepath(s),)

def test_transform_filepath_with_empty_str_args(self):
s = "/root/a/b/c/Document.txt"
self.assertEqual(
fsutil.transform_filepath(s, dirpath=""),
"Document.txt",
)
self.assertEqual(
fsutil.transform_filepath(s, basename=""),
"/root/a/b/c/txt",
)
self.assertEqual(
fsutil.transform_filepath(s, extension=""),
"/root/a/b/c/Document",
)
self.assertEqual(
fsutil.transform_filepath(
s, dirpath="/root/x/y/z/", basename="NewDocument", extension="xls"
),
"/root/x/y/z/NewDocument.xls",
)
with self.assertRaises(ValueError):
(fsutil.transform_filepath(s, dirpath="", basename="", extension=""),)

def test_transform_filepath_with_str_args(self):
s = "/root/a/b/c/Document.txt"
self.assertEqual(
fsutil.transform_filepath(s, dirpath="/root/x/y/z/"),
"/root/x/y/z/Document.txt",
)
self.assertEqual(
fsutil.transform_filepath(s, basename="NewDocument"),
"/root/a/b/c/NewDocument.txt",
)
self.assertEqual(
fsutil.transform_filepath(s, extension="xls"),
"/root/a/b/c/Document.xls",
)
self.assertEqual(
fsutil.transform_filepath(s, extension=".xls"),
"/root/a/b/c/Document.xls",
)
self.assertEqual(
fsutil.transform_filepath(
s, dirpath="/root/x/y/z/", basename="NewDocument", extension="xls"
),
"/root/x/y/z/NewDocument.xls",
)

def test_transform_filepath_with_callable_args(self):
s = "/root/a/b/c/Document.txt"
self.assertEqual(
fsutil.transform_filepath(s, dirpath=lambda d: f"{d}/x/y/z/"),
"/root/a/b/c/x/y/z/Document.txt",
)
self.assertEqual(
fsutil.transform_filepath(s, basename=lambda b: b.lower()),
"/root/a/b/c/document.txt",
)
self.assertEqual(
fsutil.transform_filepath(s, extension=lambda e: "xls"),
"/root/a/b/c/Document.xls",
)
self.assertEqual(
fsutil.transform_filepath(
s,
dirpath=lambda d: f"{d}/x/y/z/",
basename=lambda b: b.lower(),
extension=lambda e: "xls",
),
"/root/a/b/c/x/y/z/document.xls",
)

def test_write_file(self):
path = self.temp_path("a/b/c.txt")
fsutil.write_file(path, content="Hello World")
Expand Down

0 comments on commit 18f3ded

Please sign in to comment.