Skip to content

Commit

Permalink
2.8.054
Browse files Browse the repository at this point in the history
  • Loading branch information
chapmanjacobd committed Jun 5, 2024
1 parent b8aa1b0 commit b29aecf
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 176 deletions.
36 changes: 34 additions & 2 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ To stop playing press Ctrl+C in either the terminal or mpv
<details><summary>List all subcommands</summary>

$ library
library (v2.8.053; 78 subcommands)
library (v2.8.054; 79 subcommands)

Create database subcommands:
╭───────────────┬──────────────────────────────────────────╮
Expand Down Expand Up @@ -143,6 +143,8 @@ To stop playing press Ctrl+C in either the terminal or mpv
│ dates │ Unstructured text -> timestamps, dates, time │
├──────────────────┼──────────────────────────────────────────────┤
│ json-keys-rename │ Rename JSON keys by substring match │
├──────────────────┼──────────────────────────────────────────────┤
│ combinations │ Enumerate possible combinations │
╰──────────────────┴──────────────────────────────────────────────╯

Folder subcommands:
Expand Down Expand Up @@ -960,7 +962,7 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
<details><summary>Add arbitrary data to SQLITE</summary>

$ library row-add -h
usage: library row-add DATABASE [--table-name TABLE_NAME]
usage: library row-add DATABASE [--table-name TABLE_NAME] --COLUMN-NAME VALUE

Add a row to sqlite

Expand Down Expand Up @@ -1124,6 +1126,25 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
{"country": "Yo Mama"}


</details>

###### combinations

<details><summary>Enumerate possible combinations</summary>

$ library combinations -h
usage: library combinations --PROPERTY OPTION

Enumerate the possible combinations of things that have multiple properties with more than one options

library combinations --prop1 opt1 --prop1 opt2 --prop2 A --prop2 B

{"prop1": "opt1", "prop2": "A"}
{"prop1": "opt1", "prop2": "B"}
{"prop1": "opt2", "prop2": "A"}
{"prop1": "opt2", "prop2": "B"}


</details>

### Folder subcommands
Expand Down Expand Up @@ -2272,6 +2293,17 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th

echo 'fish -c "export DISPLAY=:0 && library tabs /full/path/to/tabs.db"' | at NOW

Also, if you're just testing things out be aware that `tabs-add` assumes that you visited the
website right before adding it; eg. if you use `tabs-add --frequency yearly` today the tab won't
open until one year from now (at most). You can override this default:

library tabs-add --allow-immediate ...

To re-"play" some tabs, delete some history

library history ~/lb/tabs.db --played-within '1 day' -L inf -p --delete-rows
library tabs ~/lb/tabs.db

You can also invoke tabs manually:

library tabs -L 1 # open one tab
Expand Down
183 changes: 22 additions & 161 deletions tests/folders/test_merge_mv.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
@pytest.mark.parametrize("dest_type", ["not_exist", "folder_merge", "clobber_file", "clobber_folder"])
@pytest.mark.parametrize("clobber", ["interactive", "no_replace", "replace"])
def test_copy(mode, src_type, dest_type, clobber, temp_file_tree):
if dest_type == "clobber_folder" and src_type != "file":
return # not useful to test

if src_type == "not_exist":
src1 = temp_file_tree({})
elif src_type == "file":
Expand All @@ -35,7 +38,7 @@ def test_copy(mode, src_type, dest_type, clobber, temp_file_tree):
if dest_type == "clobber_file":
dest = os.path.join(dest, "file4.txt")
elif dest_type == "clobber_folder":
dest = os.path.join(dest, "folder1", "file4.txt")
dest = os.path.join(dest, "folder1")
# dest = os.path.join(dest, 'folder1', 'file4.txt', '') # TODO: check if any different

src1_inodes = generate_file_tree_dict(src1, inodes=False)
Expand All @@ -52,8 +55,8 @@ def test_copy(mode, src_type, dest_type, clobber, temp_file_tree):
clobber == "interactive"
and src_type != "not_exist"
and dest_type != "not_exist"
and (src_type, dest_type)
not in [("folder_bsd", "folder_merge"), ("folder", "clobber_folder"), ("folder_bsd", "clobber_folder")]
and dest_type != "clobber_folder"
and (src_type, dest_type) not in [("folder_bsd", "folder_merge")]
):
with pytest.raises(devices.InteractivePrompt):
lb(cmd)
Expand All @@ -63,127 +66,33 @@ def test_copy(mode, src_type, dest_type, clobber, temp_file_tree):

