Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PICARD-2519: Allow passing supported URLs on command line #2130

Merged
merged 31 commits into from
Jul 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e5b35cd
tests added
skelly37 Jul 20, 2022
af76417
Merge branch 'metabrainz:master' into url
skelly37 Jul 20, 2022
b6e98ae
added missing test
skelly37 Jul 20, 2022
44e9670
separated logic
skelly37 Jul 20, 2022
a56da66
base logic works, tho:
skelly37 Jul 20, 2022
ff09be4
unused import
skelly37 Jul 20, 2022
e8bce2b
events sent to main, works fine
skelly37 Jul 21, 2022
601786b
mbid:// added, slightly refactored
skelly37 Jul 21, 2022
ad4e634
Merge branch 'master' into url
skelly37 Jul 21, 2022
1dcf5fa
included new functionality in our test cases + re-run github actions
skelly37 Jul 21, 2022
413afd3
file append
skelly37 Jul 21, 2022
7250003
mbid netloc + path
skelly37 Jul 21, 2022
8fa8913
load sets instead of lists
skelly37 Jul 21, 2022
9593303
file://
skelly37 Jul 21, 2022
e42e4d0
FILE -> FILE_OR_URL in picard cli args
skelly37 Jul 21, 2022
c440f23
Merge branch 'metabrainz:master' into url
skelly37 Jul 22, 2022
962b25a
Merge branch 'metabrainz:master' into url
skelly37 Jul 24, 2022
0ba6a19
moved to-be-added
skelly37 Jul 24, 2022
c1e2f6c
arguments parsing and loading split into separate methods, alphabetic…
skelly37 Jul 24, 2022
8cfaede
method renamed, tests added
skelly37 Jul 24, 2022
8aca6d9
typo fix
skelly37 Jul 24, 2022
7dad643
typo fix v2
skelly37 Jul 24, 2022
74581db
test enhancements
skelly37 Jul 24, 2022
5f6dda9
changes
skelly37 Jul 24, 2022
56b54a3
Tagger._parse_items_to_load() -> ParseItemsToLoad class
zas Jul 24, 2022
62cf581
Merge pull request #3 from zas/ParseItemsToLoad
skelly37 Jul 24, 2022
4c77621
unionize mbids and urls
skelly37 Jul 25, 2022
3884612
help aded
skelly37 Jul 25, 2022
a28417c
Merge branch 'url' of https://github.com/skelly37/picard into url
skelly37 Jul 25, 2022
0416650
ParseItemsToLoad: add __bool__() and use it to bring tagger to front
zas Jul 27, 2022
1aa27aa
Merge pull request #4 from zas/ParseItemsToLoadBool
skelly37 Jul 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions picard/tagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import shutil
import signal
import sys
from urllib.parse import urlparse

from PyQt5 import (
QtCore,
Expand Down Expand Up @@ -174,6 +175,30 @@ def plugin_dirs():
yield USER_PLUGIN_DIR


class ParseItemsToLoad:

def __init__(self, items):
self.files = set()
self.mbids = set()
self.urls = set()

for item in items:
parsed = urlparse(item)
if not parsed.scheme:
self.files.add(item)
elif parsed.scheme == "file":
# remove file:// prefix safely
self.files.add(item[7:])
elif parsed.scheme == "mbid":
self.mbids.add(parsed.netloc + parsed.path)
elif parsed.scheme in {"http", "https"}:
# .path returns / before actual link
self.urls.add(parsed.path[1:])

def __bool__(self):
return bool(self.files or self.mbids or self.urls)


class Tagger(QtWidgets.QApplication):

tagger_stats_changed = QtCore.pyqtSignal()
Expand All @@ -196,7 +221,7 @@ def __init__(self, picard_args, localedir, autoupdate, pipe_handler=None):
config = get_config()
theme.setup(self)

self._cmdline_files = picard_args.FILE
self._cmdline_files = picard_args.FILE_OR_URL
self.autoupdate_enabled = autoupdate
self._no_restore = picard_args.no_restore
self._no_plugins = picard_args.no_plugins
Expand Down Expand Up @@ -322,8 +347,21 @@ def pipe_server(self):
while self.pipe_handler.pipe_running:
messages = [x for x in self.pipe_handler.read_from_pipe() if x not in IGNORED]
if messages:
self.add_paths(messages)
self.bring_tagger_front()
self.load_to_picard(messages)

def load_to_picard(self, items):
parsed_items = ParseItemsToLoad(items)

if parsed_items.files:
self.add_paths(parsed_items.files)

if parsed_items.urls or parsed_items.mbids:
file_lookup = self.get_file_lookup()
for item in parsed_items.mbids | parsed_items.urls:
thread.to_main(file_lookup.mbid_lookup, item, None, None, False)

if parsed_items:
self.bring_tagger_front()
skelly37 marked this conversation as resolved.
Show resolved Hide resolved

def enable_menu_icons(self, enabled):
self.setAttribute(QtCore.Qt.ApplicationAttribute.AA_DontShowIconsInMenus, not enabled)
Expand Down Expand Up @@ -431,8 +469,7 @@ def exit(self):

def _run_init(self):
if self._cmdline_files:
files = [decode_filename(f) for f in self._cmdline_files]
self.add_paths(files)
self.load_to_picard([decode_filename(f) for f in self._cmdline_files])
del self._cmdline_files

def run(self):
Expand Down Expand Up @@ -1071,7 +1108,8 @@ def process_picard_args():
help="display version information and exit")
parser.add_argument("-V", "--long-version", action='store_true',
help="display long version information and exit")
parser.add_argument('FILE', nargs='*')
parser.add_argument('FILE_OR_URL', nargs='*',
help="the file(s), URL(s) and MBID(s) to load")
skelly37 marked this conversation as resolved.
Show resolved Hide resolved

