summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorM.Eng. Thomas Feldmann <mail@tfeldmann.de>2022-08-17 18:25:07 +0200
committerGitHub <noreply@github.com>2022-08-17 18:25:07 +0200
commit084e6200b6e7e6206ca6ea6051fe1769ea3ea1d2 (patch)
treeaa515a901c53f99ae3683d640db1224bd21d950b /tests
parentc1ead1a3325da4d40c2d40b737f7a78c8a90d4a1 (diff)
Improve testing and support fs_urls as working dir (#234)
* wip * update comment * support working dir in `core.run()` * add copy tests * add tests * improve duplicate and regex * refactor to testfs * add test_delete * add tests * add coverage to dev deps * add unicode tests * add filecontent tests * refactor working_dir cli option * add extension test * add python filter tests * add cli test * support fs_url in cli * add test_rename * update cli * normalize paths in filters * normalize paths in action pipeline * add windows path handler * use fs.path.join instead of os
Diffstat (limited to 'tests')
-rw-r--r--tests/actions/test_copy.py193
-rw-r--r--tests/actions/test_delete.py97
-rw-r--r--tests/actions/test_move.py95
-rw-r--r--tests/actions/test_rename.py116
-rw-r--r--tests/actions/test_trash.py39
-rw-r--r--tests/conftest.py59
-rw-r--r--tests/core/test_config.py9
-rw-r--r--tests/core/test_unicode.py80
-rw-r--r--tests/docs/test_docs.py8
-rw-r--r--tests/filters/test_duplicate.py75
-rw-r--r--tests/filters/test_exif.py89
-rw-r--r--tests/filters/test_extension.py34
-rw-r--r--tests/filters/test_filecontent.py32
-rw-r--r--tests/filters/test_python.py204
-rw-r--r--tests/filters/test_regex.py22
-rw-r--r--tests/filters/test_size.py80
-rw-r--r--tests/integration/test_cli.py80
-rw-r--r--tests/integration/test_delete.py45
-rw-r--r--tests/integration/test_dependent_rules.py34
-rw-r--r--tests/integration/test_dict_merge.py33
-rw-r--r--tests/integration/test_duplicate.py76
-rw-r--r--tests/integration/test_rename.py45
-rw-r--r--tests/integration/test_rename_regex.py32
-rw-r--r--tests/resources/images-with-exif/1.jpg (renamed from tests/resources/1.jpg)bin4809 -> 4809 bytes
-rwxr-xr-xtests/resources/images-with-exif/2.jpg (renamed from tests/resources/2.jpg)bin4382 -> 4382 bytes
-rw-r--r--tests/resources/images-with-exif/3.jpg (renamed from tests/resources/3.jpg)bin5253 -> 5253 bytes
-rw-r--r--tests/resources/images-with-exif/4.jpg (renamed from tests/resources/4.jpg)bin5349 -> 5349 bytes
-rw-r--r--tests/resources/images-with-exif/5.jpg (renamed from tests/resources/5.jpg)bin6110 -> 6110 bytes
-rw-r--r--tests/todo/integration/test_exif.py128
-rw-r--r--tests/todo/integration/test_extension.py31
-rw-r--r--tests/todo/integration/test_file_content.py35
-rw-r--r--tests/todo/integration/test_filesize.py88
-rw-r--r--tests/todo/integration/test_globstrings.py154
-rw-r--r--tests/todo/integration/test_integration.py46
-rw-r--r--tests/todo/integration/test_python_filter.py180
-rw-r--r--tests/todo/integration/test_regex.py25
-rw-r--r--tests/todo/integration/test_rename.py38
-rw-r--r--tests/todo/integration/test_startswith.py34
-rw-r--r--tests/todo/integration/test_unicode.py63
-rw-r--r--tests/todo/todo_copy.py30
40 files changed, 1246 insertions, 1183 deletions
diff --git a/tests/actions/test_copy.py b/tests/actions/test_copy.py
index ea87e90..a497d17 100644
--- a/tests/actions/test_copy.py
+++ b/tests/actions/test_copy.py
@@ -1,69 +1,152 @@
-from copy import deepcopy
-
-import fs
+from fs.base import FS
+import pytest
from conftest import make_files, read_files
from organize import core
files = {
- "files": {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "folder": {
+ "x.txt": "",
+ },
+}
+
+
+@pytest.fixture
+def testfiles(testfs) -> FS:
+ make_files(testfs, files)
+ yield testfs
+
+
+def test_copy_on_itself(testfiles):
+ config = """
+ rules:
+ - locations: "/"
+ actions:
+ - copy: "/"
+ """
+ core.run(config, simulate=False, working_dir=testfiles)
+ result = read_files(testfiles)
+ assert result == files
+
+
+def test_copy_into_dir(testfiles):
+ config = """
+ rules:
+ - locations: "/"
+ actions:
+ - copy: "a brand/new/folder/"
+ """
+ core.run(config, simulate=False, working_dir=testfiles)
+ result = read_files(testfiles)
+ assert result == {
"test.txt": "",
"file.txt": "Hello world\nAnother line",
"another.txt": "",
"folder": {
"x.txt": "",
},
+ "a brand": {
+ "new": {
+ "folder": {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ }
+ }
+ },
}
-}
-def test_copy_on_itself():
- with fs.open_fs("mem://") as mem:
- config = {
- "rules": [
- {
- "locations": [
- {"path": "files", "filesystem": mem},
- ],
- "actions": [
- {"copy": {"dest": "files/", "filesystem": mem}},
- ],
- },
- ]
- }
- make_files(mem, files)
- core.run(config, simulate=False)
- result = read_files(mem)
- assert result == files
-
-
-def test_does_not_create_folder_in_simulation():
- with fs.open_fs("mem://") as mem:
- config = {
- "rules": [
- {
- "locations": [
- {"path": "files", "filesystem": mem},
- ],
- "actions": [
- {"copy": {"dest": "files/new-subfolder/", "filesystem": mem}},
- {"copy": {"dest": "files/copyhere/", "filesystem": mem}},
- ],
- },
- ]
- }
- make_files(mem, files)
- core.run(config, simulate=True)
- result = read_files(mem)
- assert result == files
-
- core.run(config, simulate=False, validate=False)
- result = read_files(mem)
-
- expected = deepcopy(files)
- expected["files"]["new-subfolder"] = deepcopy(files["files"])
- expected["files"]["new-subfolder"].pop("folder")
- expected["files"]["copyhere"] = deepcopy(files["files"])
- expected["files"]["copyhere"].pop("folder")
-
- assert result == expected
+def test_copy_into_dir_subfolders(testfiles):
+ config = """
+ rules:
+ - locations: "/"
+ subfolders: true
+ actions:
+ - copy: "a brand/new/folder/"
+ """
+ core.run(config, simulate=False, working_dir=testfiles)
+ result = read_files(testfiles)
+ assert result == {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "folder": {
+ "x.txt": "",
+ },
+ "a brand": {
+ "new": {
+ "folder": {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "x.txt": "",
+ }
+ }
+ },
+ }
+
+
+@pytest.mark.parametrize(
+ "mode,files,test_txt_content",
+ [
+ ("skip", ["file.txt", "test.txt"], "old"),
+ ("overwrite", ["file.txt", "test.txt"], "new"),
+ ("rename_new", ["file.txt", "test.txt", "test 1.txt"], "old"),
+ ("rename_existing", ["file.txt", "test.txt", "test 1.txt"], "new"),
+ ],
+)
+def test_copy_conflict(testfs: FS, mode, files, test_txt_content):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name: file
+ actions:
+ - copy:
+ dest: "test.txt"
+ on_conflict: {}
+ """.format(
+ mode
+ )
+ testfs.writetext("file.txt", "new")
+ testfs.writetext("test.txt", "old")
+ core.run(config, simulate=False, working_dir=testfs)
+ assert set(testfs.listdir("/")) == set(files)
+ assert testfs.readtext("file.txt") == "new"
+ assert testfs.readtext("test.txt") == test_txt_content
+
+
+# def test_does_not_create_folder_in_simulation():
+# with fs.open_fs("mem://") as mem:
+# config = {
+# "rules": [
+# {
+# "locations": [
+# {"path": "files", "filesystem": mem},
+# ],
+# "actions": [
+# {"copy": {"dest": "files/new-subfolder/", "filesystem": mem}},
+# {"copy": {"dest": "files/copyhere/", "filesystem": mem}},
+# ],
+# },
+# ]
+# }
+# make_files(mem, files)
+# core.run(config, simulate=True)
+# result = read_files(mem)
+# assert result == files
+
+# core.run(config, simulate=False, validate=False)
+# result = read_files(mem)
+
+# expected = deepcopy(files)
+# expected["files"]["new-subfolder"] = deepcopy(files["files"])
+# expected["files"]["new-subfolder"].pop("folder")
+# expected["files"]["copyhere"] = deepcopy(files["files"])
+# expected["files"]["copyhere"].pop("folder")
+
+# assert result == expected
diff --git a/tests/actions/test_delete.py b/tests/actions/test_delete.py
new file mode 100644
index 0000000..1b0d0f5
--- /dev/null
+++ b/tests/actions/test_delete.py
@@ -0,0 +1,97 @@
+from conftest import make_files, read_files
+
+from organize import core
+
+FILES = {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "folder": {
+ "x.txt": "",
+ "empty_sub": {},
+ },
+ "empty_folder": {},
+}
+
+
+def test_delete_empty_files(testfs):
+ config = """
+ rules:
+ - name: "Recursively delete all empty files"
+ locations:
+ - path: "/"
+ subfolders: true
+ filters:
+ - empty
+ actions:
+ - delete
+ """
+ make_files(testfs, FILES)
+ core.run(config, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ assert result == {
+ "file.txt": "Hello world\nAnother line",
+ "folder": {
+ "empty_sub": {},
+ },
+ "empty_folder": {},
+ }
+
+
+def test_delete_empty_dirs(testfs):
+ config = """
+ rules:
+ - name: "Recursively delete all empty directories"
+ locations: "/"
+ subfolders: true
+ targets: dirs
+ filters:
+ - empty
+ actions:
+ - delete
+ """
+ make_files(testfs, FILES)
+ core.run(config, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ assert result == {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "folder": {
+ "x.txt": "",
+ },
+ }
+
+
+def test_delete_deep(testfs):
+ files = {
+ "files": {
+ "folder": {
+ "subfolder": {
+ "test.txt": "",
+ "other.pdf": "binary",
+ },
+ "file.txt": "Hello world\nAnother line",
+ },
+ }
+ }
+ make_files(testfs, files)
+ config = """
+ rules:
+ - locations: "."
+ actions:
+ - delete
+ - locations: "."
+ targets: dirs
+ actions:
+ - delete
+ """
+ # sim
+ core.run(config, simulate=True, working_dir=testfs)
+ result = read_files(testfs)
+ assert result == files
+
+ # run
+ core.run(config, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ assert result == {}
diff --git a/tests/actions/test_move.py b/tests/actions/test_move.py
index e28dfc9..042430d 100644
--- a/tests/actions/test_move.py
+++ b/tests/actions/test_move.py
@@ -1,44 +1,61 @@
-import fs
+import pytest
from conftest import make_files, read_files
+from fs.base import FS
from organize import core
+files = {
+ "test.txt": "",
+ "file.txt": "Hello world\nAnother line",
+ "another.txt": "",
+ "folder": {
+ "x.txt": "",
+ },
+}
-def test_move_on_itself():
- files = {
- "files": {
- "test.txt": "",
- "file.txt": "Hello world\nAnother line",
- "another.txt": "",
- "folder": {
- "x.txt": "",
- },
- }
- }
- with fs.open_fs("mem://") as mem:
- config = {
- "rules": [
- {
- "locations": [
- {"path": "files", "filesystem": mem},
- ],
- "actions": [
- {"copy": {"dest": "files/", "filesystem": mem}},
- ],
- },
- ]
- }
- make_files(mem, files)
- core.run(config, simulate=False)
- result = read_files(mem)
-
- assert result == {
- "files": {
- "test.txt": "",
- "file.txt": "Hello world\nAnother line",
- "another.txt": "",
- "folder": {
- "x.txt": "",
- },
- }
- }
+
+@pytest.fixture
+def testfiles(testfs) -> FS:
+ make_files(testfs, files)
+ yield testfs
+
+
+def test_copy_on_itself(testfiles):
+ config = """
+ rules:
+ - locations: "/"
+ actions:
+ - move: "/"
+ """
+ core.run(config, simulate=True, working_dir=testfiles)
+ result = read_files(testfiles)
+ assert result == files
+
+
+@pytest.mark.parametrize(
+ "mode,files,test_txt_content",
+ [
+ ("skip", ["file.txt", "test.txt"], "old"),
+ ("overwrite", ["test.txt"], "new"),
+ ("rename_new", ["test.txt", "test 1.txt"], "old"),
+ ("rename_existing", ["test.txt", "test 1.txt"], "new"),
+ ],
+)
+def test_move_conflict(testfs: FS, mode, files, test_txt_content):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name: file
+ actions:
+ - move:
+ dest: "test.txt"
+ on_conflict: {}
+ """.format(
+ mode
+ )
+ testfs.writetext("file.txt", "new")
+ testfs.writetext("test.txt", "old")
+ core.run(config, simulate=False, working_dir=testfs)
+ assert set(testfs.listdir("/")) == set(files)
+ assert testfs.readtext("test.txt") == test_txt_content
diff --git a/tests/actions/test_rename.py b/tests/actions/test_rename.py
new file mode 100644
index 0000000..220142a
--- /dev/null
+++ b/tests/actions/test_rename.py
@@ -0,0 +1,116 @@
+import fs
+from conftest import make_files, read_files
+
+from organize.core import run
+
+
+def test_rename_issue51(testfs):
+ # test for issue https://github.com/tfeldmann/organize/issues/51
+ files = {
+ "19asd_WF_test2.PDF": "",
+ "other.pdf": "",
+ "18asd_WFX_test2.pdf": "",
+ }
+ make_files(testfs, files)
+
+ CONFIG = """
+ rules:
+ - locations: "./"
+ filters:
+ - extension
+ - name:
+ startswith: "19"
+ contains:
+ - "_WF_"
+ actions:
+ - rename: "{name}_unread.{extension.lower()}"
+ - copy:
+ dest: "copy/"
+ """
+ run(CONFIG, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ assert result == {
+ "copy": {
+ "19asd_WF_test2_unread.pdf": "",
+ },
+ "19asd_WF_test2_unread.pdf": "",
+ "other.pdf": "",
+ "18asd_WFX_test2.pdf": "",
+ }
+
+
+def test_rename_folders(testfs):
+ config = """
+ rules:
+ - name: "Renaming DVD folders"
+ locations: "/"
+ targets: dirs
+ filters:
+ - name:
+ contains: DVD
+ actions:
+ - rename:
+ name: "{name.replace('[DVD] ','').replace(' [1080p]','').replace(' ', '_')}"
+ """
+ files = {
+ "[DVD] Best Of Video 1080 [1080p]": {
+ "[DVD] Best Of Video 1080 [1080p]": "",
+ "Metadata": "",
+ },
+ "[DVD] This Is A Title [1080p]": {
+ "[DVD] This Is A Title [1080p]": "",
+ "Metadata": "",
+ },
+ }
+ make_files(testfs, files)
+ run(rules=config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "Best_Of_Video_1080": {
+ "[DVD] Best Of Video 1080 [1080p]": "",
+ "Metadata": "",
+ },
+ "This_Is_A_Title": {
+ "[DVD] This Is A Title [1080p]": "",
+ "Metadata": "",
+ },
+ }
+
+
+def test_rename_in_subfolders(testfs):
+ config = """
+ rules:
+ - locations: "/"
+ subfolders: true
+ filters:
+ - name:
+ contains: RENAME
+ - extension
+ actions:
+ - rename: "DONE.{extension}"
+ """
+ files = {
+ "folder": {
+ "FIRST-RENAME.pdf": "",
+ "Other": "",
+ },
+ "Another folder": {
+ "Subfolder": {
+ "RENAME-ME_TOO.txt": "",
+ },
+ "Metadata": "",
+ },
+ }
+ make_files(testfs, files)
+ run(rules=config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "folder": {
+ "DONE.pdf": "",
+ "Other": "",
+ },
+ "Another folder": {
+ "Subfolder": {
+ "DONE.txt": "",
+ },
+ "Metadata": "",
+ },
+ }
diff --git a/tests/actions/test_trash.py b/tests/actions/test_trash.py
index 258a102..a593296 100644
--- a/tests/actions/test_trash.py
+++ b/tests/actions/test_trash.py
@@ -1,10 +1,47 @@
+import fs
from unittest.mock import patch
from organize.actions import Trash
+from organize.core import run
-def test_trash():
+def test_trash_mocked():
with patch("send2trash.send2trash") as mck:
trash = Trash()
trash.trash(path="~/Desktop/Test.zip", simulate=False)
mck.assert_called_with("~/Desktop/Test.zip")
+
+
+def test_trash_file():
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name: "test-trash-209318123"
+ actions:
+ - trash
+ """
+ with fs.open_fs("temp://") as tmp:
+ tmp.writetext("test-trash-209318123.txt", "Content")
+ assert tmp.exists("test-trash-209318123.txt")
+ run(config, simulate=False, working_dir=tmp.getsyspath("/"))
+ assert not tmp.exists("test-trash-209318123.txt")
+
+
+def test_trash_folder():
+ config = """
+ rules:
+ - locations: "."
+ targets: dirs
+ filters:
+ - name: "test-trash-209318123"
+ actions:
+ - trash
+ """
+ with fs.open_fs("temp://") as tmp:
+ tmp_dir = tmp.makedir("test-trash-209318123")
+ tmp_dir.touch("file.txt")
+ assert tmp.exists("test-trash-209318123/file.txt")
+ run(config, simulate=False, working_dir=tmp.getsyspath("/"))
+ assert not tmp.exists("test-trash-209318123/file.txt")
+ assert not tmp.exists("test-trash-209318123")
diff --git a/tests/conftest.py b/tests/conftest.py
index f23b433..8dcb763 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,10 +1,33 @@
+from typing import Union
from unittest.mock import patch
+import fs
import pytest
from fs.base import FS
from fs.path import basename, join
-from organize import config
+
+@pytest.fixture
+def tempfs():
+ with fs.open_fs("temp://") as tmp:
+ yield tmp
+
+
+@pytest.fixture
+def memfs():
+ with fs.open_fs("mem://") as mem:
+ yield mem
+
+
+@pytest.fixture(
+ params=[
+ "mem://",
+ # pytest.param("temp://", marks=pytest.mark.skip),
+ ],
+)
+def testfs(request) -> FS:
+ with fs.open_fs(request.param) as tmp:
+ yield tmp
@pytest.fixture
@@ -13,7 +36,7 @@ def mock_echo():
yield mck
-def make_files(fs: FS, layout: dict, path="/"):
+def make_files(fs: FS, layout: Union[dict, list], path="/"):
"""
layout = {
"folder": {
@@ -26,6 +49,10 @@ def make_files(fs: FS, layout: dict, path="/"):
}
"""
fs.makedirs(path, recreate=True)
+ if isinstance(layout, list):
+ for f in layout:
+ fs.touch(f)
+ return
for k, v in layout.items():
respath = join(path, k)
@@ -51,31 +78,3 @@ def read_files(fs: FS, path="/"):
for x in fs.walk.dirs(path, max_depth=0):
result[basename(x)] = read_files(fs, path=join(path, x))
return result
-
-
-def rules_shortcut(fs: FS, filters, actions, location="files", max_depth=0):
- if isinstance(filters, str):
- filters = config.load_from_string(filters)
- if isinstance(actions, str):
- actions = config.load_from_string(actions)
-
- # for action in actions:
- # for opts in action.values():
- # if "filesystem" in opts and opts["filesystem"] == "mem":
- # opts["filesystem"] = fs
-
- return {
- "rules": [
- {
- "locations": [
- {
- "path": location,
- "filesystem": fs,
- "max_depth": max_depth,
- }
- ],
- "actions": actions,
- "filters": filters,
- }
- ]
- }
diff --git a/tests/core/test_config.py b/tests/core/test_config.py
index 68e1d9a..c0cdd71 100644
--- a/tests/core/test_config.py
+++ b/tests/core/test_config.py
@@ -5,11 +5,10 @@ from schema import SchemaError
from organize import config, core
-def validate_and_convert(string: str):
+def validate_config(string: str):
conf = config.load_from_string(string)
conf = config.cleanup(conf)
config.validate(conf)
- core.replace_with_instances(conf)
return conf
@@ -33,7 +32,7 @@ def test_basic():
- shell:
cmd: 'say {path.stem}'
"""
- validate_and_convert(STR)
+ validate_config(STR)
def test_yaml_ref():
@@ -64,7 +63,7 @@ def test_yaml_ref():
actions:
- trash
"""
- validate_and_convert(STR)
+ validate_config(STR)
def test_error_filter_dict():
@@ -77,7 +76,7 @@ def test_error_filter_dict():
- trash
"""
with pytest.raises(SchemaError):
- validate_and_convert(STR)
+ validate_config(STR)
# def test_error_action_dict():
diff --git a/tests/core/test_unicode.py b/tests/core/test_unicode.py
new file mode 100644
index 0000000..2cdcd4d
--- /dev/null
+++ b/tests/core/test_unicode.py
@@ -0,0 +1,80 @@
+import pytest
+
+from conftest import make_files, read_files
+from organize import core
+
+
+def test_startswith_issue74(testfs):
+ # test for issue https://github.com/tfeldmann/organize/issues/74
+ make_files(
+ testfs,
+ {
+ "Cálculo_1.pdf": "",
+ "Cálculo_2.pdf": "",
+ "Calculo.pdf": "",
+ },
+ )
+ config = r"""
+ # Cálculo PDF
+ rules:
+ - locations: "."
+ filters:
+ - extension:
+ - pdf
+ - name:
+ startswith: Cálculo
+ actions:
+ - move: "Cálculo Integral/Periodo #6/PDF's/"
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "Cálculo Integral": {
+ "Periodo #6": {
+ "PDF's": {
+ "Cálculo_1.pdf": "",
+ "Cálculo_2.pdf": "",
+ }
+ }
+ },
+ "Calculo.pdf": "",
+ }
+
+
+@pytest.mark.skip(reason="TODO")
+def test_normalization_regex(testfs):
+ make_files(
+ testfs,
+ {b"Ertra\xcc\x88gnisaufstellung.txt".decode("utf-8"): ""},
+ )
+ config = (
+ b"""
+ rules:
+ - locations: "."
+ filters:
+ - regex: 'Ertra\xc3\xa4gnisaufstellung.txt$'
+ actions:
+ - rename: "found-regex.txt"
+ """
+ ).decode("utf-8")
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {"found-regex.txt"}
+
+
+@pytest.mark.skip(reason="TODO")
+def test_normalization_filename(testfs):
+ make_files(
+ testfs,
+ {b"Ertr\xcc\x88gnisaufstellung.txt".decode("utf-8"): ""},
+ )
+ config = (
+ b"""
+ rules:
+ - locations: "."
+ filters:
+ - filename: "Ertr\xc3\xa4gnisaufstellung"
+ actions:
+ - rename: "found-regex.txt"
+ """
+ ).decode("utf-8")
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {"found-regex.txt"}
diff --git a/tests/docs/test_docs.py b/tests/docs/test_docs.py
index 63a8035..b57607d 100644
--- a/tests/docs/test_docs.py
+++ b/tests/docs/test_docs.py
@@ -39,11 +39,15 @@ def test_all_filters_documented():
docdir = fs.open_fs("docs")
filter_docs = docdir.readtext("filters.md")
for name in FILTERS.keys():
- assert "## {}".format(name) in filter_docs, f"{name} filter is not documented!"
+ assert (
+ "## {}".format(name) in filter_docs
+ ), f"The {name} filter is not documented!"
def test_all_actions_documented():
docdir = fs.open_fs("docs")
action_docs = docdir.readtext("actions.md")
for name in ACTIONS.keys():
- assert "## {}".format(name) in action_docs, f"{name} action is not documented!"
+ assert (
+ "## {}".format(name) in action_docs
+ ), f"The {name} action is not documented!"
diff --git a/tests/filters/test_duplicate.py b/tests/filters/test_duplicate.py
new file mode 100644
index 0000000..b04fcc4
--- /dev/null
+++ b/tests/filters/test_duplicate.py
@@ -0,0 +1,75 @@
+from conftest import make_files, read_files
+
+from organize import core
+
+CONTENT_SMALL = "COPY CONTENT"
+CONTENT_LARGE = "XYZ" * 300000
+
+DEEP_DUP_DELETE = """
+rules:
+ - locations: "."
+ subfolders: true
+ filters:
+ - duplicate
+ actions:
+ - delete
+"""
+
+
+def test_duplicate_smallfiles(testfs):
+ files = {
+ "unique.txt": "I'm unique.",
+ "unique_too.txt": "I'm unique: too.",
+ "a.txt": CONTENT_SMALL,
+ "copy2.txt": CONTENT_SMALL,
+ "other": {
+ "copy.txt": CONTENT_SMALL,
+ "copy.jpg": CONTENT_SMALL,
+ "large.txt": CONTENT_LARGE,
+ },
+ "large_unique.txt": CONTENT_LARGE,
+ }
+
+ make_files(testfs, files)
+ core.run(DEEP_DUP_DELETE, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ testfs.tree()
+ assert result == {
+ "unique.txt": "I'm unique.",
+ "unique_too.txt": "I'm unique: too.",
+ "a.txt": CONTENT_SMALL,
+ "other": {
+ "large.txt": CONTENT_LARGE,
+ },
+ }
+
+
+def test_duplicate_largefiles(testfs):
+ files = {
+ "unique.txt": CONTENT_LARGE + "1",
+ "unique_too.txt": CONTENT_LARGE + "2",
+ "a.txt": CONTENT_LARGE,
+ "copy2.txt": CONTENT_LARGE,
+ "other": {
+ "copy.txt": CONTENT_LARGE,
+ "copy.jpg": CONTENT_LARGE,
+ "large.txt": CONTENT_LARGE,
+ },
+ }
+
+ make_files(testfs, files)
+ core.run(DEEP_DUP_DELETE, simulate=False, working_dir=testfs)
+ result = read_files(testfs)
+ testfs.tree()
+ assert result == {
+ "unique.txt": CONTENT_LARGE + "1",
+ "unique_too.txt": CONTENT_LARGE + "2",
+ "a.txt": CONTENT_LARGE,
+ "other": {},
+ }
+
+
+# TODO detect_original_by: name
+# TODO detect_original_by: first_seen
+# TODO detect_original_by: created
+# TODO detect_original_by: lastmodified
diff --git a/tests/filters/test_exif.py b/tests/filters/test_exif.py
new file mode 100644
index 0000000..01fff18
--- /dev/null
+++ b/tests/filters/test_exif.py
@@ -0,0 +1,89 @@
+from fs import copy
+import pytest
+
+from organize.core import run
+
+
+@pytest.fixture
+def images_folder(testfs):
+ copy.copy_dir(".", "tests/resources/images-with-exif", testfs, "/")
+ yield testfs
+
+
+def test_exif_read_camera(images_folder):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name
+ - exif
+ actions:
+ - write_text:
+ text: '{name}: {exif.image.model}'
+ textfile: "out.txt"
+ mode: append
+ """
+ run(config, simulate=False, working_dir=images_folder)
+ out = images_folder.readtext("out.txt")
+ assert "1: DMC-GX80" in out
+ assert "2: NIKON D3200" in out
+ assert "3: iPhone 6s" in out
+ assert "4: iPhone 6s" in out
+ assert "5: iPhone 5s" in out
+
+
+def test_exif_filter_by_cam(images_folder):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name
+ - exif:
+ image.model: Nikon D3200
+ actions:
+ - write_text:
+ text: '{name}: {exif.image.model}'
+ textfile: "out.txt"
+ mode: append
+ """
+ run(config, simulate=False, working_dir=images_folder)
+ out = images_folder.readtext("out.txt")
+ assert out.strip() == "2: NIKON D3200"
+
+
+def test_exif_filter_tag_exists(images_folder):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name
+ - exif:
+ gps.gpsdate
+ actions:
+ - write_text:
+ text: '{name}: {exif.gps.gpsdate}'
+ textfile: "out.txt"
+ """
+ run(config, simulate=False, working_dir=images_folder)
+ out = images_folder.readtext("out.txt")
+ assert len(out.splitlines()) == 3
+ assert "4: 2018:02:22" in out
+ assert "5: 2015:07:08" in out
+ assert "3: 2017:08:12" in out
+
+
+def test_exif_filter_by_multiple_keys(images_folder):
+ config = """
+ rules:
+ - locations: "/"
+ filters:
+ - name
+ - exif:
+ image.make: Apple
+ exif.lensmodel: "iPhone 6s back camera 4.15mm f/2.2"
+ actions:
+ - move: "chosen/"
+ """
+ run(config, simulate=False, working_dir=images_folder)
+ chosen = set(images_folder.listdir("chosen"))
+ assert chosen == set(["3.jpg", "4.jpg"])
diff --git a/tests/filters/test_extension.py b/tests/filters/test_extension.py
index 4318f41..1e48e1a 100644
--- a/tests/filters/test_extension.py
+++ b/tests/filters/test_extension.py
@@ -1,6 +1,10 @@
+from unittest.mock import call
+
+from conftest import make_files
from fs import open_fs
from fs.path import dirname
+from organize import core
from organize.filters import Extension
@@ -46,3 +50,33 @@ def test_extension_result():
assert str(result) == "TxT"
assert result.lower() == "txt"
assert result.upper() == "TXT"
+
+
+def test_filename_move(testfs, mock_echo):
+ files = {
+ "test.jpg": "",
+ "asd.JPG": "",
+ "nomatch.jpg.zip": "",
+ "camel.jPeG": "",
+ }
+ make_files(testfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name
+ - extension:
+ - .jpg
+ - jpeg
+ actions:
+ - echo: 'Found JPG file: {name}'
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ mock_echo.assert_has_calls(
+ (
+ call("Found JPG file: test"),
+ call("Found JPG file: asd"),
+ call("Found JPG file: camel"),
+ ),
+ any_order=True,
+ )
diff --git a/tests/filters/test_filecontent.py b/tests/filters/test_filecontent.py
new file mode 100644
index 0000000..43bae6f
--- /dev/null
+++ b/tests/filters/test_filecontent.py
@@ -0,0 +1,32 @@
+from conftest import make_files, read_files
+
+from organize import core
+
+
+def test_filecontent(tempfs):
+ # inspired by https://github.com/tfeldmann/organize/issues/43
+ files = {
+ "Test1.txt": "Lorem MegaCorp Ltd. ipsum\nInvoice 12345\nMore text\nID: 98765",
+ "Test2.txt": "Tests",
+ "Test3.txt": "My Homework ...",
+ }
+ make_files(tempfs, files)
+ config = r"""
+ rules:
+ - locations: "."
+ filters:
+ - filecontent: 'MegaCorp Ltd.+^Invoice (?P<number>\w+)$.+^ID: 98765$'
+ actions:
+ - rename: "MegaCorp_Invoice_{filecontent.number}.txt"
+ - locations: "."
+ filters:
+ - filecontent: '.*Homework.*'
+ actions:
+ - rename: "Homework.txt"
+ """
+ core.run(config, simulate=False, working_dir=tempfs)
+ assert read_files(tempfs) == {
+ "Homework.txt": "My Homework ...",
+ "MegaCorp_Invoice_12345.txt": "Lorem MegaCorp Ltd. ipsum\nInvoice 12345\nMore text\nID: 98765",
+ "Test2.txt": "Tests",
+ }
diff --git a/tests/filters/test_python.py b/tests/filters/test_python.py
index dfe68b3..25cc3e8 100644
--- a/tests/filters/test_python.py
+++ b/tests/filters/test_python.py
@@ -1,3 +1,8 @@
+from unittest.mock import call
+
+from conftest import make_files, read_files
+
+from organize import core
from organize.filters import Python
@@ -10,3 +15,202 @@ def test_basic():
result = p.run()
assert result.matches
assert result.updates == {"python": "some-string"}
+
+
+def test_python(testfs, mock_echo):
+ make_files(
+ testfs,
+ ["student-01.jpg", "student-01.txt", "student-02.txt", "student-03.txt"],
+ )
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name
+ - extension: txt
+ - python: |
+ return int(name.split('.')[0][-2:]) * 100
+ actions:
+ - echo: '{python}'
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ mock_echo.assert_has_calls(
+ (
+ call("100"),
+ call("200"),
+ call("300"),
+ ),
+ any_order=True,
+ )
+
+
+def test_odd_detector(testfs, mock_echo):
+ make_files(
+ testfs,
+ ["student-01.txt", "student-02.txt", "student-03.txt", "student-04.txt"],
+ )
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name
+ - python: |
+ return int(name.split('-')[1]) % 2 == 1
+ actions:
+ - echo: 'Odd student numbers: {name}'
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ mock_echo.assert_has_calls(
+ (
+ call("Odd student numbers: student-01"),
+ call("Odd student numbers: student-03"),
+ ),
+ any_order=True,
+ )
+
+
+def test_python_dict(testfs, mock_echo):
+ make_files(
+ testfs,
+ ["foo-01.jpg", "foo-01.txt", "bar-02.txt", "baz-03.txt"],
+ )
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - extension: txt
+ - name
+ - python: |
+ return {
+ "name": name[:3],
+ "code": int(name.split('.')[0][-2:]) * 100,
+ }
+ actions:
+ - echo: '{python.code} {python.name}'
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ mock_echo.assert_has_calls(
+ (
+ call("100 foo"),
+ call("200 bar"),
+ call("300 baz"),
+ ),
+ any_order=True,
+ )
+
+
+def test_name_reverser(testfs):
+ make_files(testfs, ["desrever.jpg", "emanelif.txt"])
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - extension
+ - name
+ - python: |
+ return {
+ "reversed_name": name[::-1],
+ }
+ actions:
+ - rename: '{python.reversed_name}.{extension}'
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "reversed.jpg": "",
+ "filename.txt": "",
+ }
+
+
+def test_folder_instructions(testfs):
+ """
+ I would like to include path/folder-instructions into the filename because I have a
+ lot of different files (and there are always new categories added) I don't want
+ create rules for. For example my filename is
+
+ '2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx'
+
+ which means: Move the file to the folder '2019/Jobs/CategoryA/TagB/Media/drafts/eng'
+ whereby 'A-' is an additional instruction and should be removed from the filename
+ afterwards ('2019_Jobs_CategoryA_TagB_content-name_V01_draft_eng.docx').
+
+ I have a rough idea to figure it out with python but I'm new to it (see below a
+ sketch). Is there a possibility to use such variables, conditions etc. with
+ organizer natively? If no, is it possible to do it with Python in Organizer at all?
+
+ - Transform file-string into array
+ - Search for 'A-...', 'V...' and 'content-name' and get index of values
+ - remove value 'A-... and 'content-name' of array
+ - build new filename string
+ - remove value 'V...' and 'A-' of array
+ - build folder-path string (convert _ to /) etc.
+
+ """
+ # inspired by: https://github.com/tfeldmann/organize/issues/52
+ make_files(
+ testfs,
+ [
+ "2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx",
+ "2019_Work_CategoryC_V-Test_A-Audio_V14_final.pdf",
+ "other.pdf",
+ ],
+ )
+ config = r"""
+ rules:
+ - locations: .
+ filters:
+ - extension:
+ - pdf
+ - docx
+ - name:
+ contains: "_"
+ - python: |
+ import fs
+ parts = []
+ instructions = dict()
+ for part in name.split("_"):
+ if part.startswith("A-"):
+ instructions["A"] = part[2:]
+ elif part.startswith("V-"):
+ instructions["V"] = part[2:]
+ elif part.startswith("content-name"):
+ instructions["content"] = part[12:]
+ else:
+ parts.append(part)
+ return {
+ "new_path": fs.path.join(*parts),
+ "instructions": instructions,
+ }
+ actions:
+ - echo: "New path: {python.new_path}"
+ - echo: "Instructions: {python.instructions}"
+ - echo: "Value of A: {python.instructions.A}"
+ - move: "{python.new_path}/{name}.{extension}"
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "other.pdf": "",
+ "2019": {
+ "Jobs": {
+ "CategoryA": {
+ "TagB": {
+ "V01": {
+ "draft": {
+ "eng": {
+ "2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx": "",
+ }
+ }
+ }
+ }
+ }
+ },
+ "Work": {
+ "CategoryC": {
+ "V14": {
+ "final": {
+ "2019_Work_CategoryC_V-Test_A-Audio_V14_final.pdf": "",
+ }
+ }
+ }
+ },
+ },
+ }
diff --git a/tests/filters/test_regex.py b/tests/filters/test_regex.py
index af7a091..8cf4251 100644
--- a/tests/filters/test_regex.py
+++ b/tests/filters/test_regex.py
@@ -1,5 +1,6 @@
from pathlib import Path
+from organize import core
from organize.filters import Regex
TESTDATA = [
@@ -39,3 +40,24 @@ def test_regex_umlaut():
result = regex.run(fs_path=doc)
assert result.updates == {"regex": {"year": "1998"}}
assert result.matches
+
+
+def test_multiple_regex_placeholders(testfs):
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - regex: (?P<word>\w+)-(?P<number>\d+).*
+ - regex: (?P<all>.+?)\.\w{3}
+ - extension
+ actions:
+ - write_text:
+ text: '{regex.word} {regex.number} {regex.all} {extension}'
+ textfile: out.txt
+ """
+ testfs.touch("test-123.jpg")
+ testfs.touch("other-456.pdf")
+ core.run(config, simulate=False, working_dir=testfs)
+ out = testfs.readtext("out.txt")
+ assert "test 123 test-123 jpg" in out
+ assert "other 456 other-456 pdf" in out
diff --git a/tests/filters/test_size.py b/tests/filters/test_size.py
index 1bbd41e..8dda501 100644
--- a/tests/filters/test_size.py
+++ b/tests/filters/test_size.py
@@ -1,3 +1,7 @@
+import pytest
+from conftest import make_files, read_files
+
+from organize import core
from organize.filters import Size
@@ -26,3 +30,79 @@ def test_other():
assert Size("<100 Mb").matches(20)
assert Size("<100 Mb, <10 mb, <1 mb, > 0").matches(20)
assert Size(["<100 Mb", ">= 0 Tb"]).matches(20)
+
+
+def test_size_zero(testfs):
+ files = {"1": "", "2": "", "3": ""}
+ make_files(testfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - size: 0
+ actions:
+ - echo: '{path.name}'
+ - delete
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {}
+
+
+def test_basic(testfs):
+ files = {
+ "empty": "",
+ "full": "0" * 2000,
+ "halffull": "0" * 1010,
+ "two_thirds.txt": "0" * 666,
+ }
+ make_files(testfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - size: '> 1kb, <= 1.0 KiB'
+ actions:
+ - echo: '{path.name} {size.bytes}'
+ - locations: "."
+ filters:
+ - not size:
+ - '> 0.5 kb'
+ - '<1.0 KiB'
+ actions:
+ - delete
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "halffull": "0" * 1010,
+ "two_thirds.txt": "0" * 666,
+ }
+
+
+# @pytest.mark.skip(reason="TODO - template vars in filters not supported")
+# def test_python_args(tmp_path, mock_echo):
+# create_filesystem(
+# tmp_path,
+# files=[
+# "empty",
+# ("full", "0" * 2000),
+# ("halffull", "0" * 1010),
+# ("two_thirds.txt", "0" * 666),
+# ],
+# config="""
+# rules:
+# - folders: files
+# filters:
+# - python: |
+# return 2000
+# - filesize: '= {python}b'
+# actions:
+# - echo: '{path.name} {filesize.bytes}'
+# """,
+# )
+# main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
+# mock_echo.assert_has_calls(
+# [
+# call("full 2000"),
+# ],
+# any_order=True,
+# )
diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py
new file mode 100644
index 0000000..4549a77
--- /dev/null
+++ b/tests/integration/test_cli.py
@@ -0,0 +1,80 @@
+import os
+
+import fs
+from click.testing import CliRunner
+from conftest import make_files
+from fs.base import FS
+
+from organize import cli
+
+runner = CliRunner()
+
+
+def test_config_file(tempfs: FS):
+ files = ["my-test-file-name.txt", "my-test-file-name.jpg", "other-file.txt"]
+ make_files(tempfs, files)
+ config = """
+ rules:
+ - locations: %s
+ filters:
+ - name: my-test-file-name
+ actions:
+ - delete
+ """
+ with fs.open_fs("temp://") as configfs:
+ configfs.writetext("config.yaml", config % tempfs.getsyspath("/"))
+ args = [configfs.getsyspath("config.yaml")]
+ result = runner.invoke(cli.sim, args)
+ print(result.output)
+ assert set(tempfs.listdir("/")) == set(files)
+ result = runner.invoke(cli.run, args)
+ print(result.output)
+ assert set(tempfs.listdir("/")) == set(["other-file.txt"])
+
+
+def test_working_dir(tempfs: FS):
+ files = ["my-test-file-name.txt", "my-test-file-name.jpg", "other-file.txt"]
+ make_files(tempfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name: my-test-file-name
+ actions:
+ - delete
+ """
+ with fs.open_fs("temp://") as configfs:
+ configfs.writetext("config.yaml", config)
+ args = [
+ configfs.getsyspath("config.yaml"),
+ "--working-dir=%s" % tempfs.getsyspath("/"),
+ ]
+ print(args)
+ runner.invoke(cli.sim, args)
+ assert set(tempfs.listdir("/")) == set(files)
+ runner.invoke(cli.run, args)
+ assert set(tempfs.listdir("/")) == set(["other-file.txt"])
+
+
+def test_with_os_chdir(tempfs: FS):
+ files = ["my-test-file-name.txt", "my-test-file-name.jpg", "other-file.txt"]
+ make_files(tempfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name: my-test-file-name
+ actions:
+ - delete
+ """
+ with fs.open_fs("temp://") as configfs:
+ configfs.writetext("config.yaml", config)
+ args = [
+ configfs.getsyspath("config.yaml"),
+ ]
+ print(args)
+ os.chdir(tempfs.getsyspath("/"))
+ runner.invoke(cli.sim, args)
+ assert set(tempfs.listdir("/")) == set(files)
+ runner.invoke(cli.run, args)
+ assert set(tempfs.listdir("/")) == set(["other-file.txt"])
diff --git a/tests/integration/test_delete.py b/tests/integration/test_delete.py
deleted file mode 100644
index 7261e8e..0000000
--- a/tests/integration/test_delete.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import fs
-from conftest import make_files, read_files
-
-from organize import core
-
-
-def test_delete():
- files = {
- "files": {
- "folder": {
- "subfolder": {
- "test.txt": "",
- "other.pdf": "binary",
- },
- "file.txt": "Hello world\nAnother line",
- },
- }
- }
- with fs.open_fs("mem://") as mem:
- config = {
- "rules": [
- {
- "locations": [{"path": "files", "filesystem": mem}],
- "actions": ["delete"],
- },
- {
- "locations": [{"path": "files", "filesystem": mem}],
- "targets": "dirs",
- "actions": ["delete"],
- },
- ]
- }
- make_files(mem, files)
-
- # simulate
- core.run(config, simulate=True)
- result = read_files(mem)
- assert result == files
-
- # run
- core.run(config, simulate=False, validate=False)
- result = read_files(mem)
- assert result == {
- "files": {},
- }
diff --git a/tests/integration/test_dependent_rules.py b/tests/integration/test_dependent_rules.py
new file mode 100644
index 0000000..6334b2e
--- /dev/null
+++ b/tests/integration/test_dependent_rules.py
@@ -0,0 +1,34 @@
+from conftest import make_files, read_files
+
+from organize import core
+
+
+def test_dependent_rules(testfs):
+ files = {
+ "asd.txt": "",
+ "newname 2.pdf": "",
+ "newname.pdf": "",
+ "test.pdf": "",
+ }
+ make_files(testfs, files)
+ config = """
+ rules:
+ - locations: "."
+ filters:
+ - name: test
+ actions:
+ - copy: newfolder/test.pdf
+ - locations: "newfolder"
+ filters:
+ - name: test
+ actions:
+ - rename: test-found.pdf
+ """
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "newname.pdf": "",
+ "newname 2.pdf": "",
+ "test.pdf": "",
+ "asd.txt": "",
+ "newfolder": {"test-found.pdf": ""},
+ }
diff --git a/tests/integration/test_dict_merge.py b/tests/integration/test_dict_merge.py
deleted file mode 100644
index 521466c..0000000
--- a/tests/integration/test_dict_merge.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from unittest.mock import call
-
-import fs
-from conftest import make_files, rules_shortcut
-
-from organize import core
-
-
-def test_multiple_regex_placeholders(mock_echo):
- files = {
- "files": {"test-123.jpg": "", "other-456.pdf": ""},
- }
- with fs.open_fs("mem://") as mem:
- rules = rules_shortcut(
- fs=mem,
- filters=r"""
- - regex: (?P<word>\w+)-(?P<number>\d+).*
- - regex: (?P<all>.+?)\.\w{3}
- - extension
- """,
- actions="""
- - echo: '{regex.word} {regex.number} {regex.all} {extension}'
- """,
- )
- make_files(mem, files)
- core.run(rules, simulate=False, validate=False)
- mock_echo.assert_has_calls(
- (
- call("test 123 test-123 jpg"),
- call("other 456 other-456 pdf"),
- ),
- any_order=True,
- )
diff --git a/tests/integration/test_duplicate.py b/tests/integration/test_duplicate.py
deleted file mode 100644
index d728b32..0000000
--- a/tests/integration/test_duplicate.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import fs
-from conftest import make_files, read_files, rules_shortcut
-
-from organize import core
-
-CONTENT_SMALL = "COPY CONTENT"
-CONTENT_LARGE = "XYZ" * 3000
-
-
-def test_duplicate_smallfiles():
- files = {
- "files": {
- "unique.txt": "I'm unique.",
- "unique_too.txt": "I'm unique: too.",
- "a.txt": CONTENT_SMALL,
- "copy2.txt": CONTENT_SMALL,
- "other": {
- "copy.txt": CONTENT_SMALL,
- "copy.jpg": CONTENT_SMALL,
- "large.txt": CONTENT_LARGE,
- },
- "large_unique.txt": CONTENT_LARGE,
- },
- }
-
- with fs.open_fs("mem://") as mem:
- make_files(mem, files)
- rules = rules_shortcut(
- mem,
- filters="- duplicate",
- actions="- echo: '{fs_path} is duplicate of {duplicate}'\n- delete",
- max_depth=None,
- )
- core.run(rules, simulate=False, validate=False)
- result = read_files(mem)
- mem.tree()
- assert result == {
- "files": {
- "unique.txt": "I'm unique.",
- "unique_too.txt": "I'm unique: too.",
- "a.txt": CONTENT_SMALL,
- "other": {
- "large.txt": CONTENT_LARGE,
- },
- },
- }
-
-
-# main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
-# assertdir(tmp_path,)
-
-
-# def test_duplicate_largefiles(tmp_path):
-# create_filesystem(
-# tmp_path,
-# files=[
-# ("unique.txt", CONTENT_LARGE + "1"),
-# ("unique_too.txt", CONTENT_LARGE + "2"),
-# ("a.txt", CONTENT_LARGE),
-# ("copy2.txt", CONTENT_LARGE),
-# ("other/copy.txt", CONTENT_LARGE),
-# ("other/copy.jpg", CONTENT_LARGE),
-# ("other/large.txt", CONTENT_LARGE),
-# ],
-# config="""
-# rules:
-# - folders: files
-# subfolders: true
-# filters:
-# - duplicate
-# actions:
-# - trash
-# """,
-# )
-# main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
-# assertdir(tmp_path, "unique.txt", "unique_too.txt", "a.txt")
diff --git a/tests/integration/test_rename.py b/tests/integration/test_rename.py
deleted file mode 100644
index 84fb0e4..0000000
--- a/tests/integration/test_rename.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import fs
-from conftest import make_files, read_files, rules_shortcut
-
-from organize import core
-
-
-def test_rename_issue52():
- # test for issue https://github.com/tfeldmann/organize/issues/51
- files = {
- "files": {
- "19asd_WF_test2.PDF": "",
- "other.pdf": "",
- "18asd_WFX_test2.pdf": "",
- }
- }
- with fs.open_fs("temp://") as mem:
- make_files(mem, files)
- config = rules_shortcut(
- mem,
- filters="""
- - extension
- - name:
- startswith: "19"
- contains:
- - "_WF_"
- """,
- actions=[
- {"rename": "{path.stem}_unread.{extension.lower()}"},
- {"copy": {"dest": "files/copy/", "filesystem": mem}},
- ],
- )
- core.run(config, simulate=False)
- mem.tree()
- result = read_files(mem)
-
- assert result == {
- "files": {
- "copy": {
- "19asd_WF_test2_unread.pdf": "",
- },
- "19asd_WF_test2_unread.pdf": "",
- "other.pdf": "",
- "18asd_WFX_test2.pdf": "",
- }
- }
diff --git a/tests/integration/test_rename_regex.py b/tests/integration/test_rename_regex.py
new file mode 100644
index 0000000..889e39d
--- /dev/null
+++ b/tests/integration/test_rename_regex.py
@@ -0,0 +1,32 @@
+import pytest
+from conftest import make_files, read_files
+
+from organize import core
+
+
+@pytest.mark.parametrize("loc", (".", "/"))
+def test_rename_files_date(testfs, loc):
+ # inspired by https://github.com/tfeldmann/organize/issues/43
+ files = {
+ "File_abc_dat20190812_xyz.pdf": "",
+ "File_xyz_bar19990101_a.pdf": "",
+ "File_123456_foo20000101_xyz20190101.pdf": "",
+ }
+ make_files(testfs, files)
+ config = (
+ r"""
+ rules:
+ - locations: "%s"
+ filters:
+ - regex: 'File_.*?(?P<y>\d{4})(?P<m>\d{2})(?P<d>\d{2}).*?.pdf'
+ actions:
+ - rename: "File_{regex.d}{regex.m}{regex.y}.pdf"
+ """
+ % loc
+ )
+ core.run(config, simulate=False, working_dir=testfs)
+ assert read_files(testfs) == {
+ "File_12082019.pdf": "",
+ "File_01011999.pdf": "",
+ "File_01012000.pdf": "",
+ }
diff --git a/tests/resources/1.jpg b/tests/resources/images-with-exif/1.jpg
index a034a3c..a034a3c 100644
--- a/tests/resources/1.jpg
+++ b/tests/resources/images-with-exif/1.jpg
Binary files differ
diff --git a/tests/resources/2.jpg b/tests/resources/images-with-exif/2.jpg
index 9d124b9..9d124b9 100755
--- a/tests/resources/2.jpg
+++ b/tests/resources/images-with-exif/2.jpg
Binary files differ
diff --git a/tests/resources/3.jpg b/tests/resources/images-with-exif/3.jpg
index e8723a7..e8723a7 100644
--- a/tests/resources/3.jpg
+++ b/tests/resources/images-with-exif/3.jpg
Binary files differ
diff --git a/tests/resources/4.jpg b/tests/resources/images-with-exif/4.jpg
index ded1738..ded1738 100644
--- a/tests/resources/4.jpg
+++ b/tests/resources/images-with-exif/4.jpg
Binary files differ
diff --git a/tests/resources/5.jpg b/tests/resources/images-with-exif/5.jpg
index 4da9b86..4da9b86 100644
--- a/tests/resources/5.jpg
+++ b/tests/resources/images-with-exif/5.jpg
Binary files differ
diff --git a/tests/todo/integration/test_exif.py b/tests/todo/integration/test_exif.py
deleted file mode 100644
index c3826d5..0000000
--- a/tests/todo/integration/test_exif.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import os
-import shutil
-
-from conftest import TESTS_FOLDER, assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def copy_resources(tmp_path):
- src = os.path.join(TESTS_FOLDER, "resources")
- dst = os.path.join(str(tmp_path), "files")
- shutil.copytree(src=src, dst=dst)
-
-
-def test_exif(tmp_path):
- """Sort photos by camera"""
- copy_resources(tmp_path)
- create_filesystem(
- tmp_path,
- files=["nothing.jpg"],
- config="""
- rules:
- - folders: files
- filters:
- - extension: jpg
- - exif
- actions:
- - move: 'files/{exif.image.model}/'
- - echo: "{exif}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "nothing.jpg",
- "DMC-GX80/1.jpg",
- "NIKON D3200/2.jpg",
- "iPhone 6s/3.jpg",
- "iPhone 6s/4.jpg",
- "iPhone 5s/5.jpg",
- )
-
-
-def test_exif_filter_single(tmp_path):
- """Filter by camera"""
- copy_resources(tmp_path)
- create_filesystem(
- tmp_path,
- files=["nothing.jpg"],
- config="""
- rules:
- - folders: files
- filters:
- - exif:
- image.model: Nikon D3200
- actions:
- - move: 'files/{exif.image.model}/'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "nothing.jpg",
- "1.jpg",
- "NIKON D3200/2.jpg",
- "3.jpg",
- "4.jpg",
- "5.jpg",
- )
-
-
-def test_exif_filter_tag_exists(tmp_path):
- """Filter by GPS"""
- copy_resources(tmp_path)
- create_filesystem(
- tmp_path,
- files=["nothing.jpg"],
- config="""
- rules:
- - folders: files
- filters:
- - exif:
- gps.gpsdate
- actions:
- - echo: "{exif.gps.gpsdate}"
- - move: 'files/has_gps/'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "nothing.jpg",
- "1.jpg",
- "2.jpg",
- "has_gps/3.jpg",
- "has_gps/4.jpg",
- "has_gps/5.jpg",
- )
-
-
-def test_exif_filter_multiple(tmp_path):
- """Filter by camera"""
- copy_resources(tmp_path)
- create_filesystem(
- tmp_path,
- files=["nothing.jpg"],
- config="""
- rules:
- - folders: files
- filters:
- - exif:
- image.make: Apple
- exif.lensmodel: "iPhone 6s back camera 4.15mm f/2.2"
- actions:
- - echo: "{exif.image}"
- - move: 'files/chosen/'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "nothing.jpg",
- "1.jpg",
- "2.jpg",
- "chosen/3.jpg",
- "chosen/4.jpg",
- "5.jpg",
- )
diff --git a/tests/todo/integration/test_extension.py b/tests/todo/integration/test_extension.py
deleted file mode 100644
index 66c88ff..0000000
--- a/tests/todo/integration/test_extension.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from unittest.mock import call
-
-from conftest import create_filesystem
-
-from organize.cli import main
-
-
-def test_filename_move(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=["test.jpg", "asd.JPG", "nomatch.jpg.zip", "camel.jPeG"],
- config="""
- rules:
- - folders: files
- filters:
- - extension:
- - .jpg
- - jpeg
- actions:
- - echo: 'Found JPG file: {path.name}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- (
- call("Found JPG file: test.jpg"),
- call("Found JPG file: asd.JPG"),
- call("Found JPG file: camel.jPeG"),
- ),
- any_order=True,
- )
diff --git a/tests/todo/integration/test_file_content.py b/tests/todo/integration/test_file_content.py
deleted file mode 100644
index b290b9a..0000000
--- a/tests/todo/integration/test_file_content.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import os
-
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_file_content(tmp_path):
- # inspired by https://github.com/tfeldmann/organize/issues/43
- create_filesystem(
- tmp_path,
- files=[
- (
- "Test1.txt",
- "Lorem MegaCorp Ltd. ipsum\nInvoice 12345\nMore text\nID: 98765",
- ),
- ("Test2.txt", "Tests"),
- ("Test3.txt", "My Homework ..."),
- ],
- config=r"""
- rules:
- - folders: files
- filters:
- - filecontent: 'MegaCorp Ltd.+^Invoice (?P<number>\w+)$.+^ID: 98765$'
- actions:
- - rename: "MegaCorp_Invoice_{filecontent.number}.txt"
- - folders: files
- filters:
- - filecontent: '.*Homework.*'
- actions:
- - rename: "Homework.txt"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "Homework.txt", "MegaCorp_Invoice_12345.txt", "Test2.txt")
diff --git a/tests/todo/integration/test_filesize.py b/tests/todo/integration/test_filesize.py
deleted file mode 100644
index 11aea4b..0000000
--- a/tests/todo/integration/test_filesize.py
+++ /dev/null
@@ -1,88 +0,0 @@
-from unittest.mock import call
-
-import pytest
-from conftest import create_filesystem
-
-from organize.cli import main
-
-
-def test_size_zero(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=["1", "2", "3"],
- config="""
- rules:
- - folders: files
- filters:
- - filesize: 0
- actions:
- - echo: '{path.name}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls((call("1"), call("2"), call("3")), any_order=True)
-
-
-def test_basic(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=[
- "empty",
- ("full", "0" * 2000),
- ("halffull", "0" * 1010),
- ("two_thirds.txt", "0" * 666),
- ],
- config="""
- rules:
- - folders: files
- filters:
- - filesize: '> 1kb, <= 1.0 KiB'
- actions:
- - echo: '{path.name} {filesize.bytes}'
- - folders: files
- filters:
- - filesize:
- - '> 0.5 kb'
- - '<1.0 KiB'
- actions:
- - echo: '2/3 {filesize.bytes}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- [
- call("halffull 1010"),
- call("2/3 666"),
- ],
- any_order=True,
- )
-
-
-@pytest.mark.skip(reason="TODO - template vars in filters not supported")
-def test_python_args(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=[
- "empty",
- ("full", "0" * 2000),
- ("halffull", "0" * 1010),
- ("two_thirds.txt", "0" * 666),
- ],
- config="""
- rules:
- - folders: files
- filters:
- - python: |
- return 2000
- - filesize: '= {python}b'
- actions:
- - echo: '{path.name} {filesize.bytes}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- [
- call("full 2000"),
- ],
- any_order=True,
- )
diff --git a/tests/todo/integration/test_globstrings.py b/tests/todo/integration/test_globstrings.py
deleted file mode 100644
index d8d9a6c..0000000
--- a/tests/todo/integration/test_globstrings.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_globstr(tmp_path):
- # inspired by https://github.com/tfeldmann/organize/issues/39
- create_filesystem(
- tmp_path,
- files=[
- "Test.pdf",
- "Invoice.pdf",
- "Other.pdf",
- "Start.txt",
- "journal.md",
- "sub/test.pdf",
- "sub/other/marks.pdf",
- ],
- config="""
- rules:
- - folders: files/*.pdf
- actions:
- - shell: "rm {path}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path, "Start.txt", "journal.md", "sub/test.pdf", "sub/other/marks.pdf"
- )
-
-
-def test_globstr_subfolder(tmp_path):
- create_filesystem(
- tmp_path,
- files=[
- "Test.pdf",
- "Invoice.pdf",
- "Other.pdf",
- "Start.txt",
- "sub/journal.md",
- "sub/test.pdf",
- "sub/other/marks.pdf",
- ],
- config="""
- rules:
- - folders: files/**/*.pdf
- actions:
- - shell: "rm {path}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "Start.txt", "sub/journal.md")
-
-
-def test_globstr_subfolder_serious(tmp_path):
- create_filesystem(
- tmp_path,
- files=[
- "Test.pdf",
- "Invoice.pdf",
- "Other.pdf",
- "Start.txt",
- "x/foo/test.pdf",
- "x/sub/journal.md",
- "x/sub/journal.pdf",
- "wub/best.pdf",
- "sub/other/marks.pdf",
- "x/sub/testjournal.pdf",
- "sub/test.pdf",
- "wub/test.pdf",
- "dub/test.pdf",
- ],
- config="""
- rules:
- - folders:
- - files/**/*ub/**/test*.pdf
- - !files/dub/*
- actions:
- - shell: "rm {path}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "Test.pdf",
- "Invoice.pdf",
- "Other.pdf",
- "Start.txt",
- "x/foo/test.pdf",
- "x/sub/journal.md",
- "x/sub/journal.pdf",
- "wub/best.pdf",
- "sub/other/marks.pdf",
- "dub/test.pdf",
- )
-
-
-def test_globstr_exclude(tmp_path):
- create_filesystem(
- tmp_path,
- files=[
- "Test.pdf",
- "Invoice.pdf",
- "Start.txt",
- "other/a.txt",
- "other/next/b.txt",
- "exclude/test.pdf",
- "exclude/sub/journal.md",
- "exclude/sub/journal.pdf",
- ],
- config="""
- rules:
- - folders:
- - files/**/*
- - !files/exclude/*
- - '! files/*'
- actions:
- - shell: "rm {path}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "Test.pdf",
- "Invoice.pdf",
- "Start.txt",
- "exclude/test.pdf",
- )
-
-
-def test_globstr_subfolder_setting(tmp_path):
- create_filesystem(
- tmp_path,
- files=[
- "Test.pdf",
- "Invoice.pdf",
- "Other.pdf",
- "Start.txt",
- "sub/journal.md",
- "sub/test.pdf",
- "sub/other/marks.pdf",
- ],
- config="""
- rules:
- - folders: files
- subfolders: true
- filters:
- - extension: pdf
- actions:
- - shell: "rm {path}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "Start.txt", "sub/journal.md")
diff --git a/tests/todo/integration/test_integration.py b/tests/todo/integration/test_integration.py
index a313fb7..44095c4 100644
--- a/tests/todo/integration/test_integration.py
+++ b/tests/todo/integration/test_integration.py
@@ -38,49 +38,3 @@ def test_basic(tmp_path):
assertdir(
tmp_path, "newname.pdf", "newname 2.pdf", "newname 3.pdf", "test.pdf", "asd.txt"
)
-
-
-def test_globstr(tmp_path):
- create_filesystem(
- tmp_path,
- files=["asd.txt", "newname 2.pdf", "newname.pdf", "test.pdf"],
- config="""
- rules:
- - folders: 'file[s]/*.pdf'
- actions:
- - delete
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "asd.txt")
-
-
-@pytest.mark.skip(reason="Todo")
-def test_dependent_rules(tmp_path):
- create_filesystem(
- tmp_path,
- files=["asd.txt", "newname 2.pdf", "newname.pdf", "test.pdf"],
- config="""
- rules:
- - folders: files
- filters:
- - filename: test
- actions:
- - copy: files/newfolder/test.pdf
-
- - folders: files/newfolder/
- filters:
- - filename: test
- actions:
- - rename: test-found.pdf
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "newname.pdf",
- "newname 2.pdf",
- "test.pdf",
- "asd.txt",
- "newfolder/test-found.pdf",
- )
diff --git a/tests/todo/integration/test_python_filter.py b/tests/todo/integration/test_python_filter.py
deleted file mode 100644
index 97cf790..0000000
--- a/tests/todo/integration/test_python_filter.py
+++ /dev/null
@@ -1,180 +0,0 @@
-from unittest.mock import call
-
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_python(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=["student-01.jpg", "student-01.txt", "student-02.txt", "student-03.txt"],
- config="""
- rules:
- - folders: files
- filters:
- - extension: txt
- - python: |
- return int(path.name.split('.')[0][-2:]) * 100
- actions:
- - echo: '{python}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- (
- call("100"),
- call("200"),
- call("300"),
- ),
- any_order=True,
- )
-
-
-def test_odd_detector(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=["student-01.txt", "student-02.txt", "student-03.txt", "student-04.txt"],
- config="""
- rules:
- - folders: files
- filters:
- - python: |
- return int(path.stem.split('-')[1]) % 2 == 1
- actions:
- - echo: 'Odd student numbers: {path.name}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- (
- call("Odd student numbers: student-01.txt"),
- call("Odd student numbers: student-03.txt"),
- ),
- any_order=True,
- )
-
-
-def test_python_dict(tmp_path, mock_echo):
- create_filesystem(
- tmp_path,
- files=["foo-01.jpg", "foo-01.txt", "bar-02.txt", "baz-03.txt"],
- config="""
- rules:
- - folders: files
- filters:
- - extension: txt
- - python: |
- return {
- "name": path.name[:3],
- "code": int(path.name.split('.')[0][-2:]) * 100,
- }
- actions:
- - echo: '{python.code} {python.name}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- mock_echo.assert_has_calls(
- (
- call("100 foo"),
- call("200 bar"),
- call("300 baz"),
- ),
- any_order=True,
- )
-
-
-def test_name_reverser(tmp_path):
- create_filesystem(
- tmp_path,
- files=["desrever.jpg", "emanelif.txt"],
- config="""
- rules:
- - folders: files
- filters:
- - extension
- - python: |
- return {
- "reversed_name": path.stem[::-1],
- }
- actions:
- - rename: '{python.reversed_name}.{extension}'
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "reversed.jpg", "filename.txt")
-
-
-def test_folder_instructions(tmp_path):
- """
- I would like to include path/folder-instructions into the filename because I have a
- lot of different files (and there are always new categories added) I don't want
- create rules for. For example my filename is
-
- '2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx'
-
- which means: Move the file to the folder '2019/Jobs/CategoryA/TagB/Media/drafts/eng'
- whereby 'A-' is an additional instruction and should be removed from the filename
- afterwards ('2019_Jobs_CategoryA_TagB_content-name_V01_draft_eng.docx').
-
- I have a rough idea to figure it out with python but I'm new to it (see below a
- sketch). Is there a possibility to use such variables, conditions etc. with
- organizer natively? If no, is it possible to do it with Python in Organizer at all?
-
- - Transform file-string into array
- - Search for 'A-...', 'V...' and 'content-name' and get index of values
- - remove value 'A-... and 'content-name' of array
- - build new filename string
- - remove value 'V...' and 'A-' of array
- - build folder-path string (convert _ to /) etc.
-
- """
- # inspired by: https://github.com/tfeldmann/organize/issues/52
- create_filesystem(
- tmp_path,
- files=[
- "2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx",
- "2019_Work_CategoryC_V-Test_A-Audio_V14_final.pdf",
- "other.pdf",
- ],
- config=r"""
- rules:
- - folders: files
- filters:
- - extension:
- - pdf
- - docx
- - filename:
- contains: "_"
- - python: |
- import os
- parts = []
- instructions = dict()
- for part in path.stem.split("_"):
- if part.startswith("A-"):
- instructions["A"] = part[2:]
- elif part.startswith("V-"):
- instructions["V"] = part[2:]
- elif part.startswith("content-name"):
- instructions["content"] = part[12:]
- else:
- parts.append(part)
- return {
- "new_path": os.path.join(*parts),
- "instructions": instructions,
- }
- actions:
- - echo: "New path: {python.new_path}"
- - echo: "Instructions: {python.instructions}"
- - echo: "Value of A: {python.instructions.A}"
- - move: "files/{python.new_path}/{path.name}"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "other.pdf",
- "2019/Jobs/CategoryA/TagB/V01/draft/eng/2019_Jobs_CategoryA_TagB_A-Media_content-name_V01_draft_eng.docx",
- "2019/Work/CategoryC/V14/final/2019_Work_CategoryC_V-Test_A-Audio_V14_final.pdf",
- "other.pdf",
- )
diff --git a/tests/todo/integration/test_regex.py b/tests/todo/integration/test_regex.py
deleted file mode 100644
index f44eb4b..0000000
--- a/tests/todo/integration/test_regex.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_rename_files_date(tmp_path):
- # inspired by https://github.com/tfeldmann/organize/issues/43
- create_filesystem(
- tmp_path,
- files=[
- "File_abc_dat20190812_xyz.pdf",
- "File_xyz_bar19990101_a.pdf",
- "File_123456_foo20000101_xyz20190101.pdf",
- ],
- config=r"""
- rules:
- - folders: files
- filters:
- - regex: 'File_.*?(?P<y>\d{4})(?P<m>\d{2})(?P<d>\d{2}).*?.pdf'
- actions:
- - rename: "File_{regex.d}{regex.m}{regex.y}.pdf"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "File_12082019.pdf", "File_01011999.pdf", "File_01012000.pdf")
diff --git a/tests/todo/integration/test_rename.py b/tests/todo/integration/test_rename.py
deleted file mode 100644
index ccd0d1a..0000000
--- a/tests/todo/integration/test_rename.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_rename_issue51(tmp_path):
- # test for issue https://github.com/tfeldmann/organize/issues/51
- create_filesystem(
- tmp_path,
- files=[
- "19asd_WF_test2.pdf",
- "other.pdf",
- "18asd_WFX_test2.pdf",
- ],
- config=r"""
- rules:
- - folders: files
- filters:
- - filename:
- startswith: "19"
- contains:
- - "_WF_"
- actions:
- - rename: "{path.stem}_unread{path.suffix}"
- - copy:
- dest: "files/copy/"
- overwrite: false
- counter_separator: "_"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "19asd_WF_test2_unread.pdf",
- "other.pdf",
- "copy/19asd_WF_test2_unread.pdf",
- "18asd_WFX_test2.pdf",
- )
diff --git a/tests/todo/integration/test_startswith.py b/tests/todo/integration/test_startswith.py
deleted file mode 100644
index ec8f452..0000000
--- a/tests/todo/integration/test_startswith.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-def test_startswith_issue74(tmp_path):
- # test for issue https://github.com/tfeldmann/organize/issues/74
- create_filesystem(
- tmp_path,
- files=[
- "Cálculo_1.pdf",
- "Cálculo_2.pdf",
- "Calculo.pdf",
- ],
- config=r"""
- # Cálculo PDF
- rules:
- - folders: files
- filters:
- - extension:
- - pdf
- - filename:
- startswith: Cálculo
- actions:
- - move: "files/Cálculo Integral/Periodo #6/PDF's/"
- """,
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(
- tmp_path,
- "Cálculo Integral/Periodo #6/PDF's/Cálculo_1.pdf",
- "Cálculo Integral/Periodo #6/PDF's/Cálculo_2.pdf",
- "Calculo.pdf",
- )
diff --git a/tests/todo/integration/test_unicode.py b/tests/todo/integration/test_unicode.py
deleted file mode 100644
index 29b5d57..0000000
--- a/tests/todo/integration/test_unicode.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import pytest
-from conftest import assertdir, create_filesystem
-
-from organize.cli import main
-
-
-@pytest.mark.skip(reason="Todo")
-def test_normalization_regex(tmp_path):
- create_filesystem(
- tmp_path,
- files=[b"Ertra\xcc\x88gnisaufstellung.txt".decode("utf-8")],
- config="""
- rules:
- - folders: files
- filters:
- - regex: '^{}$'
- actions:
- - rename: "found-regex.txt"
- """.format(
- b"Ertr\xc3\xa4gnisaufstellung\\.txt".decode("utf-8")
- ),
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "found-regex.txt")
-
-
-@pytest.mark.skip(reason="Todo")
-def test_normalization_glob(tmp_path):
- create_filesystem(
- tmp_path,
- files=[b"Ertra\xcc\x88gnisaufstellung.txt".decode("utf-8")],
- config="""
- rules:
- - folders: ./**/{}.*
- actions:
- - rename: "found-glob.txt"
- """.format(
- b"Ertr\xc3\xa4gnisaufstellung".decode("utf-8")
- ),
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "found-glob.txt")
-
-
-@pytest.mark.skip(reason="Todo")
-def test_normalization_filename(tmp_path):
- create_filesystem(
- tmp_path,
- files=[b"Ertra\xcc\x88gnisaufstellung.txt".decode("utf-8")],
- config="""
- rules:
- - folders: files
- filters:
- - filename:
- contains: {}
- actions:
- - rename: "found-filename.txt"
- """.format(
- b"Ertr\xc3\xa4gnisaufstellung".decode("utf-8")
- ),
- )
- main(["run", "--config-file=%s" % (tmp_path / "config.yaml")])
- assertdir(tmp_path, "found-filename.txt")
diff --git a/tests/todo/todo_copy.py b/tests/todo/todo_copy.py
index 8f794b8..8698381 100644
--- a/tests/todo/todo_copy.py
+++ b/tests/todo/todo_copy.py
@@ -55,36 +55,6 @@ def test_overwrite(mock_exists, mock_samefile, mock_copy, mock_trash, mock_mkdir
)
-def test_already_exists(mock_exists, mock_samefile, mock_copy, mock_trash, mock_mkdir):
- mock_exists.side_effect = [True, False]
- mock_samefile.return_value = False
- copy = Copy(dest="~/folder/", overwrite=False)
- copy.run(**DEFAULT_ARGS)
- mock_mkdir.assert_called_with(exist_ok=True, parents=True)
- mock_exists.assert_called_with()
- mock_trash.assert_not_called()
- mock_copy.assert_called_with(
- src=os.path.join(USER_DIR, "test.py"),
- dst=os.path.join(USER_DIR, "folder", "test 2.py"),
- )
-
-
-def test_already_exists_multiple(
- mock_exists, mock_samefile, mock_copy, mock_trash, mock_mkdir
-):
- mock_exists.side_effect = [True, True, True, False]
- mock_samefile.return_value = False
- copy = Copy(dest="~/folder/", overwrite=False)
- copy.run(**DEFAULT_ARGS)
- mock_mkdir.assert_called_with(exist_ok=True, parents=True)
- mock_exists.assert_called_with()
- mock_trash.assert_not_called()
- mock_copy.assert_called_with(
- src=os.path.join(USER_DIR, "test.py"),
- dst=os.path.join(USER_DIR, "folder", "test 4.py"),
- )
-
-
def test_already_exists_multiple_with_separator(
mock_exists, mock_samefile, mock_copy, mock_trash, mock_mkdir
):