Browse Source

first working script

master
Holger Frey 6 years ago
parent
commit
cb29c6d1c5
  1. 49
      s2rename/cli.py
  2. 45
      s2rename/helpers.py
  3. 2
      setup.py
  4. 21
      tests/test_cli.py
  5. 182
      tests/test_helpers.py
  6. 111
      tests/test_s2rename.py

49
s2rename/cli.py

@ -4,14 +4,55 @@
import sys import sys
import click import click
from . import helpers
@click.command() @click.command()
def main(args=None): @click.argument(
"folder",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
writable=True,
readable=True,
allow_dash=False,
),
)
@click.option(
"--from",
"-f",
"from_",
type=click.Choice(["sensovation", "scienion"]),
required=True,
)
@click.option(
"--to", "-t", type=click.Choice(["sensovation", "scienion"]), required=True
)
@click.option("--digits", "-d", type=click.IntRange(1, 2), default=1)
@click.option("--ext", "-e", default=None)
@click.option("--verbose", "-v", count=True)
def main(folder, from_, to, digits, ext, verbose):
"""Console script for s2rename.""" """Console script for s2rename."""
click.echo("Replace this message by putting your code into " "s2rename.cli.main") try:
click.echo("See click documentation at http://click.pocoo.org/") if from_.startswith("sc"):
regex = helpers.RE_SCIENION
else:
regex = helpers.RE_SENSOVATION
if to.startswith("sc"):
template = helpers.template_scienion
else:
template = helpers.template_sensovation
file_list = helpers.get_source_list(folder, ext)
renamables = helpers.parse_source_list(file_list, regex)
helpers.rename_files(renamables, template, digits)
except IOError as e:
click.echo("could not rename files")
if verbose:
raise e
return 1
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main()) # pragma: no cover sys.exit(main())

45
s2rename/s2rename.py → s2rename/helpers.py

@ -7,21 +7,29 @@ import re
from collections import namedtuple from collections import namedtuple
from pathlib import Path from pathlib import Path
# on the complete regex '.*' is not used, since it would also capture
# double column definitions like "something_AB12"
REGEX_ID = r"(?P<row>[A-H])(?P<col>(0?[1-9]|1[0-2]))_(?P<channel>\d)" REGEX_ID = r"(?P<row>[A-H])(?P<col>(0?[1-9]|1[0-2]))_(?P<channel>\d)"
REGEX_SENSOVATION = r"(?P<stem>(.+_|))" + REGEX_ID REGEX_SENSOVATION = r"(?P<stem>(.+_|))" + REGEX_ID
REGEX_SCIENION = REGEX_ID + r"(?P<stem>(.+_|))" REGEX_SCIENION = REGEX_ID + r"(?P<stem>(_.+|))"
RE_SENSOVATION = re.compile(REGEX_SENSOVATION) RE_SENSOVATION = re.compile(REGEX_SENSOVATION)
RE_SCIENION = re.compile(REGEX_SENSOVATION) RE_SCIENION = re.compile(REGEX_SCIENION)
TPL_ID = "{row}{col:0>{dec}d}_{channel}"
TPL_SENSOVATION = "{stem}" + TPL_ID
TPL_SCIENION = TPL_ID + "{stem}"
TPL_SENSOVATION = '{r.stem}_{r.row}{r.col:0>{dec}d}_{r.channel}'
class S2IOError(IOError): Renamable = namedtuple("Renamable", "path,stem,row,col,channel,ext")
""" custom IO Exception """ FileNameTemplate = namedtuple("FileNameTemplate", "template,prefix,suffix")
template_sensovation = FileNameTemplate(template=TPL_SENSOVATION, prefix="", suffix="_")
template_scienion = FileNameTemplate(TPL_SCIENION, prefix="_", suffix="")
Renamable = namedtuple("Renamable", "path,stem,row,col,channel") class S2IOError(IOError):
""" custom IO Exception """
def get_source_list(folder, suffix=None): def get_source_list(folder, suffix=None):
@ -49,16 +57,35 @@ def filter_source_list(source_list, suffix):
def parse_source_list(source_list, regex): def parse_source_list(source_list, regex):
""" returns a list of items that can be renamed """ """ returns a list of items that can be renamed """
for path in source_list: for path in source_list:
if path.name.startswith("."):
continue
groups = regex.match(path.stem) groups = regex.match(path.stem)
if groups: if groups:
stem = groups["stem"] stem = groups["stem"].strip("_")
if stem.endswith('_'):
stem = stem[:-1]
entry = Renamable( entry = Renamable(
path=path, path=path,
stem=stem, stem=stem,
row=groups["row"], row=groups["row"],
col=int(groups["col"]), col=int(groups["col"]),
channel=groups["channel"], channel=groups["channel"],
ext=path.suffix,
) )
yield entry yield entry
def get_new_name(item, name_template, digits):
stem = item.stem
if stem:
# only apply prefix and suffix if the name is not empty
stem = name_template.prefix + stem + name_template.suffix
new_name = name_template.template.format(
stem=stem, row=item.row, col=item.col, channel=item.channel, dec=digits
)
return new_name + item.ext
def rename_files(renamable_list, name_template, digits):
for item in renamable_list:
new_name = get_new_name(item, name_template, digits)
new_path = item.path.with_name(new_name)
item.path.replace(new_path)