if mode == "copy":
assert generate_file_tree_dict(src1, inodes=False) == src1_inodes
else:
elif clobber != "no_replace":
assert not Path(src1).exists()

target_inodes = generate_file_tree_dict(dest, inodes=False)
if src_type == "not_exist":
assert target_inodes == dest_inodes
elif src_type == "folder" and dest_type == "folder_merge":
assert target_inodes == dest_inodes | src1_inodes
elif src_type == "folder_bsd" and dest_type == "not_exist":
assert target_inodes == {Path(src1).name: src1_inodes}
elif src_type == "folder_bsd" and dest_type == "folder_merge":
assert target_inodes == dest_inodes | {Path(src1).name: src1_inodes}
elif dest_type in ("not_exist",):
assert target_inodes == src1_inodes
elif src_type == "folder_bsd" and dest_type == "folder_merge":
assert target_inodes == dest_inodes | {Path(src1).name: src1_inodes}
elif dest_type == "folder_merge" and clobber == "replace":
assert target_inodes == dest_inodes | src1_inodes
elif dest_type == "folder_merge":
assert target_inodes == dest_inodes
elif dest_type == "clobber_folder":
assert target_inodes == dest_inodes | {"folder1": {"file4.txt": src1_inodes}}
dest_inodes["file4.txt"] = dest_inodes["file4.txt"] | src1_inodes # type: ignore
assert target_inodes == dest_inodes
elif src_type == "folder_bsd" and dest_type == "clobber_file" and clobber == "replace":
assert target_inodes == {Path(src1).name: src1_inodes}
elif dest_type == "clobber_file" and clobber == "replace":
assert target_inodes == src1_inodes
elif dest_type == "clobber_file":
assert target_inodes == dest_inodes
else:
assert target_inodes == None


def test_copy_simple_file(temp_file_tree):
file_tree = {"file4.txt": "4"}
src1 = temp_file_tree(file_tree)
src1_inodes = generate_file_tree_dict(src1, inodes=False)

target = temp_file_tree({})
lb(["merge-cp", src1, target])

assert generate_file_tree_dict(target, inodes=False) == {Path(src1).name: src1_inodes}


def test_copy_simple_tree(temp_file_tree):
file_tree = {"file4.txt": "4"}
src1 = temp_file_tree(file_tree)
src1_inodes = generate_file_tree_dict(src1, inodes=False)

target = temp_file_tree({})
lb(["merge-cp", src1 + os.sep, target])

assert generate_file_tree_dict(target, inodes=False) == src1_inodes


def test_copy_two_simple_folders(temp_file_tree):
src1 = temp_file_tree(simple_file_tree)
src2 = temp_file_tree(simple_file_tree)
src1_inodes = generate_file_tree_dict(src1, inodes=False)
src2_inodes = generate_file_tree_dict(src2, inodes=False)

target = temp_file_tree({})
lb(["merge-cp", src1, src2, target])

assert generate_file_tree_dict(target, inodes=False) == {Path(src1).name: src1_inodes} | {
Path(src2).name: src2_inodes
}


def test_copy_dupe_no_replace(temp_file_tree):
src1 = temp_file_tree({"file4.txt": "5"})
target = temp_file_tree(simple_file_tree)

src1_inodes = generate_file_tree_dict(src1, inodes=False)
target_inodes = generate_file_tree_dict(target, inodes=False)
lb(["merge-cp", "--no-replace", os.path.join(src1, "file4.txt"), target])
lb(["merge-cp", "--no-replace", src1 + os.sep, target])

assert generate_file_tree_dict(src1, inodes=False) == src1_inodes
assert generate_file_tree_dict(target, inodes=False) == target_inodes


def test_copy_dupe_replace(temp_file_tree):
src1 = temp_file_tree(simple_file_tree | {"file4.txt": "5"})
target = temp_file_tree(simple_file_tree)

