diff --git a/Makefile b/Makefile index 0699ddf..e2e7ea6 100644 --- a/Makefile +++ b/Makefile @@ -51,11 +51,15 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache lint: ## check style with flake8 + black s2rename tests setup.py flake8 s2rename tests -test: ## run tests quickly with the default Python +alltests: ## run all tests with the default Python py.test +test: ## run tests quickly with the default Python, exit on first error + py.test --exitfirst -s + coverage: ## check code coverage quickly with the default Python coverage run --source s2rename -m pytest coverage report -m diff --git a/requirements_dev.txt b/requirements_dev.txt index 41d51f6..3621f8b 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -4,7 +4,7 @@ wheel==0.32.1 watchdog==0.9.0 flake8==3.5.0 coverage==4.5.1 -black>=18.9 +black>=18.9b0 pytest==3.8.2 pytest-runner==4.2 diff --git a/s2rename/__init__.py b/s2rename/__init__.py index 55ec5d3..7bccd85 100644 --- a/s2rename/__init__.py +++ b/s2rename/__init__.py @@ -3,5 +3,5 @@ """Top-level package for S2Rename.""" __author__ = """Holger Frey""" -__email__ = 'frey@imtek.de' -__version__ = '0.0.1' +__email__ = "frey@imtek.de" +__version__ = "0.0.1" diff --git a/s2rename/cli.py b/s2rename/cli.py index 5276f59..2dc9512 100644 --- a/s2rename/cli.py +++ b/s2rename/cli.py @@ -8,8 +8,7 @@ import click @click.command() def main(args=None): """Console script for s2rename.""" - click.echo("Replace this message by putting your code into " - "s2rename.cli.main") + click.echo("Replace this message by putting your code into " "s2rename.cli.main") click.echo("See click documentation at http://click.pocoo.org/") return 0 diff --git a/s2rename/s2rename.py b/s2rename/s2rename.py index 7fbbae4..1536dc3 100644 --- a/s2rename/s2rename.py +++ b/s2rename/s2rename.py @@ -1,3 +1,64 @@ # -*- coding: utf-8 -*- """Main module.""" + +import re + +from collections import namedtuple +from pathlib import Path + +REGEX_ID = r"(?P[A-H])(?P(0?[1-9]|1[0-2]))_(?P\d)" +REGEX_SENSOVATION = r"(?P(.+_|))" + REGEX_ID +REGEX_SCIENION = REGEX_ID + r"(?P(.+_|))" + +RE_SENSOVATION = re.compile(REGEX_SENSOVATION) +RE_SCIENION = re.compile(REGEX_SENSOVATION) + + +TPL_SENSOVATION = '{r.stem}_{r.row}{r.col:0>{dec}d}_{r.channel}' + +class S2IOError(IOError): + """ custom IO Exception """ + + +Renamable = namedtuple("Renamable", "path,stem,row,col,channel") + + +def get_source_list(folder, suffix=None): + """ returns the files in a directory that are not hidden + + if 'suffix' is given, the list will only return files with the given + extension + """ + src_dir = Path(folder) + if not src_dir.is_dir(): + raise S2IOError(f"{src_dir} is not a directory") + all_files = (f for f in src_dir.iterdir() if f.is_file()) + non_hidden_files = (f for f in all_files if not f.stem.startswith(".")) + if suffix is None: + return non_hidden_files + else: + return filter_source_list(non_hidden_files, suffix) + + +def filter_source_list(source_list, suffix): + """ filters pathlib.Path objects by only containing a given suffix """ + return (f for f in source_list if f.suffix.lower() == suffix) + + +def parse_source_list(source_list, regex): + """ returns a list of items that can be renamed """ + for path in source_list: + groups = regex.match(path.stem) + if groups: + stem = groups["stem"] + if stem.endswith('_'): + stem = stem[:-1] + entry = Renamable( + path=path, + stem=stem, + row=groups["row"], + col=int(groups["col"]), + channel=groups["channel"], + ) + yield entry diff --git a/setup.cfg b/setup.cfg index 5c4fd98..fcaad88 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,7 +15,10 @@ replace = __version__ = '{new_version}' universal = 1 [flake8] -exclude = docs +max-line-length = 88 +exclude = + .venv, + docs [aliases] # Define setup.py command aliases here diff --git a/setup.py b/setup.py index 63edcd6..00de172 100644 --- a/setup.py +++ b/setup.py @@ -5,42 +5,38 @@ from setuptools import setup, find_packages -with open('README.md') as readme_file: +with open("README.md") as readme_file: readme = readme_file.read() -requirements = ['Click>=6.0', ] +requirements = ["Click>=6.0"] -setup_requirements = ['pytest-runner', ] +setup_requirements = ["pytest-runner"] -test_requirements = ['pytest', ] +test_requirements = ["pytest"] setup( author="Holger Frey", - author_email='frey@imtek.de', + author_email="frey@imtek.de", classifiers=[ - 'Development Status :: 2 - Pre-Alpha', - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', + "Development Status :: 2 - Pre-Alpha", + "Intended Audience :: Developers", + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", ], description="Renaming files for SensoSpot and Scienion software", - entry_points={ - 'console_scripts': [ - 's2rename=s2rename.cli:main', - ], - }, + entry_points={"console_scripts": ["s2rename=s2rename.cli:main"]}, install_requires=requirements, long_description=readme, include_package_data=True, - keywords='s2rename', - name='s2rename', - packages=find_packages(include=['s2rename']), + keywords="s2rename", + name="s2rename", + packages=find_packages(include=["s2rename"]), setup_requires=setup_requirements, - test_suite='tests', + test_suite="tests", tests_require=test_requirements, - url='https://github.com/audreyr/s2rename', - version='0.0.1', + url="https://github.com/audreyr/s2rename", + version="0.0.1", zip_safe=False, ) diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..74fd281 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,21 @@ +#!/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 diff --git a/tests/test_s2rename.py b/tests/test_s2rename.py index 01870d5..c5dbcce 100644 --- a/tests/test_s2rename.py +++ b/tests/test_s2rename.py @@ -5,34 +5,107 @@ import pytest -from click.testing import CliRunner +from pathlib import Path -from s2rename import s2rename -from s2rename import cli +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"), +] -@pytest.fixture -def response(): - """Sample pytest fixture. +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"), +] - See more at: http://doc.pytest.org/en/latest/fixture.html - """ - # import requests - # return requests.get('https://github.com/audreyr/cookiecutter-pypackage') +@pytest.mark.parametrize("sources", [sensovation_source_list, scienion_source_list]) +def test_parse_source_list_sensovation(sources): + from s2rename import s2rename -def test_content(response): - """Sample pytest test function with the pytest fixture as an argument.""" - # from bs4 import BeautifulSoup - # assert 'GitHub' in BeautifulSoup(response.content).title.string + 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" -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