return parser.parse_known_args()[0]

Expand Down Expand Up @@ -1113,8 +1151,14 @@ def main(localedir=None, autoupdate=True):
}

if not should_start:
to_be_added = []
for x in picard_args.FILE_OR_URL:
if not urlparse(x).netloc:
x = os.path.abspath(x)
to_be_added.append(x)

try:
pipe_handler = pipe.Pipe(app_name=PICARD_APP_NAME, app_version=PICARD_FANCY_VERSION_STR, args=[os.path.abspath(x) for x in picard_args.FILE])
pipe_handler = pipe.Pipe(app_name=PICARD_APP_NAME, app_version=PICARD_FANCY_VERSION_STR, args=to_be_added)
skelly37 marked this conversation as resolved.
Show resolved Hide resolved
should_start = pipe_handler.is_pipe_owner
except pipe.PipeErrorNoPermission as err:
log.error(err)
Expand Down
68 changes: 68 additions & 0 deletions test/test_tagger_message_parsing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
#
# Picard, the next-generation MusicBrainz tagger
#
# Copyright (C) 2022 skelly37
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

from test.picardtestcase import PicardTestCase

from picard.tagger import ParseItemsToLoad


class TestMessageParsing(PicardTestCase):
def test(self):
test_cases = {
"test_case.mp3",
"file:///home/picard/music/test.flac",
"mbid://recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
"https://musicbrainz.org/recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
"http://musicbrainz.org/recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
}

result = ParseItemsToLoad(test_cases)
self.assertSetEqual(result.files, {"test_case.mp3", "/home/picard/music/test.flac"}, "Files test")
self.assertSetEqual(result.mbids, {"recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94"}, "MBIDs test")
self.assertSetEqual(result.urls, {"recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
"recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94"}, "URLs test")

def test_bool_files_true(self):
test_cases = {
"test_case.mp3",
}
self.assertTrue(ParseItemsToLoad(test_cases))

def test_bool_mbids_true(self):
test_cases = {
"mbid://recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
}
self.assertTrue(ParseItemsToLoad(test_cases))

def test_bool_urls_true(self):
test_cases = {
"https://musicbrainz.org/recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
}
self.assertTrue(ParseItemsToLoad(test_cases))

def test_bool_invalid_false(self):
test_cases = {
"mbd://recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
}
self.assertFalse(ParseItemsToLoad(test_cases))

def test_bool_empty_false(self):
test_cases = {}
self.assertFalse(ParseItemsToLoad(test_cases))
5 changes: 5 additions & 0 deletions test/test_util_pipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def test_pipe_protocol(self):
"my_music_file.mp3",
TestPipe.NAME, TestPipe.VERSION,
"last-case",
"https://test-ca.se/index.html",
"file:///data/test.py",
"www.wikipedia.mp3",
"mbid://recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
"https://musicbrainz.org/recording/7cd3782d-86dc-4dd1-8d9b-e37f9cbe6b94",
)

pipe_listener_handler = pipe.Pipe(self.NAME, self.VERSION)
Expand Down