src1_inodes = generate_file_tree_dict(src1, inodes=False)
target_inodes = generate_file_tree_dict(target, inodes=False)
lb(["merge-cp", "--replace", src1, target])

assert generate_file_tree_dict(src1, inodes=False) == src1_inodes
assert generate_file_tree_dict(target, inodes=False) == target_inodes | {Path(src1).name: src1_inodes}


def test_copy_dupe_replace_tree(temp_file_tree):
src1 = temp_file_tree(simple_file_tree | {"file4.txt": "5"})
target = temp_file_tree(simple_file_tree)

src1_inodes = generate_file_tree_dict(src1, inodes=False)
target_inodes = generate_file_tree_dict(target, inodes=False)
lb(["merge-cp", "--replace", src1 + os.sep, target])

assert generate_file_tree_dict(src1, inodes=False) == src1_inodes
assert generate_file_tree_dict(target, inodes=False) == target_inodes | src1_inodes


def test_copy_folder_conflict_replace(temp_file_tree):
src1 = temp_file_tree({"file1": "5"})
target = temp_file_tree({"file1": {"file1": "4"}})

src1_inodes = generate_file_tree_dict(src1, inodes=False)
target_inodes = generate_file_tree_dict(target, inodes=False)
lb(["merge-cp", "--replace", src1 + os.sep, target])

assert generate_file_tree_dict(src1, inodes=False) == src1_inodes
assert generate_file_tree_dict(target, inodes=False) == {"file1": src1_inodes}


def test_copy_file_conflict_replace(temp_file_tree):
src1 = temp_file_tree({"file1": {"file1": "5"}})
target = temp_file_tree({"file1": "5"})
with pytest.raises(FileExistsError):
lb(["merge-cp", "--replace", src1 + os.sep, target])


def test_move_simple_file(temp_file_tree):
file_tree = {"file4.txt": "4"}
src1 = temp_file_tree(file_tree)
src1_inodes = generate_file_tree_dict(src1)

target = temp_file_tree({})
lb(["merge-mv", src1, target])

assert generate_file_tree_dict(target) == {Path(src1).name: src1_inodes}
raise NotImplementedError


def test_move_two_simple_folders(temp_file_tree):
Expand All @@ -198,52 +107,4 @@ def test_move_two_simple_folders(temp_file_tree):
assert generate_file_tree_dict(target) == {Path(src1).name: src1_inodes} | {Path(src2).name: src2_inodes}


def test_move_dupe_no_replace(temp_file_tree):
src1 = temp_file_tree(simple_file_tree | {"file4.txt": "5"})
target = temp_file_tree({Path(src1).name: simple_file_tree})

src1_inodes = generate_file_tree_dict(src1)
target_inodes = generate_file_tree_dict(target)
lb(["merge-mv", "--no-replace", src1, target])

assert generate_file_tree_dict(src1) == src1_inodes
assert generate_file_tree_dict(target) == target_inodes


def test_move_dupe_replace(temp_file_tree):
src1 = temp_file_tree(simple_file_tree | {"file4.txt": "5"})
target = temp_file_tree({Path(src1).name: simple_file_tree})

src1_inodes = generate_file_tree_dict(src1)
target_inodes = generate_file_tree_dict(target)
lb(["merge-mv", "--replace", src1, target])

assert not Path(src1).exists()
assert generate_file_tree_dict(target) == target_inodes | {Path(src1).name: src1_inodes}


def test_move_folder_conflict_replace(temp_file_tree):
src1 = temp_file_tree({"file1": "5"})
target = temp_file_tree({"file1": {"file1": "5"}})

src1_inodes = generate_file_tree_dict(src1)
target_inodes = generate_file_tree_dict(target)
lb(["merge-mv", src1, target])

assert not Path(src1).exists()
assert generate_file_tree_dict(target) == target_inodes | {Path(src1).name: src1_inodes}


def test_move_file_conflict_replace(temp_file_tree):
src1 = temp_file_tree({"file1": {"file1": "5"}})
target = temp_file_tree({"file1": "5"})

src1_inodes = generate_file_tree_dict(src1)
target_inodes = generate_file_tree_dict(target)
lb(["merge-mv", src1, target])

