Skip to content

Commit 18f3ded

Browse files
committed
Add transform_filepath method. #12 #13
1 parent c8c7301 commit 18f3ded

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ import fsutil
112112
- [`split_filename`](#split_filename)
113113
- [`split_filepath`](#split_filepath)
114114
- [`split_path`](#split_path)
115+
- [`transform_filepath`](#transform_filepath)
115116
- [`write_file`](#write_file)
116117
- [`write_file_json`](#write_file_json)
117118

@@ -726,6 +727,13 @@ dirpath, filename = fsutil.split_filepath(path)
726727
path_names = fsutil.split_path(path)
727728
```
728729

730+
#### `transform_filepath`
731+
732+
```python
733+
# Trasform a filepath by applying the provided optional changes.
734+
filepath = fsutil.transform_filepath(path, dirpath=None, basename=lambda b: slugify(b), extension="webp")
735+
```
736+
729737
#### `write_file`
730738

731739
```python

fsutil/__init__.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,63 @@ def split_path(path: PathIn) -> list[str]:
13391339
return names
13401340

13411341

1342+
def transform_filepath(
1343+
path: PathIn,
1344+
*,
1345+
dirpath: str | Callable[[str], str] | None = None,
1346+
basename: str | Callable[[str], str] | None = None,
1347+
extension: str | Callable[[str], str] | None = None,
1348+
) -> str:
1349+
"""
1350+
Trasform a filepath by applying the provided optional changes.
1351+
1352+
:param path: The path.
1353+
:type path: PathIn
1354+
:param dirpath: The new dirpath or a callable.
1355+
:type dirpath: str | Callable[[str], str] | None
1356+
:param basename: The new basename or a callable.
1357+
:type basename: str | Callable[[str], str] | None
1358+
:param extension: The new extension or a callable.
1359+
:type extension: str | Callable[[str], str] | None
1360+
1361+
:returns: The filepath with the applied changes.
1362+
:rtype: str
1363+
"""
1364+
1365+
def _get_value(
1366+
new_value: str | Callable[[str], str] | None,
1367+
old_value: str,
1368+
) -> str:
1369+
value = old_value
1370+
if new_value is not None:
1371+
if callable(new_value):
1372+
value = new_value(old_value)
1373+
elif isinstance(new_value, str):
1374+
value = new_value
1375+
else:
1376+
value = old_value
1377+
return value
1378+
1379+
if all([dirpath is None, basename is None, extension is None]):
1380+
raise ValueError(
1381+
"Invalid arguments: at least one of "
1382+
"'dirpath', 'basename' or 'extension' is required."
1383+
)
1384+
old_dirpath, old_filename = split_filepath(path)
1385+
old_basename, old_extension = split_filename(old_filename)
1386+
new_dirpath = _get_value(dirpath, old_dirpath)
1387+
new_basename = _get_value(basename, old_basename)
1388+
new_extension = _get_value(extension, old_extension)
1389+
if not any([new_dirpath, new_basename, new_extension]):
1390+
raise ValueError(
1391+
"Invalid arguments: at least one of "
1392+
"'dirpath', 'basename' or 'extension' is required."
1393+
)
1394+
new_filename = join_filename(new_basename, new_extension)
1395+
new_filepath = join_filepath(new_dirpath, new_filename)
1396+
return new_filepath
1397+
1398+
13421399
def _write_file_atomic(
13431400
path: PathIn,
13441401
content: str,

tests/test.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,83 @@ def test_split_path(self):
12221222
s = "/root/a/b/c/Document.txt"
12231223
self.assertEqual(fsutil.split_path(s), ["root", "a", "b", "c", "Document.txt"])
12241224

1225+
def test_transform_filepath_without_args(self):
1226+
s = "/root/a/b/c/Document.txt"
1227+
with self.assertRaises(ValueError):
1228+
(fsutil.transform_filepath(s),)
1229+
1230+
def test_transform_filepath_with_empty_str_args(self):
1231+
s = "/root/a/b/c/Document.txt"
1232+
self.assertEqual(
1233+
fsutil.transform_filepath(s, dirpath=""),
1234+
"Document.txt",
1235+
)
1236+
self.assertEqual(
1237+
fsutil.transform_filepath(s, basename=""),
1238+
"/root/a/b/c/txt",
1239+
)
1240+
self.assertEqual(
1241+
fsutil.transform_filepath(s, extension=""),
1242+
"/root/a/b/c/Document",
1243+
)
1244+
self.assertEqual(
1245+
fsutil.transform_filepath(
1246+
s, dirpath="/root/x/y/z/", basename="NewDocument", extension="xls"
1247+
),
1248+
"/root/x/y/z/NewDocument.xls",
1249+
)
1250+
with self.assertRaises(ValueError):
1251+
(fsutil.transform_filepath(s, dirpath="", basename="", extension=""),)
1252+
1253+
def test_transform_filepath_with_str_args(self):
1254+
s = "/root/a/b/c/Document.txt"
1255+
self.assertEqual(
1256+
fsutil.transform_filepath(s, dirpath="/root/x/y/z/"),
1257+
"/root/x/y/z/Document.txt",
1258+
)
1259+
self.assertEqual(
1260+
fsutil.transform_filepath(s, basename="NewDocument"),
1261+
"/root/a/b/c/NewDocument.txt",
1262+
)
1263+
self.assertEqual(
1264+
fsutil.transform_filepath(s, extension="xls"),
1265+
"/root/a/b/c/Document.xls",
1266+
)
1267+
self.assertEqual(
1268+
fsutil.transform_filepath(s, extension=".xls"),
1269+
"/root/a/b/c/Document.xls",
1270+
)
1271+
self.assertEqual(
1272+
fsutil.transform_filepath(
1273+
s, dirpath="/root/x/y/z/", basename="NewDocument", extension="xls"
1274+
),
1275+
"/root/x/y/z/NewDocument.xls",
1276+
)
1277+
1278+
def test_transform_filepath_with_callable_args(self):
1279+
s = "/root/a/b/c/Document.txt"
1280+
self.assertEqual(
1281+
fsutil.transform_filepath(s, dirpath=lambda d: f"{d}/x/y/z/"),
1282+
"/root/a/b/c/x/y/z/Document.txt",
1283+
)
1284+
self.assertEqual(
1285+
fsutil.transform_filepath(s, basename=lambda b: b.lower()),
1286+
"/root/a/b/c/document.txt",
1287+
)
1288+
self.assertEqual(
1289+
fsutil.transform_filepath(s, extension=lambda e: "xls"),
1290+
"/root/a/b/c/Document.xls",
1291+
)
1292+
self.assertEqual(
1293+
fsutil.transform_filepath(
1294+
s,
1295+
dirpath=lambda d: f"{d}/x/y/z/",
1296+
basename=lambda b: b.lower(),
1297+
extension=lambda e: "xls",
1298+
),
1299+
"/root/a/b/c/x/y/z/document.xls",
1300+
)
1301+
12251302
def test_write_file(self):
12261303
path = self.temp_path("a/b/c.txt")
12271304
fsutil.write_file(path, content="Hello World")

0 commit comments

Comments
 (0)