2
setup.py

@ -26,7 +26,7 @@ setup(
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.7",
], ],
description="Renaming files for SensoSpot and Scienion software", description="Renaming files for SensoSpot and Scienion software",
entry_points={"console_scripts": ["s2rename=s2rename.cli:main"]}, entry_points={"console_scripts": ["s2renamecli=s2rename.cli:main"]},
install_requires=requirements, install_requires=requirements,
long_description=readme, long_description=readme,
include_package_data=True, include_package_data=True,

21
tests/test_cli.py

@ -1,21 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests for `s2rename` package."""
import pytest
from click.testing import CliRunner
from s2rename import cli
def test_command_line_interface():
"""Test the CLI."""
runner = CliRunner()
result = runner.invoke(cli.main)
assert result.exit_code == 0
assert "s2rename.cli.main" in result.output
help_result = runner.invoke(cli.main, ["--help"])
assert help_result.exit_code == 0
assert "--help Show this message and exit." in help_result.output

182
tests/test_helpers.py

@ -0,0 +1,182 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests for `s2rename` package."""
import pytest
from pathlib import Path
sensovation_source_list = [
Path("some thing_A1_1.tif"),
Path("some thing_A02_2.tif"),
Path("A03_3.tif"),
Path("some thing_A10_4"),
Path("some thing_A11_5.csv"),
Path("some thing_A12_6.xml"),
Path("some thing_B01_1.tif"),
Path("some thing_C01_1.tif"),
Path("some thing_D01_1.tif"),
Path("some thing_E01_1.tif"),
Path("some thing_F01_1.tif"),
Path("some thing_G01_1.tif"),
Path("some thing_H01_1.tif"),
Path("some thing_I01_1.tif"),
Path("some thing_FF01_1.tif"),
Path("some thing_F21_1.tif"),
Path("some thing_F00_1.tif"),
Path("some thing_F0_1.tif"),
Path("some thing_F13_1.tif"),
Path("some thing_F08.tif"),
Path(".some thing_F09_1.tif"),
]
scienion_source_list = [
Path("A1_1_some thing.tif"),
Path("A02_2_some thing.tif"),
Path("A03_3.tif"),
Path("A10_4_some thing"),
Path("A11_5_some thing.csv"),
Path("A12_6_some thing.xml"),
Path("B01_1_some thing.tif"),
Path("C01_1_some thing.tif"),
Path("D01_1_some thing.tif"),
Path("E01_1_some thing.tif"),
Path("F01_1_some thing.tif"),
Path("G01_1_some thing.tif"),
Path("H01_1_some thing.tif"),
Path("I01_1_some thing.tif"),
Path("FF01_1_some thing.tif"),
Path("F21_1_some thing.tif"),
Path("F00_1_some thing.tif"),
Path("F0_1_some thing.tif"),
Path("F13_1_some thing.tif"),
Path("F08_some thing.tif"),
Path(".F09_1_some thing.tif"),
]
@pytest.mark.parametrize("sources", [sensovation_source_list, scienion_source_list])
def test_parse_source_list_sensovation(sources):
from s2rename.helpers import RE_SENSOVATION, RE_SCIENION, parse_source_list
regex = RE_SENSOVATION if sources == sensovation_source_list else RE_SCIENION
result = list(parse_source_list(sources, regex))
assert len(result) == 13
assert {r.row for r in result} == set("ABCDEFGH")
assert {r.col for r in result} == {1, 2, 3, 10, 11, 12}
assert {r.channel for r in result} == set("123456")
assert {r.ext for r in result} == {".tif", ".csv", ".xml", ""}
assert {r.stem for r in result} == {"some thing", ""}
def test_get_source_list():
from s2rename.helpers import get_source_list
result = list(get_source_list("."))
assert {p.name for p in result} == {
"LICENSE",
"Pipfile",
"requirements_dev.txt",
"setup.cfg",
"Makefile",
"README.md",
"setup.py",
}
@pytest.mark.parametrize("path", ["/i/hope/this/doesnt/exist", "setup.py"])
def test_get_source_list_raises_error(path):
from s2rename.helpers import get_source_list, S2IOError
with pytest.raises(S2IOError):
get_source_list(path)
def test_get_source_list_with_type():
from s2rename.helpers import get_source_list
result = get_source_list(".", ".txt")
assert {p.name for p in result} == {"requirements_dev.txt"}
def test_filter_source_list_type():
from s2rename.helpers import filter_source_list
result = list(filter_source_list(sensovation_source_list, ".csv"))
assert len(result) == 1
assert result[0].name == "some thing_A11_5.csv"
def test_get_new_name_simple():
from s2rename.helpers import get_new_name, Renamable, template_sensovation
r = Renamable(
path=Path("x.csv"), stem="some_name", row="A", col=2, channel=3, ext=".csv"
)
result = get_new_name(r, template_sensovation, digits=2)
assert result == "some_name_A02_3.csv"
@pytest.mark.parametrize(
"tpl,stem,row,col,channel,digits,ext,expected",
[
("sen", "some_name", "A", 1, 2, 1, ".xls", "some_name_A1_2.xls"),
("sen", "some_name", "A", 1, 2, 2, ".xls", "some_name_A01_2.xls"),
("sen", "some_name", "A", 1, 2, 3, ".xls", "some_name_A001_2.xls"),
("sen", "some_name", "B", 1, 2, 2, ".xls", "some_name_B01_2.xls"),
("sen", "some_name", "A", 2, 2, 2, ".xls", "some_name_A02_2.xls"),
("sen", "some_name", "A", 1, 3, 2, ".xls", "some_name_A01_3.xls"),
("sen", "some_name", "A", 1, 3, 2, ".tif", "some_name_A01_3.tif"),
("sen", "", "A", 1, 3, 2, ".xls", "A01_3.xls"),
("sci", "some_name", "A", 1, 2, 1, ".xls", "A1_2_some_name.xls"),
("sci", "some_name", "A", 1, 2, 2, ".xls", "A01_2_some_name.xls"),
("sci", "some_name", "A", 1, 2, 3, ".xls", "A001_2_some_name.xls"),
("sci", "some_name", "B", 1, 2, 2, ".xls", "B01_2_some_name.xls"),
("sci", "some_name", "A", 2, 2, 2, ".xls", "A02_2_some_name.xls"),
("sci", "some_name", "A", 1, 3, 2, ".xls", "A01_3_some_name.xls"),
("sci", "some_name", "A", 1, 3, 2, ".tif", "A01_3_some_name.tif"),
("sci", "", "A", 1, 3, 2, ".xls", "A01_3.xls"),
],
)
def test_get_new_name(tpl, stem, row, col, channel, digits, ext, expected):
from s2rename.helpers import (
get_new_name,
Renamable,
template_sensovation,
template_scienion,
)
path = Path("x" + ext)
r = Renamable(path=path, stem=stem, row=row, col=col, channel=channel, ext=ext)
tpl = template_sensovation if tpl == "sen" else template_scienion
result = get_new_name(r, tpl, digits=digits)
assert result == expected
def test_rename_files():
from s2rename.helpers import rename_files, Renamable, template_sensovation
old_path = Path("old.txt")
new_path = Path("new_A001_2.xxx")
renamable_item = Renamable(
path=old_path, stem="new", row="A", col=1, channel=2, ext=".xxx"
)
with open(old_path, "w") as fh:
fh.write("\n")
assert old_path.is_file()
assert not new_path.is_file()
rename_files([renamable_item], template_sensovation, 3)
assert not old_path.is_file()
assert new_path.is_file()
new_path.unlink()