assert not Path(src1).exists()
assert generate_file_tree_dict(target) == target_inodes | {Path(src1).name: src1_inodes}


# TODO: test same-file same-folder
2 changes: 1 addition & 1 deletion xklb/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.8.053"
__version__ = "2.8.054"
7 changes: 3 additions & 4 deletions xklb/createdb/av.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime
from pathlib import Path


from xklb.createdb import subtitle
from xklb.mediafiles import media_check
from xklb.utils import consts, file_utils, iterables, nums, objects, processes, strings
Expand Down Expand Up @@ -233,9 +232,9 @@ def parse_framerate(string) -> float | None:
video_count = len(probe.video_streams)
audio_count = len(probe.audio_streams)

video_types = ','.join(iterables.ordered_set(s.get('codec_name') for s in probe.video_streams))
audio_types = ','.join(iterables.ordered_set(s.get('codec_name') for s in probe.audio_streams))
subtitle_types = ','.join(iterables.ordered_set(s.get('codec_name') for s in probe.subtitle_streams))
video_types = ",".join(iterables.ordered_set(s.get("codec_name") for s in probe.video_streams))
audio_types = ",".join(iterables.ordered_set(s.get("codec_name") for s in probe.audio_streams))
subtitle_types = ",".join(iterables.ordered_set(s.get("codec_name") for s in probe.subtitle_streams))

chapters = probe.chapters or []
chapter_count = len(chapters)
Expand Down
9 changes: 5 additions & 4 deletions xklb/folders/merge_mv.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ def mmv_file(args, source, destination):

if os.path.exists(destination):
if os.path.isdir(destination):
# cannot replace directory with file of same name: move the file inside folder instead
# cannot replace directory with file of same name: move the file inside the folder instead
destination = os.path.join(destination, os.path.basename(destination))
return mmv_file(args, source, destination)

if os.path.exists(destination):
if os.path.isdir(destination):
raise FolderExistsError
if devices.clobber_confirm(source, destination):
if devices.clobber_confirm(source, destination, args.replace):
os.unlink(destination)
else:
log.warning("not replacing file %s", destination)
Expand All @@ -55,12 +56,12 @@ def mmv_file(args, source, destination):
parent_dir = os.path.dirname(parent_dir) # we keep going up until we find a valid file

log.warning("FileExistsError: A file exists instead of a folder %s", parent_dir)
if devices.clobber_confirm(source, parent_dir):
if devices.clobber_confirm(source, parent_dir, args.replace):
os.unlink(parent_dir)
os.makedirs(os.path.dirname(destination), exist_ok=True) # use original destination parent
else:
log.warning("not replacing file %s", parent_dir)
return
os.makedirs(os.path.dirname(destination), exist_ok=True) # use original destination parent

if args.copy:
shutil.copy2(source, destination)
Expand Down
2 changes: 1 addition & 1 deletion xklb/playback/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def infer_command(self, m) -> tuple[list[str], bool]:

if args.fullscreen:
player.extend(["--fullscreen=yes"])
else:
elif args.fullscreen is False:
player.extend(["--fullscreen=no"])

if getattr(args, "loop", False):
Expand Down
4 changes: 1 addition & 3 deletions xklb/utils/arggroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,7 @@ def playback(parent_parser):
action="store_true",
help="Loop media after reaching end (useful for curation activities like multiple-playback)",
)
parser.add_argument(
"--fullscreen", "--fs", action=argparse.BooleanOptionalAction, help="Open videos in fullscreen"
)
parser.add_argument("--fullscreen", "--fs", action=argparse.BooleanOptionalAction, help="Open videos in fullscreen")
parser.add_argument("--pause", action="store_true", help="Start media paused")
parser.add_argument(
"--start",
Expand Down
2 changes: 2 additions & 0 deletions xklb/utils/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,13 @@ def Pclose(process) -> subprocess.CompletedProcess: # noqa: N802
class UnplayableFile(RuntimeError):
pass


def is_album_art(s):
from yt_dlp.utils import traverse_obj

return traverse_obj(s, ["disposition", "attached_pic"]) == 1


class FFProbe:
def __init__(self, path, *args):
args = [
Expand Down

0 comments on commit b29aecf

Please sign in to comment.