Skip to content
84 changes: 50 additions & 34 deletions src/imcflibs/pathtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


def parse_path(path, prefix=""):
"""Parse a path into its components.
r"""Parse a path into its components.

If the path doesn't end with the pathsep, it is assumed being a file!
No tests based on existing files are done, as this is supposed to also work
Expand All @@ -20,6 +20,11 @@ def parse_path(path, prefix=""):
*Script Parameter* `#@ File`) for either of the parameters, so it is safe to
use this in ImageJ Python scripts without additional measures.

**WARNING**: when passing in **Windows paths** literally, make sure to
declare them as **raw strings** using the `r""` notation, otherwise
unexpected things might happen if the path contains sections that Python
will interpret as escape sequences (e.g. `\n`, `\t`, `\u2324`, ...).

Parameters
----------
path : str or str-like
Expand Down Expand Up @@ -55,50 +60,61 @@ def parse_path(path, prefix=""):
POSIX-style path to a file with a suffix:

>>> parse_path('/tmp/foo/file.suffix')
{'dname': 'foo',
'ext': '',
'fname': 'file',
'full': '/tmp/foo/file',
'basename': 'file',
'orig': '/tmp/foo/file',
'parent': '/tmp/',
'path': '/tmp/foo/'}
{
"dname": "foo",
"ext": "",
"fname": "file",
"full": "/tmp/foo/file",
"basename": "file",
"orig": "/tmp/foo/file",
"parent": "/tmp/",
"path": "/tmp/foo/",
}


POSIX-style path to a directory:

>>> parse_path('/tmp/foo/')
{'dname': 'foo',
'ext': '',
'fname': '',
'full': '/tmp/foo/',
'basename': '',
'orig': '/tmp/foo/',
'parent': '/tmp/',
'path': '/tmp/foo/'}
{
"dname": "foo",
"ext": "",
"fname": "",
"full": "/tmp/foo/",
"basename": "",
"orig": "/tmp/foo/",
"parent": "/tmp/",
"path": "/tmp/foo/",
}


Windows-style path to a file:

>>> parse_path('C:\\Temp\\foo\\file.ext')
{'dname': 'foo',
'ext': '.ext',
'fname': 'file.ext',
'full': 'C:/Temp/foo/file.ext',
'basename': 'file',
'orig': 'C:\\Temp\\foo\\file.ext',
'parent': 'C:/Temp/',
'path': 'C:/Temp/foo/'}
>>> parse_path(r'C:\Temp\new\file.ext')
{
"dname": "new",
"ext": ".ext",
"fname": "file.ext",
"full": "C:/Temp/new/file.ext",
"basename": "file",
"orig": "C:\\Temp\\new\\file.ext",
"parent": "C:/Temp",
"path": "C:/Temp/new/",
}


Special treatment for *OME-TIFF* suffixes:

>>> parse_path("/path/to/some/nice.OME.tIf")
{'basename': 'nice',
'dname': 'some',
'ext': '.OME.tIf',
'fname': 'nice.OME.tIf',
'full': '/path/to/some/nice.OME.tIf',
'orig': '/path/to/some/nice.OME.tIf',
'parent': '/path/to/',
'path': '/path/to/some/'}
{
"basename": "nice",
"dname": "some",
"ext": ".OME.tIf",
"fname": "nice.OME.tIf",
"full": "/path/to/some/nice.OME.tIf",
"orig": "/path/to/some/nice.OME.tIf",
"parent": "/path/to/",
"path": "/path/to/some/",
}
"""
path = str(path)
if prefix:
Expand Down
43 changes: 38 additions & 5 deletions tests/test_pathtools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Tests for `imcflibs.pathtools`."""
# -*- coding: utf-8 -*-

import pytest
from imcflibs.pathtools import parse_path
from imcflibs.pathtools import jython_fiji_exists
from imcflibs.pathtools import image_basename
Expand All @@ -12,6 +11,7 @@


def test_parse_path():
"""Tests using regular POSIX-style paths."""
path = "/tmp/foo/"
path_to_dir = parse_path(path)
path_to_file = parse_path(path + "file.ext")
Expand All @@ -35,20 +35,53 @@ def test_parse_path():


def test_parse_path_windows():
path = r"C:\foo\bar"
"""Test using a Windows-style path."""
path = r"C:\Foo\Bar"
parsed = parse_path(path)

assert parsed["orig"] == path
assert parsed["full"] == r"C:/foo/bar"
assert parsed["fname"] == "bar"
assert parsed["dname"] == "foo"
assert parsed["full"] == "C:/Foo/Bar"
assert parsed["fname"] == "Bar"
assert parsed["dname"] == "Foo"


def test_parse_path_windows_newline_tab():
"""Test a Windows path with newline and tab sequences as raw string."""
path = r"C:\Temp\new\file.ext"
parsed = parse_path(path)

assert parsed == {
"dname": "new",
"ext": ".ext",
"fname": "file.ext",
"full": "C:/Temp/new/file.ext",
"basename": "file",
"orig": "C:\\Temp\\new\\file.ext",
"parent": "C:/Temp",
"path": "C:/Temp/new/",
}


def test_parse_path_windows_nonraw():
r"""Test non-raw string containing newline `\n` and tab `\t` sequences.

As `parse_path()` cannot work on non-raw strings containing escape
sequences, the parsed result will not be the expected one.
"""
path = "C:\new_folder\test"
parsed = parse_path(path)

assert parsed["full"] != r"C:\new_folder\test"
assert parsed["fname"] != "test"


def test_jython_fiji_exists(tmpdir):
"""Test the Jython/Fiji `os.path.exists()` workaround."""
assert jython_fiji_exists(str(tmpdir)) == True


def test_image_basename():
"""Test basename extraction for various image file names."""
assert image_basename("/path/to/image_file_01.png") == "image_file_01"
assert image_basename("more-complex-stack.ome.tif") == "more-complex-stack"
assert image_basename("/tmp/FoObAr.OMe.tIf") == "FoObAr"
Loading