111
tests/test_s2rename.py

@ -1,111 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests for `s2rename` package."""
import pytest
from pathlib import Path
sensovation_source_list = [
Path("some prefix thing_A1_1.tif"),
Path("some prefix thing_A02_2.tif"),
Path("A03_3.tif"),
Path("some prefix thing_A10_4"),
Path("some prefix thing_A11_5.csv"),
Path("some prefix thing_A12_6.xml"),
Path("some prefix thing_B01_1.tif"),
Path("some prefix thing_C01_1.tif"),
Path("some prefix thing_D01_1.tif"),
Path("some prefix thing_E01_1.tif"),
Path("some prefix thing_F01_1.tif"),
Path("some prefix thing_G01_1.tif"),
Path("some prefix thing_H01_1.tif"),
Path("some prefix thing_I01_1.tif"),
Path("some prefix thing_FF01_1.tif"),
Path("some prefix thing_F21_1.tif"),
Path("some prefix thing_F00_1.tif"),
Path("some prefix thing_F0_1.tif"),
Path("some prefix thing_F13_1.tif"),
Path("some prefix thing_F08.tif"),
Path(".some prefix thing_F09_1.tif"),
]
scienion_source_list = [
Path("A1_1_some suffix thing.tif"),
Path("A02_2_some suffix thing.tif"),
Path("A03_3.tif"),
Path("A10_3_some suffix thing"),
Path("A11_4_some suffix thing.csv"),
Path("A12_5_some suffix thing.xml"),
Path("B01_1_some suffix thing.tif"),
Path("C01_1_some suffix thing.tif"),
Path("D01_1_some suffix thing.tif"),
Path("E01_1_some suffix thing.tif"),
Path("F01_1_some suffix thing.tif"),
Path("G01_1_some suffix thing.tif"),
Path("H01_1_some suffix thing.tif"),
Path("I01_1_some suffix thing.tif"),
Path("FF01_1_some suffix thing.tif"),
Path("F21_1_some suffix thing.tif"),
Path("F00_1_some suffix thing.tif"),
Path("F0_1_some suffix thing.tif"),
Path("F13_1_some suffix thing.tif"),
Path("F08_some suffix thing.tif"),
Path(".F09_1_some suffix thing.tif"),
]
@pytest.mark.parametrize("sources", [sensovation_source_list, scienion_source_list])
def test_parse_source_list_sensovation(sources):
from s2rename import s2rename
if sources == sensovation_source_list:
regex = s2rename.RE_SENSOVATION
else:
regex = s2rename.RE_SCIENION
result = list(s2rename.parse_source_list(sensovation_source_list, regex))
assert len(result) == 14
assert {r.row for r in result} == set("ABCDEFGH")
assert {r.col for r in result} == set([1, 2, 3, 9, 10, 11, 12])
def test_get_source_list():
from s2rename import s2rename
result = list(s2rename.get_source_list("."))
assert {p.name for p in result} == {
"LICENSE",
"Pipfile",
"requirements_dev.txt",
"setup.cfg",
"Makefile",
"README.md",
"setup.py",
}
@pytest.mark.parametrize("path", ["/i/hope/this/doesnt/exist", "setup.py"])
def test_get_source_list_raises_error(path):
from s2rename import s2rename
with pytest.raises(s2rename.S2IOError):
result = s2rename.get_source_list(path)
def test_get_source_list_with_type():
from s2rename import s2rename
result = s2rename.get_source_list(".", ".txt")
assert {p.name for p in result} == {"requirements_dev.txt"}
def test_filter_source_list_type():
from s2rename import s2rename
result = list(s2rename.filter_source_list(sensovation_source_list, ".csv"))
assert len(result) == 1
assert result[0].name == "some prefix thing_A11_5.csv"