diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d549136af0..7e97eedb52 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,7 +97,15 @@ print(d['small']) In above example, `l1` contains identifiers (keys of dict `d`) while others are English words/phrases. In the dict declaration, keys are single-quoted but values are double-quoted. -Otherwise, choose whichever limit the number of escaped characters. +URIs (and paths used in URIs) should be, in general, enclosed in double quotes, +mainly because single quotes can appear in URI, unencoded, as sub-delimiters as specified +by [RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-2.2). + +HTML/XML code often contains attributes that are enclosed by double quotes, so in this case, +better use single quotes, e.g. `html = 'text'`. + +In doubt, choose whichever limit the number of escaped characters. +Typically single quote strings that are meant to contain double quotes (e.g. `'The file is "{file}"'`). ## Git Work-flow diff --git a/picard/acoustid/__init__.py b/picard/acoustid/__init__.py index fce1b386ba..e319008e42 100644 --- a/picard/acoustid/__init__.py +++ b/picard/acoustid/__init__.py @@ -264,7 +264,7 @@ def _run_next_task(self): # long path support is enabled. Ensure the path is properly prefixed. if IS_WIN: file_path = win_prefix_longpath(file_path) - process.start(self._fpcalc, ["-json", "-length", "120", file_path]) + process.start(self._fpcalc, ['-json', '-length', '120', file_path]) log.debug("Starting fingerprint calculator %r %r", self._fpcalc, task.file.filename) def analyze(self, file, next_func): @@ -273,7 +273,7 @@ def analyze(self, file, next_func): config = get_config() fingerprint = task.file.acoustid_fingerprint - if not fingerprint and not config.setting["ignore_existing_acoustid_fingerprints"]: + if not fingerprint and not config.setting['ignore_existing_acoustid_fingerprints']: # use cached fingerprint from file metadata fingerprints = task.file.metadata.getall('acoustid_fingerprint') if fingerprints: diff --git a/picard/acoustid/manager.py b/picard/acoustid/manager.py index 1478fab01b..23929684ed 100644 --- a/picard/acoustid/manager.py +++ b/picard/acoustid/manager.py @@ -206,7 +206,7 @@ def _batch_submit(self, submissions, errors=None): log.debug("AcoustID: submitting batch of %d fingerprints (%d remaining)…", len(batch), len(submissions)) self.tagger.window.set_statusbar_message( - N_('Submitting AcoustIDs …'), + N_("Submitting AcoustIDs …"), echo=None ) if not errors: @@ -228,7 +228,7 @@ def _batch_submit_finished(self, submissions, batch, previous_errors, document, else: try: errordoc = load_json(document) - message = errordoc["error"]["message"] + message = errordoc['error']['message'] except BaseException: message = "" mparms = { @@ -241,7 +241,7 @@ def _batch_submit_finished(self, submissions, batch, previous_errors, document, self.tagger.window.set_statusbar_message( log_msg, mparms, echo=None, timeout=3000) else: - log.debug('AcoustID: %d fingerprints successfully submitted', len(batch)) + log.debug("AcoustID: %d fingerprints successfully submitted", len(batch)) for file, submission in batch: submission.orig_recordingid = submission.recordingid file.update() diff --git a/picard/album.py b/picard/album.py index 896fe924d1..b5eaae2d20 100644 --- a/picard/album.py +++ b/picard/album.py @@ -154,7 +154,7 @@ def __init__(self, album_id, discid=None): self.update_metadata_images_enabled = True def __repr__(self): - return '' % (self.id, self.metadata["album"]) + return '' % (self.id, self.metadata['album']) def iterfiles(self, save=False): for track in self.tracks: @@ -288,11 +288,11 @@ def _release_request_finished(self, document, http, error): if error == QtNetwork.QNetworkReply.NetworkError.ContentNotFoundError: config = get_config() nats = False - nat_name = config.setting["nat_name"] + nat_name = config.setting['nat_name'] files = list(self.unmatched_files.files) for file in files: - recordingid = file.metadata["musicbrainz_recordingid"] - if mbid_validate(recordingid) and file.metadata["album"] == nat_name: + recordingid = file.metadata['musicbrainz_recordingid'] + if mbid_validate(recordingid) and file.metadata['album'] == nat_name: nats = True self.tagger.move_file_to_nat(file, recordingid) self.tagger.nats.update() @@ -304,7 +304,7 @@ def _release_request_finished(self, document, http, error): parse_result = self._parse_release(document) config = get_config() if parse_result == ParseResult.MISSING_TRACK_RELS: - log.debug('Recording relationships not loaded in initial request for %r, issuing separate requests', self) + log.debug("Recording relationships not loaded in initial request for %r, issuing separate requests", self) self._request_recording_relationships() elif parse_result == ParseResult.PARSED: self._run_album_metadata_processors() @@ -327,7 +327,7 @@ def _request_recording_relationships(self, offset=0, limit=RECORDING_QUERY_LIMIT 'work-rels', 'work-level-rels', ) - log.debug('Loading recording relationships for %r (offset=%i, limit=%i)', self, offset, limit) + log.debug("Loading recording relationships for %r (offset=%i, limit=%i)", self, offset, limit) self._requests += 1 self.load_task = self.tagger.mb_api.browse_recordings( self._recordings_request_finished, @@ -400,7 +400,7 @@ def _finalize_loading_track(self, track_node, metadata, artists, extra_metadata= track._customize_metadata() self._new_metadata.length += tm.length - artists.add(tm["artist"]) + artists.add(tm['artist']) if extra_metadata: tm.update(extra_metadata) @@ -426,7 +426,7 @@ def _load_track(node, mm, artists, extra_metadata): va = self._new_metadata['musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID djmix_ars = {} - if hasattr(self._new_metadata, "_djmix_ars"): + if hasattr(self._new_metadata, '_djmix_ars'): djmix_ars = self._new_metadata._djmix_ars for medium_node in self._release_node['media']: @@ -437,13 +437,13 @@ def _load_track(node, mm, artists, extra_metadata): if fmt: all_media.append(fmt) - for dj in djmix_ars.get(mm["discnumber"], []): - mm.add("djmixer", dj) + for dj in djmix_ars.get(mm['discnumber'], []): + mm.add('djmixer', dj) if va: - mm["compilation"] = "1" + mm['compilation'] = '1' else: - del mm["compilation"] + del mm['compilation'] if 'discs' in medium_node: discids = [disc.get('id') for disc in medium_node['discs']] @@ -468,9 +468,9 @@ def _load_track(node, mm, artists, extra_metadata): multiartists = len(artists) > 1 for track in self._new_tracks: - track.metadata["~totalalbumtracks"] = totalalbumtracks + track.metadata['~totalalbumtracks'] = totalalbumtracks if multiartists: - track.metadata["~multiartist"] = "1" + track.metadata['~multiartist'] = '1' del self._release_node del self._release_artist_nodes self._tracks_loaded = True @@ -535,10 +535,10 @@ def _finalize_loading(self, error): import inspect stack = inspect.stack() args = [self] - msg = 'Album._finalize_loading called for already loaded album %r' + msg = "Album._finalize_loading called for already loaded album %r" if len(stack) > 1: f = stack[1] - msg += ' at %s:%d in %s' + msg += " at %s:%d in %s" args.extend((f.filename, f.lineno, f.function)) log.warning(msg, *args) return @@ -570,7 +570,7 @@ def load(self, priority=False, refresh=False): log.info("Not reloading, some requests are still active.") return self.tagger.window.set_statusbar_message( - N_('Loading album %(id)s …'), + N_("Loading album %(id)s …"), {'id': self.id} ) self.loaded = False @@ -863,18 +863,18 @@ def keep_original_images(self): class NatAlbum(Album): def __init__(self): - super().__init__("NATS") + super().__init__('NATS') self.loaded = True self.update() def update(self, update_tracks=True, update_selection=True): config = get_config() self.enable_update_metadata_images(False) - old_album_title = self.metadata["album"] - self.metadata["album"] = config.setting["nat_name"] + old_album_title = self.metadata['album'] + self.metadata['album'] = config.setting['nat_name'] for track in self.tracks: - if old_album_title == track.metadata["album"]: - track.metadata["album"] = self.metadata["album"] + if old_album_title == track.metadata['album']: + track.metadata['album'] = self.metadata['album'] for file in track.files: track.update_file_metadata(file) self.enable_update_metadata_images(True) diff --git a/picard/browser/addrelease.py b/picard/browser/addrelease.py index 9b838c0026..03d9cd9cfd 100644 --- a/picard/browser/addrelease.py +++ b/picard/browser/addrelease.py @@ -37,7 +37,7 @@ import jwt import jwt.exceptions except ImportError: - log.debug('PyJWT not available, addrelease functionality disabled') + log.debug("PyJWT not available, addrelease functionality disabled") jwt = None __key = token_bytes() # Generating a new secret on each startup @@ -89,18 +89,18 @@ def submit_file(file, as_release=False): def serve_form(token): try: payload = jwt.decode(token, __key, algorithms=__algorithm) - log.debug('received JWT token %r', payload) + log.debug("received JWT token %r", payload) tagger = QCoreApplication.instance() tport = tagger.browser_integration.port if 'cluster' in payload: cluster = _find_cluster(tagger, payload['cluster']) if not cluster: - raise NotFoundError('Cluster not found') + raise NotFoundError("Cluster not found") return _get_cluster_form(cluster, tport) elif 'file' in payload: file = _find_file(tagger, payload['file']) if not file: - raise NotFoundError('File not found') + raise NotFoundError("File not found") if payload.get('as_release', False): return _get_file_as_release_form(file, tport) else: @@ -141,9 +141,9 @@ def _find_file(tagger, path): def _get_cluster_form(cluster, tport): return _get_form( - _('Add cluster as release'), + _("Add cluster as release"), '/release/add', - _('Add cluster as release…'), + _("Add cluster as release…"), _get_cluster_data(cluster), {'tport': tport} ) @@ -151,9 +151,9 @@ def _get_cluster_form(cluster, tport): def _get_file_as_release_form(file, tport): return _get_form( - _('Add file as release'), + _("Add file as release"), '/release/add', - _('Add file as release…'), + _("Add file as release…"), _get_file_as_release_data(file), {'tport': tport} ) @@ -161,9 +161,9 @@ def _get_file_as_release_form(file, tport): def _get_file_as_recording_form(file, tport): return _get_form( - _('Add file as recording'), + _("Add file as recording"), '/recording/create', - _('Add file as recording…'), + _("Add file as recording…"), _get_file_as_recording_data(file), {'tport': tport} ) diff --git a/picard/browser/filelookup.py b/picard/browser/filelookup.py index 07ca9a2774..48b3748b37 100644 --- a/picard/browser/filelookup.py +++ b/picard/browser/filelookup.py @@ -133,7 +133,7 @@ def mbid_lookup(self, string, type_=None, mbid_matched_callback=None, browser_fa id = m.group('id') if entity != 'cdtoc': id = id.lower() - log.debug('Lookup for %s:%s', entity, id) + log.debug("Lookup for %s:%s", entity, id) if mbid_matched_callback: mbid_matched_callback(entity, id) if entity == 'release': @@ -162,10 +162,10 @@ def tag_lookup(self, artist, release, track, tracknum, duration, filename): 'duration': duration, 'filename': os.path.basename(filename), } - return self._build_launch('/taglookup', params) + return self._build_launch("/taglookup", params) def collection_lookup(self, userid): - return self._build_launch('/user/%s/collections' % userid) + return self._build_launch("/user/%s/collections" % userid) def search_entity(self, type_, query, adv=False, mbid_matched_callback=None, force_browser=False): if not force_browser and self.mbid_lookup(query, type_, mbid_matched_callback=mbid_matched_callback): @@ -178,4 +178,4 @@ def search_entity(self, type_, query, adv=False, mbid_matched_callback=None, for } if adv: params['adv'] = 'on' - return self._build_launch('/search/textsearch', params) + return self._build_launch("/search/textsearch", params) diff --git a/picard/cluster.py b/picard/cluster.py index 221f50fbd0..9d32ad5110 100644 --- a/picard/cluster.py +++ b/picard/cluster.py @@ -120,7 +120,7 @@ def __repr__(self): if self.related_album: return '' % ( self.related_album.id, - self.related_album.metadata["album"] + '/' + self.metadata['album'] + self.related_album.metadata['album'] + '/' + self.metadata['album'] ) return '' % self.metadata['album'] @@ -308,8 +308,8 @@ def cluster(files): cluster_list = defaultdict(FileCluster) for file in files: - artist = file.metadata["albumartist"] or file.metadata["artist"] - album = file.metadata["album"] + artist = file.metadata['albumartist'] or file.metadata['artist'] + album = file.metadata['album'] # Improve clustering from directory structure if no existing tags # Only used for grouping and to provide cluster title / artist - not added to file tags. diff --git a/picard/collection.py b/picard/collection.py index 2207139ebf..b03db3f766 100644 --- a/picard/collection.py +++ b/picard/collection.py @@ -121,12 +121,12 @@ def request_finished(document, reply, error): echo=log.error ) return - if document and "collections" in document: + if document and 'collections' in document: collection_list = document['collections'] new_collections = set() for node in collection_list: - if node["entity-type"] != "release": + if node['entity-type'] != 'release': continue col_id = node['id'] col_name = node['name'] @@ -152,10 +152,10 @@ def request_finished(document, reply, error): def add_release_to_user_collections(release_node): """Add album to collections""" # Check for empy collection list - if "collections" in release_node: + if 'collections' in release_node: release_id = release_node['id'] config = get_config() - username = config.persist["oauth_username"].lower() + username = config.persist['oauth_username'].lower() for node in release_node['collections']: if node['editor'].lower() == username: col_id = node['id'] diff --git a/picard/config.py b/picard/config.py index ad279aced3..88783f46dd 100644 --- a/picard/config.py +++ b/picard/config.py @@ -143,8 +143,8 @@ class SettingConfigSection(ConfigSection): @classmethod def init_profile_options(cls): - ListOption.add_if_missing("profiles", cls.PROFILES_KEY, []) - Option.add_if_missing("profiles", cls.SETTINGS_KEY, {}) + ListOption.add_if_missing('profiles', cls.PROFILES_KEY, []) + Option.add_if_missing('profiles', cls.SETTINGS_KEY, {}) def __init__(self, config, name): super().__init__(config, name) @@ -165,7 +165,7 @@ def _get_active_profile_ids(self): return for profile in profiles: if profile['enabled']: - yield profile["id"] + yield profile['id'] def _get_active_profile_settings(self): for profile_id in self._get_active_profile_ids(): @@ -242,14 +242,14 @@ def __initialize(self): :meth:`from_file`.""" self.setAtomicSyncRequired(False) # See comment in event() - self.application = ConfigSection(self, "application") - self.profiles = ConfigSection(self, "profiles") - self.setting = SettingConfigSection(self, "setting") - self.persist = ConfigSection(self, "persist") + self.application = ConfigSection(self, 'application') + self.profiles = ConfigSection(self, 'profiles') + self.setting = SettingConfigSection(self, 'setting') + self.persist = ConfigSection(self, 'persist') if 'version' not in self.application or not self.application['version']: - TextOption("application", "version", '0.0.0dev0') - self._version = Version.from_string(self.application["version"]) + TextOption('application', 'version', '0.0.0dev0') + self._version = Version.from_string(self.application['version']) self._upgrade_hooks = dict() def event(self, event): @@ -258,7 +258,7 @@ def event(self, event): # the Python GIL in PyQt up to 5.15.2. Workaround this by handling this ourselves # with custom file locking. # See also https: // tickets.metabrainz.org/browse/PICARD-2088 - log.debug('Config file update requested on thread %r', threading.get_ident()) + log.debug("Config file update requested on thread %r", threading.get_ident()) self.sync() return True else: @@ -367,7 +367,7 @@ def run_upgrade_hooks(self, outputfunc=None): # hook is not applicable, mark as done hook['done'] = True - if all(map(itemgetter("done"), self._upgrade_hooks.values())): + if all(map(itemgetter('done'), self._upgrade_hooks.values())): # all hooks were executed, ensure config is marked with latest version self._version = PICARD_VERSION self._write_version() @@ -378,16 +378,16 @@ def _backup_settings(self): self._save_backup(backup_path) def _save_backup(self, backup_path): - log.info('Backing up config file to %s', backup_path) + log.info("Backing up config file to %s", backup_path) try: shutil.copyfile(self.fileName(), backup_path) except OSError: - log.error('Failed backing up config file to %s', backup_path) + log.error("Failed backing up config file to %s", backup_path) return False return True def _write_version(self): - self.application["version"] = self._version.to_string() + self.application['version'] = self._version.to_string() self.sync() def _versioned_config_filename(self, version=None): @@ -505,7 +505,7 @@ def load_new_config(filename=None): try: shutil.copy(filename, config_file) except OSError: - log.error('Failed restoring config file from %s', filename) + log.error("Failed restoring config file from %s", filename) return False setup_config(QtCore.QObject.tagger, config_file) return True diff --git a/picard/config_upgrade.py b/picard/config_upgrade.py index 9646f1df43..6e45658542 100644 --- a/picard/config_upgrade.py +++ b/picard/config_upgrade.py @@ -63,18 +63,18 @@ def upgrade_to_v1_0_0_final_0(config, interactive=True, merge=True): def remove_va_file_naming_format(merge=True): if merge: - _s["file_naming_format"] = ( + _s['file_naming_format'] = ( "$if($eq(%%compilation%%,1),\n$noop(Various Artist " "albums)\n%s,\n$noop(Single Artist Albums)\n%s)" % ( - _s.value("va_file_naming_format", TextOption), - _s["file_naming_format"] + _s.value('va_file_naming_format', TextOption), + _s['file_naming_format'] )) - _s.remove("va_file_naming_format") - _s.remove("use_va_format") + _s.remove('va_file_naming_format') + _s.remove('use_va_format') - if "va_file_naming_format" in _s and "use_va_format" in _s: + if 'va_file_naming_format' in _s and 'use_va_format' in _s: - if _s.value("use_va_format", BoolOption): + if _s.value('use_va_format', BoolOption): remove_va_file_naming_format() if interactive: msgbox = QtWidgets.QMessageBox() @@ -86,7 +86,7 @@ def remove_va_file_naming_format(merge=True): "merged with that of single artist albums."), QtWidgets.QMessageBox.StandardButton.Ok) - elif (_s.value("va_file_naming_format", TextOption) + elif (_s.value('va_file_naming_format', TextOption) != r"$if2(%albumartist%,%artist%)/%album%/$if($gt(%totaldis" "cs%,1),%discnumber%-,)$num(%tracknumber%,2) %artist% - " "%title%"): @@ -100,8 +100,8 @@ def remove_va_file_naming_format(merge=True): "Do you want to remove it or merge it with your file " "naming scheme for single artist albums?")) msgbox.setIcon(QtWidgets.QMessageBox.Icon.Question) - merge_button = msgbox.addButton(_('Merge'), QtWidgets.QMessageBox.ButtonRole.AcceptRole) - msgbox.addButton(_('Remove'), QtWidgets.QMessageBox.ButtonRole.DestructiveRole) + merge_button = msgbox.addButton(_("Merge"), QtWidgets.QMessageBox.ButtonRole.AcceptRole) + msgbox.addButton(_("Remove"), QtWidgets.QMessageBox.ButtonRole.DestructiveRole) msgbox.exec_() merge = msgbox.clickedButton() == merge_button remove_va_file_naming_format(merge=merge) @@ -113,8 +113,8 @@ def remove_va_file_naming_format(merge=True): def upgrade_to_v1_3_0_dev_1(config): """Option "windows_compatible_filenames" was renamed "windows_compatibility" (PICARD-110). """ - old_opt = "windows_compatible_filenames" - new_opt = "windows_compatibility" + old_opt = 'windows_compatible_filenames' + new_opt = 'windows_compatibility' rename_option(config, old_opt, new_opt, BoolOption, True) @@ -122,7 +122,7 @@ def upgrade_to_v1_3_0_dev_2(config): """Option "preserved_tags" is now using comma instead of spaces as tag separator (PICARD-536) """ _s = config.setting - opt = "preserved_tags" + opt = 'preserved_tags' if opt in _s and isinstance(_s[opt], str): _s[opt] = re.sub(r"\s+", ",", _s[opt].strip()) @@ -132,11 +132,11 @@ def upgrade_to_v1_3_0_dev_3(config): """ _s = config.setting option_separators = { - "preferred_release_countries": " ", - "preferred_release_formats": " ", - "enabled_plugins": None, - "caa_image_types": None, - "metadata_box_sizes": None, + 'preferred_release_countries': ' ', + 'preferred_release_formats': ' ', + 'enabled_plugins': None, + 'caa_image_types': None, + 'metadata_box_sizes': None, } for (opt, sep) in option_separators.items(): if opt in _s: @@ -162,7 +162,7 @@ def load_release_type_scores(setting): scores.append((values[i], score)) return scores - opt = "release_type_scores" + opt = 'release_type_scores' if opt in _s: try: _s[opt] = load_release_type_scores(_s.raw_value(opt, qtype='QString')) @@ -176,7 +176,7 @@ def upgrade_to_v1_4_0_dev_2(config): """ _s = config.setting - opts = ["username", "password"] + opts = ['username', 'password'] for opt in opts: _s.remove(opt) @@ -209,8 +209,8 @@ def upgrade_to_v1_4_0_dev_3(config): def upgrade_to_v1_4_0_dev_4(config): """Adds trailing comma to default file names for scripts""" _s = config.setting - if _s["file_naming_format"] == OLD_DEFAULT_FILE_NAMING_FORMAT_v1_3: - _s["file_naming_format"] = DEFAULT_FILE_NAMING_FORMAT + if _s['file_naming_format'] == OLD_DEFAULT_FILE_NAMING_FORMAT_v1_3: + _s['file_naming_format'] = DEFAULT_FILE_NAMING_FORMAT def upgrade_to_v1_4_0_dev_5(config): @@ -221,37 +221,37 @@ def upgrade_to_v1_4_0_dev_5(config): def upgrade_to_v1_4_0_dev_6(config): """Adds support for multiple and selective tagger scripts""" _s = config.setting - old_enabled_option = "enable_tagger_script" - old_script_text_option = "tagger_script" + old_enabled_option = 'enable_tagger_script' + old_script_text_option = 'tagger_script' list_of_scripts = [] if old_enabled_option in _s: - _s["enable_tagger_scripts"] = _s.value(old_enabled_option, BoolOption, False) + _s['enable_tagger_scripts'] = _s.value(old_enabled_option, BoolOption, False) if old_script_text_option in _s: old_script_text = _s.value(old_script_text_option, TextOption, "") if old_script_text: old_script = ( 0, unique_numbered_title(gettext_constants(DEFAULT_SCRIPT_NAME), list_of_scripts), - _s["enable_tagger_scripts"], + _s['enable_tagger_scripts'], old_script_text, ) list_of_scripts.append(old_script) - _s["list_of_scripts"] = list_of_scripts + _s['list_of_scripts'] = list_of_scripts _s.remove(old_enabled_option) _s.remove(old_script_text_option) def upgrade_to_v1_4_0_dev_7(config): """Option "save_only_front_images_to_tags" was renamed to "embed_only_one_front_image".""" - old_opt = "save_only_front_images_to_tags" - new_opt = "embed_only_one_front_image" + old_opt = 'save_only_front_images_to_tags' + new_opt = 'embed_only_one_front_image' rename_option(config, old_opt, new_opt, BoolOption, True) def upgrade_to_v2_0_0_dev_3(config): """Option "caa_image_size" value has different meaning.""" _s = config.setting - opt = "caa_image_size" + opt = 'caa_image_size' if opt in _s: # caa_image_size option was storing index of a combobox item as size # therefore it depends on items order and/or number, which is bad @@ -270,25 +270,25 @@ def upgrade_to_v2_0_0_dev_3(config): def upgrade_to_v2_1_0_dev_1(config): """Upgrade genre related options""" _s = config.setting - if "folksonomy_tags" in _s and _s["folksonomy_tags"]: - _s["use_genres"] = True - rename_option(config, "max_tags", "max_genres", IntOption, 5) - rename_option(config, "min_tag_usage", "min_genre_usage", IntOption, 90) - rename_option(config, "ignore_tags", "ignore_genres", TextOption, "") - rename_option(config, "join_tags", "join_genres", TextOption, "") - rename_option(config, "only_my_tags", "only_my_genres", BoolOption, False) - rename_option(config, "artists_tags", "artists_genres", BoolOption, False) + if 'folksonomy_tags' in _s and _s['folksonomy_tags']: + _s['use_genres'] = True + rename_option(config, 'max_tags', 'max_genres', IntOption, 5) + rename_option(config, 'min_tag_usage', 'min_genre_usage', IntOption, 90) + rename_option(config, 'ignore_tags', 'ignore_genres', TextOption, '') + rename_option(config, 'join_tags', 'join_genres', TextOption, '') + rename_option(config, 'only_my_tags', 'only_my_genres', BoolOption, False) + rename_option(config, 'artists_tags', 'artists_genres', BoolOption, False) def upgrade_to_v2_2_0_dev_3(config): """Option ignore_genres was replaced by option genres_filter""" _s = config.setting - old_opt = "ignore_genres" + old_opt = 'ignore_genres' if old_opt in _s: if _s[old_opt]: - new_opt = "genres_filter" - tags = ["-" + e.strip().lower() for e in _s[old_opt].split(',')] - _s[new_opt] = "\n".join(tags) + new_opt = 'genres_filter' + tags = ['-' + e.strip().lower() for e in _s[old_opt].split(',')] + _s[new_opt] = '\n'.join(tags) _s.remove(old_opt) @@ -303,8 +303,8 @@ def upgrade_to_v2_2_0_dev_3(config): def upgrade_to_v2_2_0_dev_4(config): """Improved default file naming script""" _s = config.setting - if _s["file_naming_format"] == OLD_DEFAULT_FILE_NAMING_FORMAT_v2_1: - _s["file_naming_format"] = DEFAULT_FILE_NAMING_FORMAT + if _s['file_naming_format'] == OLD_DEFAULT_FILE_NAMING_FORMAT_v2_1: + _s['file_naming_format'] = DEFAULT_FILE_NAMING_FORMAT def upgrade_to_v2_4_0_beta_3(config): @@ -327,8 +327,8 @@ def upgrade_to_v2_5_0_dev_1(config): def upgrade_to_v2_5_0_dev_2(config): """Reset main view splitter states""" - config.persist["splitter_state"] = b'' - config.persist["bottom_splitter_state"] = b'' + config.persist['splitter_state'] = b'' + config.persist['bottom_splitter_state'] = b'' def upgrade_to_v2_6_0_dev_1(config): @@ -339,18 +339,18 @@ def upgrade_to_v2_6_0_dev_1(config): def upgrade_to_v2_6_0_beta_2(config): """Rename caa_image_type_as_filename and caa_save_single_front_image options""" - rename_option(config, "caa_image_type_as_filename", "image_type_as_filename", BoolOption, False) - rename_option(config, "caa_save_single_front_image", "save_only_one_front_image", BoolOption, False) + rename_option(config, 'caa_image_type_as_filename', 'image_type_as_filename', BoolOption, False) + rename_option(config, 'caa_save_single_front_image', 'save_only_one_front_image', BoolOption, False) def upgrade_to_v2_6_0_beta_3(config): """Replace use_system_theme with ui_theme options""" from picard.ui.theme import UiTheme _s = config.setting - TextOption("setting", "ui_theme", str(UiTheme.DEFAULT)) - if _s["use_system_theme"]: - _s["ui_theme"] = str(UiTheme.SYSTEM) - _s.remove("use_system_theme") + TextOption('setting', 'ui_theme', str(UiTheme.DEFAULT)) + if _s['use_system_theme']: + _s['ui_theme'] = str(UiTheme.SYSTEM) + _s.remove('use_system_theme') def upgrade_to_v2_7_0_dev_2(config): @@ -364,12 +364,12 @@ def upgrade_persisted_splitter(new_persist_key, key_map): if _p[old_splitter_key] is not None: splitter_dict[new_splitter_key] = bytearray(_p[old_splitter_key]) _p.remove(old_splitter_key) - Option("persist", new_persist_key, {}) + Option('persist', new_persist_key, {}) _p[new_persist_key] = splitter_dict # MainWindow splitters upgrade_persisted_splitter( - new_persist_key="splitters_MainWindow", + new_persist_key='splitters_MainWindow', key_map=[ ('bottom_splitter_state', 'main_window_bottom_splitter'), ('splitter_state', 'main_panel_splitter'), @@ -378,7 +378,7 @@ def upgrade_persisted_splitter(new_persist_key, key_map): # ScriptEditorDialog splitters upgrade_persisted_splitter( - new_persist_key="splitters_ScriptEditorDialog", + new_persist_key='splitters_ScriptEditorDialog', key_map=[ ('script_editor_splitter_samples', 'splitter_between_editor_and_examples'), ('script_editor_splitter_samples_before_after', 'splitter_between_before_and_after'), @@ -388,7 +388,7 @@ def upgrade_persisted_splitter(new_persist_key, key_map): # OptionsDialog splitters upgrade_persisted_splitter( - new_persist_key="splitters_OptionsDialog", + new_persist_key='splitters_OptionsDialog', key_map=[ ('options_splitter', 'dialog_splitter'), ('scripting_splitter', 'scripting_options_splitter'), @@ -404,54 +404,54 @@ def upgrade_to_v2_7_0_dev_3(config): FileNamingScript, ScriptImportError, ) - Option("setting", "file_renaming_scripts", {}) - ListOption("setting", "file_naming_scripts", []) - TextOption("setting", "file_naming_format", DEFAULT_FILE_NAMING_FORMAT) - TextOption("setting", "selected_file_naming_script_id", "") + Option('setting', 'file_renaming_scripts', {}) + ListOption('setting', 'file_naming_scripts', []) + TextOption('setting', 'file_naming_format', DEFAULT_FILE_NAMING_FORMAT) + TextOption('setting', 'selected_file_naming_script_id', '') scripts = {} - for item in config.setting["file_naming_scripts"]: + for item in config.setting['file_naming_scripts']: try: script_item = FileNamingScript().create_from_yaml(item, create_new_id=False) - scripts[script_item["id"]] = script_item.to_dict() + scripts[script_item['id']] = script_item.to_dict() except ScriptImportError: log.error("Error converting file naming script") - script_list = set(scripts.keys()) | set(map(lambda item: item["id"], get_file_naming_script_presets())) - if config.setting["selected_file_naming_script_id"] not in script_list: + script_list = set(scripts.keys()) | set(map(lambda item: item['id'], get_file_naming_script_presets())) + if config.setting['selected_file_naming_script_id'] not in script_list: script_item = FileNamingScript( - script=config.setting["file_naming_format"], + script=config.setting['file_naming_format'], title=_("Primary file naming script"), readonly=False, deletable=True, ) - scripts[script_item["id"]] = script_item.to_dict() - config.setting["selected_file_naming_script_id"] = script_item["id"] - config.setting["file_renaming_scripts"] = scripts - config.setting.remove("file_naming_scripts") - config.setting.remove("file_naming_format") + scripts[script_item['id']] = script_item.to_dict() + config.setting['selected_file_naming_script_id'] = script_item['id'] + config.setting['file_renaming_scripts'] = scripts + config.setting.remove('file_naming_scripts') + config.setting.remove('file_naming_format') def upgrade_to_v2_7_0_dev_4(config): """Replace artist_script_exception with artist_script_exceptions""" _s = config.setting - ListOption("setting", "artist_script_exceptions", []) - if _s["artist_script_exception"]: - _s["artist_script_exceptions"] = [_s["artist_script_exception"]] - _s.remove("artist_script_exception") - ListOption("setting", "artist_locales", ['en']) - if _s["artist_locale"]: - _s["artist_locales"] = [_s["artist_locale"]] - _s.remove("artist_locale") + ListOption('setting', 'artist_script_exceptions', []) + if _s['artist_script_exception']: + _s['artist_script_exceptions'] = [_s['artist_script_exception']] + _s.remove('artist_script_exception') + ListOption('setting', 'artist_locales', ['en']) + if _s['artist_locale']: + _s['artist_locales'] = [_s['artist_locale']] + _s.remove('artist_locale') def upgrade_to_v2_7_0_dev_5(config): """Replace artist_script_exceptions with script_exceptions and remove artist_script_exception_weighting""" _s = config.setting - ListOption("setting", "script_exceptions", []) - weighting = _s["artist_script_exception_weighting"] or 0 - artist_script_exceptions = _s["artist_script_exceptions"] or [] - _s["script_exceptions"] = [(script_exception, weighting) for script_exception in artist_script_exceptions] - _s.remove("artist_script_exceptions") - _s.remove("artist_script_exception_weighting") + ListOption('setting', 'script_exceptions', []) + weighting = _s['artist_script_exception_weighting'] or 0 + artist_script_exceptions = _s['artist_script_exceptions'] or [] + _s['script_exceptions'] = [(script_exception, weighting) for script_exception in artist_script_exceptions] + _s.remove('artist_script_exceptions') + _s.remove('artist_script_exception_weighting') def upgrade_to_v2_8_0_dev_2(config): @@ -467,10 +467,10 @@ def upgrade_to_v2_8_0_dev_2(config): def upgrade_to_v2_9_0_alpha_2(config): """Add preset file naming scripts to editable user scripts disctionary""" from picard.script import get_file_naming_script_presets - scripts = config.setting["file_renaming_scripts"] + scripts = config.setting['file_renaming_scripts'] for item in get_file_naming_script_presets(): - scripts[item["id"]] = item.to_dict() - config.setting["file_renaming_scripts"] = scripts + scripts[item['id']] = item.to_dict() + config.setting['file_renaming_scripts'] = scripts def rename_option(config, old_opt, new_opt, option_type, default): @@ -481,13 +481,13 @@ def rename_option(config, old_opt, new_opt, option_type, default): _p = config.profiles _s.init_profile_options() - all_settings = _p["user_profile_settings"] - for profile in _p["user_profiles"]: - id = profile["id"] + all_settings = _p['user_profile_settings'] + for profile in _p['user_profiles']: + id = profile['id'] if id in all_settings and old_opt in all_settings[id]: all_settings[id][new_opt] = all_settings[id][old_opt] all_settings[id].pop(old_opt) - _p["user_profile_settings"] = all_settings + _p['user_profile_settings'] = all_settings def upgrade_config(config): diff --git a/picard/const/__init__.py b/picard/const/__init__.py index 133b1c23c1..799e56aed3 100644 --- a/picard/const/__init__.py +++ b/picard/const/__init__.py @@ -78,12 +78,12 @@ 'home': "https://picard.musicbrainz.org/", 'license': "https://www.gnu.org/licenses/gpl-2.0.html", 'documentation_server': DOCS_SERVER_URL, # Shows latest version and tries to match the user's language if available. - 'documentation': DOCS_BASE_URL + '/', - 'troubleshooting': DOCS_BASE_URL + '/troubleshooting/troubleshooting.html', - 'doc_options': DOCS_BASE_URL + '/config/configuration.html', - 'doc_scripting': DOCS_BASE_URL + '/extending/scripting.html', - 'doc_tags_from_filenames': DOCS_BASE_URL + '/usage/tags_from_file_names.html', - 'doc_naming_script_edit': DOCS_BASE_URL + '/config/options_filerenaming_editor.html', + 'documentation': DOCS_BASE_URL + "/", + 'troubleshooting': DOCS_BASE_URL + "/troubleshooting/troubleshooting.html", + 'doc_options': DOCS_BASE_URL + "/config/configuration.html", + 'doc_scripting': DOCS_BASE_URL + "/extending/scripting.html", + 'doc_tags_from_filenames': DOCS_BASE_URL + "/usage/tags_from_file_names.html", + 'doc_naming_script_edit': DOCS_BASE_URL + "/config/options_filerenaming_editor.html", 'doc_cover_art_types': "https://musicbrainz.org/doc/Cover_Art/Types", 'plugins': "https://picard.musicbrainz.org/plugins/", 'forum': "https://community.metabrainz.org/c/picard", @@ -166,19 +166,19 @@ ( 0, { 'name': 'stable', - 'title': N_('Stable releases only'), + 'title': N_("Stable releases only"), } ), ( 1, { 'name': 'beta', - 'title': N_('Stable and Beta releases'), + 'title': N_("Stable and Beta releases"), } ), ( 2, { 'name': 'dev', - 'title': N_('Stable, Beta and Dev releases'), + 'title': N_("Stable, Beta and Dev releases"), } ), ] @@ -197,7 +197,7 @@ DEFAULT_SCRIPT_NAME = N_("My script") -DEFAULT_COVER_IMAGE_FILENAME = "cover" +DEFAULT_COVER_IMAGE_FILENAME = 'cover' DEFAULT_PROFILE_NAME = N_("My profile") DEFAULT_COPY_TEXT = N_("(copy)") DEFAULT_NUMBERED_TITLE_FORMAT = N_("{title} ({count})") diff --git a/picard/coverart/image.py b/picard/coverart/image.py index ae31000188..6b246796bb 100644 --- a/picard/coverart/image.py +++ b/picard/coverart/image.py @@ -81,7 +81,7 @@ def __init__(self, data, prefix='picard', suffix=''): if self._hash not in _datafiles: (fd, self._filename) = tempfile.mkstemp(prefix=prefix, suffix=suffix) QObject.tagger.register_cleanup(self.delete_file) - with os.fdopen(fd, "wb") as imagefile: + with os.fdopen(fd, 'wb') as imagefile: imagefile.write(data) _datafiles[self._hash] = self._filename periodictouch.register_file(self._filename) @@ -116,7 +116,7 @@ def delete_file(self): @property def data(self): if self._filename: - with open(self._filename, "rb") as imagefile: + with open(self._filename, 'rb') as imagefile: return imagefile.read() return None @@ -148,7 +148,7 @@ class CoverArtImage: # `is_front` has to be explicitly set, it is used to handle CAA is_front # indicator is_front = None - sourceprefix = "URL" + sourceprefix = 'URL' def __init__(self, url=None, types=None, comment='', data=None, support_types=None, support_multi_types=None, id3_type=None): @@ -310,12 +310,12 @@ def id3_type(self, type): def _make_image_filename(self, filename, dirname, _metadata, win_compat, win_shorten_path): metadata = Metadata() metadata.copy(_metadata) - metadata["coverart_maintype"] = self.maintype - metadata["coverart_comment"] = self.comment + metadata['coverart_maintype'] = self.maintype + metadata['coverart_comment'] = self.comment if self.is_front: - metadata.add_unique("coverart_types", "front") + metadata.add_unique('coverart_types', 'front') for cover_type in self.types: - metadata.add_unique("coverart_types", cover_type) + metadata.add_unique('coverart_types', cover_type) filename = script_to_filename(filename, metadata) if not filename: filename = DEFAULT_COVER_IMAGE_FILENAME @@ -344,19 +344,19 @@ def save(self, dirname, metadata, counters): if not self.can_be_saved_to_disk: return config = get_config() - win_compat = IS_WIN or config.setting["windows_compatibility"] + win_compat = IS_WIN or config.setting['windows_compatibility'] win_shorten_path = win_compat and not config.setting['windows_long_paths'] - if config.setting["image_type_as_filename"] and not self.is_front_image(): + if config.setting['image_type_as_filename'] and not self.is_front_image(): filename = sanitize_filename(self.maintype, win_compat=win_compat) log.debug("Make cover filename from types: %r -> %r", self.types, filename) else: - filename = config.setting["cover_image_filename"] + filename = config.setting['cover_image_filename'] log.debug("Using default cover image filename %r", filename) filename = self._make_image_filename( filename, dirname, metadata, win_compat, win_shorten_path) - overwrite = config.setting["save_images_overwrite"] + overwrite = config.setting['save_images_overwrite'] ext = encode_filename(self.extension) image_filename = self._next_filename(filename, counters) while os.path.exists(image_filename + ext) and not overwrite: @@ -430,7 +430,7 @@ class CaaCoverArtImage(CoverArtImage): support_types = True support_multi_types = True - sourceprefix = "CAA" + sourceprefix = 'CAA' def __init__(self, url, types=None, is_front=False, comment='', data=None): super().__init__(url=url, types=types, comment=comment, data=data) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index e88f23fa8b..7807b2eb8e 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -83,7 +83,7 @@ _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE = ['matrix/runout', 'raw/unedited', 'watermark'] ratecontrol.set_minimum_delay_for_url(CAA_URL, 0) -ratecontrol.set_minimum_delay_for_url('https://archive.org', 0) +ratecontrol.set_minimum_delay_for_url("https://archive.org", 0) def caa_url_fallback_list(desired_size, thumbnails): @@ -118,14 +118,14 @@ class ProviderOptionsCaa(ProviderOptions): """ TITLE = N_("Cover Art Archive") - HELP_URL = '/config/options_cover_art_archive.html' + HELP_URL = "/config/options_cover_art_archive.html" options = [ - BoolOption("setting", "caa_approved_only", False), - IntOption("setting", "caa_image_size", _CAA_IMAGE_SIZE_DEFAULT), - ListOption("setting", "caa_image_types", _CAA_IMAGE_TYPE_DEFAULT_INCLUDE), - BoolOption("setting", "caa_restrict_image_types", True), - ListOption("setting", "caa_image_types_to_omit", _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE), + BoolOption('setting', 'caa_approved_only', False), + IntOption('setting', 'caa_image_size', _CAA_IMAGE_SIZE_DEFAULT), + ListOption('setting', 'caa_image_types', _CAA_IMAGE_TYPE_DEFAULT_INCLUDE), + BoolOption('setting', 'caa_restrict_image_types', True), + ListOption('setting', 'caa_image_types_to_omit', _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE), ] _options_ui = Ui_CaaOptions @@ -146,29 +146,29 @@ def load(self): self.ui.cb_image_size.addItem(_(item.label), userData=item_id) config = get_config() - size = config.setting["caa_image_size"] + size = config.setting['caa_image_size'] index = self.ui.cb_image_size.findData(size) if index < 0: index = self.ui.cb_image_size.findData(_CAA_IMAGE_SIZE_DEFAULT) self.ui.cb_image_size.setCurrentIndex(index) - self.ui.cb_approved_only.setChecked(config.setting["caa_approved_only"]) + self.ui.cb_approved_only.setChecked(config.setting['caa_approved_only']) self.ui.restrict_images_types.setChecked( - config.setting["caa_restrict_image_types"]) - self.caa_image_types = config.setting["caa_image_types"] - self.caa_image_types_to_omit = config.setting["caa_image_types_to_omit"] + config.setting['caa_restrict_image_types']) + self.caa_image_types = config.setting['caa_image_types'] + self.caa_image_types_to_omit = config.setting['caa_image_types_to_omit'] self.update_caa_types() def save(self): config = get_config() size = self.ui.cb_image_size.currentData() - config.setting["caa_image_size"] = size - config.setting["caa_approved_only"] = \ + config.setting['caa_image_size'] = size + config.setting['caa_approved_only'] = \ self.ui.cb_approved_only.isChecked() - config.setting["caa_restrict_image_types"] = \ + config.setting['caa_restrict_image_types'] = \ self.ui.restrict_images_types.isChecked() - config.setting["caa_image_types"] = self.caa_image_types - config.setting["caa_image_types_to_omit"] = self.caa_image_types_to_omit + config.setting['caa_image_types'] = self.caa_image_types + config.setting['caa_image_types_to_omit'] = self.caa_image_types_to_omit def update_caa_types(self): enabled = self.ui.restrict_images_types.isChecked() @@ -194,7 +194,7 @@ class CoverArtProviderCaa(CoverArtProvider): """Get cover art from Cover Art Archive using release mbid""" NAME = "Cover Art Archive" - TITLE = N_('Cover Art Archive: Release') + TITLE = N_("Cover Art Archive: Release") OPTIONS = ProviderOptionsCaa ignore_json_not_found_error = False @@ -215,14 +215,14 @@ def _has_suitable_artwork(self): # MB web service indicates if CAA has artwork # https://tickets.metabrainz.org/browse/MBS-4536 if 'cover-art-archive' not in self.release: - log.debug('No Cover Art Archive information for %s', self.release['id']) + log.debug("No Cover Art Archive information for %s", self.release['id']) return False caa_node = self.release['cover-art-archive'] caa_has_suitable_artwork = caa_node['artwork'] if not caa_has_suitable_artwork: - log.debug('There are no images in the Cover Art Archive for %s', self.release['id']) + log.debug("There are no images in the Cover Art Archive for %s", self.release['id']) return False if self.restrict_types: @@ -251,9 +251,9 @@ def _has_suitable_artwork(self): caa_has_suitable_artwork = front_in_caa or back_in_caa if not caa_has_suitable_artwork: - log.debug('There are no suitable images in the Cover Art Archive for %s', self.release['id']) + log.debug("There are no suitable images in the Cover Art Archive for %s", self.release['id']) else: - log.debug('There are suitable images in the Cover Art Archive for %s', self.release['id']) + log.debug("There are suitable images in the Cover Art Archive for %s", self.release['id']) return caa_has_suitable_artwork @@ -262,13 +262,13 @@ def enabled(self): if not super().enabled(): return False if self.restrict_types and not self.included_types_count: - log.debug('User disabled all Cover Art Archive types') + log.debug("User disabled all Cover Art Archive types") return False return self._has_suitable_artwork @property def _caa_path(self): - return "/release/%s/" % self.metadata["musicbrainz_albumid"] + return "/release/%s/" % self.metadata['musicbrainz_albumid'] def queue_images(self): self.album.tagger.webservice.get_url( @@ -287,10 +287,10 @@ def _caa_json_downloaded(self, data, http, error): self.album._requests -= 1 if error: if not (error == QNetworkReply.NetworkError.ContentNotFoundError and self.ignore_json_not_found_error): - self.error('CAA JSON error: %s' % (http.errorString())) + self.error("CAA JSON error: %s" % (http.errorString())) else: if self.restrict_types: - log.debug('CAA types: included: %s, excluded: %s', self.included_types, self.excluded_types) + log.debug("CAA types: included: %s, excluded: %s", self.included_types, self.excluded_types) try: config = get_config() for image in data['images']: @@ -298,7 +298,7 @@ def _caa_json_downloaded(self, data, http, error): continue is_pdf = image['image'].endswith('.pdf') if is_pdf and not config.setting['save_images_to_files']: - log.debug("Skipping pdf cover art : %s", image["image"]) + log.debug("Skipping pdf cover art : %s", image['image']) continue # if image has no type set, we still want it to match # pseudo type 'unknown' @@ -310,7 +310,7 @@ def _caa_json_downloaded(self, data, http, error): if self.restrict_types: # accept only if image types matches according to included/excluded types accepted = bool(set(image['types']).intersection(self.included_types).difference(self.excluded_types)) - log.debug('CAA image %s: %s %s', + log.debug("CAA image %s: %s %s", ('accepted' if accepted else 'rejected'), image['image'], image['types'] @@ -350,6 +350,6 @@ def _caa_json_downloaded(self, data, http, error): image['front']: break except (AttributeError, KeyError, TypeError) as e: - self.error('CAA JSON error: %s' % e) + self.error("CAA JSON error: %s" % e) self.next_in_queue() diff --git a/picard/coverart/providers/caa_release_group.py b/picard/coverart/providers/caa_release_group.py index 9a4c85be0a..cd3655c6e5 100644 --- a/picard/coverart/providers/caa_release_group.py +++ b/picard/coverart/providers/caa_release_group.py @@ -54,4 +54,4 @@ def enabled(self): @property def _caa_path(self): - return "/release-group/%s/" % self.metadata["musicbrainz_releasegroupid"] + return "/release-group/%s/" % self.metadata['musicbrainz_releasegroupid'] diff --git a/picard/coverart/providers/local.py b/picard/coverart/providers/local.py index 563b0614e4..fb56eef639 100644 --- a/picard/coverart/providers/local.py +++ b/picard/coverart/providers/local.py @@ -48,7 +48,7 @@ class ProviderOptionsLocal(ProviderOptions): _DEFAULT_LOCAL_COVER_ART_REGEX = r'^(?:cover|folder|albumart)(.*)\.(?:jpe?g|png|gif|tiff?|webp)$' options = [ - TextOption("setting", "local_cover_regex", _DEFAULT_LOCAL_COVER_ART_REGEX), + TextOption('setting', 'local_cover_regex', _DEFAULT_LOCAL_COVER_ART_REGEX), ] _options_ui = Ui_LocalOptions @@ -63,11 +63,11 @@ def set_local_cover_regex_default(self): def load(self): config = get_config() - self.ui.local_cover_regex_edit.setText(config.setting["local_cover_regex"]) + self.ui.local_cover_regex_edit.setText(config.setting['local_cover_regex']) def save(self): config = get_config() - config.setting["local_cover_regex"] = self.ui.local_cover_regex_edit.text() + config.setting['local_cover_regex'] = self.ui.local_cover_regex_edit.text() class CoverArtProviderLocal(CoverArtProvider): diff --git a/picard/coverart/providers/urlrels.py b/picard/coverart/providers/urlrels.py index b07b9897b1..a9fac7b377 100644 --- a/picard/coverart/providers/urlrels.py +++ b/picard/coverart/providers/urlrels.py @@ -36,7 +36,7 @@ class CoverArtProviderUrlRelationships(CoverArtProvider): cover art""" NAME = "UrlRelationships" - TITLE = N_('Allowed Cover Art URLs') + TITLE = N_("Allowed Cover Art URLs") def queue_images(self): self.match_url_relations(('cover art link', 'has_cover_art_at'), diff --git a/picard/coverart/utils.py b/picard/coverart/utils.py index 0dd0df901d..13d4ec5653 100644 --- a/picard/coverart/utils.py +++ b/picard/coverart/utils.py @@ -35,7 +35,7 @@ CAA_TYPES.append({'name': v.lower(), 'title': v}) # pseudo type, used for the no type case -CAA_TYPES.append({'name': "unknown", 'title': N_("Unknown")}) +CAA_TYPES.append({'name': 'unknown', 'title': N_("Unknown")}) CAA_TYPES_TR = {} for t in CAA_TYPES: @@ -76,23 +76,23 @@ class Id3ImageType(IntEnum): __ID3_IMAGE_TYPE_MAP = { - "obi": Id3ImageType.OTHER, - "tray": Id3ImageType.OTHER, - "spine": Id3ImageType.OTHER, - "sticker": Id3ImageType.OTHER, - "other": Id3ImageType.OTHER, - "front": Id3ImageType.COVER_FRONT, - "back": Id3ImageType.COVER_BACK, - "booklet": Id3ImageType.LEAFLET_PAGE, - "track": Id3ImageType.MEDIA, - "medium": Id3ImageType.MEDIA, + 'obi': Id3ImageType.OTHER, + 'tray': Id3ImageType.OTHER, + 'spine': Id3ImageType.OTHER, + 'sticker': Id3ImageType.OTHER, + 'other': Id3ImageType.OTHER, + 'front': Id3ImageType.COVER_FRONT, + 'back': Id3ImageType.COVER_BACK, + 'booklet': Id3ImageType.LEAFLET_PAGE, + 'track': Id3ImageType.MEDIA, + 'medium': Id3ImageType.MEDIA, } __ID3_REVERSE_IMAGE_TYPE_MAP = {v: k for k, v in __ID3_IMAGE_TYPE_MAP.items()} def image_type_from_id3_num(id3type): - return __ID3_REVERSE_IMAGE_TYPE_MAP.get(id3type, "other") + return __ID3_REVERSE_IMAGE_TYPE_MAP.get(id3type, 'other') def image_type_as_id3_num(texttype): diff --git a/picard/disc/__init__.py b/picard/disc/__init__.py index b7e3986b67..d5084b9a28 100644 --- a/picard/disc/__init__.py +++ b/picard/disc/__init__.py @@ -93,7 +93,7 @@ def _set_disc_details(self, disc): @property def submission_url(self): if self.id and self.tracks and self.toc_string: - return build_submission_url('/cdtoc/attach', query_args={ + return build_submission_url("/cdtoc/attach", query_args={ 'id': self.id, 'tracks': self.tracks, 'toc': self.toc_string.replace(' ', '+'), diff --git a/picard/disc/dbpoweramplog.py b/picard/disc/dbpoweramplog.py index 685bb55eb0..b243df57c2 100644 --- a/picard/disc/dbpoweramplog.py +++ b/picard/disc/dbpoweramplog.py @@ -43,7 +43,7 @@ def filter_toc_entries(lines): if m: track_num = int(m['num']) if last_track_num + 1 != track_num: - raise NotSupportedTOCError(f'Non consecutive track numbers ({last_track_num} => {track_num}) in dBPoweramp log. Likely a partial rip, disc ID cannot be calculated') + raise NotSupportedTOCError(f"Non consecutive track numbers ({last_track_num} => {track_num}) in dBPoweramp log. Likely a partial rip, disc ID cannot be calculated") last_track_num = track_num yield TocEntry(track_num, int(m['start_sector']), int(m['end_sector'])-1) diff --git a/picard/file.py b/picard/file.py index 1a059febe6..9c4078dc1e 100644 --- a/picard/file.py +++ b/picard/file.py @@ -135,16 +135,16 @@ class File(QtCore.QObject, Item): FILE_INFO_TAGS = ('~bitrate', '~sample_rate', '~channels', '~bits_per_sample', '~format') comparison_weights = { - "title": 13, - "artist": 4, - "album": 5, - "length": 10, - "totaltracks": 4, - "releasetype": 14, - "releasecountry": 2, - "format": 2, - "isvideo": 2, - "date": 4, + 'title': 13, + 'artist': 4, + 'album': 5, + 'length': 10, + 'totaltracks': 4, + 'releasetype': 14, + 'releasecountry': 2, + 'format': 2, + 'isvideo': 2, + 'date': 4, } class PreserveTimesStatError(Exception): @@ -213,7 +213,7 @@ def _set_error(self, error): self.state = File.ERROR if any_exception_isinstance(error, MutagenError): self.error_type = FileErrorType.PARSER - self.error_append(_('The file failed to parse, either the file is damaged or has an unsupported file format.')) + self.error_append(_("The file failed to parse, either the file is damaged or has an unsupported file format.")) elif any_exception_isinstance(error, FileNotFoundError): self.error_type = FileErrorType.NOTFOUND elif any_exception_isinstance(error, PermissionError): @@ -261,7 +261,7 @@ def _loading_finished(self, callback, result=None, error=None): if alternative_file: # Do not retry reloading exactly the same file format if type(alternative_file) != type(self): # pylint: disable=unidiomatic-typecheck # noqa: E721 - log.debug('Loading %r failed, retrying as %r', self, alternative_file) + log.debug("Loading %r failed, retrying as %r", self, alternative_file) self.remove() alternative_file.load(callback) return @@ -270,18 +270,18 @@ def _loading_finished(self, callback, result=None, error=None): from picard.formats import supported_extensions file_name, file_extension = os.path.splitext(self.base_filename) if file_extension not in supported_extensions(): - log.error('Unsupported media file %r wrongly loaded. Removing …', self) + log.error("Unsupported media file %r wrongly loaded. Removing …", self) callback(self, remove_file=True) return else: self.clear_errors() self.state = self.NORMAL postprocessors = [] - if config.setting["guess_tracknumber_and_title"]: + if config.setting['guess_tracknumber_and_title']: postprocessors.append(self._guess_tracknumber_and_title) self._copy_loaded_metadata(result, postprocessors) # use cached fingerprint from file metadata - if not config.setting["ignore_existing_acoustid_fingerprints"]: + if not config.setting['ignore_existing_acoustid_fingerprints']: fingerprints = self.metadata.getall('acoustid_fingerprint') if fingerprints: self.set_acoustid_fingerprint(fingerprints[0]) @@ -382,9 +382,9 @@ def _save_and_rename(self, old_filename, metadata): log.debug("File not saved because %s is stopping: %r", PICARD_APP_NAME, self.filename) return None new_filename = old_filename - if not config.setting["dont_write_tags"]: + if not config.setting['dont_write_tags']: save = partial(self._save, old_filename, metadata) - if config.setting["preserve_timestamps"]: + if config.setting['preserve_timestamps']: try: self._preserve_times(old_filename, save) except self.PreserveTimesUtimeError as why: @@ -392,12 +392,12 @@ def _save_and_rename(self, old_filename, metadata): else: save() # Rename files - if config.setting["rename_files"] or config.setting["move_files"]: + if config.setting['rename_files'] or config.setting['move_files']: new_filename = self._rename(old_filename, metadata, config.setting) # Move extra files (images, playlists, etc.) self._move_additional_files(old_filename, new_filename, config) # Delete empty directories - if config.setting["delete_empty_dirs"]: + if config.setting['delete_empty_dirs']: dirname = os.path.dirname(old_filename) try: emptydir.rm_empty_dir(dirname) @@ -412,7 +412,7 @@ def _save_and_rename(self, old_filename, metadata): except emptydir.SkipRemoveDir as why: log.debug("Not removing empty directory: %s", why) # Save cover art images - if config.setting["save_images_to_files"]: + if config.setting['save_images_to_files']: self._save_images(os.path.dirname(new_filename), metadata) return new_filename @@ -436,7 +436,7 @@ def _saving_finished(self, result=None, error=None): # conversions (e.g. for ID3v2.3) config = get_config() new_metadata = self._format_specific_copy(self.metadata, config.setting) - if config.setting["clear_existing_tags"]: + if config.setting['clear_existing_tags']: self.orig_metadata = new_metadata else: self.orig_metadata.update(new_metadata) @@ -474,7 +474,7 @@ def _script_to_filename(self, naming_format, file_metadata, file_extension, sett config = get_config() settings = config.setting metadata = Metadata() - if settings["clear_existing_tags"]: + if settings['clear_existing_tags']: # script_to_filename_with_metadata guarantees this is not modified metadata = file_metadata else: @@ -538,15 +538,15 @@ def make_filename(self, filename, metadata, settings=None, naming_format=None): settings = config.setting if naming_format is None: naming_format = get_file_naming_script(settings) - if settings["move_files"]: - new_dirname = settings["move_files_to"] + if settings['move_files']: + new_dirname = settings['move_files_to'] if not is_absolute_path(new_dirname): new_dirname = os.path.join(os.path.dirname(filename), new_dirname) else: new_dirname = os.path.dirname(filename) new_filename = os.path.basename(filename) - if settings["rename_files"] or settings["move_files"]: + if settings['rename_files'] or settings['move_files']: new_filename = self._format_filename(new_dirname, new_filename, metadata, settings, naming_format) new_path = os.path.join(new_dirname, new_filename) @@ -572,7 +572,7 @@ def _save_images(self, dirname, metadata): counters = Counter() images = [] config = get_config() - if config.setting["save_only_one_front_image"]: + if config.setting['save_only_one_front_image']: front = metadata.images.get_front_image() if front: images.append(front) @@ -583,11 +583,11 @@ def _save_images(self, dirname, metadata): def _move_additional_files(self, old_filename, new_filename, config): """Move extra files, like images, playlists…""" - if config.setting["move_files"] and config.setting["move_additional_files"]: + if config.setting['move_files'] and config.setting['move_additional_files']: new_path = os.path.dirname(new_filename) old_path = os.path.dirname(old_filename) if new_path != old_path: - patterns_string = config.setting["move_additional_files_pattern"] + patterns_string = config.setting['move_additional_files_pattern'] patterns = self._compile_move_additional_files_pattern(patterns_string) try: moves = self._get_additional_files_moves(old_path, new_path, patterns) @@ -705,8 +705,8 @@ def _tags_to_update(self, ignored_tags): def update(self, signal=True): if not (self.state == File.ERROR and self.errors): config = get_config() - clear_existing_tags = config.setting["clear_existing_tags"] - ignored_tags = set(config.setting["compare_ignore_tags"]) + clear_existing_tags = config.setting['clear_existing_tags'] + ignored_tags = set(config.setting['compare_ignore_tags']) for name in self._tags_to_update(ignored_tags): new_values = self.format_specific_metadata(self.metadata, name, config.setting) @@ -812,9 +812,9 @@ def state(self, state): def column(self, column): m = self.metadata - if column == "title" and not m["title"]: + if column == 'title' and not m['title']: return self.base_filename - elif column == "covercount": + elif column == 'covercount': return self.cover_art_description() return m[column] diff --git a/picard/formats/apev2.py b/picard/formats/apev2.py index d152e22c75..1d29b7718c 100644 --- a/picard/formats/apev2.py +++ b/picard/formats/apev2.py @@ -95,33 +95,33 @@ class APEv2File(File): _File = None __translate = { - "albumartist": "Album Artist", - "remixer": "MixArtist", - "director": "Director", - "website": "Weblink", - "discsubtitle": "DiscSubtitle", - "bpm": "BPM", - "isrc": "ISRC", - "catalognumber": "CatalogNumber", - "barcode": "Barcode", - "encodedby": "EncodedBy", - "language": "Language", - "movementnumber": "MOVEMENT", - "movement": "MOVEMENTNAME", - "movementtotal": "MOVEMENTTOTAL", - "showmovement": "SHOWMOVEMENT", - "releasestatus": "MUSICBRAINZ_ALBUMSTATUS", - "releasetype": "MUSICBRAINZ_ALBUMTYPE", - "musicbrainz_recordingid": "musicbrainz_trackid", - "musicbrainz_trackid": "musicbrainz_releasetrackid", - "originalartist": "Original Artist", - "replaygain_album_gain": "REPLAYGAIN_ALBUM_GAIN", - "replaygain_album_peak": "REPLAYGAIN_ALBUM_PEAK", - "replaygain_album_range": "REPLAYGAIN_ALBUM_RANGE", - "replaygain_track_gain": "REPLAYGAIN_TRACK_GAIN", - "replaygain_track_peak": "REPLAYGAIN_TRACK_PEAK", - "replaygain_track_range": "REPLAYGAIN_TRACK_RANGE", - "replaygain_reference_loudness": "REPLAYGAIN_REFERENCE_LOUDNESS", + 'albumartist': 'Album Artist', + 'remixer': 'MixArtist', + 'director': 'Director', + 'website': 'Weblink', + 'discsubtitle': 'DiscSubtitle', + 'bpm': 'BPM', + 'isrc': 'ISRC', + 'catalognumber': 'CatalogNumber', + 'barcode': 'Barcode', + 'encodedby': 'EncodedBy', + 'language': 'Language', + 'movementnumber': 'MOVEMENT', + 'movement': 'MOVEMENTNAME', + 'movementtotal': 'MOVEMENTTOTAL', + 'showmovement': 'SHOWMOVEMENT', + 'releasestatus': 'MUSICBRAINZ_ALBUMSTATUS', + 'releasetype': 'MUSICBRAINZ_ALBUMTYPE', + 'musicbrainz_recordingid': 'musicbrainz_trackid', + 'musicbrainz_trackid': 'musicbrainz_releasetrackid', + 'originalartist': 'Original Artist', + 'replaygain_album_gain': 'REPLAYGAIN_ALBUM_GAIN', + 'replaygain_album_peak': 'REPLAYGAIN_ALBUM_PEAK', + 'replaygain_album_range': 'REPLAYGAIN_ALBUM_RANGE', + 'replaygain_track_gain': 'REPLAYGAIN_TRACK_GAIN', + 'replaygain_track_peak': 'REPLAYGAIN_TRACK_PEAK', + 'replaygain_track_range': 'REPLAYGAIN_TRACK_RANGE', + 'replaygain_reference_loudness': 'REPLAYGAIN_REFERENCE_LOUDNESS', } __rtranslate = {v.lower(): k for k, v in __translate.items()} @@ -138,7 +138,7 @@ def _load(self, filename): for origname, values in file.tags.items(): name_lower = origname.lower() if (values.kind == mutagen.apev2.BINARY - and name_lower.startswith("cover art")): + and name_lower.startswith('cover art')): if b'\0' in values.value: descr, data = values.value.split(b'\0', 1) try: @@ -148,7 +148,7 @@ def _load(self, filename): data=data, ) except CoverArtImageError as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) @@ -157,20 +157,20 @@ def _load(self, filename): continue for value in values: name = name_lower - if name == "year": - name = "date" + if name == 'year': + name = 'date' value = sanitize_date(value) - elif name == "track": - name = "tracknumber" - track = value.split("/") + elif name == 'track': + name = 'tracknumber' + track = value.split('/') if len(track) > 1: - metadata["totaltracks"] = track[1] + metadata['totaltracks'] = track[1] value = track[0] - elif name == "disc": - name = "discnumber" - disc = value.split("/") + elif name == 'disc': + name = 'discnumber' + disc = value.split('/') if len(disc) > 1: - metadata["totaldiscs"] = disc[1] + metadata['totaldiscs'] = disc[1] value = disc[0] elif name in {'performer', 'comment'}: if value.endswith(')'): @@ -194,7 +194,7 @@ def _save(self, filename, metadata): except mutagen.apev2.APENoHeaderError: tags = mutagen.apev2.APEv2() images_to_save = list(metadata.images.to_be_saved_to_tags()) - if config.setting["clear_existing_tags"]: + if config.setting['clear_existing_tags']: preserved = [] if config.setting['preserve_images']: preserved = list(self._iter_cover_art_tags(tags)) @@ -206,7 +206,7 @@ def _save(self, filename, metadata): del tags[name] temp = {} for name, value in metadata.items(): - if name.startswith("~") or not self.supports_tag(name): + if name.startswith('~') or not self.supports_tag(name): continue real_name = self._get_tag_name(name) # tracknumber/totaltracks => Track @@ -326,7 +326,7 @@ def _move_or_rename_wvc(self, old_filename, new_filename): def _move_additional_files(self, old_filename, new_filename, config): """Includes an additional check for WavPack correction files""" - if config.setting["rename_files"] or config.setting["move_files"]: + if config.setting['rename_files'] or config.setting['move_files']: self._move_or_rename_wvc(old_filename, new_filename) return super()._move_additional_files(old_filename, new_filename, config) @@ -384,7 +384,7 @@ def _save(self, filename, metadata): try: mutagen.apev2.delete(encode_filename(filename)) except BaseException: - log.exception('Error removing APEv2 tags from %s', filename) + log.exception("Error removing APEv2 tags from %s", filename) @classmethod def supports_tag(cls, name): diff --git a/picard/formats/asf.py b/picard/formats/asf.py index 3db2a14088..c10e2af03b 100644 --- a/picard/formats/asf.py +++ b/picard/formats/asf.py @@ -59,32 +59,32 @@ def unpack_image(data): The image data in the given length """ try: - (type_, size) = struct.unpack_from(" 1: - metadata["totaldiscs"] = disc[1] + metadata['totaldiscs'] = disc[1] values[0] = disc[0] name_lower = name.lower() if name in self.__RTRANS: diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 2f993ea113..e3ce1b7cf6 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -89,7 +89,7 @@ def id3text(text, encoding): """ if encoding == Id3Encoding.LATIN1: - return text.encode("latin1", "replace").decode("latin1") + return text.encode('latin1', 'replace').decode('latin1') return text @@ -220,9 +220,9 @@ class ID3File(File): } _rtipl_roles = {v: k for k, v in _tipl_roles.items()} - __other_supported_tags = ("discnumber", "tracknumber", - "totaldiscs", "totaltracks", - "movementnumber", "movementtotal") + __other_supported_tags = ('discnumber', 'tracknumber', + 'totaldiscs', 'totaltracks', + 'movementnumber', 'movementtotal') __tag_re_parse = { 'TRCK': re.compile(r'^(?P\d+)(?:/(?P\d+))?$'), 'TPOS': re.compile(r'^(?P\d+)(?:/(?P\d+))?$'), @@ -262,7 +262,7 @@ def _load(self, filename): frameid = frame.FrameID if frameid in self.__translate: name = self.__translate[frameid] - if frameid.startswith('T') or frameid in {"GRP1", "MVNM"}: + if frameid.startswith('T') or frameid in {'GRP1', 'MVNM'}: for text in frame.text: if text: metadata.add(name, text) @@ -281,7 +281,7 @@ def _load(self, filename): for text in frame.text: if text: metadata.add(name, text) - elif frameid == "TMCL": + elif frameid == 'TMCL': for role, name in frame.people: if role == 'performer': role = '' @@ -289,7 +289,7 @@ def _load(self, filename): metadata.add('performer:%s' % role, name) else: metadata.add('performer', name) - elif frameid == "TIPL": + elif frameid == 'TIPL': # If file is ID3v2.3, TIPL tag could contain TMCL # so we will test for TMCL values and add to TIPL if not TMCL for role, name in frame.people: @@ -330,7 +330,7 @@ def _load(self, filename): if frame.desc: name += ':%s' % frame.desc metadata.add(name, frame.text) - elif frameid == 'UFID' and frame.owner == 'http://musicbrainz.org': + elif frameid == 'UFID' and frame.owner == "http://musicbrainz.org": metadata['musicbrainz_recordingid'] = frame.data.decode('ascii', 'ignore') elif frameid in self.__tag_re_parse.keys(): m = self.__tag_re_parse[frameid].search(frame.text[0]) @@ -352,7 +352,7 @@ def _load(self, filename): id3_type=frame.type, ) except CoverArtImageError as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) elif frameid == 'POPM': @@ -375,7 +375,7 @@ def _save(self, filename, metadata): tags = self._get_tags(filename) config = get_config() if config.setting['clear_existing_tags']: - cover = tags.getall('APIC') if config.setting["preserve_images"] else None + cover = tags.getall('APIC') if config.setting['preserve_images'] else None tags.clear() if cover: tags.setall('APIC', cover) @@ -463,7 +463,7 @@ def _save(self, filename, metadata): for value in values: tipl.people.append([self._rtipl_roles[name], value]) elif name == 'musicbrainz_recordingid': - tags.add(id3.UFID(owner='http://musicbrainz.org', data=bytes(values[0], 'ascii'))) + tags.add(id3.UFID(owner="http://musicbrainz.org", data=bytes(values[0], 'ascii'))) elif name == '~rating': rating_user_email = id3text(config.setting['rating_user_email'], Id3Encoding.LATIN1) # Search for an existing POPM frame to get the current playcount @@ -538,7 +538,7 @@ def _save(self, filename, metadata): if frameclass: tags.add(frameclass(encoding=encoding, text=values)) # don't save private / already stored tags - elif not name.startswith("~") and name not in self.__other_supported_tags: + elif not name.startswith('~') and name not in self.__other_supported_tags: tags.add(self.build_TXXX(encoding, name, values)) if tmcl.people: @@ -550,7 +550,7 @@ def _save(self, filename, metadata): self._save_tags(tags, encode_filename(filename)) - if self._IsMP3 and config.setting["remove_ape_from_mp3"]: + if self._IsMP3 and config.setting['remove_ape_from_mp3']: try: mutagen.apev2.delete(encode_filename(filename)) except BaseException: @@ -585,7 +585,7 @@ def _remove_deleted_tags(self, metadata, tags): _remove_people_with_role(tags, ['TIPL', 'IPLS'], role) elif name == 'musicbrainz_recordingid': for key, frame in list(tags.items()): - if frame.FrameID == 'UFID' and frame.owner == 'http://musicbrainz.org': + if frame.FrameID == 'UFID' and frame.owner == "http://musicbrainz.org": del tags[key] elif name == 'license': tags.delall(real_name) @@ -603,9 +603,9 @@ def _remove_deleted_tags(self, metadata, tags): tags.delall('TXXX:' + real_name) if real_name in self.__rrename_freetext: tags.delall('TXXX:' + self.__rrename_freetext[real_name]) - elif not name.startswith("~id3:") and name not in self.__other_supported_tags: + elif not name.startswith('~id3:') and name not in self.__other_supported_tags: tags.delall('TXXX:' + name) - elif name.startswith("~id3:"): + elif name.startswith('~id3:'): frameid = name[5:] tags.delall(frameid) elif name in self.__other_supported_tags: @@ -615,9 +615,9 @@ def _remove_deleted_tags(self, metadata, tags): @classmethod def supports_tag(cls, name): - return ((name and not name.startswith("~") and name not in UNSUPPORTED_TAGS) - or name == "~rating" - or name.startswith("~id3")) + return ((name and not name.startswith('~') and name not in UNSUPPORTED_TAGS) + or name == '~rating' + or name.startswith('~id3')) def _get_tag_name(self, name): if name in self.__rtranslate: @@ -663,23 +663,23 @@ def format_specific_metadata(self, metadata, tag, settings=None): if not settings: settings = get_config().setting - if not settings["write_id3v23"]: + if not settings['write_id3v23']: return super().format_specific_metadata(metadata, tag, settings) values = metadata.getall(tag) if not values: return values - if tag == "originaldate": + if tag == 'originaldate': values = [v[:4] for v in values] - elif tag == "date": + elif tag == 'date': values = [(v[:4] if len(v) < 10 else v) for v in values] # If this is a multi-valued field, then it needs to be flattened, # unless it's TIPL or TMCL which can still be multi-valued. if (len(values) > 1 and tag not in ID3File._rtipl_roles - and not tag.startswith("performer:")): - join_with = settings["id3v23_join_with"] + and not tag.startswith('performer:')): + join_with = settings['id3v23_join_with'] values = [join_with.join(values)] return values diff --git a/picard/formats/mp4.py b/picard/formats/mp4.py index ca2c8de82c..82a2291b43 100644 --- a/picard/formats/mp4.py +++ b/picard/formats/mp4.py @@ -51,7 +51,7 @@ def _add_text_values_to_metadata(metadata, name, values): for value in values: - metadata.add(name, value.decode("utf-8", "replace").strip("\x00")) + metadata.add(name, value.decode('utf-8', 'replace').strip('\x00')) _VALID_KEY_CHARS = re.compile('^[\x00-\xff]+$') @@ -71,106 +71,106 @@ class MP4File(File): _File = MP4 __text_tags = { - "\xa9ART": "artist", - "\xa9nam": "title", - "\xa9alb": "album", - "\xa9wrt": "composer", - "aART": "albumartist", - "\xa9grp": "grouping", - "\xa9day": "date", - "\xa9gen": "genre", - "\xa9lyr": "lyrics", - "\xa9cmt": "comment", - "\xa9too": "encodedby", - "\xa9dir": "director", - "cprt": "copyright", - "soal": "albumsort", - "soaa": "albumartistsort", - "soar": "artistsort", - "sonm": "titlesort", - "soco": "composersort", - "sosn": "showsort", - "tvsh": "show", - "purl": "podcasturl", - "\xa9mvn": "movement", - "\xa9wrk": "work", + '\xa9ART': 'artist', + '\xa9nam': 'title', + '\xa9alb': 'album', + '\xa9wrt': 'composer', + 'aART': 'albumartist', + '\xa9grp': 'grouping', + '\xa9day': 'date', + '\xa9gen': 'genre', + '\xa9lyr': 'lyrics', + '\xa9cmt': 'comment', + '\xa9too': 'encodedby', + '\xa9dir': 'director', + 'cprt': 'copyright', + 'soal': 'albumsort', + 'soaa': 'albumartistsort', + 'soar': 'artistsort', + 'sonm': 'titlesort', + 'soco': 'composersort', + 'sosn': 'showsort', + 'tvsh': 'show', + 'purl': 'podcasturl', + '\xa9mvn': 'movement', + '\xa9wrk': 'work', } __r_text_tags = {v: k for k, v in __text_tags.items()} __bool_tags = { - "pcst": "podcast", - "cpil": "compilation", - "pgap": "gapless", + 'pcst': 'podcast', + 'cpil': 'compilation', + 'pgap': 'gapless', } __r_bool_tags = {v: k for k, v in __bool_tags.items()} __int_tags = { - "tmpo": "bpm", - "\xa9mvi": "movementnumber", - "\xa9mvc": "movementtotal", - "shwm": "showmovement", + 'tmpo': 'bpm', + '\xa9mvi': 'movementnumber', + '\xa9mvc': 'movementtotal', + 'shwm': 'showmovement', } __r_int_tags = {v: k for k, v in __int_tags.items()} __freeform_tags = { - "----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_recordingid", - "----:com.apple.iTunes:MusicBrainz Artist Id": "musicbrainz_artistid", - "----:com.apple.iTunes:MusicBrainz Album Id": "musicbrainz_albumid", - "----:com.apple.iTunes:MusicBrainz Album Artist Id": "musicbrainz_albumartistid", - "----:com.apple.iTunes:MusicIP PUID": "musicip_puid", - "----:com.apple.iTunes:MusicBrainz Album Status": "releasestatus", - "----:com.apple.iTunes:MusicBrainz Album Release Country": "releasecountry", - "----:com.apple.iTunes:MusicBrainz Album Type": "releasetype", - "----:com.apple.iTunes:MusicBrainz Disc Id": "musicbrainz_discid", - "----:com.apple.iTunes:MusicBrainz TRM Id": "musicbrainz_trmid", - "----:com.apple.iTunes:MusicBrainz Work Id": "musicbrainz_workid", - "----:com.apple.iTunes:MusicBrainz Release Group Id": "musicbrainz_releasegroupid", - "----:com.apple.iTunes:MusicBrainz Release Track Id": "musicbrainz_trackid", - "----:com.apple.iTunes:MusicBrainz Original Album Id": "musicbrainz_originalalbumid", - "----:com.apple.iTunes:MusicBrainz Original Artist Id": "musicbrainz_originalartistid", - "----:com.apple.iTunes:Acoustid Fingerprint": "acoustid_fingerprint", - "----:com.apple.iTunes:Acoustid Id": "acoustid_id", - "----:com.apple.iTunes:ASIN": "asin", - "----:com.apple.iTunes:BARCODE": "barcode", - "----:com.apple.iTunes:PRODUCER": "producer", - "----:com.apple.iTunes:LYRICIST": "lyricist", - "----:com.apple.iTunes:CONDUCTOR": "conductor", - "----:com.apple.iTunes:ENGINEER": "engineer", - "----:com.apple.iTunes:MIXER": "mixer", - "----:com.apple.iTunes:DJMIXER": "djmixer", - "----:com.apple.iTunes:REMIXER": "remixer", - "----:com.apple.iTunes:ISRC": "isrc", - "----:com.apple.iTunes:MEDIA": "media", - "----:com.apple.iTunes:LABEL": "label", - "----:com.apple.iTunes:LICENSE": "license", - "----:com.apple.iTunes:CATALOGNUMBER": "catalognumber", - "----:com.apple.iTunes:SUBTITLE": "subtitle", - "----:com.apple.iTunes:DISCSUBTITLE": "discsubtitle", - "----:com.apple.iTunes:MOOD": "mood", - "----:com.apple.iTunes:SCRIPT": "script", - "----:com.apple.iTunes:LANGUAGE": "language", - "----:com.apple.iTunes:ARTISTS": "artists", - "----:com.apple.iTunes:WORK": "work", - "----:com.apple.iTunes:initialkey": "key", + '----:com.apple.iTunes:MusicBrainz Track Id': 'musicbrainz_recordingid', + '----:com.apple.iTunes:MusicBrainz Artist Id': 'musicbrainz_artistid', + '----:com.apple.iTunes:MusicBrainz Album Id': 'musicbrainz_albumid', + '----:com.apple.iTunes:MusicBrainz Album Artist Id': 'musicbrainz_albumartistid', + '----:com.apple.iTunes:MusicIP PUID': 'musicip_puid', + '----:com.apple.iTunes:MusicBrainz Album Status': 'releasestatus', + '----:com.apple.iTunes:MusicBrainz Album Release Country': 'releasecountry', + '----:com.apple.iTunes:MusicBrainz Album Type': 'releasetype', + '----:com.apple.iTunes:MusicBrainz Disc Id': 'musicbrainz_discid', + '----:com.apple.iTunes:MusicBrainz TRM Id': 'musicbrainz_trmid', + '----:com.apple.iTunes:MusicBrainz Work Id': 'musicbrainz_workid', + '----:com.apple.iTunes:MusicBrainz Release Group Id': 'musicbrainz_releasegroupid', + '----:com.apple.iTunes:MusicBrainz Release Track Id': 'musicbrainz_trackid', + '----:com.apple.iTunes:MusicBrainz Original Album Id': 'musicbrainz_originalalbumid', + '----:com.apple.iTunes:MusicBrainz Original Artist Id': 'musicbrainz_originalartistid', + '----:com.apple.iTunes:Acoustid Fingerprint': 'acoustid_fingerprint', + '----:com.apple.iTunes:Acoustid Id': 'acoustid_id', + '----:com.apple.iTunes:ASIN': 'asin', + '----:com.apple.iTunes:BARCODE': 'barcode', + '----:com.apple.iTunes:PRODUCER': 'producer', + '----:com.apple.iTunes:LYRICIST': 'lyricist', + '----:com.apple.iTunes:CONDUCTOR': 'conductor', + '----:com.apple.iTunes:ENGINEER': 'engineer', + '----:com.apple.iTunes:MIXER': 'mixer', + '----:com.apple.iTunes:DJMIXER': 'djmixer', + '----:com.apple.iTunes:REMIXER': 'remixer', + '----:com.apple.iTunes:ISRC': 'isrc', + '----:com.apple.iTunes:MEDIA': 'media', + '----:com.apple.iTunes:LABEL': 'label', + '----:com.apple.iTunes:LICENSE': 'license', + '----:com.apple.iTunes:CATALOGNUMBER': 'catalognumber', + '----:com.apple.iTunes:SUBTITLE': 'subtitle', + '----:com.apple.iTunes:DISCSUBTITLE': 'discsubtitle', + '----:com.apple.iTunes:MOOD': 'mood', + '----:com.apple.iTunes:SCRIPT': 'script', + '----:com.apple.iTunes:LANGUAGE': 'language', + '----:com.apple.iTunes:ARTISTS': 'artists', + '----:com.apple.iTunes:WORK': 'work', + '----:com.apple.iTunes:initialkey': 'key', } __r_freeform_tags = {v: k for k, v in __freeform_tags.items()} # Tags to load case insensitive. Case is preserved, but the specified case # is written if it is unset. __r_freeform_tags_ci = { - "replaygain_album_gain": "----:com.apple.iTunes:REPLAYGAIN_ALBUM_GAIN", - "replaygain_album_peak": "----:com.apple.iTunes:REPLAYGAIN_ALBUM_PEAK", - "replaygain_album_range": "----:com.apple.iTunes:REPLAYGAIN_ALBUM_RANGE", - "replaygain_track_gain": "----:com.apple.iTunes:REPLAYGAIN_TRACK_GAIN", - "replaygain_track_peak": "----:com.apple.iTunes:REPLAYGAIN_TRACK_PEAK", - "replaygain_track_range": "----:com.apple.iTunes:REPLAYGAIN_TRACK_RANGE", - "replaygain_reference_loudness": "----:com.apple.iTunes:REPLAYGAIN_REFERENCE_LOUDNESS", - "releasedate": "----:com.apple.iTunes:RELEASEDATE", + 'replaygain_album_gain': '----:com.apple.iTunes:REPLAYGAIN_ALBUM_GAIN', + 'replaygain_album_peak': '----:com.apple.iTunes:REPLAYGAIN_ALBUM_PEAK', + 'replaygain_album_range': '----:com.apple.iTunes:REPLAYGAIN_ALBUM_RANGE', + 'replaygain_track_gain': '----:com.apple.iTunes:REPLAYGAIN_TRACK_GAIN', + 'replaygain_track_peak': '----:com.apple.iTunes:REPLAYGAIN_TRACK_PEAK', + 'replaygain_track_range': '----:com.apple.iTunes:REPLAYGAIN_TRACK_RANGE', + 'replaygain_reference_loudness': '----:com.apple.iTunes:REPLAYGAIN_REFERENCE_LOUDNESS', + 'releasedate': '----:com.apple.iTunes:RELEASEDATE', } __freeform_tags_ci = {b.lower(): a for a, b in __r_freeform_tags_ci.items()} - __other_supported_tags = ("discnumber", "tracknumber", - "totaldiscs", "totaltracks") + __other_supported_tags = ('discnumber', 'tracknumber', + 'totaldiscs', 'totaltracks') def __init__(self, filename): super().__init__(filename) @@ -199,24 +199,24 @@ def _load(self, filename): tag_name = self.__freeform_tags_ci[name_lower] self.__casemap[tag_name] = name _add_text_values_to_metadata(metadata, tag_name, values) - elif name == "----:com.apple.iTunes:fingerprint": + elif name == '----:com.apple.iTunes:fingerprint': for value in values: - value = value.decode("utf-8", "replace").strip("\x00") - if value.startswith("MusicMagic Fingerprint"): - metadata.add("musicip_fingerprint", value[22:]) - elif name == "trkn": + value = value.decode('utf-8', 'replace').strip('\x00') + if value.startswith('MusicMagic Fingerprint'): + metadata.add('musicip_fingerprint', value[22:]) + elif name == 'trkn': try: - metadata["tracknumber"] = values[0][0] - metadata["totaltracks"] = values[0][1] + metadata['tracknumber'] = values[0][0] + metadata['totaltracks'] = values[0][1] except IndexError: - log.debug('trkn is invalid, ignoring') - elif name == "disk": + log.debug("trkn is invalid, ignoring") + elif name == 'disk': try: - metadata["discnumber"] = values[0][0] - metadata["totaldiscs"] = values[0][1] + metadata['discnumber'] = values[0][0] + metadata['totaldiscs'] = values[0][1] except IndexError: - log.debug('disk is invalid, ignoring') - elif name == "covr": + log.debug("disk is invalid, ignoring") + elif name == 'covr': for value in values: if value.imageformat not in {value.FORMAT_JPEG, value.FORMAT_PNG}: continue @@ -227,7 +227,7 @@ def _load(self, filename): data=value, ) except CoverArtImageError as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) # Read other freeform tags always case insensitive @@ -253,7 +253,7 @@ def _save(self, filename, metadata): file.add_tags() tags = file.tags - if config.setting["clear_existing_tags"]: + if config.setting['clear_existing_tags']: cover = tags.get('covr') if config.setting['preserve_images'] else None tags.clear() if cover: @@ -274,59 +274,59 @@ def _save(self, filename, metadata): except ValueError: pass elif name in self.__r_freeform_tags: - values = [v.encode("utf-8") for v in values] + values = [v.encode('utf-8') for v in values] tags[self.__r_freeform_tags[name]] = values elif name in self.__r_freeform_tags_ci: - values = [v.encode("utf-8") for v in values] + values = [v.encode('utf-8') for v in values] delall_ci(tags, self.__r_freeform_tags_ci[name]) if name in self.__casemap: name = self.__casemap[name] else: name = self.__r_freeform_tags_ci[name] tags[name] = values - elif name == "musicip_fingerprint": - tags["----:com.apple.iTunes:fingerprint"] = [b"MusicMagic Fingerprint%s" % v.encode('ascii') for v in values] + elif name == 'musicip_fingerprint': + tags['----:com.apple.iTunes:fingerprint'] = [b'MusicMagic Fingerprint%s' % v.encode('ascii') for v in values] elif self.supports_tag(name) and name not in self.__other_supported_tags: - values = [v.encode("utf-8") for v in values] + values = [v.encode('utf-8') for v in values] name = self.__casemap.get(name, name) tags['----:com.apple.iTunes:' + name] = values - if "tracknumber" in metadata: + if 'tracknumber' in metadata: try: - tracknumber = int(metadata["tracknumber"]) + tracknumber = int(metadata['tracknumber']) except ValueError: pass else: totaltracks = 0 - if "totaltracks" in metadata: + if 'totaltracks' in metadata: try: - totaltracks = int(metadata["totaltracks"]) + totaltracks = int(metadata['totaltracks']) except ValueError: pass - tags["trkn"] = [(tracknumber, totaltracks)] + tags['trkn'] = [(tracknumber, totaltracks)] - if "discnumber" in metadata: + if 'discnumber' in metadata: try: - discnumber = int(metadata["discnumber"]) + discnumber = int(metadata['discnumber']) except ValueError: pass else: totaldiscs = 0 - if "totaldiscs" in metadata: + if 'totaldiscs' in metadata: try: - totaldiscs = int(metadata["totaldiscs"]) + totaldiscs = int(metadata['totaldiscs']) except ValueError: pass - tags["disk"] = [(discnumber, totaldiscs)] + tags['disk'] = [(discnumber, totaldiscs)] covr = [] for image in metadata.images.to_be_saved_to_tags(): - if image.mimetype == "image/jpeg": + if image.mimetype == 'image/jpeg': covr.append(MP4Cover(image.data, MP4Cover.FORMAT_JPEG)) - elif image.mimetype == "image/png": + elif image.mimetype == 'image/png': covr.append(MP4Cover(image.data, MP4Cover.FORMAT_PNG)) if covr: - tags["covr"] = covr + tags['covr'] = covr self._remove_deleted_tags(metadata, tags) @@ -337,13 +337,13 @@ def _remove_deleted_tags(self, metadata, tags): for tag in metadata.deleted_tags: real_name = self._get_tag_name(tag) if real_name and real_name in tags: - if tag not in {"totaltracks", "totaldiscs"}: + if tag not in {'totaltracks', 'totaldiscs'}: del tags[real_name] @classmethod def supports_tag(cls, name): return (name - and not name.startswith("~") + and not name.startswith('~') and name not in UNSUPPORTED_TAGS and not (name.startswith('comment:') and len(name) > 9) and not name.startswith('performer:') @@ -362,12 +362,12 @@ def _get_tag_name(self, name): return self.__r_freeform_tags[name] elif name in self.__r_freeform_tags_ci: return self.__r_freeform_tags_ci[name] - elif name == "musicip_fingerprint": - return "----:com.apple.iTunes:fingerprint" - elif name in {"tracknumber", "totaltracks"}: - return "trkn" - elif name in {"discnumber", "totaldiscs"}: - return "disk" + elif name == 'musicip_fingerprint': + return '----:com.apple.iTunes:fingerprint' + elif name in {'tracknumber', 'totaltracks'}: + return 'trkn' + elif name in {'discnumber', 'totaldiscs'}: + return 'disk' elif self.supports_tag(name) and name not in self.__other_supported_tags: name = self.__casemap.get(name, name) return '----:com.apple.iTunes:' + name diff --git a/picard/formats/util.py b/picard/formats/util.py index bce9784510..777d447881 100644 --- a/picard/formats/util.py +++ b/picard/formats/util.py @@ -59,7 +59,7 @@ def guess_format(filename, options=_formats): results = [] # Since we are reading only 128 bytes and then immediately closing the file, # use unbuffered mode. - with open(filename, "rb", 0) as fileobj: + with open(filename, 'rb', 0) as fileobj: header = fileobj.read(128) # Calls the score method of a particular format's associated filetype # and assigns a positive score depending on how closely the fileobj's header matches diff --git a/picard/formats/vorbis.py b/picard/formats/vorbis.py index 0061c56304..0e59da0914 100644 --- a/picard/formats/vorbis.py +++ b/picard/formats/vorbis.py @@ -122,11 +122,11 @@ class VCommentFile(File): _File = None __translate = { - "movement": "movementnumber", - "movementname": "movement", - "musicbrainz_releasetrackid": "musicbrainz_trackid", - "musicbrainz_trackid": "musicbrainz_recordingid", - "waveformatextensible_channel_mask": "~waveformatextensible_channel_mask", + 'movement': 'movementnumber', + 'movementname': 'movement', + 'musicbrainz_releasetrackid': 'musicbrainz_trackid', + 'musicbrainz_trackid': 'musicbrainz_recordingid', + 'waveformatextensible_channel_mask': '~waveformatextensible_channel_mask', } __rtranslate = {v: k for k, v in __translate.items()} @@ -170,18 +170,18 @@ def _load(self, filename): value = str(round((float(value) * (config.setting['rating_steps'] - 1)))) except ValueError: log.warning('Invalid rating value in %r: %s', filename, value) - elif name == "fingerprint" and value.startswith("MusicMagic Fingerprint"): - name = "musicip_fingerprint" + elif name == 'fingerprint' and value.startswith('MusicMagic Fingerprint'): + name = 'musicip_fingerprint' value = value[22:] - elif name == "tracktotal": - if "totaltracks" in file.tags: + elif name == 'tracktotal': + if 'totaltracks' in file.tags: continue - name = "totaltracks" - elif name == "disctotal": - if "totaldiscs" in file.tags: + name = 'totaltracks' + elif name == 'disctotal': + if 'totaldiscs' in file.tags: continue - name = "totaldiscs" - elif name == "metadata_block_picture": + name = 'totaldiscs' + elif name == 'metadata_block_picture': try: image = mutagen.flac.Picture(base64.standard_b64decode(value)) coverartimage = TagCoverArtImage( @@ -194,7 +194,7 @@ def _load(self, filename): id3_type=image.type ) except (CoverArtImageError, TypeError, ValueError, mutagen.flac.error) as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) continue @@ -214,14 +214,14 @@ def _load(self, filename): id3_type=image.type ) except CoverArtImageError as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) # Read the unofficial COVERART tags, for backward compatibility only - if "metadata_block_picture" not in file.tags: + if 'metadata_block_picture' not in file.tags: try: - for data in file["COVERART"]: + for data in file['COVERART']: try: coverartimage = TagCoverArtImage( file=filename, @@ -229,7 +229,7 @@ def _load(self, filename): data=base64.standard_b64decode(data) ) except (CoverArtImageError, TypeError, ValueError) as e: - log.error('Cannot load image from %r: %s', filename, e) + log.error("Cannot load image from %r: %s", filename, e) else: metadata.images.append(coverartimage) except KeyError: @@ -245,9 +245,9 @@ def _save(self, filename, metadata): file = self._File(encode_filename(filename)) if file.tags is None: file.add_tags() - if config.setting["clear_existing_tags"]: + if config.setting['clear_existing_tags']: preserve_tags = ['waveformatextensible_channel_mask'] - if not is_flac and config.setting["preserve_images"]: + if not is_flac and config.setting['preserve_images']: preserve_tags.append('metadata_block_picture') preserve_tags.append('coverart') preserved_values = {} @@ -259,8 +259,8 @@ def _save(self, filename, metadata): file.tags[name] = value images_to_save = list(metadata.images.to_be_saved_to_tags()) if is_flac and (images_to_save - or (config.setting["clear_existing_tags"] - and not config.setting["preserve_images"])): + or (config.setting['clear_existing_tags'] + and not config.setting['preserve_images'])): file.clear_pictures() tags = {} @@ -293,10 +293,10 @@ def _save(self, filename, metadata): name = self.__rtranslate[name] tags.setdefault(name.upper(), []).append(value.rstrip('\0')) - if "totaltracks" in metadata: - tags.setdefault("TRACKTOTAL", []).append(metadata["totaltracks"]) - if "totaldiscs" in metadata: - tags.setdefault("DISCTOTAL", []).append(metadata["totaldiscs"]) + if 'totaltracks' in metadata: + tags.setdefault('TRACKTOTAL', []).append(metadata['totaltracks']) + if 'totaldiscs' in metadata: + tags.setdefault('DISCTOTAL', []).append(metadata['totaldiscs']) for image in images_to_save: picture = mutagen.flac.Picture() @@ -312,12 +312,12 @@ def _save(self, filename, metadata): + len(picture.mime) + len(picture.desc.encode('UTF-8'))) if expected_block_size > FLAC_MAX_BLOCK_SIZE: - log.error('Failed saving image to %r: Image size of %d bytes exceeds maximum FLAC block size of %d bytes', + log.error("Failed saving image to %r: Image size of %d bytes exceeds maximum FLAC block size of %d bytes", filename, expected_block_size, FLAC_MAX_BLOCK_SIZE) continue file.add_picture(picture) else: - tags.setdefault("METADATA_BLOCK_PICTURE", []).append( + tags.setdefault('METADATA_BLOCK_PICTURE', []).append( base64.b64encode(picture.write()).decode('ascii')) file.tags.update(tags) @@ -327,10 +327,10 @@ def _save(self, filename, metadata): kwargs = {} if is_flac: flac_sort_pics_after_tags(file.metadata_blocks) - if config.setting["fix_missing_seekpoints_flac"]: + if config.setting['fix_missing_seekpoints_flac']: flac_remove_empty_seektable(file) - if config.setting["remove_id3_from_flac"]: - kwargs["deleteid3"] = True + if config.setting['remove_id3_from_flac']: + kwargs['deleteid3'] = True try: file.save(**kwargs) except TypeError: diff --git a/picard/metadata.py b/picard/metadata.py index 5eadad7723..8fe0f7ff57 100644 --- a/picard/metadata.py +++ b/picard/metadata.py @@ -253,18 +253,18 @@ def compare_to_release_parts(self, release, weights): parts = [] with self._lock.lock_for_read(): - if "album" in self and "album" in weights: + if 'album' in self and 'album' in weights: b = release['title'] - parts.append((similarity2(self["album"], b), weights["album"])) + parts.append((similarity2(self['album'], b), weights['album'])) - if "albumartist" in self and "albumartist" in weights: - a = self["albumartist"] + if 'albumartist' in self and 'albumartist' in weights: + a = self['albumartist'] b = artist_credit_from_node(release['artist-credit'])[0] - parts.append((similarity2(a, b), weights["albumartist"])) + parts.append((similarity2(a, b), weights['albumartist'])) - if "totaltracks" in weights: + if 'totaltracks' in weights: try: - a = int(self["totaltracks"]) + a = int(self['totaltracks']) if 'media' in release: score = 0.0 for media in release['media']: @@ -275,25 +275,25 @@ def compare_to_release_parts(self, release, weights): else: b = release['track-count'] score = trackcount_score(a, b) - parts.append((score, weights["totaltracks"])) + parts.append((score, weights['totaltracks'])) except (ValueError, KeyError): pass - if "totalalbumtracks" in weights: + if 'totalalbumtracks' in weights: try: - a = int(self["~totalalbumtracks"] or self["totaltracks"]) + a = int(self['~totalalbumtracks'] or self['totaltracks']) b = release['track-count'] score = trackcount_score(a, b) - parts.append((score, weights["totalalbumtracks"])) + parts.append((score, weights['totalalbumtracks'])) except (ValueError, KeyError): pass # Date Logic date_match_factor = 0.0 - if "date" in weights: - if "date" in release and release['date'] != '': + if 'date' in weights: + if 'date' in release and release['date'] != '': release_date = release['date'] - if "date" in self: + if 'date' in self: metadata_date = self['date'] if release_date == metadata_date: # release has a date and it matches what our metadata had exactly. @@ -326,20 +326,20 @@ def compare_to_release_parts(self, release, weights): parts.append((date_match_factor, weights['date'])) config = get_config() - if "releasecountry" in weights: + if 'releasecountry' in weights: weights_from_preferred_countries(parts, release, - config.setting["preferred_release_countries"], - weights["releasecountry"]) + config.setting['preferred_release_countries'], + weights['releasecountry']) - if "format" in weights: + if 'format' in weights: weights_from_preferred_formats(parts, release, - config.setting["preferred_release_formats"], - weights["format"]) + config.setting['preferred_release_formats'], + weights['format']) - if "releasetype" in weights: + if 'releasetype' in weights: weights_from_release_type_scores(parts, release, - config.setting["release_type_scores"], - weights["releasetype"]) + config.setting['release_type_scores'], + weights['releasetype']) rg = QObject.tagger.get_release_group_by_id(release['release-group']['id']) if release['id'] in rg.loaded_albums: diff --git a/picard/oauth.py b/picard/oauth.py index 971a0f9f63..79d26ae8e0 100644 --- a/picard/oauth.py +++ b/picard/oauth.py @@ -67,59 +67,59 @@ def port(self): @property def refresh_token(self): - return self.persist["oauth_refresh_token"] + return self.persist['oauth_refresh_token'] @refresh_token.setter def refresh_token(self, value): - self.persist["oauth_refresh_token"] = value + self.persist['oauth_refresh_token'] = value @refresh_token.deleter def refresh_token(self): - self.persist.remove("oauth_refresh_token") + self.persist.remove('oauth_refresh_token') @property def refresh_token_scopes(self): - return self.persist["oauth_refresh_token_scopes"] + return self.persist['oauth_refresh_token_scopes'] @refresh_token_scopes.setter def refresh_token_scopes(self, value): - self.persist["oauth_refresh_token_scopes"] = value + self.persist['oauth_refresh_token_scopes'] = value @refresh_token_scopes.deleter def refresh_token_scopes(self): - self.persist.remove("oauth_refresh_token_scopes") + self.persist.remove('oauth_refresh_token_scopes') @property def access_token(self): - return self.persist["oauth_access_token"] + return self.persist['oauth_access_token'] @access_token.setter def access_token(self, value): - self.persist["oauth_access_token"] = value + self.persist['oauth_access_token'] = value @access_token.deleter def access_token(self): - self.persist.remove("oauth_access_token") + self.persist.remove('oauth_access_token') @property def access_token_expires(self): - return self.persist["oauth_access_token_expires"] + return self.persist['oauth_access_token_expires'] @access_token_expires.setter def access_token_expires(self, value): - self.persist["oauth_access_token_expires"] = value + self.persist['oauth_access_token_expires'] = value @access_token_expires.deleter def access_token_expires(self): - self.persist.remove("oauth_access_token_expires") + self.persist.remove('oauth_access_token_expires') @property def username(self): - return self.persist["oauth_username"] + return self.persist['oauth_username'] @username.setter def username(self, value): - self.persist["oauth_username"] = value + self.persist['oauth_username'] = value def is_authorized(self): return bool(self.refresh_token and self.refresh_token_scopes) @@ -158,10 +158,10 @@ def url(self, path=None, params=None): def get_authorization_url(self, scopes): params = { - "response_type": "code", - "client_id": MUSICBRAINZ_OAUTH_CLIENT_ID, - "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", - "scope": scopes, + 'response_type': 'code', + 'client_id': MUSICBRAINZ_OAUTH_CLIENT_ID, + 'redirect_uri': "urn:ietf:wg:oauth:2.0:oob", + 'scope': scopes, } return bytes(self.url(path="/oauth2/authorize", params=params).toEncoded()).decode() @@ -182,10 +182,10 @@ def _query_data(params): def refresh_access_token(self, callback): log.debug("OAuth: refreshing access_token with a refresh_token %s", self.refresh_token) params = { - "grant_type": "refresh_token", - "refresh_token": self.refresh_token, - "client_id": MUSICBRAINZ_OAUTH_CLIENT_ID, - "client_secret": MUSICBRAINZ_OAUTH_CLIENT_SECRET, + 'grant_type': 'refresh_token', + 'refresh_token': self.refresh_token, + 'client_id': MUSICBRAINZ_OAUTH_CLIENT_ID, + 'client_secret': MUSICBRAINZ_OAUTH_CLIENT_SECRET, } self.webservice.post_url( url=self.url(path="/oauth2/token"), @@ -194,7 +194,7 @@ def refresh_access_token(self, callback): mblogin=True, priority=True, important=True, - request_mimetype="application/x-www-form-urlencoded", + request_mimetype='application/x-www-form-urlencoded', ) def on_refresh_access_token_finished(self, callback, data, http, error): @@ -204,24 +204,24 @@ def on_refresh_access_token_finished(self, callback, data, http, error): log.error("OAuth: access_token refresh failed: %s", data) if self._http_code(http) == 400: response = load_json(data) - if response["error"] == "invalid_grant": + if response['error'] == 'invalid_grant': self.forget_refresh_token() else: - access_token = data["access_token"] - self.set_access_token(access_token, data["expires_in"]) + access_token = data['access_token'] + self.set_access_token(access_token, data['expires_in']) except Exception as e: - log.error('OAuth: Unexpected error handling access token response: %r', e) + log.error("OAuth: Unexpected error handling access token response: %r", e) finally: callback(access_token=access_token) def exchange_authorization_code(self, authorization_code, scopes, callback): log.debug("OAuth: exchanging authorization_code %s for an access_token", authorization_code) params = { - "grant_type": "authorization_code", - "code": authorization_code, - "client_id": MUSICBRAINZ_OAUTH_CLIENT_ID, - "client_secret": MUSICBRAINZ_OAUTH_CLIENT_SECRET, - "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", + 'grant_type': 'authorization_code', + 'code': authorization_code, + 'client_id': MUSICBRAINZ_OAUTH_CLIENT_ID, + 'client_secret': MUSICBRAINZ_OAUTH_CLIENT_SECRET, + 'redirect_uri': "urn:ietf:wg:oauth:2.0:oob", } self.webservice.post_url( url=self.url(path="/oauth2/token"), @@ -230,7 +230,7 @@ def exchange_authorization_code(self, authorization_code, scopes, callback): mblogin=True, priority=True, important=True, - request_mimetype="application/x-www-form-urlencoded", + request_mimetype='application/x-www-form-urlencoded', ) def on_exchange_authorization_code_finished(self, scopes, callback, data, http, error): @@ -241,12 +241,12 @@ def on_exchange_authorization_code_finished(self, scopes, callback, data, http, log.error("OAuth: authorization_code exchange failed: %s", data) error_msg = self._extract_error_description(http, data) else: - self.set_refresh_token(data["refresh_token"], scopes) - self.set_access_token(data["access_token"], data["expires_in"]) + self.set_refresh_token(data['refresh_token'], scopes) + self.set_access_token(data['access_token'], data['expires_in']) successful = True except Exception as e: - log.error('OAuth: Unexpected error handling authorization code response: %r', e) - error_msg = _('Unexpected authentication error') + log.error("OAuth: Unexpected error handling authorization code response: %r", e) + error_msg = _("Unexpected authentication error") finally: callback(successful=successful, error_msg=error_msg) @@ -268,12 +268,12 @@ def on_fetch_username_finished(self, callback, data, http, error): log.error("OAuth: username fetching failed: %s", data) error_msg = self._extract_error_description(http, data) else: - self.username = data["sub"] + self.username = data['sub'] log.debug("OAuth: got username %s", self.username) successful = True except Exception as e: - log.error('OAuth: Unexpected error handling username fetch response: %r', e) - error_msg = _('Unexpected authentication error') + log.error("OAuth: Unexpected error handling username fetch response: %r", e) + error_msg = _("Unexpected authentication error") finally: callback(successful=successful, error_msg=error_msg) @@ -285,4 +285,4 @@ def _extract_error_description(self, http, data): response = load_json(data) return response['error_description'] except (JSONDecodeError, KeyError, TypeError): - return _('Unexpected request error (HTTP code %s)') % self._http_code(http) + return _("Unexpected request error (HTTP code %s)") % self._http_code(http) diff --git a/picard/plugin.py b/picard/plugin.py index 634f2f81d8..d3cadeb1a5 100644 --- a/picard/plugin.py +++ b/picard/plugin.py @@ -102,7 +102,7 @@ def unregister_module(self, name): def __iter__(self): config = get_config() - enabled_plugins = config.setting["enabled_plugins"] if config else [] + enabled_plugins = config.setting['enabled_plugins'] if config else [] for name in self.__dict: if name is None or name in enabled_plugins: yield from self.__dict[name] @@ -216,7 +216,7 @@ def __getattribute__(self, name): try: return super().__getattribute__(name) except AttributeError: - log.debug('Attribute %r not found for plugin %r', name, self.module_name) + log.debug("Attribute %r not found for plugin %r", name, self.module_name) return None @property diff --git a/picard/pluginmanager.py b/picard/pluginmanager.py index 0e2a3bfae8..0f912b643a 100644 --- a/picard/pluginmanager.py +++ b/picard/pluginmanager.py @@ -244,7 +244,7 @@ def handle_plugin_updates(self): for source_path, target_path, plugin_name in self._marked_for_update(): self._remove_plugin(plugin_name) os.rename(source_path, target_path) - log.debug('Updating plugin %r (%r))', plugin_name, target_path) + log.debug("Updating plugin %r (%r))", plugin_name, target_path) def load_plugins_from_directory(self, plugindir): plugindir = os.path.normpath(plugindir) diff --git a/picard/profile.py b/picard/profile.py index 5056306d5c..bb3065ce77 100644 --- a/picard/profile.py +++ b/picard/profile.py @@ -42,216 +42,216 @@ class UserProfileGroups(): SETTINGS_GROUPS = OrderedDict() # Add groups in the order they should be displayed # Each item in "settings" is a tuple of the setting key, the display title, and a list of the names of the widgets to highlight - SETTINGS_GROUPS["general"] = { - "title": N_("General"), - "settings": [ - SettingDesc("server_host", N_("Server address"), ["server_host"]), - SettingDesc("server_port", N_("Port"), ["server_port"]), - SettingDesc("analyze_new_files", N_("Automatically scan all new files"), ["analyze_new_files"]), - SettingDesc("cluster_new_files", N_("Automatically cluster all new files"), ["cluster_new_files"]), - SettingDesc("ignore_file_mbids", N_("Ignore MBIDs when loading new files"), ["ignore_file_mbids"]), - SettingDesc("check_for_plugin_updates", N_("Check for plugin updates during startup"), ["check_for_plugin_updates"]), - SettingDesc("check_for_updates", N_("Check for program updates during startup"), ["check_for_updates"]), - SettingDesc("update_check_days", N_("Days between update checks"), ["update_check_days"]), - SettingDesc("update_level", N_("Updates to check"), ["update_level"]), + SETTINGS_GROUPS['general'] = { + 'title': N_("General"), + 'settings': [ + SettingDesc('server_host', N_("Server address"), ['server_host']), + SettingDesc('server_port', N_("Port"), ['server_port']), + SettingDesc('analyze_new_files', N_("Automatically scan all new files"), ['analyze_new_files']), + SettingDesc('cluster_new_files', N_("Automatically cluster all new files"), ['cluster_new_files']), + SettingDesc('ignore_file_mbids', N_("Ignore MBIDs when loading new files"), ['ignore_file_mbids']), + SettingDesc('check_for_plugin_updates', N_("Check for plugin updates during startup"), ['check_for_plugin_updates']), + SettingDesc('check_for_updates', N_("Check for program updates during startup"), ['check_for_updates']), + SettingDesc('update_check_days', N_("Days between update checks"), ['update_check_days']), + SettingDesc('update_level', N_("Updates to check"), ['update_level']), ], } - SETTINGS_GROUPS["metadata"] = { - "title": N_("Metadata"), - "settings": [ + SETTINGS_GROUPS['metadata'] = { + 'title': N_("Metadata"), + 'settings': [ # Main Metadata Page - SettingDesc("translate_artist_names", N_("Translate artist names"), ["translate_artist_names"]), - SettingDesc("artist_locales", N_("Translation locales"), ["selected_locales"]), - SettingDesc("translate_artist_names_script_exception", N_("Translate artist names exception"), ["translate_artist_names_script_exception"]), - SettingDesc("script_exceptions", N_("Translation script exceptions"), ["selected_scripts"]), - SettingDesc("standardize_artists", N_("Use standardized artist names"), ["standardize_artists"]), - SettingDesc("standardize_instruments", N_("Use standardized instrument and vocal credits"), ["standardize_instruments"]), - SettingDesc("convert_punctuation", N_("Convert Unicode punctuation characters to ASCII"), ["convert_punctuation"]), - SettingDesc("release_ars", N_("Use release relationships"), ["release_ars"]), - SettingDesc("track_ars", N_("Use track relationships"), ["track_ars"]), - SettingDesc("guess_tracknumber_and_title", N_("Guess track number and title from filename if empty"), ["guess_tracknumber_and_title"]), - SettingDesc("va_name", N_("Various Artists name"), ["va_name"]), - SettingDesc("nat_name", N_("Standalone recordings name"), ["nat_name"]), + SettingDesc('translate_artist_names', N_("Translate artist names"), ['translate_artist_names']), + SettingDesc('artist_locales', N_("Translation locales"), ['selected_locales']), + SettingDesc('translate_artist_names_script_exception', N_("Translate artist names exception"), ['translate_artist_names_script_exception']), + SettingDesc('script_exceptions', N_("Translation script exceptions"), ['selected_scripts']), + SettingDesc('standardize_artists', N_("Use standardized artist names"), ['standardize_artists']), + SettingDesc('standardize_instruments', N_("Use standardized instrument and vocal credits"), ['standardize_instruments']), + SettingDesc('convert_punctuation', N_("Convert Unicode punctuation characters to ASCII"), ['convert_punctuation']), + SettingDesc('release_ars', N_("Use release relationships"), ['release_ars']), + SettingDesc('track_ars', N_("Use track relationships"), ['track_ars']), + SettingDesc('guess_tracknumber_and_title', N_("Guess track number and title from filename if empty"), ['guess_tracknumber_and_title']), + SettingDesc('va_name', N_("Various Artists name"), ['va_name']), + SettingDesc('nat_name', N_("Standalone recordings name"), ['nat_name']), # Preferred Releases Page - SettingDesc("release_type_scores", N_("Preferred release types"), ["type_group"]), - SettingDesc("preferred_release_countries", N_("Preferred release countries"), ["country_group"]), - SettingDesc("preferred_release_formats", N_("Preferred medium formats"), ["format_group"]), + SettingDesc('release_type_scores', N_("Preferred release types"), ['type_group']), + SettingDesc('preferred_release_countries', N_("Preferred release countries"), ['country_group']), + SettingDesc('preferred_release_formats', N_("Preferred medium formats"), ['format_group']), # Genres Page - SettingDesc("use_genres", N_("Use genres from MusicBrainz"), []), # No highlight specified because the "use_genres" + SettingDesc('use_genres', N_("Use genres from MusicBrainz"), []), # No highlight specified because the 'use_genres' # object is a QGroupBox and it highlights all sub # options, even if the sub options are not selected. - SettingDesc("only_my_genres", N_("Use only my genres"), ["only_my_genres"]), - SettingDesc("artists_genres", N_("Use album artist genres"), ["artists_genres"]), - SettingDesc("folksonomy_tags", N_("Use folksonomy tags as genre"), ["folksonomy_tags"]), - SettingDesc("min_genre_usage", N_("Minimal genre usage"), ["min_genre_usage"]), - SettingDesc("max_genres", N_("Maximum number of genres"), ["max_genres"]), - SettingDesc("join_genres", N_("Join multiple genres with"), ["join_genres"]), - SettingDesc("genres_filter", N_("Genres to include or exclude"), ["genres_filter"]), + SettingDesc('only_my_genres', N_("Use only my genres"), ['only_my_genres']), + SettingDesc('artists_genres', N_("Use album artist genres"), ['artists_genres']), + SettingDesc('folksonomy_tags', N_("Use folksonomy tags as genre"), ['folksonomy_tags']), + SettingDesc('min_genre_usage', N_("Minimal genre usage"), ['min_genre_usage']), + SettingDesc('max_genres', N_("Maximum number of genres"), ['max_genres']), + SettingDesc('join_genres', N_("Join multiple genres with"), ['join_genres']), + SettingDesc('genres_filter', N_("Genres to include or exclude"), ['genres_filter']), # Ratings Page - SettingDesc("enable_ratings", N_("Enable track ratings"), []), # No highlight specified because the "enable_ratings" + SettingDesc('enable_ratings', N_("Enable track ratings"), []), # No highlight specified because the 'enable_ratings' # object is a QGroupBox and it highlights all sub options, # even if the sub options are not selected. - SettingDesc("rating_user_email", N_("Email to use when saving ratings"), ["rating_user_email"]), - SettingDesc("submit_ratings", N_("Submit ratings to MusicBrainz"), ["submit_ratings"]), + SettingDesc('rating_user_email', N_("Email to use when saving ratings"), ['rating_user_email']), + SettingDesc('submit_ratings', N_("Submit ratings to MusicBrainz"), ['submit_ratings']), ], } - SETTINGS_GROUPS["tags"] = { - "title": N_("Tags"), - "settings": [ + SETTINGS_GROUPS['tags'] = { + 'title': N_("Tags"), + 'settings': [ # Main Tags Page - SettingDesc("dont_write_tags", N_("Don't write tags"), ["write_tags"]), - SettingDesc("preserve_timestamps", N_("Preserve timestamps of tagged files"), ["preserve_timestamps"]), - SettingDesc("clear_existing_tags", N_("Clear existing tags"), ["clear_existing_tags"]), - SettingDesc("preserve_images", N_("Keep embedded images when clearing tags"), ["preserve_images"]), - SettingDesc("remove_id3_from_flac", N_("Remove ID3 tags from FLAC files"), ["remove_id3_from_flac"]), - SettingDesc("remove_ape_from_mp3", N_("Remove APEv2 tags from MP3 files"), ["remove_ape_from_mp3"]), - SettingDesc("fix_missing_seekpoints_flac", N_("Fix missing seekpoints for FLAC files"), ["fix_missing_seekpoints_flac"]), - SettingDesc("preserved_tags", N_("Preserved tags list"), ["preserved_tags"]), + SettingDesc('dont_write_tags', N_("Don't write tags"), ['write_tags']), + SettingDesc('preserve_timestamps', N_("Preserve timestamps of tagged files"), ['preserve_timestamps']), + SettingDesc('clear_existing_tags', N_("Clear existing tags"), ['clear_existing_tags']), + SettingDesc('preserve_images', N_("Keep embedded images when clearing tags"), ['preserve_images']), + SettingDesc('remove_id3_from_flac', N_("Remove ID3 tags from FLAC files"), ['remove_id3_from_flac']), + SettingDesc('remove_ape_from_mp3', N_("Remove APEv2 tags from MP3 files"), ['remove_ape_from_mp3']), + SettingDesc('fix_missing_seekpoints_flac', N_("Fix missing seekpoints for FLAC files"), ['fix_missing_seekpoints_flac']), + SettingDesc('preserved_tags', N_("Preserved tags list"), ['preserved_tags']), # ID3 Tags Page - SettingDesc("write_id3v23", N_("ID3v2 version to write"), ["write_id3v23", "write_id3v24"]), - SettingDesc("id3v2_encoding", N_("ID3v2 text encoding"), ["enc_utf8", "enc_utf16", "enc_iso88591"]), - SettingDesc("id3v23_join_with", N_("ID3v2.3 join character"), ["id3v23_join_with"]), - SettingDesc("itunes_compatible_grouping", N_("Save iTunes compatible grouping and work"), ["itunes_compatible_grouping"]), - SettingDesc("write_id3v1", N_("Write ID3v1 tags"), ["write_id3v1"]), + SettingDesc('write_id3v23', N_("ID3v2 version to write"), ['write_id3v23', 'write_id3v24']), + SettingDesc('id3v2_encoding', N_("ID3v2 text encoding"), ['enc_utf8', 'enc_utf16', 'enc_iso88591']), + SettingDesc('id3v23_join_with', N_("ID3v2.3 join character"), ['id3v23_join_with']), + SettingDesc('itunes_compatible_grouping', N_("Save iTunes compatible grouping and work"), ['itunes_compatible_grouping']), + SettingDesc('write_id3v1', N_("Write ID3v1 tags"), ['write_id3v1']), # AAC Tags Page - SettingDesc("aac_save_ape", N_("Save APEv2 tags to AAC"), ["aac_save_ape", "aac_no_tags"]), - SettingDesc("remove_ape_from_aac", N_("Remove APEv2 tags from AAC files"), ["remove_ape_from_aac"]), + SettingDesc('aac_save_ape', N_("Save APEv2 tags to AAC"), ['aac_save_ape', 'aac_no_tags']), + SettingDesc('remove_ape_from_aac', N_("Remove APEv2 tags from AAC files"), ['remove_ape_from_aac']), # AC3 Tags Page - SettingDesc("ac3_save_ape", N_("Save APEv2 tags to AC3"), ["ac3_save_ape", "ac3_no_tags"]), - SettingDesc("remove_ape_from_ac3", N_("Remove APEv2 tags from AC3 files"), ["remove_ape_from_ac3"]), + SettingDesc('ac3_save_ape', N_("Save APEv2 tags to AC3"), ['ac3_save_ape', 'ac3_no_tags']), + SettingDesc('remove_ape_from_ac3', N_("Remove APEv2 tags from AC3 files"), ['remove_ape_from_ac3']), # WAVE Tags Page - SettingDesc("write_wave_riff_info", N_("Write RIFF INFO tags to WAVE files"), ["write_wave_riff_info"]), - SettingDesc("remove_wave_riff_info", N_("Remove existing RIFF INFO tags from WAVE files"), ["remove_wave_riff_info"]), - SettingDesc("wave_riff_info_encoding", N_("RIFF INFO text encoding"), ["wave_riff_info_enc_cp1252", "wave_riff_info_enc_utf8"]), + SettingDesc('write_wave_riff_info', N_("Write RIFF INFO tags to WAVE files"), ['write_wave_riff_info']), + SettingDesc('remove_wave_riff_info', N_("Remove existing RIFF INFO tags from WAVE files"), ['remove_wave_riff_info']), + SettingDesc('wave_riff_info_encoding', N_("RIFF INFO text encoding"), ['wave_riff_info_enc_cp1252', 'wave_riff_info_enc_utf8']), ], } - SETTINGS_GROUPS["cover"] = { - "title": N_("Cover Art"), - "settings": [ - SettingDesc("save_images_to_tags", N_("Embed cover images into tags"), ["save_images_to_tags"]), - SettingDesc("embed_only_one_front_image", N_("Embed only a single front image"), ["cb_embed_front_only"]), - SettingDesc("save_images_to_files", N_("Save cover images as separate files"), ["save_images_to_files"]), - SettingDesc("cover_image_filename", N_("File name for images"), ["cover_image_filename"]), - SettingDesc("save_images_overwrite", N_("Overwrite existing image files"), ["save_images_overwrite"]), - SettingDesc("save_only_one_front_image", N_("Save only a single front image as separate file"), ["save_only_one_front_image"]), - SettingDesc("image_type_as_filename", N_("Always use the primary image type as the file name for non-front images"), ["image_type_as_filename"]), - SettingDesc("ca_providers", N_("Cover art providers"), ["ca_providers_list"]), + SETTINGS_GROUPS['cover'] = { + 'title': N_("Cover Art"), + 'settings': [ + SettingDesc('save_images_to_tags', N_("Embed cover images into tags"), ['save_images_to_tags']), + SettingDesc('embed_only_one_front_image', N_("Embed only a single front image"), ['cb_embed_front_only']), + SettingDesc('save_images_to_files', N_("Save cover images as separate files"), ['save_images_to_files']), + SettingDesc('cover_image_filename', N_("File name for images"), ['cover_image_filename']), + SettingDesc('save_images_overwrite', N_("Overwrite existing image files"), ['save_images_overwrite']), + SettingDesc('save_only_one_front_image', N_("Save only a single front image as separate file"), ['save_only_one_front_image']), + SettingDesc('image_type_as_filename', N_("Always use the primary image type as the file name for non-front images"), ['image_type_as_filename']), + SettingDesc('ca_providers', N_("Cover art providers"), ['ca_providers_list']), ], } - SETTINGS_GROUPS["filerenaming"] = { - "title": N_("File Naming"), - "settings": [ + SETTINGS_GROUPS['filerenaming'] = { + 'title': N_("File Naming"), + 'settings': [ # Main File Naming Page - SettingDesc("move_files", N_("Move files"), ["move_files"]), - SettingDesc("move_files_to", N_("Destination directory"), ["move_files_to"]), - SettingDesc("move_additional_files", N_("Move additional files"), ["move_additional_files"]), - SettingDesc("move_additional_files_pattern", N_("Additional file patterns"), ["move_additional_files_pattern"]), - SettingDesc("delete_empty_dirs", N_("Delete empty directories"), ["delete_empty_dirs"]), - SettingDesc("rename_files", N_("Rename files"), ["rename_files"]), - SettingDesc("selected_file_naming_script_id", N_("Selected file naming script"), ["naming_script_selector"]), + SettingDesc('move_files', N_("Move files"), ['move_files']), + SettingDesc('move_files_to', N_("Destination directory"), ['move_files_to']), + SettingDesc('move_additional_files', N_("Move additional files"), ['move_additional_files']), + SettingDesc('move_additional_files_pattern', N_("Additional file patterns"), ['move_additional_files_pattern']), + SettingDesc('delete_empty_dirs', N_("Delete empty directories"), ['delete_empty_dirs']), + SettingDesc('rename_files', N_("Rename files"), ['rename_files']), + SettingDesc('selected_file_naming_script_id', N_("Selected file naming script"), ['naming_script_selector']), # File Naming Compatibility Page - SettingDesc("ascii_filenames", N_("Replace non-ASCII characters"), ["ascii_filenames"]), - SettingDesc("windows_compatibility", N_("Windows compatibility"), ["windows_compatibility"]), - SettingDesc("win_compat_replacements", N_("Replacement characters used for Windows compatibility"), ["win_compat_replacements"]), - SettingDesc("windows_long_paths", N_("Windows long path support"), ["windows_long_paths"]), - SettingDesc("replace_spaces_with_underscores", N_("Replace spaces with underscores"), ["replace_spaces_with_underscores"]), - SettingDesc("replace_dir_separator", N_("Replacement character to use for directory separators"), ["replace_dir_separator"]), + SettingDesc('ascii_filenames', N_("Replace non-ASCII characters"), ['ascii_filenames']), + SettingDesc('windows_compatibility', N_("Windows compatibility"), ['windows_compatibility']), + SettingDesc('win_compat_replacements', N_("Replacement characters used for Windows compatibility"), ['win_compat_replacements']), + SettingDesc('windows_long_paths', N_("Windows long path support"), ['windows_long_paths']), + SettingDesc('replace_spaces_with_underscores', N_("Replace spaces with underscores"), ['replace_spaces_with_underscores']), + SettingDesc('replace_dir_separator', N_("Replacement character to use for directory separators"), ['replace_dir_separator']), ], } - SETTINGS_GROUPS["scripting"] = { - "title": N_("Scripting"), - "settings": [ - SettingDesc("enable_tagger_scripts", N_("Enable tagger scripts"), ["enable_tagger_scripts"]), - SettingDesc("list_of_scripts", N_("Tagger scripts"), ["script_list"]), + SETTINGS_GROUPS['scripting'] = { + 'title': N_("Scripting"), + 'settings': [ + SettingDesc('enable_tagger_scripts', N_("Enable tagger scripts"), ['enable_tagger_scripts']), + SettingDesc('list_of_scripts', N_("Tagger scripts"), ['script_list']), ], } - SETTINGS_GROUPS["interface"] = { - "title": N_("User Interface"), - "settings": [ + SETTINGS_GROUPS['interface'] = { + 'title': N_("User Interface"), + 'settings': [ # Main User Interface Page - SettingDesc("toolbar_show_labels", N_("Show text labels under icons"), ["toolbar_show_labels"]), - SettingDesc("show_menu_icons", N_("Show icons in menus"), ["show_menu_icons"]), - SettingDesc("ui_language", N_("User interface language"), ["ui_language"]), - SettingDesc("ui_theme", N_("User interface color theme"), ["ui_theme"]), - SettingDesc("toolbar_multiselect", N_("Allow selection of multiple directories"), ["toolbar_multiselect"]), - SettingDesc("builtin_search", N_("Use builtin search rather than looking in browser"), ["builtin_search"]), - SettingDesc("use_adv_search_syntax", N_("Use advanced search syntax"), ["use_adv_search_syntax"]), - SettingDesc("show_new_user_dialog", N_("Show a usage warning dialog when Picard starts"), ["new_user_dialog"]), - SettingDesc("quit_confirmation", N_("Show a quit confirmation dialog for unsaved changes"), ["quit_confirmation"]), - SettingDesc("file_save_warning", N_("Show a confirmation dialog when saving files"), ["file_save_warning"]), - SettingDesc("filebrowser_horizontal_autoscroll", N_("Adjust horizontal position in file browser automatically"), ["filebrowser_horizontal_autoscroll"]), - SettingDesc("starting_directory", N_("Begin browsing in a specific directory"), ["starting_directory"]), - SettingDesc("starting_directory_path", N_("Directory to begin browsing"), ["starting_directory_path"]), + SettingDesc('toolbar_show_labels', N_("Show text labels under icons"), ['toolbar_show_labels']), + SettingDesc('show_menu_icons', N_("Show icons in menus"), ['show_menu_icons']), + SettingDesc('ui_language', N_("User interface language"), ['ui_language']), + SettingDesc('ui_theme', N_("User interface color theme"), ['ui_theme']), + SettingDesc('toolbar_multiselect', N_("Allow selection of multiple directories"), ['toolbar_multiselect']), + SettingDesc('builtin_search', N_("Use builtin search rather than looking in browser"), ['builtin_search']), + SettingDesc('use_adv_search_syntax', N_("Use advanced search syntax"), ['use_adv_search_syntax']), + SettingDesc('show_new_user_dialog', N_("Show a usage warning dialog when Picard starts"), ['new_user_dialog']), + SettingDesc('quit_confirmation', N_("Show a quit confirmation dialog for unsaved changes"), ['quit_confirmation']), + SettingDesc('file_save_warning', N_("Show a confirmation dialog when saving files"), ['file_save_warning']), + SettingDesc('filebrowser_horizontal_autoscroll', N_("Adjust horizontal position in file browser automatically"), ['filebrowser_horizontal_autoscroll']), + SettingDesc('starting_directory', N_("Begin browsing in a specific directory"), ['starting_directory']), + SettingDesc('starting_directory_path', N_("Directory to begin browsing"), ['starting_directory_path']), # User Interface Colors Page - SettingDesc("interface_colors", N_("Colors to use for light theme"), ["colors"]), - SettingDesc("interface_colors_dark", N_("Colors to use for dark theme"), ["colors"]), + SettingDesc('interface_colors', N_("Colors to use for light theme"), ['colors']), + SettingDesc('interface_colors_dark', N_("Colors to use for dark theme"), ['colors']), # User Interface Top Tags Page - SettingDesc("metadatabox_top_tags", N_("Tags to show at the top"), ["top_tags_groupBox"]), + SettingDesc('metadatabox_top_tags', N_("Tags to show at the top"), ['top_tags_groupBox']), # User Interface Action Toolbar Page - SettingDesc("toolbar_layout", N_("Layout of the tool bar"), ["toolbar_layout_list"]), + SettingDesc('toolbar_layout', N_("Layout of the tool bar"), ['toolbar_layout_list']), ], } - SETTINGS_GROUPS["advanced"] = { - "title": N_("Advanced"), - "settings": [ + SETTINGS_GROUPS['advanced'] = { + 'title': N_("Advanced"), + 'settings': [ # Main Advanced Options Page - SettingDesc("ignore_regex", N_("Ignore file paths matching a regular expression"), ["ignore_regex"]), - SettingDesc("ignore_hidden_files", N_("Ignore hidden files"), ["ignore_hidden_files"]), - SettingDesc("recursively_add_files", N_("Include sub-folders when adding files from folder"), ["recursively_add_files"]), + SettingDesc('ignore_regex', N_("Ignore file paths matching a regular expression"), ['ignore_regex']), + SettingDesc('ignore_hidden_files', N_("Ignore hidden files"), ['ignore_hidden_files']), + SettingDesc('recursively_add_files', N_("Include sub-folders when adding files from folder"), ['recursively_add_files']), SettingDesc( - "ignore_track_duration_difference_under", + 'ignore_track_duration_difference_under', N_("Ignore track duration difference under x seconds"), - ["ignore_track_duration_difference_under", "label_track_duration_diff"] + ['ignore_track_duration_difference_under', 'label_track_duration_diff'] ), SettingDesc( - "query_limit", + 'query_limit', N_("Maximum number of entities to return per MusicBrainz query"), - ["query_limit", "label_query_limit"] + ['query_limit', 'label_query_limit'] ), - SettingDesc("completeness_ignore_videos", N_("Completeness check ignore: Video tracks"), ["completeness_ignore_videos"]), - SettingDesc("completeness_ignore_pregap", N_("Completeness check ignore: Pregap tracks"), ["completeness_ignore_pregap"]), - SettingDesc("completeness_ignore_data", N_("Completeness check ignore: Data tracks"), ["completeness_ignore_data"]), - SettingDesc("completeness_ignore_silence", N_("Completeness check ignore: Silent tracks"), ["completeness_ignore_silence"]), - SettingDesc("compare_ignore_tags", N_("Tags to ignore for comparison"), ["groupBox_2"]), + SettingDesc('completeness_ignore_videos', N_("Completeness check ignore: Video tracks"), ['completeness_ignore_videos']), + SettingDesc('completeness_ignore_pregap', N_("Completeness check ignore: Pregap tracks"), ['completeness_ignore_pregap']), + SettingDesc('completeness_ignore_data', N_("Completeness check ignore: Data tracks"), ['completeness_ignore_data']), + SettingDesc('completeness_ignore_silence', N_("Completeness check ignore: Silent tracks"), ['completeness_ignore_silence']), + SettingDesc('compare_ignore_tags', N_("Tags to ignore for comparison"), ['groupBox_2']), # Network Options Page - SettingDesc("use_proxy", N_("Use a web proxy server"), []), # No highlight specified because the "use_proxy" + SettingDesc('use_proxy', N_("Use a web proxy server"), []), # No highlight specified because the 'use_proxy' # object is a QGroupBox and it highlights all sub # options, even if the sub options are not selected. - SettingDesc("proxy_type", N_("type of proxy server"), ["proxy_type_socks", "proxy_type_http"]), - SettingDesc("proxy_server_host", N_("Proxy server address"), ["server_host"]), - SettingDesc("proxy_server_port", N_("Proxy server port"), ["server_port"]), - SettingDesc("proxy_username", N_("Proxy username"), ["username"]), - SettingDesc("proxy_password", N_("Proxy password"), ["password"]), - SettingDesc("network_transfer_timeout_seconds", N_("Request timeout in seconds"), ["transfer_timeout"]), - SettingDesc("browser_integration", N_("Browser integration"), []), # No highlight specified because the "browser_integration" + SettingDesc('proxy_type', N_("type of proxy server"), ['proxy_type_socks', 'proxy_type_http']), + SettingDesc('proxy_server_host', N_("Proxy server address"), ['server_host']), + SettingDesc('proxy_server_port', N_("Proxy server port"), ['server_port']), + SettingDesc('proxy_username', N_("Proxy username"), ['username']), + SettingDesc('proxy_password', N_("Proxy password"), ['password']), + SettingDesc('network_transfer_timeout_seconds', N_("Request timeout in seconds"), ['transfer_timeout']), + SettingDesc('browser_integration', N_("Browser integration"), []), # No highlight specified because the 'browser_integration' # object is a QGroupBox and it highlights all sub options, # even if the sub options are not selected. - SettingDesc("browser_integration_port", N_("Default listening port"), ["browser_integration_port"]), - SettingDesc("browser_integration_localhost_only", N_("Listen only on localhost"), ["browser_integration_localhost_only"]), + SettingDesc('browser_integration_port', N_("Default listening port"), ['browser_integration_port']), + SettingDesc('browser_integration_localhost_only', N_("Listen only on localhost"), ['browser_integration_localhost_only']), # Matching Options Page - SettingDesc("file_lookup_threshold", N_("Minimal similarity for file lookups"), ["file_lookup_threshold"]), - SettingDesc("cluster_lookup_threshold", N_("Minimal similarity for cluster lookups"), ["cluster_lookup_threshold"]), - SettingDesc("track_matching_threshold", N_("Minimal similarity for matching files to tracks"), ["track_matching_threshold"]), + SettingDesc('file_lookup_threshold', N_("Minimal similarity for file lookups"), ['file_lookup_threshold']), + SettingDesc('cluster_lookup_threshold', N_("Minimal similarity for cluster lookups"), ['cluster_lookup_threshold']), + SettingDesc('track_matching_threshold', N_("Minimal similarity for matching files to tracks"), ['track_matching_threshold']), ], } diff --git a/picard/releasegroup.py b/picard/releasegroup.py index f8b2b6d60a..0fdcf986d0 100644 --- a/picard/releasegroup.py +++ b/picard/releasegroup.py @@ -56,7 +56,7 @@ def __init__(self, rg_id): self.refcount = 0 def load_versions(self, callback): - kwargs = {"release-group": self.id, "limit": 100} + kwargs = {'release-group': self.id, 'limit': 100} self.tagger.mb_api.browse_releases(partial(self._request_finished, callback), **kwargs) def _parse_versions(self, document): @@ -64,17 +64,17 @@ def _parse_versions(self, document): del self.versions[:] data = [] - namekeys = ("tracks", "year", "country", "format", "label", "catnum") + namekeys = ('tracks', 'year', 'country', 'format', 'label', 'catnum') headings = { - "tracks": N_('Tracks'), - "year": N_('Year'), - "country": N_('Country'), - "format": N_('Format'), - "label": N_('Label'), - "catnum": N_('Cat No'), + 'tracks': N_("Tracks"), + 'year': N_("Year"), + 'country': N_("Country"), + 'format': N_("Format"), + 'label': N_("Label"), + 'catnum': N_("Cat No"), } # additional keys displayed only for disambiguation - extrakeys = ("packaging", "barcode", "disambiguation") + extrakeys = ('packaging', 'barcode', 'disambiguation') try: releases = document['releases'] @@ -97,23 +97,23 @@ def _parse_versions(self, document): tracks = "+".join(str(m['track-count']) for m in node['media']) formats = [] for medium in node['media']: - if "format" in medium: + if 'format' in medium: formats.append(medium['format']) release = { - "id": node['id'], - "year": node['date'][:4] if "date" in node else "????", - "country": country_label, - "format": media_formats_from_node(node['media']), - "label": ", ".join(' '.join(x.split(' ')[:2]) for x in set(labels)), - "catnum": ", ".join(set(catnums)), - "tracks": tracks, - "barcode": node.get('barcode', '') or _('[no barcode]'), - "packaging": node.get('packaging', '') or '??', - "disambiguation": node.get('disambiguation', ''), - "_disambiguate_name": list(), - "totaltracks": sum(m['track-count'] for m in node['media']), - "countries": countries, - "formats": formats, + 'id': node['id'], + 'year': node['date'][:4] if 'date' in node else '????', + 'country': country_label, + 'format': media_formats_from_node(node['media']), + 'label': ', '.join(' '.join(x.split(' ')[:2]) for x in set(labels)), + 'catnum': ', '.join(set(catnums)), + 'tracks': tracks, + 'barcode': node.get('barcode', '') or _('[no barcode]'), + 'packaging': node.get('packaging', '') or '??', + 'disambiguation': node.get('disambiguation', ''), + '_disambiguate_name': list(), + 'totaltracks': sum(m['track-count'] for m in node['media']), + 'countries': countries, + 'formats': formats, } data.append(release) @@ -122,7 +122,7 @@ def _parse_versions(self, document): # Group versions by same display name for release in data: name = " / ".join(release[k] for k in namekeys) - if name == release["tracks"]: + if name == release['tracks']: name = "%s / %s" % (_('[no release info]'), name) versions[name].append(release) diff --git a/picard/script/__init__.py b/picard/script/__init__.py index 5715ee261a..3d7294b5d3 100644 --- a/picard/script/__init__.py +++ b/picard/script/__init__.py @@ -104,9 +104,9 @@ def enabled_tagger_scripts_texts(): """Returns an iterator over the enabled tagger scripts. For each script, you'll get a tuple consisting of the script name and text""" config = get_config() - if not config.setting["enable_tagger_scripts"]: + if not config.setting['enable_tagger_scripts']: return [] - return [(s_name, s_text) for _s_pos, s_name, s_enabled, s_text in config.setting["list_of_scripts"] if s_enabled and s_text] + return [(s_name, s_text) for _s_pos, s_name, s_enabled, s_text in config.setting['list_of_scripts'] if s_enabled and s_text] def get_file_naming_script(settings): @@ -119,14 +119,14 @@ def get_file_naming_script(settings): str: The text of the file naming script if available, otherwise None """ from picard.script import get_file_naming_script_presets - scripts = settings["file_renaming_scripts"] - selected_id = settings["selected_file_naming_script_id"] + scripts = settings['file_renaming_scripts'] + selected_id = settings['selected_file_naming_script_id'] if selected_id: if scripts and selected_id in scripts: - return scripts[selected_id]["script"] + return scripts[selected_id]['script'] for item in get_file_naming_script_presets(): - if item["id"] == selected_id: - return str(item["script"]) + if item['id'] == selected_id: + return str(item['script']) log.error("Unable to retrieve the file naming script '%s'", selected_id) return None diff --git a/picard/script/functions.py b/picard/script/functions.py index e687ab1dba..8652fcb488 100644 --- a/picard/script/functions.py +++ b/picard/script/functions.py @@ -64,7 +64,7 @@ markdown = None -Bound = namedtuple("Bound", ["lower", "upper"]) +Bound = namedtuple('Bound', ['lower', 'upper']) class FunctionRegistryItem: @@ -227,7 +227,7 @@ def func_left(parser, text, length): try: return text[:int(length)] except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -239,7 +239,7 @@ def func_right(parser, text, length): try: return text[-int(length):] except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -270,7 +270,7 @@ def func_pad(parser, text, length, char): try: return char * (int(length) - len(text)) + text except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -324,9 +324,9 @@ def func_replacemulti(parser, multi, search, replace, separator=MULTI_VALUED_JOI )) def func_in(parser, text, needle): if needle in text: - return "1" + return '1' else: - return "" + return '' @script_function(eval_args=False, documentation=N_( @@ -368,13 +368,13 @@ def func_rsearch(parser, text, pattern): try: match = re.search(pattern, text) except re.error: - return "" + return '' if match: try: return match.group(1) except IndexError: return match.group(0) - return "" + return '' @script_function(documentation=N_( @@ -386,7 +386,7 @@ def func_num(parser, text, length): try: format_ = "%%0%dd" % max(0, min(int(length), 20)) except ValueError: - return "" + return '' try: value = int(text) except ValueError: @@ -409,9 +409,9 @@ def func_unset(parser, name): for key in list(parser.context.keys()): if key.startswith(name): parser.context.unset(key) - return "" + return '' parser.context.unset(name) - return "" + return '' @script_function(documentation=N_( @@ -426,7 +426,7 @@ def func_unset(parser, name): )) def func_delete(parser, name): parser.context.delete(normalize_tagname(name)) - return "" + return '' @script_function(documentation=N_( @@ -444,7 +444,7 @@ def func_set(parser, name, value): parser.context[normalize_tagname(name)] = value else: func_unset(parser, name) - return "" + return '' @script_function(documentation=N_( @@ -488,7 +488,7 @@ def func_copy(parser, new, old): new = normalize_tagname(new) old = normalize_tagname(old) parser.context[new] = parser.context.getall(old)[:] - return "" + return '' @script_function(documentation=N_( @@ -508,7 +508,7 @@ def func_copymerge(parser, new, old, keep_duplicates=False): newvals = parser.context.getall(new) oldvals = parser.context.getall(old) parser.context[new] = newvals + oldvals if keep_duplicates else uniqify(newvals + oldvals) - return "" + return '' @script_function(documentation=N_( @@ -539,7 +539,7 @@ def func_add(parser, x, y, *args): try: return _compute_int(operator.add, x, y, *args) except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -557,7 +557,7 @@ def func_sub(parser, x, y, *args): try: return _compute_int(operator.sub, x, y, *args) except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -575,9 +575,9 @@ def func_div(parser, x, y, *args): try: return _compute_int(operator.floordiv, x, y, *args) except ValueError: - return "" + return '' except ZeroDivisionError: - return "" + return '' @script_function(documentation=N_( @@ -595,7 +595,7 @@ def func_mod(parser, x, y, *args): try: return _compute_int(operator.mod, x, y, *args) except (ValueError, ZeroDivisionError): - return "" + return '' @script_function(documentation=N_( @@ -613,7 +613,7 @@ def func_mul(parser, x, y, *args): try: return _compute_int(operator.mul, x, y, *args) except ValueError: - return "" + return '' @script_function(documentation=N_( @@ -625,9 +625,9 @@ def func_mul(parser, x, y, *args): )) def func_or(parser, x, y, *args): if _compute_logic(any, x, y, *args): - return "1" + return '1' else: - return "" + return '' @script_function(documentation=N_( @@ -639,9 +639,9 @@ def func_or(parser, x, y, *args): )) def func_and(parser, x, y, *args): if _compute_logic(all, x, y, *args): - return "1" + return '1' else: - return "" + return '' @script_function(documentation=N_( @@ -651,9 +651,9 @@ def func_and(parser, x, y, *args): )) def func_not(parser, x): if not x: - return "1" + return '1' else: - return "" + return '' @script_function(documentation=N_( @@ -663,9 +663,9 @@ def func_not(parser, x): )) def func_eq(parser, x, y): if x == y: - return "1" + return '1' else: - return "" + return '' @script_function(documentation=N_( @@ -675,9 +675,9 @@ def func_eq(parser, x, y): )) def func_ne(parser, x, y): if x != y: - return "1" + return '1' else: - return "" + return '' def _cmp(op, x, y, _type): @@ -697,9 +697,9 @@ def _cmp(op, x, y, _type): except ValueError: pass if _type == 'text': - return "1" if op(x, y) else "" + return '1' if op(x, y) else "" elif _type == 'nocase': - return "1" if op(x.lower(), y.lower()) else "" + return '1' if op(x.lower(), y.lower()) else "" elif _type == 'float': _typer = float elif _type == 'int': @@ -707,10 +707,10 @@ def _cmp(op, x, y, _type): if _typer is not None: try: if op(_typer(x), _typer(y)): - return "1" + return '1' except ValueError: pass - return "" + return '' @script_function(documentation=N_( @@ -836,7 +836,7 @@ def func_matchedtracks(parser, *args): file = parser.file if file and file.parent and hasattr(file.parent, 'album') and file.parent.album: return str(parser.file.parent.album.get_num_matched_tracks()) - return "0" + return '0' @script_function(documentation=N_( @@ -850,8 +850,8 @@ def func_is_complete(parser): file = parser.file if (file and file.parent and hasattr(file.parent, 'album') and file.parent.album and file.parent.album.is_complete()): - return "1" - return "" + return '1' + return '' @script_function(documentation=N_( @@ -881,7 +881,7 @@ def func_firstalphachar(parser, text="", nonalpha="#"): _Since Picard 0.12_""" )) def func_initials(parser, text=""): - return "".join(a[:1] for a in text.split(" ") if a[:1].isalpha()) + return ''.join(a[:1] for a in text.split(" ") if a[:1].isalpha()) @script_function(documentation=N_( @@ -916,8 +916,8 @@ def func_firstwords(parser, text, length): )) def func_startswith(parser, text, prefix): if text.startswith(prefix): - return "1" - return "" + return '1' + return '' @script_function(documentation=N_( @@ -929,8 +929,8 @@ def func_startswith(parser, text, prefix): )) def func_endswith(parser, text, suffix): if text.endswith(suffix): - return "1" - return "" + return '1' + return '' @script_function(documentation=N_( @@ -1102,7 +1102,7 @@ def iswbound(char): # from https://github.com/metabrainz/picard-plugins/blob/2.0/plugins/titlecase/titlecase.py """ Checks whether the given character is a word boundary """ category = unicodedata.category(char) - return "Zs" == category or "Sk" == category or "P" == category[0] + return 'Zs' == category or 'Sk' == category or 'P' == category[0] @script_function(documentation=N_( @@ -1114,9 +1114,9 @@ def iswbound(char): )) def func_is_audio(parser): if func_is_video(parser) == "1": - return "" + return '' else: - return "1" + return '1' @script_function(documentation=N_( @@ -1128,9 +1128,9 @@ def func_is_audio(parser): )) def func_is_video(parser): if parser.context['~video'] and parser.context['~video'] != '0': - return "1" + return '1' else: - return "" + return '' @script_function(documentation=N_( @@ -1553,7 +1553,7 @@ def func_cleanmulti(parser, multi): name = normalize_tagname(multi) values = [str(value) for value in parser.context.getall(name) if value or value == 0] parser.context[name] = values - return "" + return '' def _type_args(_type, *args): @@ -1592,7 +1592,7 @@ def _extract(_func, _type, *args): try: haystack = _type_args(_type, *args) except ValueError: - return "" + return '' if _type == 'nocase': op = operator.lt if _func == min else operator.gt diff --git a/picard/script/parser.py b/picard/script/parser.py index 73a74bd2c6..8393248ac4 100644 --- a/picard/script/parser.py +++ b/picard/script/parser.py @@ -104,12 +104,12 @@ def __init__(self, line, column, name=None): def __str__(self): if self.name is None: - return '{line:d}:{column:d}'.format( + return "{line:d}:{column:d}".format( line=self.line, column=self.column ) else: - return '{line:d}:{column:d}:{name}'.format( + return "{line:d}:{column:d}:{name}".format( line=self.line, column=self.column, name=self.name @@ -124,7 +124,7 @@ def eval(self, state): def normalize_tagname(name): if name.startswith('_'): - return "~" + name[1:] + return '~' + name[1:] return name @@ -134,7 +134,7 @@ def __init__(self, name): self.name = name def __repr__(self): - return '' % self.name + return "" % self.name def eval(self, state): return state.context.get(normalize_tagname(self.name), "") @@ -427,7 +427,7 @@ def insert(self, index, value): return self._multi.insert(index, value) def __repr__(self): - return '%s(%r, %r, %r)' % (self.__class__.__name__, self.parser, self._multi, self.separator) + return "%s(%r, %r, %r)" % (self.__class__.__name__, self.parser, self._multi, self.separator) def __str__(self): return self.separator.join(x for x in self if x) diff --git a/picard/script/serializer.py b/picard/script/serializer.py index 7b73b94561..e073aabc94 100644 --- a/picard/script/serializer.py +++ b/picard/script/serializer.py @@ -72,7 +72,7 @@ class MultilineLiteral(str): def yaml_presenter(dumper, data): if data: data = data.rstrip() + '\n' - return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") + return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') yaml.add_representer(MultilineLiteral, MultilineLiteral.yaml_presenter) @@ -191,8 +191,8 @@ def to_dict(self): dict: Dictionary of the object's OUTPUT_FIELDS """ items = {key: getattr(self, key) for key in self.OUTPUT_FIELDS} - items["description"] = str(items["description"]) - items["script"] = str(items["script"]) + items['description'] = str(items['description']) + items['script'] = str(items['script']) return items def export_script(self, parent=None): @@ -216,13 +216,13 @@ def export_script(self, parent=None): (name, ext) = os.path.splitext(filename) if ext and str(name).endswith('.' + ext): filename = name - log.debug('Exporting script file: %s', filename) + log.debug("Exporting script file: %s", filename) if file_type == self._file_types()['package']: script_text = self.to_yaml() else: script_text = self.script + "\n" try: - with open(filename, 'w', encoding='utf8') as o_file: + with open(filename, 'w', encoding='utf-8') as o_file: o_file.write(script_text) except OSError as error: raise ScriptImportExportError(format=FILE_ERROR_EXPORT, filename=filename, error_msg=error.strerror) @@ -250,14 +250,14 @@ def import_script(cls, parent=None): filename, file_type = QtWidgets.QFileDialog.getOpenFileName(parent, dialog_title, default_script_directory, dialog_file_types, options=options) if not filename: return None - log.debug('Importing script file: %s', filename) + log.debug("Importing script file: %s", filename) try: - with open(filename, 'r', encoding='utf8') as i_file: + with open(filename, 'r', encoding='utf-8') as i_file: file_content = i_file.read() except OSError as error: raise ScriptImportExportError(format=FILE_ERROR_IMPORT, filename=filename, error_msg=error.strerror) if not file_content.strip(): - raise ScriptImportExportError(format=FILE_ERROR_IMPORT, filename=filename, error_msg=N_('The file was empty')) + raise ScriptImportExportError(format=FILE_ERROR_IMPORT, filename=filename, error_msg=N_("The file was empty")) if file_type == cls._file_types()['package']: try: return cls().create_from_yaml(file_content) @@ -285,7 +285,7 @@ def create_from_dict(cls, script_dict, create_new_id=True): if not isinstance(script_dict, Mapping): raise ScriptImportError(N_("Argument is not a dictionary")) if 'title' not in script_dict or 'script' not in script_dict: - raise ScriptImportError(N_('Invalid script package')) + raise ScriptImportError(N_("Invalid script package")) new_object.update_from_dict(script_dict) if create_new_id or not new_object['id']: new_object._set_new_id() @@ -329,7 +329,7 @@ def create_from_yaml(cls, yaml_string, create_new_id=True): if not isinstance(yaml_dict, dict): raise ScriptImportError(N_("File content not a dictionary")) if 'title' not in yaml_dict or 'script' not in yaml_dict: - raise ScriptImportError(N_('Invalid script package')) + raise ScriptImportError(N_("Invalid script package")) new_object.update_from_dict(yaml_dict) if create_new_id or not new_object['id']: new_object._set_new_id() diff --git a/picard/tagger.py b/picard/tagger.py index 6b95327a0e..ff4c852e93 100644 --- a/picard/tagger.py +++ b/picard/tagger.py @@ -189,12 +189,12 @@ def __init__(self, items): log.debug(f"Parsed: {repr(parsed)}") if not parsed.scheme: self.files.add(item) - if parsed.scheme == "file": + if parsed.scheme == 'file': # remove file:// prefix safely self.files.add(item[7:]) - elif parsed.scheme == "mbid": + elif parsed.scheme == 'mbid': self.mbids.add(parsed.netloc + parsed.path) - elif parsed.scheme in {"http", "https"}: + elif parsed.scheme in {'http', 'https'}: # .path returns / before actual link self.urls.add(parsed.path[1:]) elif IS_WIN and self.WINDOWS_DRIVE_TEST.match(item): @@ -254,7 +254,7 @@ def __init__(self, picard_args, localedir, autoupdate, pipe_handler=None): self.set_log_level(config.setting['log_verbosity']) - if picard_args.debug or "PICARD_DEBUG" in os.environ: + if picard_args.debug or 'PICARD_DEBUG' in os.environ: self.set_log_level(logging.DEBUG) if picard_args.audit: @@ -330,7 +330,7 @@ def __init__(self, picard_args, localedir, autoupdate, pipe_handler=None): # Must be before config upgrade because upgrade dialogs need to be # translated - setup_gettext(localedir, config.setting["ui_language"], log.debug) + setup_gettext(localedir, config.setting['ui_language'], log.debug) upgrade_config(config) @@ -390,9 +390,9 @@ def pipe_server(self): def _pipe_server_finished(self, result=None, error=None): if error: - log.error('pipe server failed: %r', error) + log.error("pipe server failed: %r", error) else: - log.debug('pipe server stopped') + log.debug("pipe server stopped") def start_process_commands(self): if not self._command_thread_running: @@ -455,9 +455,9 @@ def run_commands(self): def _run_commands_finished(self, result=None, error=None): if error: - log.error('command executor failed: %r', error) + log.error("command executor failed: %r", error) else: - log.debug('command executor stopped') + log.debug("command executor stopped") def load_to_picard(self, items): commands = [] @@ -615,7 +615,7 @@ def handle_command_submit_fingerprints(self, argstring): def handle_command_write_logs(self, argstring): try: - with open(argstring, 'w', encoding='utf8') as f: + with open(argstring, 'w', encoding='utf-8') as f: for x in self.window.log_dialog.log_tail.contents(): f.write(f"{x.message}\n") except Exception as e: @@ -649,7 +649,7 @@ def _mb_login_dialog(self, parent): return None def mb_login(self, callback, parent=None): - scopes = "profile tag rating collection submit_isrc submit_barcode" + scopes = 'profile tag rating collection submit_isrc submit_barcode' authorization_url = self.webservice.oauth_manager.get_authorization_url(scopes) webbrowser2.open(authorization_url) authorization_code = self._mb_login_dialog(parent) @@ -696,7 +696,7 @@ def move_file_to_track(self, file, albumid, recordingid): def create_nats(self): if self.nats is None: self.nats = NatAlbum() - self.albums["NATS"] = self.nats + self.albums['NATS'] = self.nats self.album_added.emit(self.nats) self.nats.item.setExpanded(True) return self.nats @@ -750,7 +750,7 @@ def run(self): def update_browser_integration(self): config = get_config() - if config.setting["browser_integration"]: + if config.setting['browser_integration']: self.browser_integration.start() else: self.browser_integration.stop() @@ -787,7 +787,7 @@ def _file_loaded(self, file, target=None, remove_file=False, unmatched_files=Non return file_moved = False - if not config.setting["ignore_file_mbids"]: + if not config.setting['ignore_file_mbids']: recordingid = file.metadata.getall('musicbrainz_recordingid') recordingid = recordingid[0] if recordingid else '' is_valid_recordingid = mbid_validate(recordingid) @@ -826,7 +826,7 @@ def _file_loaded(self, file, target=None, remove_file=False, unmatched_files=Non self.analyze([file]) # Auto cluster newly added files if they are not explicitly moved elsewhere - if self._pending_files_count == 0 and unmatched_files and config.setting["cluster_new_files"]: + if self._pending_files_count == 0 and unmatched_files and config.setting['cluster_new_files']: self.cluster(unmatched_files) def move_file(self, file, target): @@ -948,8 +948,8 @@ def add_paths(self, paths, target=None): def get_file_lookup(self): """Return a FileLookup object.""" config = get_config() - return FileLookup(self, config.setting["server_host"], - config.setting["server_port"], + return FileLookup(self, config.setting['server_host'], + config.setting['server_port'], self.browser_integration.port) def search(self, text, search_type, adv=False, mbid_matched_callback=None, force_browser=False): @@ -988,7 +988,7 @@ def collection_lookup(self): """Lookup the users collections on the MusicBrainz website.""" lookup = self.get_file_lookup() config = get_config() - lookup.collection_lookup(config.persist["oauth_username"]) + lookup.collection_lookup(config.persist['oauth_username']) def browser_lookup(self, item): """Lookup the object's metadata on the MusicBrainz website.""" @@ -1003,10 +1003,10 @@ def browser_lookup(self, item): lookup.album_lookup(itemid) else: lookup.tag_lookup( - metadata["albumartist"] if item.is_album_like() else metadata["artist"], - metadata["album"], - metadata["title"], - metadata["tracknumber"], + metadata['albumartist'] if item.is_album_like() else metadata['artist'], + metadata['album'], + metadata['title'], + metadata['tracknumber'], '' if item.is_album_like() else str(metadata.length), item.filename if isinstance(item, File) else '') @@ -1029,7 +1029,7 @@ def load_mbid(self, type, mbid): elif type == 'nat': self.load_nat(mbid) else: - log.warning('Unknown type to load: %s', type) + log.warning("Unknown type to load: %s", type) def load_album(self, album_id, discid=None): album_id = self.mbid_redirects.get(album_id, album_id) @@ -1162,8 +1162,8 @@ def lookup_cd(self, action): return self.lookup_discid_from_logfile() else: device = data - elif config.setting["cd_lookup_device"] != '': - device = config.setting["cd_lookup_device"].split(",", 1)[0] + elif config.setting['cd_lookup_device'] != '': + device = config.setting['cd_lookup_device'].split(',', 1)[0] else: # rely on python-discid auto detection device = None @@ -1215,7 +1215,7 @@ def _parse_disc_ripping_log(self, disc, path): @property def use_acoustid(self): config = get_config() - return config.setting["fingerprinting_system"] == "acoustid" + return config.setting['fingerprinting_system'] == 'acoustid' def analyze(self, objs): """Analyze the file(s).""" @@ -1266,7 +1266,7 @@ def _do_clustering(self, files): def _clustering_finished(self, callback, result=None, error=None): if error: - log.error('Error while clustering: %r', error) + log.error("Error while clustering: %r", error) return self.window.set_sorting(False) @@ -1285,7 +1285,7 @@ def _clustering_finished(self, callback, result=None, error=None): def load_cluster(self, name, artist): for cluster in self.clusters: cm = cluster.metadata - if name == cm["album"] and artist == cm["albumartist"]: + if name == cm['album'] and artist == cm['albumartist']: return cluster cluster = Cluster(name, artist) self.clusters.append(cluster) @@ -1401,7 +1401,7 @@ def print_help_for_commands(): maxwidth = 80 informative_text = [] - message = """usage: picard -e [command] [arguments ...] + message = """Usage: picard -e [command] [arguments ...] or picard -e [command 1] [arguments ...] -e [command 2] [arguments ...] List of the commands available to execute in Picard from the command-line: @@ -1435,38 +1435,38 @@ def process_picard_args(): ) # Qt default arguments. Parse them so Picard does not interpret the # arguments as file names to load. - parser.add_argument("-style", nargs=1, help=argparse.SUPPRESS) - parser.add_argument("-stylesheet", nargs=1, help=argparse.SUPPRESS) + parser.add_argument('-style', nargs=1, help=argparse.SUPPRESS) + parser.add_argument('-stylesheet', nargs=1, help=argparse.SUPPRESS) # Same for default X arguments - parser.add_argument("-display", nargs=1, help=argparse.SUPPRESS) + parser.add_argument('-display', nargs=1, help=argparse.SUPPRESS) # Picard specific arguments - parser.add_argument("-a", "--audit", action='store', + parser.add_argument('-a', '--audit', action='store', default=None, help="audit events passed as a comma-separated list, prefixes supported, " "use all to match any (see https://docs.python.org/3/library/audit_events.html#audit-events)") - parser.add_argument("-c", "--config-file", action='store', + parser.add_argument('-c', '--config-file', action='store', default=None, help="location of the configuration file") - parser.add_argument("-d", "--debug", action='store_true', + parser.add_argument('-d', '--debug', action='store_true', help="enable debug-level logging") - parser.add_argument("-e", "--exec", nargs="+", action='append', + parser.add_argument('-e', '--exec', nargs='+', action='append', help="send command (arguments can be entered after space) to a running instance " "(use `-e help` for a list of the available commands)", - metavar="COMMAND") - parser.add_argument("-M", "--no-player", action='store_true', + metavar='COMMAND') + parser.add_argument('-M', '--no-player', action='store_true', help="disable built-in media player") - parser.add_argument("-N", "--no-restore", action='store_true', + parser.add_argument('-N', '--no-restore', action='store_true', help="do not restore positions and/or sizes") - parser.add_argument("-P", "--no-plugins", action='store_true', + parser.add_argument('-P', '--no-plugins', action='store_true', help="do not load any plugins") - parser.add_argument("--no-crash-dialog", action='store_true', + parser.add_argument('--no-crash-dialog', action='store_true', help="disable the crash dialog") - parser.add_argument("-s", "--stand-alone-instance", action='store_true', + parser.add_argument('-s', '--stand-alone-instance', action='store_true', help="force Picard to create a new, stand-alone instance") parser.add_argument('-v', '--version', action='store_true', help="display version information and exit") - parser.add_argument("-V", "--long-version", action='store_true', + parser.add_argument('-V', '--long-version', action='store_true', help="display long version information and exit") parser.add_argument('FILE_OR_URL', nargs='*', help="the file(s), URL(s) and MBID(s) to load") @@ -1488,7 +1488,7 @@ def process_picard_args(): if args.exec: for e in args.exec: - args.remote_commands_help = args.remote_commands_help or "HELP" in {x.upper().strip() for x in e} + args.remote_commands_help = args.remote_commands_help or 'HELP' in {x.upper().strip() for x in e} remote_command_args = e[1:] or [''] for arg in remote_command_args: args.processable.append(f"{e[0]} {arg}") @@ -1533,7 +1533,7 @@ def main(localedir=None, autoupdate=True): identifier = uuid4().hex else: if picard_args.config_file: - identifier = blake2b(picard_args.config_file.encode('utf8'), digest_size=16).hexdigest() + identifier = blake2b(picard_args.config_file.encode('utf-8'), digest_size=16).hexdigest() else: identifier = 'main' if picard_args.no_plugins: @@ -1571,10 +1571,10 @@ def main(localedir=None, autoupdate=True): locale = QtCore.QLocale() translation_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.LibraryLocation.TranslationsPath) log.debug("Looking for Qt locale %s in %s", locale.name(), translation_path) - if translator.load(locale, "qtbase_", directory=translation_path): + if translator.load(locale, 'qtbase_', directory=translation_path): tagger.installTranslator(translator) else: - log.debug('Qt locale %s not available', locale.name()) + log.debug("Qt locale %s not available", locale.name()) tagger.startTimer(1000) exit_code = tagger.run() diff --git a/picard/track.py b/picard/track.py index fbdbe06fbe..e60736f574 100644 --- a/picard/track.py +++ b/picard/track.py @@ -176,7 +176,7 @@ def update_file_metadata(self, file): # Run the scripts for the file to allow usage of # file specific metadata and variables config = get_config() - if config.setting["clear_existing_tags"]: + if config.setting['clear_existing_tags']: metadata = Metadata(self.orig_metadata) metadata_proxy = MultiMetadataProxy(metadata, file.metadata) self.run_scripts(metadata_proxy) @@ -394,22 +394,22 @@ def load(self, priority=False, refresh=False): config = get_config() require_authentication = False inc = { - "aliases", - "artist-credits", - "artists", + 'aliases', + 'artist-credits', + 'artists', } - if config.setting["track_ars"]: + if config.setting['track_ars']: inc |= { - "artist-rels", - "recording-rels", - "url-rels", - "work-level-rels", - "work-rels", + 'artist-rels', + 'recording-rels', + 'url-rels', + 'work-level-rels', + 'work-rels', } require_authentication = self.set_genre_inc_params(inc, config) or require_authentication - if config.setting["enable_ratings"]: + if config.setting['enable_ratings']: require_authentication = True - inc |= {"user-ratings"} + inc |= {'user-ratings'} self.tagger.mb_api.get_track_by_id( self.id, self._recording_request_finished, diff --git a/picard/ui/__init__.py b/picard/ui/__init__.py index deec2391ce..20bff96f26 100644 --- a/picard/ui/__init__.py +++ b/picard/ui/__init__.py @@ -65,8 +65,8 @@ class PreserveGeometry: defaultsize = None def __init__(self): - Option.add_if_missing("persist", self.opt_name(), QtCore.QByteArray()) - Option.add_if_missing("persist", self.splitters_name(), {}) + Option.add_if_missing('persist', self.opt_name(), QtCore.QByteArray()) + Option.add_if_missing('persist', self.splitters_name(), {}) if getattr(self, 'finished', None): self.finished.connect(self.save_geometry) diff --git a/picard/ui/aboutdialog.py b/picard/ui/aboutdialog.py index 79d93d11c8..6f7074666c 100644 --- a/picard/ui/aboutdialog.py +++ b/picard/ui/aboutdialog.py @@ -71,12 +71,12 @@ def _update_content(self): ]) # TR: Replace this with your name to have it appear in the "About" dialog. - args["translator_credits"] = _("translator-credits") - if args["translator_credits"] != "translator-credits": + args['translator_credits'] = _('translator-credits') + if args['translator_credits'] != 'translator-credits': # TR: Replace LANG with language you are translating to. - args["translator_credits"] = _("
Translated to LANG by %s") % args["translator_credits"].replace("\n", "
") + args['translator_credits'] = _("
Translated to LANG by %s") % args['translator_credits'].replace("\n", "
") else: - args["translator_credits"] = "" + args['translator_credits'] = "" args['icons_credits'] = _( 'Icons made by Sambhav Kothari ' 'and Madebyoliver, ' diff --git a/picard/ui/cdlookup.py b/picard/ui/cdlookup.py index 503a1bd77a..89345bd9d1 100644 --- a/picard/ui/cdlookup.py +++ b/picard/ui/cdlookup.py @@ -53,10 +53,10 @@ class CDLookupDialog(PicardDialog): - dialog_header_state = "cdlookupdialog_header_state" + dialog_header_state = 'cdlookupdialog_header_state' options = [ - Option("persist", dialog_header_state, QtCore.QByteArray()) + Option('persist', dialog_header_state, QtCore.QByteArray()) ] def __init__(self, releases, disc, parent=None): @@ -126,7 +126,7 @@ def lookup(self): lookup = self.tagger.get_file_lookup() lookup.discid_submission(submission_url) else: - log.error('No submission URL for disc ID "%s"', self.disc.id) + log.error("No submission URL for disc ID %s", self.disc.id) super().accept() @restore_method diff --git a/picard/ui/coverartbox.py b/picard/ui/coverartbox.py index 968b1a3acc..07d88eae30 100644 --- a/picard/ui/coverartbox.py +++ b/picard/ui/coverartbox.py @@ -96,7 +96,7 @@ def __init__(self, active=False, drops=False, pixmap_cache=None, *args, **kwargs def screen_changed(self, screen): pixel_ratio = screen.devicePixelRatio() - log.debug('screen changed, pixel ratio %s', pixel_ratio) + log.debug("screen changed, pixel ratio %s", pixel_ratio) if pixel_ratio != self.pixel_ratio: self.pixel_ratio = pixel_ratio self._update_default_pixmaps() @@ -107,8 +107,8 @@ def screen_changed(self, screen): def _update_default_pixmaps(self): w, h = self.scaled(THUMBNAIL_WIDTH, THUMBNAIL_WIDTH) - self.shadow = self._load_cached_default_pixmap(':/images/CoverArtShadow.png', w, h) - self.file_missing_pixmap = self._load_cached_default_pixmap(':/images/image-missing.png', w, h) + self.shadow = self._load_cached_default_pixmap(":/images/CoverArtShadow.png", w, h) + self.file_missing_pixmap = self._load_cached_default_pixmap(":/images/image-missing.png", w, h) def _load_cached_default_pixmap(self, pixmap_path, w, h): key = hash((pixmap_path, self.pixel_ratio)) @@ -291,7 +291,7 @@ def calculate_cover_coordinates(pixmap, cx, cy): if not has_common_images: # Draw a golden highlight around the first cover to indicate that # images are not common to all selected items - color = QtGui.QColor("darkgoldenrod") + color = QtGui.QColor('darkgoldenrod') border_length = 10 for k in range(border_length): color.setAlpha(255 - k * 255 // border_length) @@ -322,7 +322,7 @@ def set_metadata(self, metadata): self.set_data(data, has_common_images=has_common_images) release = None if metadata: - release = metadata.get("musicbrainz_albumid", None) + release = metadata.get('musicbrainz_albumid', None) if release: self.setActive(True) text = _("View release on MusicBrainz") @@ -550,7 +550,7 @@ def _try_load_remote_image(self, url, data): ) config = get_config() - if config.setting["load_image_behavior"] == 'replace': + if config.setting['load_image_behavior'] == 'replace': set_image = set_image_replace debug_info = "Replacing with dropped %r in %r" else: @@ -616,7 +616,7 @@ def choose_local_file(self): def set_load_image_behavior(self, behavior): config = get_config() - config.setting["load_image_behavior"] = behavior + config.setting['load_image_behavior'] = behavior def keep_original_images(self): self.item.keep_original_images() @@ -626,19 +626,19 @@ def keep_original_images(self): def contextMenuEvent(self, event): menu = QtWidgets.QMenu(self) if self.show_details_button.isVisible(): - name = _('Show more details…') + name = _("Show more details…") show_more_details_action = QtWidgets.QAction(name, self.parent) show_more_details_action.triggered.connect(self.show_cover_art_info) menu.addAction(show_more_details_action) if self.orig_cover_art.isVisible(): - name = _('Keep original cover art') + name = _("Keep original cover art") use_orig_value_action = QtWidgets.QAction(name, self.parent) use_orig_value_action.triggered.connect(self.keep_original_images) menu.addAction(use_orig_value_action) if self.item and self.item.can_show_coverart: - name = _('Choose local file…') + name = _("Choose local file…") choose_local_file_action = QtWidgets.QAction(name, self.parent) choose_local_file_action.triggered.connect(self.choose_local_file) menu.addAction(choose_local_file_action) @@ -647,20 +647,20 @@ def contextMenuEvent(self, event): menu.addSeparator() load_image_behavior_group = QtWidgets.QActionGroup(self.parent) - action = QtWidgets.QAction(_('Replace front cover art'), self.parent) + action = QtWidgets.QAction(_("Replace front cover art"), self.parent) action.setCheckable(True) action.triggered.connect(partial(self.set_load_image_behavior, behavior='replace')) load_image_behavior_group.addAction(action) config = get_config() - if config.setting["load_image_behavior"] == 'replace': + if config.setting['load_image_behavior'] == 'replace': action.setChecked(True) menu.addAction(action) - action = QtWidgets.QAction(_('Append front cover art'), self.parent) + action = QtWidgets.QAction(_("Append front cover art"), self.parent) action.setCheckable(True) action.triggered.connect(partial(self.set_load_image_behavior, behavior='append')) load_image_behavior_group.addAction(action) - if config.setting["load_image_behavior"] == 'append': + if config.setting['load_image_behavior'] == 'append': action.setChecked(True) menu.addAction(action) diff --git a/picard/ui/edittagdialog.py b/picard/ui/edittagdialog.py index b674e78dda..61a6953454 100644 --- a/picard/ui/edittagdialog.py +++ b/picard/ui/edittagdialog.py @@ -66,9 +66,9 @@ def createEditor(self, parent, option, index): editor = super().createEditor(parent, option, index) completer = None if tag in {'date', 'originaldate', 'releasedate'}: - editor.setPlaceholderText(_('YYYY-MM-DD')) + editor.setPlaceholderText(_("YYYY-MM-DD")) elif tag == 'originalyear': - editor.setPlaceholderText(_('YYYY')) + editor.setPlaceholderText(_("YYYY")) elif tag == 'releasetype': completer = QtWidgets.QCompleter(AUTOCOMPLETE_RELEASE_TYPES, editor) elif tag == 'releasestatus': diff --git a/picard/ui/filebrowser.py b/picard/ui/filebrowser.py index 55b603225f..9a1c1c48a3 100644 --- a/picard/ui/filebrowser.py +++ b/picard/ui/filebrowser.py @@ -50,19 +50,19 @@ def _macos_find_root_volume(): try: - for entry in os.scandir('/Volumes/'): - if entry.is_symlink() and os.path.realpath(entry.path) == '/': + for entry in os.scandir("/Volumes/"): + if entry.is_symlink() and os.path.realpath(entry.path) == "/": return entry.path except OSError: - log.warning('Could not detect macOS boot volume', exc_info=True) + log.warning("Could not detect macOS boot volume", exc_info=True) return None def _macos_extend_root_volume_path(path): - if not path.startswith('/Volumes/'): + if not path.startswith("/Volumes/"): root_volume = _macos_find_root_volume() if root_volume: - if path.startswith('/'): + if path.startswith("/"): path = path[1:] path = os.path.join(root_volume, path) return path @@ -77,8 +77,8 @@ def _macos_extend_root_volume_path(path): class FileBrowser(QtWidgets.QTreeView): options = [ - TextOption("persist", "current_browser_path", _default_current_browser_path), - BoolOption("persist", "show_hidden_files", False), + TextOption('persist', 'current_browser_path', _default_current_browser_path), + BoolOption('persist', 'show_hidden_files', False), ] def __init__(self, parent): @@ -94,7 +94,7 @@ def __init__(self, parent): self.toggle_hidden_action = QtWidgets.QAction(_("Show &hidden files"), self) self.toggle_hidden_action.setCheckable(True) config = get_config() - self.toggle_hidden_action.setChecked(config.persist["show_hidden_files"]) + self.toggle_hidden_action.setChecked(config.persist['show_hidden_files']) self.toggle_hidden_action.toggled.connect(self.show_hidden) self.addAction(self.toggle_hidden_action) self.set_as_starting_directory_action = QtWidgets.QAction(_("&Set as starting directory"), self) @@ -143,7 +143,7 @@ def _set_model(self): def _set_model_filter(self): config = get_config() model_filter = QtCore.QDir.Filter.AllDirs | QtCore.QDir.Filter.Files | QtCore.QDir.Filter.Drives | QtCore.QDir.Filter.NoDotAndDotDot - if config.persist["show_hidden_files"]: + if config.persist['show_hidden_files']: model_filter |= QtCore.QDir.Filter.Hidden self.model().setFilter(model_filter) @@ -188,7 +188,7 @@ def focusInEvent(self, event): def show_hidden(self, state): config = get_config() - config.persist["show_hidden_files"] = state + config.persist['show_hidden_files'] = state self._set_model_filter() def save_state(self): @@ -196,18 +196,18 @@ def save_state(self): if indexes: path = self.model().filePath(indexes[0]) config = get_config() - config.persist["current_browser_path"] = os.path.normpath(path) + config.persist['current_browser_path'] = os.path.normpath(path) def restore_state(self): pass def _restore_state(self): config = get_config() - if config.setting["starting_directory"]: - path = config.setting["starting_directory_path"] + if config.setting['starting_directory']: + path = config.setting['starting_directory_path'] scrolltype = QtWidgets.QAbstractItemView.ScrollHint.PositionAtTop else: - path = config.persist["current_browser_path"] + path = config.persist['current_browser_path'] scrolltype = QtWidgets.QAbstractItemView.ScrollHint.PositionAtCenter if path: index = self.model().index(find_existing_path(path)) @@ -241,11 +241,11 @@ def move_files_here(self): return config = get_config() path = self.model().filePath(indexes[0]) - config.setting["move_files_to"] = self._get_destination_from_path(path) + config.setting['move_files_to'] = self._get_destination_from_path(path) def set_as_starting_directory(self): indexes = self.selectedIndexes() if indexes: config = get_config() path = self.model().filePath(indexes[0]) - config.setting["starting_directory_path"] = self._get_destination_from_path(path) + config.setting['starting_directory_path'] = self._get_destination_from_path(path) diff --git a/picard/ui/infodialog.py b/picard/ui/infodialog.py index 4e75c677f3..a5d37c9375 100644 --- a/picard/ui/infodialog.py +++ b/picard/ui/infodialog.py @@ -146,7 +146,7 @@ def __init__(self, obj, parent=None): # Add the ArtworkTable to the ui self.ui.artwork_table = ArtworkTable(self.display_existing_artwork) - self.ui.artwork_table.setObjectName("artwork_table") + self.ui.artwork_table.setObjectName('artwork_table') self.ui.artwork_tab.layout().addWidget(self.ui.artwork_table) self.setTabOrder(self.ui.tabWidget, self.ui.artwork_table) self.setTabOrder(self.ui.artwork_table, self.ui.buttonBox) @@ -168,7 +168,7 @@ def _display_error_tab(self): def _show_errors(self, errors): if errors: - color = interface_colors.get_color("log_error") + color = interface_colors.get_color('log_error') text = '
'.join(map( lambda s: '%s' % (color, text_as_html(s)), errors)) self.ui.error.setText(text + '
') @@ -283,38 +283,38 @@ def show_item(self, item): def format_file_info(file_): info = [] - info.append((_('Filename:'), file_.filename)) + info.append((_("Filename:"), file_.filename)) if '~format' in file_.orig_metadata: - info.append((_('Format:'), file_.orig_metadata['~format'])) + info.append((_("Format:"), file_.orig_metadata['~format'])) try: size = os.path.getsize(encode_filename(file_.filename)) sizestr = "%s (%s)" % (bytes2human.decimal(size), bytes2human.binary(size)) - info.append((_('Size:'), sizestr)) + info.append((_("Size:"), sizestr)) except BaseException: pass if file_.orig_metadata.length: - info.append((_('Length:'), format_time(file_.orig_metadata.length))) + info.append((_("Length:"), format_time(file_.orig_metadata.length))) if '~bitrate' in file_.orig_metadata: - info.append((_('Bitrate:'), '%s kbps' % file_.orig_metadata['~bitrate'])) + info.append((_("Bitrate:"), "%s kbps" % file_.orig_metadata['~bitrate'])) if '~sample_rate' in file_.orig_metadata: - info.append((_('Sample rate:'), '%s Hz' % file_.orig_metadata['~sample_rate'])) + info.append((_("Sample rate:"), "%s Hz" % file_.orig_metadata['~sample_rate'])) if '~bits_per_sample' in file_.orig_metadata: - info.append((_('Bits per sample:'), str(file_.orig_metadata['~bits_per_sample']))) + info.append((_("Bits per sample:"), str(file_.orig_metadata['~bits_per_sample']))) if '~channels' in file_.orig_metadata: ch = file_.orig_metadata['~channels'] if ch == '1': - ch = _('Mono') + ch = _("Mono") elif ch == '2': - ch = _('Stereo') - info.append((_('Channels:'), ch)) + ch = _("Stereo") + info.append((_("Channels:"), ch)) return '
'.join(map(lambda i: '%s %s' % (escape(i[0]), escape(i[1])), info)) def format_tracklist(cluster): info = [] - info.append("%s %s" % (_('Album:'), escape(cluster.metadata["album"]))) - info.append("%s %s" % (_('Artist:'), escape(cluster.metadata["albumartist"]))) + info.append('%s %s' % (_("Album:"), escape(cluster.metadata['album']))) + info.append('%s %s' % (_("Artist:"), escape(cluster.metadata['albumartist']))) info.append("") TrackListItem = namedtuple('TrackListItem', 'number, title, artist, length') tracklists = defaultdict(list) @@ -324,9 +324,9 @@ def format_tracklist(cluster): objlist = cluster.iterfiles(False) for obj_ in objlist: m = obj_.metadata - artist = m["artist"] or m["albumartist"] or cluster.metadata["albumartist"] - track = TrackListItem(m["tracknumber"], m["title"], artist, - m["~length"]) + artist = m['artist'] or m['albumartist'] or cluster.metadata['albumartist'] + track = TrackListItem(m['tracknumber'], m['title'], artist, + m['~length']) tracklists[obj_.discnumber].append(track) def sorttracknum(track): @@ -344,9 +344,9 @@ def sorttracknum(track): for discnumber in sorted(tracklists): tracklist = tracklists[discnumber] if ndiscs > 1: - info.append("%s" % (_('Disc %d') % discnumber)) - lines = ["%s %s - %s (%s)" % item for item in sorted(tracklist, key=sorttracknum)] - info.append("%s
%s
" % (_('Tracklist:'), + info.append('%s' % (_("Disc %d") % discnumber)) + lines = ['%s %s - %s (%s)' % item for item in sorted(tracklist, key=sorttracknum)] + info.append('%s
%s
' % (_("Tracklist:"), '
'.join(escape(s).replace(' ', ' ') for s in lines))) return '
'.join(info) diff --git a/picard/ui/infostatus.py b/picard/ui/infostatus.py index 6b3a871087..e1c270b5ce 100644 --- a/picard/ui/infostatus.py +++ b/picard/ui/infostatus.py @@ -60,7 +60,7 @@ def _init_labels(self): self._init_tooltips() def _create_icons(self): - self.icon_eta = QtGui.QIcon(':/images/22x22/hourglass.png') + self.icon_eta = QtGui.QIcon(":/images/22x22/hourglass.png") self.icon_cd = icontheme.lookup('media-optical') self.icon_file = QtGui.QIcon(":/images/file.png") self.icon_file_pending = QtGui.QIcon(":/images/file-pending.png") diff --git a/picard/ui/item.py b/picard/ui/item.py index 44a9c391ce..95cea7f39d 100644 --- a/picard/ui/item.py +++ b/picard/ui/item.py @@ -86,7 +86,7 @@ def load(self, priority=False, refresh=False): def tracknumber(self): """The track number as an int.""" try: - return int(self.metadata["tracknumber"]) + return int(self.metadata['tracknumber']) except BaseException: return 0 @@ -94,7 +94,7 @@ def tracknumber(self): def discnumber(self): """The disc number as an int.""" try: - return int(self.metadata["discnumber"]) + return int(self.metadata['discnumber']) except BaseException: return 0 @@ -105,7 +105,7 @@ def errors(self): return self._errors def error_append(self, msg): - log.error('%r: %s', self, msg) + log.error("%r: %s", self, msg) self.errors.append(msg) def clear_errors(self): diff --git a/picard/ui/itemviews.py b/picard/ui/itemviews.py index 64b52e3068..a0c3a5dcc8 100644 --- a/picard/ui/itemviews.py +++ b/picard/ui/itemviews.py @@ -158,24 +158,24 @@ class MainPanel(QtWidgets.QSplitter): options = [] columns = [ - (N_('Title'), 'title'), - (N_('Length'), '~length'), - (N_('Artist'), 'artist'), - (N_('Album Artist'), 'albumartist'), - (N_('Composer'), 'composer'), - (N_('Album'), 'album'), - (N_('Disc Subtitle'), 'discsubtitle'), - (N_('Track No.'), 'tracknumber'), - (N_('Disc No.'), 'discnumber'), - (N_('Catalog No.'), 'catalognumber'), - (N_('Barcode'), 'barcode'), - (N_('Media'), 'media'), - (N_('Genre'), 'genre'), - (N_('Fingerprint status'), '~fingerprint'), - (N_('Date'), 'date'), - (N_('Original Release Date'), 'originaldate'), - (N_('Release Date'), 'releasedate'), - (N_('Cover'), 'covercount'), + (N_("Title"), 'title'), + (N_("Length"), '~length'), + (N_("Artist"), 'artist'), + (N_("Album Artist"), 'albumartist'), + (N_("Composer"), 'composer'), + (N_("Album"), 'album'), + (N_("Disc Subtitle"), 'discsubtitle'), + (N_("Track No."), 'tracknumber'), + (N_("Disc No."), 'discnumber'), + (N_("Catalog No."), 'catalognumber'), + (N_("Barcode"), 'barcode'), + (N_("Media"), 'media'), + (N_("Genre"), 'genre'), + (N_("Fingerprint status"), '~fingerprint'), + (N_("Date"), 'date'), + (N_("Original Release Date"), 'originaldate'), + (N_("Release Date"), 'releasedate'), + (N_("Cover"), 'covercount'), ] _column_indexes = {column[1]: i for i, column in enumerate(columns)} @@ -396,12 +396,12 @@ def contextMenuEvent(self, event): menu.addAction(action) menu.addSeparator() - restore_action = QtWidgets.QAction(_('Restore default columns'), parent) + restore_action = QtWidgets.QAction(_("Restore default columns"), parent) restore_action.setEnabled(not self.is_locked) restore_action.triggered.connect(self.restore_defaults) menu.addAction(restore_action) - lock_action = QtWidgets.QAction(_('Lock columns'), parent) + lock_action = QtWidgets.QAction(_("Lock columns"), parent) lock_action.setCheckable(True) lock_action.setChecked(self.is_locked) lock_action.toggled.connect(self.lock) @@ -543,9 +543,9 @@ def contextMenuEvent(self, event): releases_menu = QtWidgets.QMenu(_("&Other versions"), menu) menu.addSeparator() menu.addMenu(releases_menu) - loading = releases_menu.addAction(_('Loading…')) + loading = releases_menu.addAction(_("Loading…")) loading.setDisabled(True) - action_more = releases_menu.addAction(_('Show &more details…')) + action_more = releases_menu.addAction(_("Show &more details…")) action_more.triggered.connect(self.window.album_other_versions_action.trigger) bottom_separator = True @@ -562,8 +562,8 @@ def _add_other_versions(): versions = obj.release_group.versions album_tracks_count = obj.get_num_total_files() or len(obj.tracks) - preferred_countries = set(config.setting["preferred_release_countries"]) - preferred_formats = set(config.setting["preferred_release_formats"]) + preferred_countries = set(config.setting['preferred_release_countries']) + preferred_formats = set(config.setting['preferred_release_formats']) ORDER_BEFORE, ORDER_AFTER = 0, 1 alternatives = [] @@ -610,7 +610,7 @@ def _add_other_versions(): else: releases_menu.setEnabled(False) - if config.setting["enable_ratings"] and \ + if config.setting['enable_ratings'] and \ len(self.window.selected_objects) == 1 and isinstance(obj, Track): menu.addSeparator() action = QtWidgets.QWidgetAction(menu) @@ -626,7 +626,7 @@ def _add_other_versions(): menu.addSeparator() menu.addMenu(CollectionMenu(selected_albums, _("Collections"), menu)) - scripts = config.setting["list_of_scripts"] + scripts = config.setting['list_of_scripts'] if plugin_actions or scripts: menu.addSeparator() @@ -692,7 +692,7 @@ def supportedDropActions(self): def mimeTypes(self): """List of MIME types accepted by this view.""" - return ["text/uri-list", "application/picard.album-list"] + return ['text/uri-list', 'application/picard.album-list'] def dragEnterEvent(self, event): super().dragEnterEvent(event) @@ -733,7 +733,7 @@ def mimeData(self, items): elif obj.iterfiles: files.extend([url(f.filename) for f in obj.iterfiles()]) mimeData = QtCore.QMimeData() - mimeData.setData("application/picard.album-list", "\n".join(album_ids).encode()) + mimeData.setData('application/picard.album-list', '\n'.join(album_ids).encode()) if files: mimeData.setUrls(files) return mimeData @@ -753,14 +753,14 @@ def drop_urls(urls, target, move_to_multi_tracks=True): tagger = QtCore.QObject.tagger for url in urls: log.debug("Dropped the URL: %r", url.toString(QtCore.QUrl.UrlFormattingOption.RemoveUserInfo)) - if url.scheme() == "file" or not url.scheme(): - filename = normpath(url.toLocalFile().rstrip("\0")) + if url.scheme() == 'file' or not url.scheme(): + filename = normpath(url.toLocalFile().rstrip('\0')) file = tagger.files.get(filename) if file: files.append(file) else: new_paths.append(filename) - elif url.scheme() in {"http", "https"}: + elif url.scheme() in {'http', 'https'}: file_lookup = tagger.get_file_lookup() file_lookup.mbid_lookup(url.path(), browser_fallback=False) if files: @@ -804,7 +804,7 @@ def dropMimeData(self, parent, index, data, action): QtCore.QTimer.singleShot(0, partial(self.drop_urls, urls, target, self._move_to_multi_tracks)) handled = True # application/picard.album-list - albums = data.data("application/picard.album-list") + albums = data.data('application/picard.album-list') if albums: album_ids = bytes(albums).decode().split("\n") log.debug("Dropped albums = %r", album_ids) @@ -843,8 +843,8 @@ def moveCursor(self, action, modifiers): class FileTreeView(BaseTreeView): - header_state = Option("persist", "file_view_header_state", QtCore.QByteArray()) - header_locked = BoolOption("persist", "file_view_header_locked", False) + header_state = Option('persist', 'file_view_header_state', QtCore.QByteArray()) + header_locked = BoolOption('persist', 'file_view_header_locked', False) def __init__(self, window, parent=None): super().__init__(window, parent) @@ -869,13 +869,13 @@ def remove_file_cluster(self, cluster): self.set_clusters_text() def set_clusters_text(self): - self.clusters.setText(MainPanel.TITLE_COLUMN, '%s (%d)' % (_("Clusters"), len(self.tagger.clusters))) + self.clusters.setText(MainPanel.TITLE_COLUMN, "%s (%d)" % (_("Clusters"), len(self.tagger.clusters))) class AlbumTreeView(BaseTreeView): - header_state = Option("persist", "album_view_header_state", QtCore.QByteArray()) - header_locked = BoolOption("persist", "album_view_header_locked", False) + header_state = Option('persist', 'album_view_header_state', QtCore.QByteArray()) + header_locked = BoolOption('persist', 'album_view_header_locked', False) def __init__(self, window, parent=None): super().__init__(window, parent) @@ -1194,10 +1194,10 @@ def decide_fingerprint_icon_info(file): if getattr(file, 'acoustid_fingerprint', None): if QtCore.QObject.tagger.acoustidmanager.is_submitted(file): icon = FileItem.icon_fingerprint_gray - tooltip = _('Fingerprint has already been submitted') + tooltip = _("Fingerprint has already been submitted") else: icon = FileItem.icon_fingerprint - tooltip = _('Unsubmitted fingerprint') + tooltip = _("Unsubmitted fingerprint") else: icon = QtGui.QIcon() tooltip = _('No fingerprint was calculated for this file, use "Scan" or "Generate AcoustID Fingerprints" to calculate the fingerprint.') diff --git a/picard/ui/logview.py b/picard/ui/logview.py index 365932de37..8dfbb83a1f 100644 --- a/picard/ui/logview.py +++ b/picard/ui/logview.py @@ -162,7 +162,7 @@ def set_verbosity(self, level): class LogView(LogViewCommon): options = [ - IntOption("setting", "log_verbosity", logging.WARNING), + IntOption('setting', 'log_verbosity', logging.WARNING), ] def __init__(self, parent=None): @@ -271,7 +271,7 @@ def _save_log_as_do(self): return writer = QtGui.QTextDocumentWriter(path) - writer.setFormat(b"plaintext") + writer.setFormat(b'plaintext') success = writer.write(self.doc) if not success: QtWidgets.QMessageBox.critical( diff --git a/picard/ui/mainwindow.py b/picard/ui/mainwindow.py index 418d12c597..cb009a35df 100644 --- a/picard/ui/mainwindow.py +++ b/picard/ui/mainwindow.py @@ -177,15 +177,15 @@ class MainWindow(QtWidgets.QMainWindow, PreserveGeometry): ready_for_display = QtCore.pyqtSignal() options = [ - Option("persist", "window_state", QtCore.QByteArray()), - BoolOption("persist", "window_maximized", False), - BoolOption("persist", "view_metadata_view", True), - BoolOption("persist", "view_cover_art", True), - BoolOption("persist", "view_toolbar", True), - BoolOption("persist", "view_file_browser", False), - TextOption("persist", "current_directory", ""), - FloatOption("persist", "mediaplayer_playback_rate", 1.0), - IntOption("persist", "mediaplayer_volume", 50), + Option('persist', 'window_state', QtCore.QByteArray()), + BoolOption('persist', 'window_maximized', False), + BoolOption('persist', 'view_metadata_view', True), + BoolOption('persist', 'view_cover_art', True), + BoolOption('persist', 'view_toolbar', True), + BoolOption('persist', 'view_file_browser', False), + TextOption('persist', 'current_directory', ""), + FloatOption('persist', 'mediaplayer_playback_rate', 1.0), + IntOption('persist', 'mediaplayer_volume', 50), ] def __init__(self, parent=None, disable_player=False): @@ -316,7 +316,7 @@ def showEvent(self, event): def closeEvent(self, event): config = get_config() - if config.setting["quit_confirmation"] and not self.show_quit_confirmation(): + if config.setting['quit_confirmation'] and not self.show_quit_confirmation(): event.ignore() return if self.player: @@ -367,14 +367,14 @@ def show_quit_confirmation(self): def saveWindowState(self): config = get_config() - config.persist["window_state"] = self.saveState() + config.persist['window_state'] = self.saveState() isMaximized = int(self.windowState()) & QtCore.Qt.WindowState.WindowMaximized != 0 self.save_geometry() - config.persist["window_maximized"] = isMaximized - config.persist["view_metadata_view"] = self.show_metadata_view_action.isChecked() - config.persist["view_cover_art"] = self.show_cover_art_action.isChecked() - config.persist["view_toolbar"] = self.show_toolbar_action.isChecked() - config.persist["view_file_browser"] = self.show_file_browser_action.isChecked() + config.persist['window_maximized'] = isMaximized + config.persist['view_metadata_view'] = self.show_metadata_view_action.isChecked() + config.persist['view_cover_art'] = self.show_cover_art_action.isChecked() + config.persist['view_toolbar'] = self.show_toolbar_action.isChecked() + config.persist['view_file_browser'] = self.show_file_browser_action.isChecked() self.file_browser.save_state() self.panel.save_state() self.metadata_box.save_state() @@ -382,11 +382,11 @@ def saveWindowState(self): @restore_method def restoreWindowState(self): config = get_config() - self.restoreState(config.persist["window_state"]) + self.restoreState(config.persist['window_state']) self.restore_geometry() - if config.persist["window_maximized"]: + if config.persist['window_maximized']: self.setWindowState(QtCore.Qt.WindowState.WindowMaximized) - splitters = config.persist["splitters_MainWindow"] + splitters = config.persist['splitters_MainWindow'] if splitters is None or 'main_window_bottom_splitter' not in splitters: self.centralWidget().setSizes([366, 194]) self.file_browser.restore_state() @@ -480,7 +480,7 @@ def isdict(obj): def _on_submit_acoustid(self): if self.tagger.use_acoustid: config = get_config() - if not config.setting["acoustid_apikey"]: + if not config.setting['acoustid_apikey']: msg = QtWidgets.QMessageBox(self) msg.setIcon(QtWidgets.QMessageBox.Icon.Information) msg.setWindowModality(QtCore.Qt.WindowModality.WindowModal) @@ -493,7 +493,7 @@ def _on_submit_acoustid(self): msg.addButton(open_options, QtWidgets.QMessageBox.ButtonRole.YesRole) msg.exec_() if msg.clickedButton() == open_options: - self.show_options("fingerprinting") + self.show_options('fingerprinting') else: self.tagger.acoustidmanager.submit() @@ -705,7 +705,7 @@ def _create_show_file_browser_action(self): config = get_config() action = QtWidgets.QAction(_("File &Browser"), self) action.setCheckable(True) - if config.persist["view_file_browser"]: + if config.persist['view_file_browser']: action.setChecked(True) action.setShortcut(QtGui.QKeySequence(_("Ctrl+B"))) action.triggered.connect(self.show_file_browser) @@ -716,7 +716,7 @@ def _create_show_metadata_view_action(self): config = get_config() action = QtWidgets.QAction(_("&Metadata"), self) action.setCheckable(True) - if config.persist["view_metadata_view"]: + if config.persist['view_metadata_view']: action.setChecked(True) action.setShortcut(QtGui.QKeySequence(_("Ctrl+Shift+M"))) action.triggered.connect(self.show_metadata_view) @@ -727,7 +727,7 @@ def _create_show_cover_art_action(self): config = get_config() action = QtWidgets.QAction(_("&Cover Art"), self) action.setCheckable(True) - if config.persist["view_cover_art"]: + if config.persist['view_cover_art']: action.setChecked(True) action.setEnabled(self.show_metadata_view_action.isChecked()) action.triggered.connect(self.show_cover_art) @@ -738,7 +738,7 @@ def _create_show_toolbar_action(self): config = get_config() action = QtWidgets.QAction(_("&Actions"), self) action.setCheckable(True) - if config.persist["view_toolbar"]: + if config.persist['view_toolbar']: action.setChecked(True) action.triggered.connect(self.show_toolbar) self.show_toolbar_action = action @@ -775,7 +775,7 @@ def _create_analyze_action(self): action = QtWidgets.QAction(icontheme.lookup('picard-analyze'), _("&Scan"), self) action.setStatusTip(_("Use AcoustID audio fingerprint to identify the files by the actual music, even if they have no metadata")) action.setEnabled(False) - action.setToolTip(_('Identify the file using its AcoustID audio fingerprint')) + action.setToolTip(_("Identify the file using its AcoustID audio fingerprint")) # TR: Keyboard shortcut for "Analyze" action.setShortcut(QtGui.QKeySequence(_("Ctrl+Y"))) action.triggered.connect(self.analyze) @@ -787,7 +787,7 @@ def _create_generate_fingerprints_action(self): action.setIconText(_("Generate Fingerprints")) action.setStatusTip(_("Generate the AcoustID audio fingerprints for the selected files without doing a lookup")) action.setEnabled(False) - action.setToolTip(_('Generate the AcoustID audio fingerprints for the selected files')) + action.setToolTip(_("Generate the AcoustID audio fingerprints for the selected files")) action.setShortcut(QtGui.QKeySequence(_("Ctrl+Shift+Y"))) action.triggered.connect(self.generate_fingerprints) self.generate_fingerprints_action = action @@ -835,7 +835,7 @@ def _create_enable_renaming_action(self): config = get_config() action = QtWidgets.QAction(_("&Rename Files"), self) action.setCheckable(True) - action.setChecked(config.setting["rename_files"]) + action.setChecked(config.setting['rename_files']) action.triggered.connect(self.toggle_rename_files) self.enable_renaming_action = action @@ -844,7 +844,7 @@ def _create_enable_moving_action(self): config = get_config() action = QtWidgets.QAction(_("&Move Files"), self) action.setCheckable(True) - action.setChecked(config.setting["move_files"]) + action.setChecked(config.setting['move_files']) action.triggered.connect(self.toggle_move_files) self.enable_moving_action = action @@ -853,7 +853,7 @@ def _create_enable_tag_saving_action(self): config = get_config() action = QtWidgets.QAction(_("Save &Tags"), self) action.setCheckable(True) - action.setChecked(not config.setting["dont_write_tags"]) + action.setChecked(not config.setting['dont_write_tags']) action.triggered.connect(self.toggle_tag_saving) self.enable_tag_saving_action = action @@ -861,7 +861,7 @@ def _create_enable_tag_saving_action(self): def _create_tags_from_filenames_action(self): action = QtWidgets.QAction(icontheme.lookup('picard-tags-from-filename'), _("Tags From &File Names…"), self) action.setIconText(_("Parse File Names…")) - action.setToolTip(_('Set tags based on the file names')) + action.setToolTip(_("Set tags based on the file names")) action.setShortcut(QtGui.QKeySequence(_("Ctrl+Shift+T"))) action.setEnabled(False) action.triggered.connect(self.open_tags_from_filenames) @@ -871,7 +871,7 @@ def _create_tags_from_filenames_action(self): def _create_open_collection_in_browser_action(self): config = get_config() action = QtWidgets.QAction(_("&Open My Collections in Browser"), self) - action.setEnabled(config.setting["username"] != '') + action.setEnabled(config.setting['username'] != '') action.triggered.connect(self.open_collection_in_browser) self.open_collection_in_browser_action = action @@ -938,7 +938,7 @@ def update_cd_lookup_drives(self, drives): log.warning(DISCID_NOT_LOADED_MESSAGE) else: config = get_config() - shortcut_drive = config.setting["cd_lookup_device"].split(",")[0] if len(drives) > 1 else "" + shortcut_drive = config.setting['cd_lookup_device'].split(",")[0] if len(drives) > 1 else "" for drive in drives: action = self.cd_lookup_menu.addAction(drive) action.setData(drive) @@ -950,7 +950,7 @@ def update_cd_lookup_drives(self, drives): def _set_cd_lookup_from_file_actions(self, drives): if self.cd_lookup_menu.actions(): self.cd_lookup_menu.addSeparator() - action = self.cd_lookup_menu.addAction(_('From CD ripper &log file…')) + action = self.cd_lookup_menu.addAction(_("From CD ripper &log file…")) if not drives: self._update_cd_lookup_default_action(action) action.setData('logfile:eac') @@ -974,17 +974,17 @@ def _update_cd_lookup_button(self): def toggle_rename_files(self, checked): config = get_config() - config.setting["rename_files"] = checked + config.setting['rename_files'] = checked self.update_script_editor_examples() def toggle_move_files(self, checked): config = get_config() - config.setting["move_files"] = checked + config.setting['move_files'] = checked self.update_script_editor_examples() def toggle_tag_saving(self, checked): config = get_config() - config.setting["dont_write_tags"] = not checked + config.setting['dont_write_tags'] = not checked def get_selected_or_unmatched_files(self): if self.selected_objects: @@ -1084,7 +1084,7 @@ def create_menus(self): def update_toolbar_style(self): config = get_config() style = QtCore.Qt.ToolButtonStyle.ToolButtonIconOnly - if config.setting["toolbar_show_labels"]: + if config.setting['toolbar_show_labels']: style = QtCore.Qt.ToolButtonStyle.ToolButtonTextUnderIcon self.toolbar.setToolButtonStyle(style) if self.player: @@ -1103,7 +1103,7 @@ def create_action_toolbar(self): self.removeToolBar(self.toolbar) self.toolbar = toolbar = QtWidgets.QToolBar(_("Actions")) self.insertToolBar(self.search_toolbar, self.toolbar) - toolbar.setObjectName("main_toolbar") + toolbar.setObjectName('main_toolbar') if self._is_wayland: toolbar.setFloatable(False) # https://bugreports.qt.io/browse/QTBUG-92191 if IS_MACOS: @@ -1126,7 +1126,7 @@ def add_toolbar_action(action): try: add_toolbar_action(getattr(self, action)) except AttributeError: - log.warning('Warning: Unknown action name "%r" found in config. Ignored.', action) + log.warning("Warning: Unknown action name '%r' found in config. Ignored.", action) self.show_toolbar() def create_player_toolbar(self): @@ -1142,7 +1142,7 @@ def create_search_toolbar(self): config = get_config() self.search_toolbar = toolbar = self.addToolBar(_("Search")) self.search_toolbar_toggle_action = self.search_toolbar.toggleViewAction() - toolbar.setObjectName("search_toolbar") + toolbar.setObjectName('search_toolbar') if self._is_wayland: toolbar.setFloatable(False) # https://bugreports.qt.io/browse/QTBUG-92191 if IS_MACOS: @@ -1151,9 +1151,9 @@ def create_search_toolbar(self): search_panel = QtWidgets.QWidget(toolbar) hbox = QtWidgets.QHBoxLayout(search_panel) self.search_combo = QtWidgets.QComboBox(search_panel) - self.search_combo.addItem(_("Album"), "album") - self.search_combo.addItem(_("Artist"), "artist") - self.search_combo.addItem(_("Track"), "track") + self.search_combo.addItem(_("Album"), 'album') + self.search_combo.addItem(_("Artist"), 'artist') + self.search_combo.addItem(_("Track"), 'track') hbox.addWidget(self.search_combo, 0) self.search_edit = QtWidgets.QLineEdit(search_panel) self.search_edit.setClearButtonEnabled(True) @@ -1243,7 +1243,7 @@ def search(self): entity = self.search_combo.itemData(self.search_combo.currentIndex()) config = get_config() self.tagger.search(text, entity, - config.setting["use_adv_search_syntax"], + config.setting['use_adv_search_syntax'], mbid_matched_callback=self.search_mbid_found) def add_files(self): @@ -1271,7 +1271,7 @@ def add_files(self): files, _filter = QtWidgets.QFileDialog.getOpenFileNames(self, "", current_directory, ";;".join(formats)) if files: config = get_config() - config.persist["current_directory"] = os.path.dirname(files[0]) + config.persist['current_directory'] = os.path.dirname(files[0]) self.tagger.add_files(files) def add_directory(self): @@ -1280,7 +1280,7 @@ def add_directory(self): dir_list = [] config = get_config() - if not config.setting["toolbar_multiselect"]: + if not config.setting['toolbar_multiselect']: directory = QtWidgets.QFileDialog.getExistingDirectory(self, "", current_directory) if directory: dir_list.append(directory) @@ -1292,7 +1292,7 @@ def add_directory(self): dir_count = len(dir_list) if dir_count: parent = os.path.dirname(dir_list[0]) if dir_count > 1 else dir_list[0] - config.persist["current_directory"] = parent + config.persist['current_directory'] = parent if dir_count > 1: self.set_statusbar_message( N_("Adding multiple directories from '%(directory)s' …"), @@ -1357,11 +1357,11 @@ def open_donation_page(self): def save(self): """Tell the tagger to save the selected objects.""" config = get_config() - if config.setting["file_save_warning"]: + if config.setting['file_save_warning']: count = len(self.tagger.get_files_from_objects(self.selected_objects)) msg = SaveWarningDialog(self, count) proceed_with_save, disable_warning = msg.show() - config.setting["file_save_warning"] = not disable_warning + config.setting['file_save_warning'] = not disable_warning else: proceed_with_save = True if proceed_with_save: @@ -1405,7 +1405,7 @@ def _ensure_fingerprinting_configured(self, callback): def on_finished(result): callback(config.setting['fingerprinting_system']) - dialog = self.show_options("fingerprinting") + dialog = self.show_options('fingerprinting') dialog.finished.connect(on_finished) else: callback(config.setting['fingerprinting_system']) @@ -1438,7 +1438,7 @@ def show_more_tracks(self): if isinstance(obj, Track) and obj.files: obj = obj.files[0] if not isinstance(obj, File): - log.debug('show_more_tracks expected a File, got %r', obj) + log.debug("show_more_tracks expected a File, got %r", obj) return dialog = TrackSearchDialog(self, force_advanced_search=True) dialog.show_similar_tracks(obj) @@ -1447,7 +1447,7 @@ def show_more_tracks(self): def show_more_albums(self): obj = self.get_first_obj_with_type(Cluster) if not obj: - log.debug('show_more_albums expected a Cluster, got %r', obj) + log.debug("show_more_albums expected a Cluster, got %r", obj) return dialog = AlbumSearchDialog(self, force_advanced_search=True) dialog.show_similar_albums(obj) @@ -1532,13 +1532,13 @@ def _check_add_release(self): QtWidgets.QMessageBox.StandardButton.Yes) if ret == QtWidgets.QMessageBox.StandardButton.Yes: config = get_config() - config.setting["browser_integration"] = True + config.setting['browser_integration'] = True self.tagger.update_browser_integration() if addrelease.is_enabled(): return True else: # Something went wrong, let the user configure browser integration manually - self.show_options("network") + self.show_options('network') return False else: return False @@ -1735,12 +1735,12 @@ def show_password_dialog(self, reply, authenticator): def on_mb_login_finished(self, successful, error_msg): if successful: - log.debug('MusicBrainz authentication finished successfully') + log.debug("MusicBrainz authentication finished successfully") else: - log.info('MusicBrainz authentication failed: %s', error_msg) + log.info("MusicBrainz authentication failed: %s", error_msg) QtWidgets.QMessageBox.critical(self, _("Authentication failed"), - _('Login failed: %s') % error_msg) + _("Login failed: %s") % error_msg) def show_proxy_dialog(self, proxy, authenticator): dialog = ProxyDialog(authenticator, proxy, parent=self) @@ -1783,7 +1783,7 @@ def auto_update_check(self): update_level = config.setting['update_level'] today = datetime.date.today().toordinal() do_auto_update_check = check_for_updates and update_check_days > 0 and today >= last_update_check + update_check_days - log.debug('%(check_status)s startup check for program updates. Today: %(today_date)s, Last check: %(last_check)s (Check interval: %(check_interval)s days), Update level: %(update_level)s (%(update_level_name)s)', { + log.debug("%(check_status)s startup check for program updates. Today: %(today_date)s, Last check: %(last_check)s (Check interval: %(check_interval)s days), Update level: %(update_level)s (%(update_level_name)s)", { 'check_status': 'Initiating' if do_auto_update_check else 'Skipping', 'today_date': datetime.date.today(), 'last_check': str(datetime.date.fromordinal(last_update_check)) if last_update_check > 0 else 'never', @@ -1824,29 +1824,29 @@ def check_and_repair_profiles(self): Checks that there is a settings dictionary for each profile, and that no profiles reference a non-existant file naming script. """ - script_id_key = "selected_file_naming_script_id" + script_id_key = 'selected_file_naming_script_id' config = get_config() - naming_scripts = config.setting["file_renaming_scripts"] + naming_scripts = config.setting['file_renaming_scripts'] naming_script_ids = set(naming_scripts.keys()) profile_settings = deepcopy(config.profiles[SettingConfigSection.SETTINGS_KEY]) for profile in config.profiles[SettingConfigSection.PROFILES_KEY]: - p_id = profile["id"] + p_id = profile['id'] # Add empty settings if none found for a profile if p_id not in profile_settings: log.warning( - "No settings dict found for profile '%s' (\"%s\"). Adding empty dict.", + "No settings dict found for profile '%s' ('%s'). Adding empty dict.", p_id, - profile["title"], + profile['title'], ) profile_settings[p_id] = {} # Remove any invalid naming script ids from profiles if script_id_key in profile_settings[p_id]: if profile_settings[p_id][script_id_key] not in naming_script_ids: log.warning( - "Removing invalid naming script id '%s' from profile '%s' (\"%s\")", + "Removing invalid naming script id '%s' from profile '%s' ('%s')", profile_settings[p_id][script_id_key], p_id, - profile["title"], + profile['title'], ) profile_settings[p_id][script_id_key] = None config.profiles[SettingConfigSection.SETTINGS_KEY] = profile_settings @@ -1856,8 +1856,8 @@ def make_script_selector_menu(self): """ if self.script_editor_dialog is None or not isinstance(self.script_editor_dialog, ScriptEditorDialog): config = get_config() - naming_scripts = config.setting["file_renaming_scripts"] - selected_script_id = config.setting["selected_file_naming_script_id"] + naming_scripts = config.setting['file_renaming_scripts'] + selected_script_id = config.setting['selected_file_naming_script_id'] else: naming_scripts = self.script_editor_dialog.naming_scripts selected_script_id = self.script_editor_dialog.selected_script_id @@ -1886,7 +1886,7 @@ def select_new_naming_script(self, id): """ config = get_config() log.debug("Setting naming script to: %s", id) - config.setting["selected_file_naming_script_id"] = id + config.setting['selected_file_naming_script_id'] = id self.make_script_selector_menu() if self.script_editor_dialog: self.script_editor_dialog.set_selected_script_id(id) @@ -1993,9 +1993,9 @@ def update_profile_selection(self, profile_id): def show_new_user_dialog(self): config = get_config() - if config.setting["show_new_user_dialog"]: + if config.setting['show_new_user_dialog']: msg = NewUserDialog(self) - config.setting["show_new_user_dialog"] = msg.show() + config.setting['show_new_user_dialog'] = msg.show() def check_for_plugin_update(self): config = get_config() diff --git a/picard/ui/metadatabox.py b/picard/ui/metadatabox.py index 1aa94cd005..eb96fb1b66 100644 --- a/picard/ui/metadatabox.py +++ b/picard/ui/metadatabox.py @@ -85,7 +85,7 @@ class TagStatus: class TagCounter(dict): - __slots__ = ("parent", "counts", "different") + __slots__ = ('parent', 'counts', 'different') def __init__(self, parent): self.parent = parent @@ -111,7 +111,7 @@ def display_value(self, tag): if tag in self.different: return (ngettext("(different across %d item)", "(different across %d items)", count) % count, True) else: - if tag == "~length": + if tag == '~length': msg = format_time(self.get(tag, 0)) else: msg = MULTI_VALUED_JOINER.join(self[tag]) @@ -124,7 +124,7 @@ def display_value(self, tag): class TagDiff(object): - __slots__ = ("tag_names", "new", "orig", "status", "objects", "max_length_delta_ms") + __slots__ = ('tag_names', 'new', 'orig', 'status', 'objects', 'max_length_delta_ms') def __init__(self, max_length_diff=2): self.tag_names = [] @@ -135,7 +135,7 @@ def __init__(self, max_length_diff=2): self.max_length_delta_ms = max_length_diff * 1000 def __tag_ne(self, tag, orig, new): - if tag == "~length": + if tag == '~length': return abs(float(orig) - float(new)) > self.max_length_delta_ms else: return orig != new @@ -204,8 +204,8 @@ def get_tag_name(self, index): class MetadataBox(QtWidgets.QTableWidget): options = ( - Option("persist", "metadatabox_header_state", QtCore.QByteArray()), - BoolOption("persist", "show_changes_first", False) + Option('persist', 'metadatabox_header_state', QtCore.QByteArray()), + BoolOption('persist', 'show_changes_first', False) ) COLUMN_ORIG = 1 @@ -242,7 +242,7 @@ def __init__(self, parent): self.add_tag_action.triggered.connect(partial(self.edit_tag, "")) self.changes_first_action = QtWidgets.QAction(_("Show Changes First"), parent) self.changes_first_action.setCheckable(True) - self.changes_first_action.setChecked(config.persist["show_changes_first"]) + self.changes_first_action.setChecked(config.persist['show_changes_first']) self.changes_first_action.toggled.connect(self.toggle_changes_first) # TR: Keyboard shortcut for "Add New Tag…" self.add_tag_shortcut = QtWidgets.QShortcut(QtGui.QKeySequence(_("Alt+Shift+A")), self, partial(self.edit_tag, "")) @@ -260,22 +260,22 @@ def __init__(self, parent): def get_file_lookup(self): """Return a FileLookup object.""" config = get_config() - return FileLookup(self, config.setting["server_host"], - config.setting["server_port"], + return FileLookup(self, config.setting['server_host'], + config.setting['server_port'], self.tagger.browser_integration.port) def lookup_tags(self): lookup = self.get_file_lookup() LOOKUP_TAGS = { - "musicbrainz_recordingid": lookup.recording_lookup, - "musicbrainz_trackid": lookup.track_lookup, - "musicbrainz_albumid": lookup.album_lookup, - "musicbrainz_workid": lookup.work_lookup, - "musicbrainz_artistid": lookup.artist_lookup, - "musicbrainz_albumartistid": lookup.artist_lookup, - "musicbrainz_releasegroupid": lookup.release_group_lookup, - "musicbrainz_discid": lookup.discid_lookup, - "acoustid_id": lookup.acoust_lookup + 'musicbrainz_recordingid': lookup.recording_lookup, + 'musicbrainz_trackid': lookup.track_lookup, + 'musicbrainz_albumid': lookup.album_lookup, + 'musicbrainz_workid': lookup.work_lookup, + 'musicbrainz_artistid': lookup.artist_lookup, + 'musicbrainz_albumartistid': lookup.artist_lookup, + 'musicbrainz_releasegroupid': lookup.release_group_lookup, + 'musicbrainz_discid': lookup.discid_lookup, + 'acoustid_id': lookup.acoust_lookup } return LOOKUP_TAGS @@ -469,7 +469,7 @@ def edit_selected_tag(self): def toggle_changes_first(self, checked): config = get_config() - config.persist["show_changes_first"] = checked + config.persist['show_changes_first'] = checked self.update() def set_tag_values(self, tag, values, objects=None): @@ -557,8 +557,8 @@ def _update_tags(self, new_selection=True, drop_album_caches=False): return None if new_selection or drop_album_caches: - self._single_file_album = len({file.metadata["album"] for file in files}) == 1 - self._single_track_album = len({track.metadata["album"] for track in tracks}) == 1 + self._single_file_album = len({file.metadata['album'] for file in files}) == 1 + self._single_track_album = len({track.metadata['album'] for track in tracks}) == 1 while not new_selection: # Just an if with multiple exit points # If we are dealing with the same selection @@ -582,12 +582,12 @@ def _update_tags(self, new_selection=True, drop_album_caches=False): } config = get_config() - tag_diff = TagDiff(max_length_diff=config.setting["ignore_track_duration_difference_under"]) + tag_diff = TagDiff(max_length_diff=config.setting['ignore_track_duration_difference_under']) orig_tags = tag_diff.orig new_tags = tag_diff.new tag_diff.objects = len(files) - clear_existing_tags = config.setting["clear_existing_tags"] + clear_existing_tags = config.setting['clear_existing_tags'] top_tags = config.setting['metadatabox_top_tags'] top_tags_set = set(top_tags) @@ -608,7 +608,7 @@ def _update_tags(self, new_selection=True, drop_album_caches=False): removed = name in new_metadata.deleted_tags tag_diff.add(name, orig_values, new_values, True, removed, top_tags=top_tags_set) - tag_diff.add("~length", str(orig_metadata.length), str(new_metadata.length), + tag_diff.add('~length', str(orig_metadata.length), str(new_metadata.length), removable=False, readonly=True) for track in tracks: @@ -622,7 +622,7 @@ def _update_tags(self, new_selection=True, drop_album_caches=False): tag_diff.add(name, orig_values, new_values, True) length = str(track.metadata.length) - tag_diff.add("~length", length, length, removable=False, readonly=True) + tag_diff.add('~length', length, length, removable=False, readonly=True) tag_diff.objects += 1 @@ -631,7 +631,7 @@ def _update_tags(self, new_selection=True, drop_album_caches=False): tag_names = common_tags + sorted(all_tags.difference(common_tags), key=lambda x: display_tag_name(x).lower()) - if config.persist["show_changes_first"]: + if config.persist['show_changes_first']: tags_by_status = {} for tag in tag_names: @@ -685,7 +685,7 @@ def _update_items(self, result=None, error=None): self.setItem(i, 2, new_item) tag_item.setText(display_tag_name(name)) self.set_item_value(orig_item, self.tag_diff.orig, name) - if name == "~length": + if name == '~length': new_item.setFlags(orig_flags) else: new_item.setFlags(new_flags) @@ -723,7 +723,7 @@ def set_item_value(self, item, tags, name): @restore_method def restore_state(self): config = get_config() - state = config.persist["metadatabox_header_state"] + state = config.persist['metadatabox_header_state'] header = self.horizontalHeader() header.restoreState(state) header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeMode.Interactive) @@ -732,4 +732,4 @@ def save_state(self): config = get_config() header = self.horizontalHeader() state = header.saveState() - config.persist["metadatabox_header_state"] = state + config.persist['metadatabox_header_state'] = state diff --git a/picard/ui/options/advanced.py b/picard/ui/options/advanced.py index 35cb862f35..8052e6f0f0 100644 --- a/picard/ui/options/advanced.py +++ b/picard/ui/options/advanced.py @@ -40,24 +40,24 @@ class AdvancedOptionsPage(OptionsPage): - NAME = "advanced" + NAME = 'advanced' TITLE = N_("Advanced") PARENT = None SORT_ORDER = 90 ACTIVE = True - HELP_URL = '/config/options_advanced.html' + HELP_URL = "/config/options_advanced.html" options = [ - TextOption("setting", "ignore_regex", ""), - BoolOption("setting", "ignore_hidden_files", False), - BoolOption("setting", "recursively_add_files", True), - IntOption("setting", "ignore_track_duration_difference_under", 2), - IntOption("setting", "query_limit", QUERY_LIMIT), - BoolOption("setting", "completeness_ignore_videos", False), - BoolOption("setting", "completeness_ignore_pregap", False), - BoolOption("setting", "completeness_ignore_data", False), - BoolOption("setting", "completeness_ignore_silence", False), - ListOption("setting", "compare_ignore_tags", []), + TextOption('setting', 'ignore_regex', ''), + BoolOption('setting', 'ignore_hidden_files', False), + BoolOption('setting', 'recursively_add_files', True), + IntOption('setting', 'ignore_track_duration_difference_under', 2), + IntOption('setting', 'query_limit', QUERY_LIMIT), + BoolOption('setting', 'completeness_ignore_videos', False), + BoolOption('setting', 'completeness_ignore_pregap', False), + BoolOption('setting', 'completeness_ignore_data', False), + BoolOption('setting', 'completeness_ignore_silence', False), + ListOption('setting', 'compare_ignore_tags', []), ] def __init__(self, parent=None): @@ -68,32 +68,32 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.ignore_regex.setText(config.setting["ignore_regex"]) - self.ui.ignore_hidden_files.setChecked(config.setting["ignore_hidden_files"]) - self.ui.recursively_add_files.setChecked(config.setting["recursively_add_files"]) - self.ui.ignore_track_duration_difference_under.setValue(config.setting["ignore_track_duration_difference_under"]) - self.ui.query_limit.setCurrentText(str(config.setting["query_limit"])) - self.ui.completeness_ignore_videos.setChecked(config.setting["completeness_ignore_videos"]) - self.ui.completeness_ignore_pregap.setChecked(config.setting["completeness_ignore_pregap"]) - self.ui.completeness_ignore_data.setChecked(config.setting["completeness_ignore_data"]) - self.ui.completeness_ignore_silence.setChecked(config.setting["completeness_ignore_silence"]) - self.ui.compare_ignore_tags.update(config.setting["compare_ignore_tags"]) + self.ui.ignore_regex.setText(config.setting['ignore_regex']) + self.ui.ignore_hidden_files.setChecked(config.setting['ignore_hidden_files']) + self.ui.recursively_add_files.setChecked(config.setting['recursively_add_files']) + self.ui.ignore_track_duration_difference_under.setValue(config.setting['ignore_track_duration_difference_under']) + self.ui.query_limit.setCurrentText(str(config.setting['query_limit'])) + self.ui.completeness_ignore_videos.setChecked(config.setting['completeness_ignore_videos']) + self.ui.completeness_ignore_pregap.setChecked(config.setting['completeness_ignore_pregap']) + self.ui.completeness_ignore_data.setChecked(config.setting['completeness_ignore_data']) + self.ui.completeness_ignore_silence.setChecked(config.setting['completeness_ignore_silence']) + self.ui.compare_ignore_tags.update(config.setting['compare_ignore_tags']) self.ui.compare_ignore_tags.set_user_sortable(False) def save(self): config = get_config() - config.setting["ignore_regex"] = self.ui.ignore_regex.text() - config.setting["ignore_hidden_files"] = self.ui.ignore_hidden_files.isChecked() - config.setting["recursively_add_files"] = self.ui.recursively_add_files.isChecked() - config.setting["ignore_track_duration_difference_under"] = self.ui.ignore_track_duration_difference_under.value() - config.setting["query_limit"] = self.ui.query_limit.currentText() - config.setting["completeness_ignore_videos"] = self.ui.completeness_ignore_videos.isChecked() - config.setting["completeness_ignore_pregap"] = self.ui.completeness_ignore_pregap.isChecked() - config.setting["completeness_ignore_data"] = self.ui.completeness_ignore_data.isChecked() - config.setting["completeness_ignore_silence"] = self.ui.completeness_ignore_silence.isChecked() + config.setting['ignore_regex'] = self.ui.ignore_regex.text() + config.setting['ignore_hidden_files'] = self.ui.ignore_hidden_files.isChecked() + config.setting['recursively_add_files'] = self.ui.recursively_add_files.isChecked() + config.setting['ignore_track_duration_difference_under'] = self.ui.ignore_track_duration_difference_under.value() + config.setting['query_limit'] = self.ui.query_limit.currentText() + config.setting['completeness_ignore_videos'] = self.ui.completeness_ignore_videos.isChecked() + config.setting['completeness_ignore_pregap'] = self.ui.completeness_ignore_pregap.isChecked() + config.setting['completeness_ignore_data'] = self.ui.completeness_ignore_data.isChecked() + config.setting['completeness_ignore_silence'] = self.ui.completeness_ignore_silence.isChecked() tags = list(self.ui.compare_ignore_tags.tags) - if tags != config.setting["compare_ignore_tags"]: - config.setting["compare_ignore_tags"] = tags + if tags != config.setting['compare_ignore_tags']: + config.setting['compare_ignore_tags'] = tags def restore_defaults(self): self.ui.compare_ignore_tags.clear() diff --git a/picard/ui/options/cdlookup.py b/picard/ui/options/cdlookup.py index 556b0d2aba..253d53ec8e 100644 --- a/picard/ui/options/cdlookup.py +++ b/picard/ui/options/cdlookup.py @@ -48,15 +48,15 @@ class CDLookupOptionsPage(OptionsPage): - NAME = "cdlookup" + NAME = 'cdlookup' TITLE = N_("CD Lookup") PARENT = None SORT_ORDER = 50 ACTIVE = True - HELP_URL = '/config/options_cdlookup.html' + HELP_URL = "/config/options_cdlookup.html" options = [ - TextOption("setting", "cd_lookup_device", ",".join(DEFAULT_DRIVES)), + TextOption('setting', 'cd_lookup_device', ','.join(DEFAULT_DRIVES)), ] def __init__(self, parent=None): @@ -69,7 +69,7 @@ def __init__(self, parent=None): def load(self): config = get_config() - device = config.setting["cd_lookup_device"] + device = config.setting['cd_lookup_device'] if AUTO_DETECT_DRIVES: try: self.ui.cd_lookup_device.setCurrentIndex(self._device_list.index(device)) @@ -86,7 +86,7 @@ def save(self): else: device = self.ui.cd_lookup_device.text() device_list = [device] - config.setting["cd_lookup_device"] = device + config.setting['cd_lookup_device'] = device self.tagger.window.update_cd_lookup_drives(device_list) diff --git a/picard/ui/options/cover.py b/picard/ui/options/cover.py index d38a9cb42b..862c037e33 100644 --- a/picard/ui/options/cover.py +++ b/picard/ui/options/cover.py @@ -48,22 +48,22 @@ class CoverOptionsPage(OptionsPage): - NAME = "cover" + NAME = 'cover' TITLE = N_("Cover Art") PARENT = None SORT_ORDER = 35 ACTIVE = True - HELP_URL = '/config/options_cover.html' + HELP_URL = "/config/options_cover.html" options = [ - BoolOption("setting", "save_images_to_tags", True), - BoolOption("setting", "embed_only_one_front_image", True), - BoolOption("setting", "save_images_to_files", False), - TextOption("setting", "cover_image_filename", DEFAULT_COVER_IMAGE_FILENAME), - BoolOption("setting", "save_images_overwrite", False), - BoolOption("setting", "save_only_one_front_image", False), - BoolOption("setting", "image_type_as_filename", False), - ListOption("setting", "ca_providers", [ + BoolOption('setting', 'save_images_to_tags', True), + BoolOption('setting', 'embed_only_one_front_image', True), + BoolOption('setting', 'save_images_to_files', False), + TextOption('setting', 'cover_image_filename', DEFAULT_COVER_IMAGE_FILENAME), + BoolOption('setting', 'save_images_overwrite', False), + BoolOption('setting', 'save_only_one_front_image', False), + BoolOption('setting', 'image_type_as_filename', False), + ListOption('setting', 'ca_providers', [ ('Cover Art Archive', True), ('UrlRelationships', True), ('CaaReleaseGroup', True), @@ -97,13 +97,13 @@ def _load_cover_art_providers(self): def load(self): config = get_config() - self.ui.save_images_to_tags.setChecked(config.setting["save_images_to_tags"]) - self.ui.cb_embed_front_only.setChecked(config.setting["embed_only_one_front_image"]) - self.ui.save_images_to_files.setChecked(config.setting["save_images_to_files"]) - self.ui.cover_image_filename.setText(config.setting["cover_image_filename"]) - self.ui.save_images_overwrite.setChecked(config.setting["save_images_overwrite"]) - self.ui.save_only_one_front_image.setChecked(config.setting["save_only_one_front_image"]) - self.ui.image_type_as_filename.setChecked(config.setting["image_type_as_filename"]) + self.ui.save_images_to_tags.setChecked(config.setting['save_images_to_tags']) + self.ui.cb_embed_front_only.setChecked(config.setting['embed_only_one_front_image']) + self.ui.save_images_to_files.setChecked(config.setting['save_images_to_files']) + self.ui.cover_image_filename.setText(config.setting['cover_image_filename']) + self.ui.save_images_overwrite.setChecked(config.setting['save_images_overwrite']) + self.ui.save_only_one_front_image.setChecked(config.setting['save_only_one_front_image']) + self.ui.image_type_as_filename.setChecked(config.setting['image_type_as_filename']) self._load_cover_art_providers() self.ui.ca_providers_list.setCurrentRow(0) self.update_ca_providers_groupbox_state() @@ -114,14 +114,14 @@ def _ca_providers(self): def save(self): config = get_config() - config.setting["save_images_to_tags"] = self.ui.save_images_to_tags.isChecked() - config.setting["embed_only_one_front_image"] = self.ui.cb_embed_front_only.isChecked() - config.setting["save_images_to_files"] = self.ui.save_images_to_files.isChecked() - config.setting["cover_image_filename"] = self.ui.cover_image_filename.text() - config.setting["save_images_overwrite"] = self.ui.save_images_overwrite.isChecked() - config.setting["save_only_one_front_image"] = self.ui.save_only_one_front_image.isChecked() - config.setting["image_type_as_filename"] = self.ui.image_type_as_filename.isChecked() - config.setting["ca_providers"] = list(self._ca_providers()) + config.setting['save_images_to_tags'] = self.ui.save_images_to_tags.isChecked() + config.setting['embed_only_one_front_image'] = self.ui.cb_embed_front_only.isChecked() + config.setting['save_images_to_files'] = self.ui.save_images_to_files.isChecked() + config.setting['cover_image_filename'] = self.ui.cover_image_filename.text() + config.setting['save_images_overwrite'] = self.ui.save_images_overwrite.isChecked() + config.setting['save_only_one_front_image'] = self.ui.save_only_one_front_image.isChecked() + config.setting['image_type_as_filename'] = self.ui.image_type_as_filename.isChecked() + config.setting['ca_providers'] = list(self._ca_providers()) def update_ca_providers_groupbox_state(self): files_enabled = self.ui.save_images_to_files.isChecked() diff --git a/picard/ui/options/dialog.py b/picard/ui/options/dialog.py index 9ef978bbfd..c73b20da95 100644 --- a/picard/ui/options/dialog.py +++ b/picard/ui/options/dialog.py @@ -92,8 +92,8 @@ class OptionsDialog(PicardDialog, SingletonDialog): options = [ - TextOption("persist", "options_last_active_page", ""), - ListOption("persist", "options_pages_tree_state", []), + TextOption('persist', 'options_last_active_page', ''), + ListOption('persist', 'options_pages_tree_state', []), ] suspend_signals = False @@ -159,12 +159,12 @@ def __init__(self, default_page=None, parent=None): page.set_dialog(self) self.pages.append(page) except Exception: - log.exception('Failed initializing options page %r', Page) + log.exception("Failed initializing options page %r", Page) self.item_to_page = {} self.page_to_item = {} self.default_item = None if not default_page: - default_page = config.persist["options_last_active_page"] + default_page = config.persist['options_last_active_page'] self.add_pages(None, default_page, self.ui.pages_tree) # work-around to set optimal option pane width @@ -200,7 +200,7 @@ def load_all_pages(self): try: page.load() except Exception: - log.exception('Failed loading options page %r', page) + log.exception("Failed loading options page %r", page) self.disable_page(page.NAME) def page_has_profile_options(self, page): @@ -241,8 +241,8 @@ def show_attached_profiles_dialog(self): def _get_profile_title_from_id(self, profile_id): config = get_config() for item in config.profiles[SettingConfigSection.PROFILES_KEY]: - if item["id"] == profile_id: - return item["title"] + if item['id'] == profile_id: + return item['title'] return _('Unknown profile') def update_from_profile_changes(self): @@ -285,9 +285,9 @@ def _check_and_highlight_option(self, obj, option_name, working_profiles, workin obj.setStyleSheet(None) obj.setToolTip(None) for item in working_profiles: - if item["enabled"]: - profile_id = item["id"] - profile_title = item["title"] + if item['enabled']: + profile_id = item['id'] + profile_title = item['title'] if profile_id in working_settings: profile_settings = working_settings[profile_id] else: @@ -325,7 +325,7 @@ def page_has_attached_profiles(self, page, enabled_profiles_only=False): for item in working_profiles: if enabled_profiles_only and not item["enabled"]: continue - profile_id = item["id"] + profile_id = item['id'] if opt.name in working_settings[profile_id]: return True return False @@ -342,7 +342,7 @@ def switch_page(self): if items: config = get_config() page = self.item_to_page[items[0]] - config.persist["options_last_active_page"] = page.NAME + config.persist['options_last_active_page'] = page.NAME self.set_profiles_button_and_highlight(page) def disable_page(self, name): @@ -369,7 +369,7 @@ def accept(self): self._show_page_error(page, e) return except Exception as e: - log.exception('Failed checking options page %r', page) + log.exception("Failed checking options page %r", page) self._show_page_error(page, e) return self.profile_page.save() @@ -378,14 +378,14 @@ def accept(self): if page != self.profile_page: page.save() except Exception as e: - log.exception('Failed saving options page %r', page) + log.exception("Failed saving options page %r", page) self._show_page_error(page, e) return super().accept() def _show_page_error(self, page, error): if not isinstance(error, OptionsCheckError): - error = OptionsCheckError(_('Unexpected error'), str(error)) + error = OptionsCheckError(_("Unexpected error"), str(error)) self.ui.pages_tree.setCurrentItem(self.page_to_item[page.NAME]) page.display_error(error) @@ -396,14 +396,14 @@ def saveWindowState(self): is_expanded = self.ui.pages_tree.isExpanded(index) expanded_pages.append((page, is_expanded)) config = get_config() - config.persist["options_pages_tree_state"] = expanded_pages + config.persist['options_pages_tree_state'] = expanded_pages config.setting.set_profiles_override() config.setting.set_settings_override() @restore_method def restoreWindowState(self): config = get_config() - pages_tree_state = config.persist["options_pages_tree_state"] + pages_tree_state = config.persist['options_pages_tree_state'] if not pages_tree_state: self.ui.pages_tree.expandAll() else: @@ -420,7 +420,7 @@ def restore_all_defaults(self): try: page.restore_defaults() except Exception as e: - log.error('Failed restoring all defaults for page %r: %s', page, e) + log.error("Failed restoring all defaults for page %r: %s", page, e) self.highlight_enabled_profile_options(load_settings=False) self.suspend_signals = False @@ -449,7 +449,7 @@ def _show_dialog(self, msg, function): class AttachedProfilesDialog(PicardDialog): NAME = 'attachedprofiles' - TITLE = N_('Attached Profiles') + TITLE = N_("Attached Profiles") def __init__(self, parent=None, option_group=None, override_profiles=None, override_settings=None): super().__init__(parent=parent) @@ -479,8 +479,8 @@ def populate_table(self): model.setHorizontalHeaderLabels(header_names) group = UserProfileGroups.SETTINGS_GROUPS[self.option_group] - group_title = group["title"] - group_options = group["settings"] + group_title = group['title'] + group_options = group['settings'] window_title = _("Profiles Attached to Options in %s Section") % group_title self.setWindowTitle(window_title) @@ -491,8 +491,8 @@ def populate_table(self): row = [option_item] attached = [] for profile in self.profiles: - if name in self.settings[profile["id"]]: - attached.append("{0}{1}".format(profile["title"], _(" [Enabled]") if profile["enabled"] else "",)) + if name in self.settings[profile['id']]: + attached.append("{0}{1}".format(profile['title'], _(" [Enabled]") if profile['enabled'] else "",)) attached_profiles = "\n".join(attached) if attached else _("None") profile_item = QtGui.QStandardItem(attached_profiles) profile_item.setEditable(False) diff --git a/picard/ui/options/fingerprinting.py b/picard/ui/options/fingerprinting.py index 719974c327..c84b727d89 100644 --- a/picard/ui/options/fingerprinting.py +++ b/picard/ui/options/fingerprinting.py @@ -59,20 +59,20 @@ def validate(self, input, pos): class FingerprintingOptionsPage(OptionsPage): - NAME = "fingerprinting" + NAME = 'fingerprinting' TITLE = N_("Fingerprinting") PARENT = None SORT_ORDER = 45 ACTIVE = True - HELP_URL = '/config/options_fingerprinting.html' + HELP_URL = "/config/options_fingerprinting.html" options = [ - BoolOption("setting", "ignore_existing_acoustid_fingerprints", False), - BoolOption("setting", "save_acoustid_fingerprints", False), - TextOption("setting", "fingerprinting_system", "acoustid"), - TextOption("setting", "acoustid_fpcalc", ""), - TextOption("setting", "acoustid_apikey", ""), - IntOption("setting", "fpcalc_threads", DEFAULT_FPCALC_THREADS), + BoolOption('setting', 'ignore_existing_acoustid_fingerprints', False), + BoolOption('setting', 'save_acoustid_fingerprints', False), + TextOption('setting', 'fingerprinting_system', 'acoustid'), + TextOption('setting', 'acoustid_fpcalc', ''), + TextOption('setting', 'acoustid_apikey', ''), + IntOption('setting', 'fpcalc_threads', DEFAULT_FPCALC_THREADS), ] def __init__(self, parent=None): @@ -90,29 +90,29 @@ def __init__(self, parent=None): def load(self): config = get_config() - if config.setting["fingerprinting_system"] == "acoustid": + if config.setting['fingerprinting_system'] == 'acoustid': self.ui.use_acoustid.setChecked(True) else: self.ui.disable_fingerprinting.setChecked(True) self.ui.acoustid_fpcalc.setPlaceholderText(find_fpcalc()) - self.ui.acoustid_fpcalc.setText(config.setting["acoustid_fpcalc"]) - self.ui.acoustid_apikey.setText(config.setting["acoustid_apikey"]) - self.ui.ignore_existing_acoustid_fingerprints.setChecked(config.setting["ignore_existing_acoustid_fingerprints"]) - self.ui.save_acoustid_fingerprints.setChecked(config.setting["save_acoustid_fingerprints"]) - self.ui.fpcalc_threads.setValue(config.setting["fpcalc_threads"]) + self.ui.acoustid_fpcalc.setText(config.setting['acoustid_fpcalc']) + self.ui.acoustid_apikey.setText(config.setting['acoustid_apikey']) + self.ui.ignore_existing_acoustid_fingerprints.setChecked(config.setting['ignore_existing_acoustid_fingerprints']) + self.ui.save_acoustid_fingerprints.setChecked(config.setting['save_acoustid_fingerprints']) + self.ui.fpcalc_threads.setValue(config.setting['fpcalc_threads']) self.update_groupboxes() def save(self): config = get_config() if self.ui.use_acoustid.isChecked(): - config.setting["fingerprinting_system"] = "acoustid" + config.setting['fingerprinting_system'] = 'acoustid' else: - config.setting["fingerprinting_system"] = "" - config.setting["acoustid_fpcalc"] = self.ui.acoustid_fpcalc.text() - config.setting["acoustid_apikey"] = self.ui.acoustid_apikey.text() - config.setting["ignore_existing_acoustid_fingerprints"] = self.ui.ignore_existing_acoustid_fingerprints.isChecked() - config.setting["save_acoustid_fingerprints"] = self.ui.save_acoustid_fingerprints.isChecked() - config.setting["fpcalc_threads"] = self.ui.fpcalc_threads.value() + config.setting['fingerprinting_system'] = '' + config.setting['acoustid_fpcalc'] = self.ui.acoustid_fpcalc.text() + config.setting['acoustid_apikey'] = self.ui.acoustid_apikey.text() + config.setting['ignore_existing_acoustid_fingerprints'] = self.ui.ignore_existing_acoustid_fingerprints.isChecked() + config.setting['save_acoustid_fingerprints'] = self.ui.save_acoustid_fingerprints.isChecked() + config.setting['fpcalc_threads'] = self.ui.fpcalc_threads.value() def update_groupboxes(self): if self.ui.use_acoustid.isChecked(): diff --git a/picard/ui/options/general.py b/picard/ui/options/general.py index eeb64ba427..f358ce6b32 100644 --- a/picard/ui/options/general.py +++ b/picard/ui/options/general.py @@ -52,30 +52,30 @@ class GeneralOptionsPage(OptionsPage): - NAME = "general" + NAME = 'general' TITLE = N_("General") PARENT = None SORT_ORDER = 1 ACTIVE = True - HELP_URL = '/config/options_general.html' + HELP_URL = "/config/options_general.html" options = [ - TextOption("setting", "server_host", MUSICBRAINZ_SERVERS[0]), - IntOption("setting", "server_port", 443), - BoolOption("setting", "use_server_for_submission", False), - BoolOption("setting", "analyze_new_files", False), - BoolOption("setting", "cluster_new_files", False), - BoolOption("setting", "ignore_file_mbids", False), - TextOption("persist", "oauth_refresh_token", ""), - TextOption("persist", "oauth_refresh_token_scopes", ""), - TextOption("persist", "oauth_access_token", ""), - IntOption("persist", "oauth_access_token_expires", 0), - TextOption("persist", "oauth_username", ""), - BoolOption("setting", "check_for_updates", True), - IntOption("setting", "update_check_days", 7), - IntOption("setting", "update_level", DEFAULT_PROGRAM_UPDATE_LEVEL), - IntOption("persist", "last_update_check", 0), - BoolOption("setting", "check_for_plugin_updates", False), + TextOption('setting', 'server_host', MUSICBRAINZ_SERVERS[0]), + IntOption('setting', 'server_port', 443), + BoolOption('setting', 'use_server_for_submission', False), + BoolOption('setting', 'analyze_new_files', False), + BoolOption('setting', 'cluster_new_files', False), + BoolOption('setting', 'ignore_file_mbids', False), + TextOption('persist', 'oauth_refresh_token', ''), + TextOption('persist', 'oauth_refresh_token_scopes', ''), + TextOption('persist', 'oauth_access_token', ''), + IntOption('persist', 'oauth_access_token_expires', 0), + TextOption('persist', 'oauth_username', ''), + BoolOption('setting', 'check_for_updates', True), + IntOption('setting', 'update_check_days', 7), + IntOption('setting', 'update_level', DEFAULT_PROGRAM_UPDATE_LEVEL), + IntOption('persist', 'last_update_check', 0), + BoolOption('setting', 'check_for_plugin_updates', False), ] def __init__(self, parent=None): @@ -94,17 +94,17 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.server_host.setEditText(config.setting["server_host"]) - self.ui.server_port.setValue(config.setting["server_port"]) - self.ui.use_server_for_submission.setChecked(config.setting["use_server_for_submission"]) + self.ui.server_host.setEditText(config.setting['server_host']) + self.ui.server_port.setValue(config.setting['server_port']) + self.ui.use_server_for_submission.setChecked(config.setting['use_server_for_submission']) self.update_server_host() - self.ui.analyze_new_files.setChecked(config.setting["analyze_new_files"]) - self.ui.cluster_new_files.setChecked(config.setting["cluster_new_files"]) - self.ui.ignore_file_mbids.setChecked(config.setting["ignore_file_mbids"]) - self.ui.check_for_plugin_updates.setChecked(config.setting["check_for_plugin_updates"]) - self.ui.check_for_updates.setChecked(config.setting["check_for_updates"]) - self.set_update_level(config.setting["update_level"]) - self.ui.update_check_days.setValue(config.setting["update_check_days"]) + self.ui.analyze_new_files.setChecked(config.setting['analyze_new_files']) + self.ui.cluster_new_files.setChecked(config.setting['cluster_new_files']) + self.ui.ignore_file_mbids.setChecked(config.setting['ignore_file_mbids']) + self.ui.check_for_plugin_updates.setChecked(config.setting['check_for_plugin_updates']) + self.ui.check_for_updates.setChecked(config.setting['check_for_updates']) + self.set_update_level(config.setting['update_level']) + self.ui.update_check_days.setValue(config.setting['update_check_days']) if not self.tagger.autoupdate_enabled: self.ui.program_update_check_group.hide() @@ -123,16 +123,16 @@ def set_update_level(self, value): def save(self): config = get_config() - config.setting["server_host"] = self.ui.server_host.currentText().strip() - config.setting["server_port"] = self.ui.server_port.value() - config.setting["use_server_for_submission"] = self.ui.use_server_for_submission.isChecked() - config.setting["analyze_new_files"] = self.ui.analyze_new_files.isChecked() - config.setting["cluster_new_files"] = self.ui.cluster_new_files.isChecked() - config.setting["ignore_file_mbids"] = self.ui.ignore_file_mbids.isChecked() - config.setting["check_for_plugin_updates"] = self.ui.check_for_plugin_updates.isChecked() - config.setting["check_for_updates"] = self.ui.check_for_updates.isChecked() - config.setting["update_level"] = self.ui.update_level.currentData(QtCore.Qt.ItemDataRole.UserRole) - config.setting["update_check_days"] = self.ui.update_check_days.value() + config.setting['server_host'] = self.ui.server_host.currentText().strip() + config.setting['server_port'] = self.ui.server_port.value() + config.setting['use_server_for_submission'] = self.ui.use_server_for_submission.isChecked() + config.setting['analyze_new_files'] = self.ui.analyze_new_files.isChecked() + config.setting['cluster_new_files'] = self.ui.cluster_new_files.isChecked() + config.setting['ignore_file_mbids'] = self.ui.ignore_file_mbids.isChecked() + config.setting['check_for_plugin_updates'] = self.ui.check_for_plugin_updates.isChecked() + config.setting['check_for_updates'] = self.ui.check_for_updates.isChecked() + config.setting['update_level'] = self.ui.update_level.currentData(QtCore.Qt.ItemDataRole.UserRole) + config.setting['update_check_days'] = self.ui.update_check_days.value() def update_server_host(self): host = self.ui.server_host.currentText().strip() @@ -146,14 +146,14 @@ def update_login_logout(self, error_msg=None): return if self.tagger.webservice.oauth_manager.is_logged_in(): config = get_config() - self.ui.logged_in.setText(_("Logged in as %s.") % config.persist["oauth_username"]) + self.ui.logged_in.setText(_("Logged in as %s.") % config.persist['oauth_username']) self.ui.logged_in.show() self.ui.login_error.hide() self.ui.login.hide() self.ui.logout.show() elif error_msg: self.ui.logged_in.hide() - self.ui.login_error.setText(_('Login failed: %s') % error_msg) + self.ui.login_error.setText(_("Login failed: %s") % error_msg) self.ui.login_error.show() self.ui.login.show() self.ui.logout.hide() diff --git a/picard/ui/options/genres.py b/picard/ui/options/genres.py index 2ca99ceeaa..629b8c3427 100644 --- a/picard/ui/options/genres.py +++ b/picard/ui/options/genres.py @@ -83,22 +83,22 @@ class GenresOptionsPage(OptionsPage): - NAME = "genres" + NAME = 'genres' TITLE = N_("Genres") - PARENT = "metadata" + PARENT = 'metadata' SORT_ORDER = 20 ACTIVE = True - HELP_URL = '/config/options_genres.html' + HELP_URL = "/config/options_genres.html" options = [ - BoolOption("setting", "use_genres", False), - IntOption("setting", "max_genres", 5), - IntOption("setting", "min_genre_usage", 90), - TextOption("setting", "genres_filter", "-seen live\n-favorites\n-fixme\n-owned"), - TextOption("setting", "join_genres", ""), - BoolOption("setting", "only_my_genres", False), - BoolOption("setting", "artists_genres", False), - BoolOption("setting", "folksonomy_tags", False), + BoolOption('setting', 'use_genres', False), + IntOption('setting', 'max_genres', 5), + IntOption('setting', 'min_genre_usage', 90), + TextOption('setting', 'genres_filter', '-seen live\n-favorites\n-fixme\n-owned'), + TextOption('setting', 'join_genres', ''), + BoolOption('setting', 'only_my_genres', False), + BoolOption('setting', 'artists_genres', False), + BoolOption('setting', 'folksonomy_tags', False), ] def __init__(self, parent=None): @@ -124,7 +124,7 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.use_genres.setChecked(config.setting["use_genres"]) + self.ui.use_genres.setChecked(config.setting['use_genres']) self.ui.max_genres.setValue(config.setting["max_genres"]) self.ui.min_genre_usage.setValue(config.setting["min_genre_usage"]) self.ui.join_genres.setEditText(config.setting["join_genres"]) @@ -135,14 +135,14 @@ def load(self): def save(self): config = get_config() - config.setting["use_genres"] = self.ui.use_genres.isChecked() - config.setting["max_genres"] = self.ui.max_genres.value() - config.setting["min_genre_usage"] = self.ui.min_genre_usage.value() - config.setting["join_genres"] = self.ui.join_genres.currentText() - config.setting["genres_filter"] = self.ui.genres_filter.toPlainText() - config.setting["only_my_genres"] = self.ui.only_my_genres.isChecked() - config.setting["artists_genres"] = self.ui.artists_genres.isChecked() - config.setting["folksonomy_tags"] = self.ui.folksonomy_tags.isChecked() + config.setting['use_genres'] = self.ui.use_genres.isChecked() + config.setting['max_genres'] = self.ui.max_genres.value() + config.setting['min_genre_usage'] = self.ui.min_genre_usage.value() + config.setting['join_genres'] = self.ui.join_genres.currentText() + config.setting['genres_filter'] = self.ui.genres_filter.toPlainText() + config.setting['only_my_genres'] = self.ui.only_my_genres.isChecked() + config.setting['artists_genres'] = self.ui.artists_genres.isChecked() + config.setting['folksonomy_tags'] = self.ui.folksonomy_tags.isChecked() def update_test_genres_filter(self): test_text = self.ui.test_genres_filter.toPlainText() diff --git a/picard/ui/options/interface.py b/picard/ui/options/interface.py index 3527b9dc64..1ddb50bab5 100644 --- a/picard/ui/options/interface.py +++ b/picard/ui/options/interface.py @@ -63,47 +63,47 @@ class InterfaceOptionsPage(OptionsPage): - NAME = "interface" + NAME = 'interface' TITLE = N_("User Interface") PARENT = None SORT_ORDER = 80 ACTIVE = True - HELP_URL = '/config/options_interface.html' + HELP_URL = "/config/options_interface.html" options = [ - BoolOption("setting", "toolbar_show_labels", True), - BoolOption("setting", "toolbar_multiselect", False), - BoolOption("setting", "show_menu_icons", True if not IS_MACOS else False), # On macOS it is not common that the global menu shows icons - BoolOption("setting", "builtin_search", True), - BoolOption("setting", "use_adv_search_syntax", False), - BoolOption("setting", "show_new_user_dialog", True), - BoolOption("setting", "quit_confirmation", True), - BoolOption("setting", "file_save_warning", True), - TextOption("setting", "ui_language", ""), - TextOption("setting", "ui_theme", str(UiTheme.DEFAULT)), - BoolOption("setting", "filebrowser_horizontal_autoscroll", True), - BoolOption("setting", "starting_directory", False), - TextOption("setting", "starting_directory_path", _default_starting_dir), - TextOption("setting", "load_image_behavior", "append"), + BoolOption('setting', 'toolbar_show_labels', True), + BoolOption('setting', 'toolbar_multiselect', False), + BoolOption('setting', 'show_menu_icons', True if not IS_MACOS else False), # On macOS it is not common that the global menu shows icons + BoolOption('setting', 'builtin_search', True), + BoolOption('setting', 'use_adv_search_syntax', False), + BoolOption('setting', 'show_new_user_dialog', True), + BoolOption('setting', 'quit_confirmation', True), + BoolOption('setting', 'file_save_warning', True), + TextOption('setting', 'ui_language', ''), + TextOption('setting', 'ui_theme', str(UiTheme.DEFAULT)), + BoolOption('setting', 'filebrowser_horizontal_autoscroll', True), + BoolOption('setting', 'starting_directory', False), + TextOption('setting', 'starting_directory_path', _default_starting_dir), + TextOption('setting', 'load_image_behavior', 'append'), ] # Those are labels for theme display _UI_THEME_LABELS = { UiTheme.DEFAULT: { - 'label': N_('Default'), - 'desc': N_('The default color scheme based on the operating system display settings'), + 'label': N_("Default"), + 'desc': N_("The default color scheme based on the operating system display settings"), }, UiTheme.DARK: { - 'label': N_('Dark'), - 'desc': N_('A dark display theme'), + 'label': N_("Dark"), + 'desc': N_("A dark display theme"), }, UiTheme.LIGHT: { - 'label': N_('Light'), - 'desc': N_('A light display theme'), + 'label': N_("Light"), + 'desc': N_("A light display theme"), }, UiTheme.SYSTEM: { - 'label': N_('System'), - 'desc': N_('The Qt5 theme configured in the desktop environment'), + 'label': N_("System"), + 'desc': N_("The Qt5 theme configured in the desktop environment"), }, } @@ -121,7 +121,7 @@ def __init__(self, parent=None): self.ui.ui_theme.setItemData(idx, _(desc), QtCore.Qt.ItemDataRole.ToolTipRole) self.ui.ui_theme.setCurrentIndex(self.ui.ui_theme.findData(UiTheme.DEFAULT)) - self.ui.ui_language.addItem(_('System default'), '') + self.ui.ui_language.addItem(_("System default"), '') language_list = [(lang[0], lang[1], gettext_constants(lang[2])) for lang in UI_LANGUAGES] def fcmp(x): @@ -145,48 +145,48 @@ def fcmp(x): def load(self): config = get_config() - self.ui.toolbar_show_labels.setChecked(config.setting["toolbar_show_labels"]) - self.ui.toolbar_multiselect.setChecked(config.setting["toolbar_multiselect"]) - self.ui.show_menu_icons.setChecked(config.setting["show_menu_icons"]) - self.ui.builtin_search.setChecked(config.setting["builtin_search"]) - self.ui.use_adv_search_syntax.setChecked(config.setting["use_adv_search_syntax"]) - self.ui.new_user_dialog.setChecked(config.setting["show_new_user_dialog"]) - self.ui.quit_confirmation.setChecked(config.setting["quit_confirmation"]) - self.ui.file_save_warning.setChecked(config.setting["file_save_warning"]) - current_ui_language = config.setting["ui_language"] + self.ui.toolbar_show_labels.setChecked(config.setting['toolbar_show_labels']) + self.ui.toolbar_multiselect.setChecked(config.setting['toolbar_multiselect']) + self.ui.show_menu_icons.setChecked(config.setting['show_menu_icons']) + self.ui.builtin_search.setChecked(config.setting['builtin_search']) + self.ui.use_adv_search_syntax.setChecked(config.setting['use_adv_search_syntax']) + self.ui.new_user_dialog.setChecked(config.setting['show_new_user_dialog']) + self.ui.quit_confirmation.setChecked(config.setting['quit_confirmation']) + self.ui.file_save_warning.setChecked(config.setting['file_save_warning']) + current_ui_language = config.setting['ui_language'] self.ui.ui_language.setCurrentIndex(self.ui.ui_language.findData(current_ui_language)) - self.ui.filebrowser_horizontal_autoscroll.setChecked(config.setting["filebrowser_horizontal_autoscroll"]) - self.ui.starting_directory.setChecked(config.setting["starting_directory"]) - self.ui.starting_directory_path.setText(config.setting["starting_directory_path"]) - current_theme = UiTheme(config.setting["ui_theme"]) + self.ui.filebrowser_horizontal_autoscroll.setChecked(config.setting['filebrowser_horizontal_autoscroll']) + self.ui.starting_directory.setChecked(config.setting['starting_directory']) + self.ui.starting_directory_path.setText(config.setting['starting_directory_path']) + current_theme = UiTheme(config.setting['ui_theme']) self.ui.ui_theme.setCurrentIndex(self.ui.ui_theme.findData(current_theme)) def save(self): config = get_config() - config.setting["toolbar_show_labels"] = self.ui.toolbar_show_labels.isChecked() - config.setting["toolbar_multiselect"] = self.ui.toolbar_multiselect.isChecked() - config.setting["show_menu_icons"] = self.ui.show_menu_icons.isChecked() - self.tagger.enable_menu_icons(config.setting["show_menu_icons"]) - config.setting["builtin_search"] = self.ui.builtin_search.isChecked() - config.setting["use_adv_search_syntax"] = self.ui.use_adv_search_syntax.isChecked() - config.setting["show_new_user_dialog"] = self.ui.new_user_dialog.isChecked() - config.setting["quit_confirmation"] = self.ui.quit_confirmation.isChecked() - config.setting["file_save_warning"] = self.ui.file_save_warning.isChecked() + config.setting['toolbar_show_labels'] = self.ui.toolbar_show_labels.isChecked() + config.setting['toolbar_multiselect'] = self.ui.toolbar_multiselect.isChecked() + config.setting['show_menu_icons'] = self.ui.show_menu_icons.isChecked() + self.tagger.enable_menu_icons(config.setting['show_menu_icons']) + config.setting['builtin_search'] = self.ui.builtin_search.isChecked() + config.setting['use_adv_search_syntax'] = self.ui.use_adv_search_syntax.isChecked() + config.setting['show_new_user_dialog'] = self.ui.new_user_dialog.isChecked() + config.setting['quit_confirmation'] = self.ui.quit_confirmation.isChecked() + config.setting['file_save_warning'] = self.ui.file_save_warning.isChecked() self.tagger.window.update_toolbar_style() new_theme_setting = str(self.ui.ui_theme.itemData(self.ui.ui_theme.currentIndex())) new_language = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()) restart_warning = None - if new_theme_setting != config.setting["ui_theme"]: - restart_warning_title = _('Theme changed') - restart_warning = _('You have changed the application theme. You have to restart Picard in order for the change to take effect.') + if new_theme_setting != config.setting['ui_theme']: + restart_warning_title = _("Theme changed") + restart_warning = _("You have changed the application theme. You have to restart Picard in order for the change to take effect.") if new_theme_setting == str(UiTheme.SYSTEM): restart_warning += '\n\n' + _( - 'Please note that using the system theme might cause the user interface to be not shown correctly. ' - 'If this is the case select the "Default" theme option to use Picard\'s default theme again.' + "Please note that using the system theme might cause the user interface to be not shown correctly. " + "If this is the case select the `Default` theme option to use Picard's default theme again." ) - elif new_language != config.setting["ui_language"]: - restart_warning_title = _('Language changed') - restart_warning = _('You have changed the interface language. You have to restart Picard in order for the change to take effect.') + elif new_language != config.setting['ui_language']: + restart_warning_title = _("Language changed") + restart_warning = _("You have changed the interface language. You have to restart Picard in order for the change to take effect.") if restart_warning: dialog = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Icon.Information, @@ -195,11 +195,11 @@ def save(self): QtWidgets.QMessageBox.StandardButton.Ok, self) dialog.exec_() - config.setting["ui_theme"] = new_theme_setting - config.setting["ui_language"] = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()) - config.setting["filebrowser_horizontal_autoscroll"] = self.ui.filebrowser_horizontal_autoscroll.isChecked() - config.setting["starting_directory"] = self.ui.starting_directory.isChecked() - config.setting["starting_directory_path"] = os.path.normpath(self.ui.starting_directory_path.text()) + config.setting['ui_theme'] = new_theme_setting + config.setting['ui_language'] = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()) + config.setting['filebrowser_horizontal_autoscroll'] = self.ui.filebrowser_horizontal_autoscroll.isChecked() + config.setting['starting_directory'] = self.ui.starting_directory.isChecked() + config.setting['starting_directory_path'] = os.path.normpath(self.ui.starting_directory_path.text()) def starting_directory_browse(self): item = self.ui.starting_directory_path diff --git a/picard/ui/options/interface_colors.py b/picard/ui/options/interface_colors.py index ebace8767a..b92859d553 100644 --- a/picard/ui/options/interface_colors.py +++ b/picard/ui/options/interface_colors.py @@ -54,7 +54,7 @@ def __init__(self, initial_color=None, parent=None): self.setStyle(QtWidgets.QStyleFactory.create('macintosh')) color = QtGui.QColor(initial_color) if not color.isValid(): - color = QtGui.QColor("black") + color = QtGui.QColor('black') self.color = color self.clicked.connect(self.open_color_dialog) self.update_color() @@ -88,16 +88,16 @@ def delete_items_of_layout(layout): class InterfaceColorsOptionsPage(OptionsPage): - NAME = "interface_colors" + NAME = 'interface_colors' TITLE = N_("Colors") - PARENT = "interface" + PARENT = 'interface' SORT_ORDER = 30 ACTIVE = True - HELP_URL = '/config/options_interface_colors.html' + HELP_URL = "/config/options_interface_colors.html" options = [ - Option("setting", "interface_colors", InterfaceColors(dark_theme=False).get_colors()), - Option("setting", "interface_colors_dark", InterfaceColors(dark_theme=True).get_colors()), + Option('setting', 'interface_colors', InterfaceColors(dark_theme=False).get_colors()), + Option('setting', 'interface_colors_dark', InterfaceColors(dark_theme=True).get_colors()), ] def __init__(self, parent=None): @@ -143,8 +143,8 @@ def save(self): if interface_colors.save_to_config(): dialog = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Icon.Information, - _('Colors changed'), - _('You have changed the interface colors. You may have to restart Picard in order for the changes to take effect.'), + _("Colors changed"), + _("You have changed the interface colors. You may have to restart Picard in order for the changes to take effect."), QtWidgets.QMessageBox.StandardButton.Ok, self) dialog.exec_() diff --git a/picard/ui/options/interface_toolbar.py b/picard/ui/options/interface_toolbar.py index 43ef69fa7b..26849f17f3 100644 --- a/picard/ui/options/interface_toolbar.py +++ b/picard/ui/options/interface_toolbar.py @@ -56,52 +56,52 @@ class InterfaceToolbarOptionsPage(OptionsPage): - NAME = "interface_toolbar" + NAME = 'interface_toolbar' TITLE = N_("Action Toolbar") PARENT = 'interface' SORT_ORDER = 60 ACTIVE = True - HELP_URL = '/config/options_interface_toolbar.html' + HELP_URL = "/config/options_interface_toolbar.html" SEPARATOR = '—' * 5 TOOLBAR_BUTTONS = { 'add_directory_action': { - 'label': N_('Add Folder'), + 'label': N_("Add Folder"), 'icon': 'folder' }, 'add_files_action': { - 'label': N_('Add Files'), + 'label': N_("Add Files"), 'icon': 'document-open' }, 'cluster_action': { - 'label': N_('Cluster'), + 'label': N_("Cluster"), 'icon': 'picard-cluster' }, 'autotag_action': { - 'label': N_('Lookup'), + 'label': N_("Lookup"), 'icon': 'picard-auto-tag' }, 'analyze_action': { - 'label': N_('Scan'), + 'label': N_("Scan"), 'icon': 'picard-analyze' }, 'browser_lookup_action': { - 'label': N_('Lookup in Browser'), + 'label': N_("Lookup in Browser"), 'icon': 'lookup-musicbrainz' }, 'save_action': { - 'label': N_('Save'), + 'label': N_("Save"), 'icon': 'document-save' }, 'view_info_action': { - 'label': N_('Info'), + 'label': N_("Info"), 'icon': 'picard-edit-tags' }, 'remove_action': { - 'label': N_('Remove'), + 'label': N_("Remove"), 'icon': 'list-remove' }, 'submit_acoustid_action': { - 'label': N_('Submit AcoustIDs'), + 'label': N_("Submit AcoustIDs"), 'icon': 'acoustid-fingerprinter' }, 'generate_fingerprints_action': { @@ -109,25 +109,25 @@ class InterfaceToolbarOptionsPage(OptionsPage): 'icon': 'fingerprint' }, 'play_file_action': { - 'label': N_('Open in Player'), + 'label': N_("Open in Player"), 'icon': 'play-music' }, 'cd_lookup_action': { - 'label': N_('Lookup CD…'), + 'label': N_("Lookup CD…"), 'icon': 'media-optical' }, 'tags_from_filenames_action': { - 'label': N_('Parse File Names…'), + 'label': N_("Parse File Names…"), 'icon': 'picard-tags-from-filename' }, 'similar_items_search_action': { - 'label': N_('Similar items'), + 'label': N_("Similar items"), 'icon': 'system-search' }, } ACTION_NAMES = set(TOOLBAR_BUTTONS.keys()) options = [ - ListOption("setting", "toolbar_layout", [ + ListOption('setting', 'toolbar_layout', [ 'add_directory_action', 'add_files_action', 'separator', @@ -184,7 +184,7 @@ def _get_icon_from_name(self, name): def _insert_item(self, action, index=None): list_item = ToolbarListItem(action) - list_item.setToolTip(_('Drag and Drop to re-order')) + list_item.setToolTip(_("Drag and Drop to re-order")) if action in self.TOOLBAR_BUTTONS: # TODO: Remove temporary workaround once https://github.com/python-babel/babel/issues/415 has been resolved. babel_415_workaround = self.TOOLBAR_BUTTONS[action]['label'] diff --git a/picard/ui/options/interface_top_tags.py b/picard/ui/options/interface_top_tags.py index 049b9002d4..32a24dd3e9 100644 --- a/picard/ui/options/interface_top_tags.py +++ b/picard/ui/options/interface_top_tags.py @@ -36,21 +36,21 @@ class InterfaceTopTagsOptionsPage(OptionsPage): - NAME = "interface_top_tags" + NAME = 'interface_top_tags' TITLE = N_("Top Tags") - PARENT = "interface" + PARENT = 'interface' SORT_ORDER = 30 ACTIVE = True - HELP_URL = '/config/options_interface_top_tags.html' + HELP_URL = "/config/options_interface_top_tags.html" options = [ - ListOption("setting", "metadatabox_top_tags", [ - "title", - "artist", - "album", - "tracknumber", - "~length", - "date", + ListOption('setting', 'metadatabox_top_tags', [ + 'title', + 'artist', + 'album', + 'tracknumber', + '~length', + 'date', ]), ] @@ -61,14 +61,14 @@ def __init__(self, parent=None): def load(self): config = get_config() - tags = config.setting["metadatabox_top_tags"] + tags = config.setting['metadatabox_top_tags'] self.ui.top_tags_list.update(tags) def save(self): config = get_config() tags = list(self.ui.top_tags_list.tags) - if tags != config.setting["metadatabox_top_tags"]: - config.setting["metadatabox_top_tags"] = tags + if tags != config.setting['metadatabox_top_tags']: + config.setting['metadatabox_top_tags'] = tags self.tagger.window.metadata_box.update() def restore_defaults(self): diff --git a/picard/ui/options/maintenance.py b/picard/ui/options/maintenance.py index 150c480449..f960dd843a 100644 --- a/picard/ui/options/maintenance.py +++ b/picard/ui/options/maintenance.py @@ -60,12 +60,12 @@ class MaintenanceOptionsPage(OptionsPage): - NAME = "maintenance" + NAME = 'maintenance' TITLE = N_("Maintenance") - PARENT = "advanced" + PARENT = 'advanced' SORT_ORDER = 99 ACTIVE = True - HELP_URL = '/config/options_maintenance.html' + HELP_URL = "/config/options_maintenance.html" options = [] @@ -117,7 +117,7 @@ def load(self): current_options = OPTIONS_NOT_IN_PAGES.union(key_options) # All setting options included in the INI file. - config.beginGroup("setting") + config.beginGroup('setting') file_options = set(config.childKeys()) config.endGroup() @@ -249,7 +249,7 @@ def load_backup(self): filename, file_type = QtWidgets.QFileDialog.getOpenFileName(self, dialog_title, directory, dialog_file_types, options=options) if not filename: return - log.warning('Loading configuration from %s', filename) + log.warning("Loading configuration from %s", filename) if load_new_config(filename): config = get_config() upgrade_config(config) @@ -292,7 +292,7 @@ def save(self): to_remove = set(self.selected_options()) if to_remove and QtWidgets.QMessageBox.question( self, - _('Confirm Remove'), + _("Confirm Remove"), _("Are you sure you want to remove the selected option settings?"), ) == QtWidgets.QMessageBox.StandardButton.Yes: config = get_config() diff --git a/picard/ui/options/matching.py b/picard/ui/options/matching.py index 59cbd4a746..067de0ffad 100644 --- a/picard/ui/options/matching.py +++ b/picard/ui/options/matching.py @@ -36,17 +36,17 @@ class MatchingOptionsPage(OptionsPage): - NAME = "matching" + NAME = 'matching' TITLE = N_("Matching") - PARENT = "advanced" + PARENT = 'advanced' SORT_ORDER = 30 ACTIVE = True - HELP_URL = '/config/options_matching.html' + HELP_URL = "/config/options_matching.html" options = [ - FloatOption("setting", "file_lookup_threshold", 0.7), - FloatOption("setting", "cluster_lookup_threshold", 0.7), - FloatOption("setting", "track_matching_threshold", 0.4), + FloatOption('setting', 'file_lookup_threshold', 0.7), + FloatOption('setting', 'cluster_lookup_threshold', 0.7), + FloatOption('setting', 'track_matching_threshold', 0.4), ] _release_type_sliders = {} @@ -58,15 +58,15 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.file_lookup_threshold.setValue(int(config.setting["file_lookup_threshold"] * 100)) - self.ui.cluster_lookup_threshold.setValue(int(config.setting["cluster_lookup_threshold"] * 100)) - self.ui.track_matching_threshold.setValue(int(config.setting["track_matching_threshold"] * 100)) + self.ui.file_lookup_threshold.setValue(int(config.setting['file_lookup_threshold'] * 100)) + self.ui.cluster_lookup_threshold.setValue(int(config.setting['cluster_lookup_threshold'] * 100)) + self.ui.track_matching_threshold.setValue(int(config.setting['track_matching_threshold'] * 100)) def save(self): config = get_config() - config.setting["file_lookup_threshold"] = float(self.ui.file_lookup_threshold.value()) / 100.0 - config.setting["cluster_lookup_threshold"] = float(self.ui.cluster_lookup_threshold.value()) / 100.0 - config.setting["track_matching_threshold"] = float(self.ui.track_matching_threshold.value()) / 100.0 + config.setting['file_lookup_threshold'] = float(self.ui.file_lookup_threshold.value()) / 100.0 + config.setting['cluster_lookup_threshold'] = float(self.ui.cluster_lookup_threshold.value()) / 100.0 + config.setting['track_matching_threshold'] = float(self.ui.track_matching_threshold.value()) / 100.0 register_options_page(MatchingOptionsPage) diff --git a/picard/ui/options/metadata.py b/picard/ui/options/metadata.py index 4fbd1d8abf..f6aa3c85e8 100644 --- a/picard/ui/options/metadata.py +++ b/picard/ui/options/metadata.py @@ -75,26 +75,26 @@ def iter_sorted_locales(locales): class MetadataOptionsPage(OptionsPage): - NAME = "metadata" + NAME = 'metadata' TITLE = N_("Metadata") PARENT = None SORT_ORDER = 20 ACTIVE = True - HELP_URL = '/config/options_metadata.html' + HELP_URL = "/config/options_metadata.html" options = [ - TextOption("setting", "va_name", "Various Artists"), - TextOption("setting", "nat_name", "[standalone recordings]"), - ListOption("setting", "artist_locales", ["en"]), - BoolOption("setting", "translate_artist_names", False), - BoolOption("setting", "translate_artist_names_script_exception", False), - ListOption("setting", "script_exceptions", []), - BoolOption("setting", "release_ars", True), - BoolOption("setting", "track_ars", False), - BoolOption("setting", "convert_punctuation", False), - BoolOption("setting", "standardize_artists", False), - BoolOption("setting", "standardize_instruments", True), - BoolOption("setting", "guess_tracknumber_and_title", True), + TextOption('setting', 'va_name', "Various Artists"), + TextOption('setting', 'nat_name', '[standalone recordings]'), + ListOption('setting', 'artist_locales', ['en']), + BoolOption('setting', 'translate_artist_names', False), + BoolOption('setting', 'translate_artist_names_script_exception', False), + ListOption('setting', 'script_exceptions', []), + BoolOption('setting', 'release_ars', True), + BoolOption('setting', 'track_ars', False), + BoolOption('setting', 'convert_punctuation', False), + BoolOption('setting', 'standardize_artists', False), + BoolOption('setting', 'standardize_instruments', True), + BoolOption('setting', 'guess_tracknumber_and_title', True), ] def __init__(self, parent=None): @@ -110,21 +110,21 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.translate_artist_names.setChecked(config.setting["translate_artist_names"]) - self.current_locales = config.setting["artist_locales"] + self.ui.translate_artist_names.setChecked(config.setting['translate_artist_names']) + self.current_locales = config.setting['artist_locales'] self.make_locales_text() - self.current_scripts = config.setting["script_exceptions"] + self.current_scripts = config.setting['script_exceptions'] self.make_scripts_text() - self.ui.translate_artist_names_script_exception.setChecked(config.setting["translate_artist_names_script_exception"]) + self.ui.translate_artist_names_script_exception.setChecked(config.setting['translate_artist_names_script_exception']) - self.ui.convert_punctuation.setChecked(config.setting["convert_punctuation"]) - self.ui.release_ars.setChecked(config.setting["release_ars"]) - self.ui.track_ars.setChecked(config.setting["track_ars"]) - self.ui.va_name.setText(config.setting["va_name"]) - self.ui.nat_name.setText(config.setting["nat_name"]) - self.ui.standardize_artists.setChecked(config.setting["standardize_artists"]) - self.ui.standardize_instruments.setChecked(config.setting["standardize_instruments"]) - self.ui.guess_tracknumber_and_title.setChecked(config.setting["guess_tracknumber_and_title"]) + self.ui.convert_punctuation.setChecked(config.setting['convert_punctuation']) + self.ui.release_ars.setChecked(config.setting['release_ars']) + self.ui.track_ars.setChecked(config.setting['track_ars']) + self.ui.va_name.setText(config.setting['va_name']) + self.ui.nat_name.setText(config.setting['nat_name']) + self.ui.standardize_artists.setChecked(config.setting['standardize_artists']) + self.ui.standardize_instruments.setChecked(config.setting['standardize_instruments']) + self.ui.guess_tracknumber_and_title.setChecked(config.setting['guess_tracknumber_and_title']) self.set_enabled_states() @@ -144,22 +144,22 @@ def translated_scripts(): def save(self): config = get_config() - config.setting["translate_artist_names"] = self.ui.translate_artist_names.isChecked() - config.setting["artist_locales"] = self.current_locales - config.setting["translate_artist_names_script_exception"] = self.ui.translate_artist_names_script_exception.isChecked() - config.setting["script_exceptions"] = self.current_scripts - config.setting["convert_punctuation"] = self.ui.convert_punctuation.isChecked() - config.setting["release_ars"] = self.ui.release_ars.isChecked() - config.setting["track_ars"] = self.ui.track_ars.isChecked() - config.setting["va_name"] = self.ui.va_name.text() + config.setting['translate_artist_names'] = self.ui.translate_artist_names.isChecked() + config.setting['artist_locales'] = self.current_locales + config.setting['translate_artist_names_script_exception'] = self.ui.translate_artist_names_script_exception.isChecked() + config.setting['script_exceptions'] = self.current_scripts + config.setting['convert_punctuation'] = self.ui.convert_punctuation.isChecked() + config.setting['release_ars'] = self.ui.release_ars.isChecked() + config.setting['track_ars'] = self.ui.track_ars.isChecked() + config.setting['va_name'] = self.ui.va_name.text() nat_name = self.ui.nat_name.text() - if nat_name != config.setting["nat_name"]: - config.setting["nat_name"] = nat_name + if nat_name != config.setting['nat_name']: + config.setting['nat_name'] = nat_name if self.tagger.nats is not None: self.tagger.nats.update() - config.setting["standardize_artists"] = self.ui.standardize_artists.isChecked() - config.setting["standardize_instruments"] = self.ui.standardize_instruments.isChecked() - config.setting["guess_tracknumber_and_title"] = self.ui.guess_tracknumber_and_title.isChecked() + config.setting['standardize_artists'] = self.ui.standardize_artists.isChecked() + config.setting['standardize_instruments'] = self.ui.standardize_instruments.isChecked() + config.setting['guess_tracknumber_and_title'] = self.ui.guess_tracknumber_and_title.isChecked() def set_va_name_default(self): self.ui.va_name.setText(self.options[0].default) diff --git a/picard/ui/options/network.py b/picard/ui/options/network.py index a8a5eac6c4..46a3f8af16 100644 --- a/picard/ui/options/network.py +++ b/picard/ui/options/network.py @@ -38,24 +38,24 @@ class NetworkOptionsPage(OptionsPage): - NAME = "network" + NAME = 'network' TITLE = N_("Network") - PARENT = "advanced" + PARENT = 'advanced' SORT_ORDER = 10 ACTIVE = True - HELP_URL = '/config/options_network.html' + HELP_URL = "/config/options_network.html" options = [ - BoolOption("setting", "use_proxy", False), - TextOption("setting", "proxy_type", "http"), - TextOption("setting", "proxy_server_host", ""), - IntOption("setting", "proxy_server_port", 80), - TextOption("setting", "proxy_username", ""), - TextOption("setting", "proxy_password", ""), - BoolOption("setting", "browser_integration", True), - IntOption("setting", "browser_integration_port", 8000), - BoolOption("setting", "browser_integration_localhost_only", True), - IntOption("setting", "network_transfer_timeout_seconds", 30), + BoolOption('setting', 'use_proxy', False), + TextOption('setting', 'proxy_type', 'http'), + TextOption('setting', 'proxy_server_host', ''), + IntOption('setting', 'proxy_server_port', 80), + TextOption('setting', 'proxy_username', ''), + TextOption('setting', 'proxy_password', ''), + BoolOption('setting', 'browser_integration', True), + IntOption('setting', 'browser_integration_port', 8000), + BoolOption('setting', 'browser_integration_localhost_only', True), + IntOption('setting', 'network_transfer_timeout_seconds', 30), ] def __init__(self, parent=None): @@ -65,39 +65,39 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.web_proxy.setChecked(config.setting["use_proxy"]) - if config.setting["proxy_type"] == 'socks': + self.ui.web_proxy.setChecked(config.setting['use_proxy']) + if config.setting['proxy_type'] == 'socks': self.ui.proxy_type_socks.setChecked(True) else: self.ui.proxy_type_http.setChecked(True) - self.ui.server_host.setText(config.setting["proxy_server_host"]) - self.ui.server_port.setValue(config.setting["proxy_server_port"]) - self.ui.username.setText(config.setting["proxy_username"]) - self.ui.password.setText(config.setting["proxy_password"]) - self.ui.transfer_timeout.setValue(config.setting["network_transfer_timeout_seconds"]) - self.ui.browser_integration.setChecked(config.setting["browser_integration"]) - self.ui.browser_integration_port.setValue(config.setting["browser_integration_port"]) + self.ui.server_host.setText(config.setting['proxy_server_host']) + self.ui.server_port.setValue(config.setting['proxy_server_port']) + self.ui.username.setText(config.setting['proxy_username']) + self.ui.password.setText(config.setting['proxy_password']) + self.ui.transfer_timeout.setValue(config.setting['network_transfer_timeout_seconds']) + self.ui.browser_integration.setChecked(config.setting['browser_integration']) + self.ui.browser_integration_port.setValue(config.setting['browser_integration_port']) self.ui.browser_integration_localhost_only.setChecked( - config.setting["browser_integration_localhost_only"]) + config.setting['browser_integration_localhost_only']) def save(self): config = get_config() - config.setting["use_proxy"] = self.ui.web_proxy.isChecked() + config.setting['use_proxy'] = self.ui.web_proxy.isChecked() if self.ui.proxy_type_socks.isChecked(): - config.setting["proxy_type"] = 'socks' + config.setting['proxy_type'] = 'socks' else: - config.setting["proxy_type"] = 'http' - config.setting["proxy_server_host"] = self.ui.server_host.text() - config.setting["proxy_server_port"] = self.ui.server_port.value() - config.setting["proxy_username"] = self.ui.username.text() - config.setting["proxy_password"] = self.ui.password.text() + config.setting['proxy_type'] = 'http' + config.setting['proxy_server_host'] = self.ui.server_host.text() + config.setting['proxy_server_port'] = self.ui.server_port.value() + config.setting['proxy_username'] = self.ui.username.text() + config.setting['proxy_password'] = self.ui.password.text() self.tagger.webservice.setup_proxy() transfer_timeout = self.ui.transfer_timeout.value() - config.setting["network_transfer_timeout_seconds"] = transfer_timeout + config.setting['network_transfer_timeout_seconds'] = transfer_timeout self.tagger.webservice.set_transfer_timeout(transfer_timeout) - config.setting["browser_integration"] = self.ui.browser_integration.isChecked() - config.setting["browser_integration_port"] = self.ui.browser_integration_port.value() - config.setting["browser_integration_localhost_only"] = \ + config.setting['browser_integration'] = self.ui.browser_integration.isChecked() + config.setting['browser_integration_port'] = self.ui.browser_integration_port.value() + config.setting['browser_integration_localhost_only'] = \ self.ui.browser_integration_localhost_only.isChecked() self.tagger.update_browser_integration() diff --git a/picard/ui/options/plugins.py b/picard/ui/options/plugins.py index a8428a49e9..5c1ed303ca 100644 --- a/picard/ui/options/plugins.py +++ b/picard/ui/options/plugins.py @@ -222,18 +222,18 @@ def enable(self, boolean, greyout=None): class PluginsOptionsPage(OptionsPage): - NAME = "plugins" + NAME = 'plugins' TITLE = N_("Plugins") PARENT = None SORT_ORDER = 70 ACTIVE = True - HELP_URL = '/config/options_plugins.html' + HELP_URL = "/config/options_plugins.html" options = [ - ListOption("setting", "enabled_plugins", []), - Option("persist", "plugins_list_state", QtCore.QByteArray()), - Option("persist", "plugins_list_sort_section", 0), - Option("persist", "plugins_list_sort_order", QtCore.Qt.SortOrder.AscendingOrder), + ListOption('setting', 'enabled_plugins', []), + Option('persist', 'plugins_list_state', QtCore.QByteArray()), + Option('persist', 'plugins_list_sort_section', 0), + Option('persist', 'plugins_list_sort_order', QtCore.Qt.SortOrder.AscendingOrder), ] def __init__(self, parent=None): @@ -299,9 +299,9 @@ def selected_item(self): def save_state(self): header = self.ui.plugins.header() config = get_config() - config.persist["plugins_list_state"] = header.saveState() - config.persist["plugins_list_sort_section"] = header.sortIndicatorSection() - config.persist["plugins_list_sort_order"] = header.sortIndicatorOrder() + config.persist['plugins_list_state'] = header.saveState() + config.persist['plugins_list_sort_section'] = header.sortIndicatorSection() + config.persist['plugins_list_sort_order'] = header.sortIndicatorOrder() def set_current_item(self, item, scroll=False): if scroll: @@ -312,16 +312,16 @@ def set_current_item(self, item, scroll=False): def restore_state(self): header = self.ui.plugins.header() config = get_config() - header.restoreState(config.persist["plugins_list_state"]) - idx = config.persist["plugins_list_sort_section"] - order = config.persist["plugins_list_sort_order"] + header.restoreState(config.persist['plugins_list_state']) + idx = config.persist['plugins_list_sort_section'] + order = config.persist['plugins_list_sort_order'] header.setSortIndicator(idx, order) self.ui.plugins.sortByColumn(idx, order) @staticmethod def is_plugin_enabled(plugin): config = get_config() - return bool(plugin.module_name in config.setting["enabled_plugins"]) + return bool(plugin.module_name in config.setting['enabled_plugins']) def available_plugins_name_version(self): return {p.module_name: p.version for p in self.manager.available_plugins} @@ -610,7 +610,7 @@ def v2int(elem): def save(self): config = get_config() - config.setting["enabled_plugins"] = self.enabled_plugins() + config.setting['enabled_plugins'] = self.enabled_plugins() self.save_state() def refresh_details(self, item): @@ -687,7 +687,7 @@ def download_plugin(self, item, update=False): parse_response_type=None, priority=True, important=True, - unencoded_queryargs={"id": plugin.module_name, "version": plugin.version.to_string(short=True)}, + unencoded_queryargs={'id': plugin.module_name, 'version': plugin.version.to_string(short=True)}, ) def download_handler(self, update, response, reply, error, plugin): @@ -716,7 +716,7 @@ def open_plugin_dir(): open_local_path(USER_PLUGIN_DIR) def mimeTypes(self): - return ["text/uri-list"] + return ['text/uri-list'] def dragEnterEvent(self, event): event.setDropAction(QtCore.Qt.DropAction.CopyAction) diff --git a/picard/ui/options/profiles.py b/picard/ui/options/profiles.py index 20b9602a51..01c345bbec 100644 --- a/picard/ui/options/profiles.py +++ b/picard/ui/options/profiles.py @@ -52,23 +52,23 @@ class ProfilesOptionsPage(OptionsPage): - NAME = "profiles" + NAME = 'profiles' TITLE = N_("Option Profiles") PARENT = None SORT_ORDER = 10 ACTIVE = True - HELP_URL = '/config/options_profiles.html' + HELP_URL = "/config/options_profiles.html" PROFILES_KEY = SettingConfigSection.PROFILES_KEY SETTINGS_KEY = SettingConfigSection.SETTINGS_KEY - POSITION_KEY = "last_selected_profile_pos" - EXPANDED_KEY = "profile_settings_tree_expanded_list" + POSITION_KEY = 'last_selected_profile_pos' + EXPANDED_KEY = 'profile_settings_tree_expanded_list' TREEWIDGETITEM_COLUMN = 0 options = [ - IntOption("persist", POSITION_KEY, 0), - ListOption("persist", EXPANDED_KEY, []) + IntOption('persist', POSITION_KEY, 0), + ListOption('persist', EXPANDED_KEY, []) ] signal_refresh = QtCore.pyqtSignal() @@ -112,17 +112,17 @@ def eventFilter(self, object, event): def make_buttons(self): """Make buttons and add them to the button bars. """ - self.new_profile_button = QtWidgets.QPushButton(_('New')) + self.new_profile_button = QtWidgets.QPushButton(_("New")) self.new_profile_button.setToolTip(_("Create a new profile")) self.new_profile_button.clicked.connect(self.new_profile) self.ui.profile_list_buttonbox.addButton(self.new_profile_button, QtWidgets.QDialogButtonBox.ButtonRole.ActionRole) - self.copy_profile_button = QtWidgets.QPushButton(_('Copy')) + self.copy_profile_button = QtWidgets.QPushButton(_("Copy")) self.copy_profile_button.setToolTip(_("Copy to a new profile")) self.copy_profile_button.clicked.connect(self.copy_profile) self.ui.profile_list_buttonbox.addButton(self.copy_profile_button, QtWidgets.QDialogButtonBox.ButtonRole.ActionRole) - self.delete_profile_button = QtWidgets.QPushButton(_('Delete')) + self.delete_profile_button = QtWidgets.QPushButton(_("Delete")) self.delete_profile_button.setToolTip(_("Delete the profile")) self.delete_profile_button.clicked.connect(self.delete_profile) self.ui.profile_list_buttonbox.addButton(self.delete_profile_button, QtWidgets.QDialogButtonBox.ButtonRole.ActionRole) @@ -220,8 +220,8 @@ def make_setting_tree(self, settings=None): return self.building_tree = True for group in UserProfileGroups.SETTINGS_GROUPS.values(): - title = group["title"] - group_settings = group["settings"] + title = group['title'] + group_settings = group['settings'] widget_item = QtWidgets.QTreeWidgetItem([title]) widget_item.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable | QtCore.Qt.ItemFlag.ItemIsAutoTristate) widget_item.setCheckState(self.TREEWIDGETITEM_COLUMN, QtCore.Qt.CheckState.Unchecked) @@ -243,9 +243,9 @@ def make_setting_tree(self, settings=None): self.building_tree = False def _get_naming_script(self, config, value): - if value in config.setting["file_renaming_scripts"]: - return config.setting["file_renaming_scripts"][value]["title"] - presets = {x["id"]: x["title"] for x in get_file_naming_script_presets()} + if value in config.setting['file_renaming_scripts']: + return config.setting['file_renaming_scripts'][value]['title'] + presets = {x['id']: x['title'] for x in get_file_naming_script_presets()} if value in presets: return presets[value] return _("Unknown script") @@ -282,11 +282,11 @@ def make_setting_value_text(self, key, value): config = get_config() if value is None: return NONE_TEXT - if key == "selected_file_naming_script_id": + if key == 'selected_file_naming_script_id': return self._get_naming_script(config, value) - if key == "list_of_scripts": + if key == 'list_of_scripts': return self._get_scripts_list(config, key, ITEMS_TEMPLATE, NONE_TEXT) - if key == "ca_providers": + if key == 'ca_providers': return self._get_ca_providers_list(config, key, ITEMS_TEMPLATE, NONE_TEXT) if isinstance(value, str): return '"%s"' % value diff --git a/picard/ui/options/ratings.py b/picard/ui/options/ratings.py index e83921316d..bd5d6e84f8 100644 --- a/picard/ui/options/ratings.py +++ b/picard/ui/options/ratings.py @@ -37,18 +37,18 @@ class RatingsOptionsPage(OptionsPage): - NAME = "ratings" + NAME = 'ratings' TITLE = N_("Ratings") - PARENT = "metadata" + PARENT = 'metadata' SORT_ORDER = 20 ACTIVE = True - HELP_URL = '/config/options_ratings.html' + HELP_URL = "/config/options_ratings.html" options = [ - BoolOption("setting", "enable_ratings", False), - TextOption("setting", "rating_user_email", "users@musicbrainz.org"), - BoolOption("setting", "submit_ratings", True), - IntOption("setting", "rating_steps", 6), + BoolOption('setting', 'enable_ratings', False), + TextOption('setting', 'rating_user_email', 'users@musicbrainz.org'), + BoolOption('setting', 'submit_ratings', True), + IntOption('setting', 'rating_steps', 6), ] def __init__(self, parent=None): @@ -58,15 +58,15 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.enable_ratings.setChecked(config.setting["enable_ratings"]) - self.ui.rating_user_email.setText(config.setting["rating_user_email"]) - self.ui.submit_ratings.setChecked(config.setting["submit_ratings"]) + self.ui.enable_ratings.setChecked(config.setting['enable_ratings']) + self.ui.rating_user_email.setText(config.setting['rating_user_email']) + self.ui.submit_ratings.setChecked(config.setting['submit_ratings']) def save(self): config = get_config() - config.setting["enable_ratings"] = self.ui.enable_ratings.isChecked() - config.setting["rating_user_email"] = self.ui.rating_user_email.text() - config.setting["submit_ratings"] = self.ui.submit_ratings.isChecked() + config.setting['enable_ratings'] = self.ui.enable_ratings.isChecked() + config.setting['rating_user_email'] = self.ui.rating_user_email.text() + config.setting['submit_ratings'] = self.ui.submit_ratings.isChecked() register_options_page(RatingsOptionsPage) diff --git a/picard/ui/options/releases.py b/picard/ui/options/releases.py index dc83f56777..c0be036523 100644 --- a/picard/ui/options/releases.py +++ b/picard/ui/options/releases.py @@ -154,17 +154,17 @@ def __next__(self): class ReleasesOptionsPage(OptionsPage): - NAME = "releases" + NAME = 'releases' TITLE = N_("Preferred Releases") - PARENT = "metadata" + PARENT = 'metadata' SORT_ORDER = 10 ACTIVE = True - HELP_URL = '/config/options_releases.html' + HELP_URL = "/config/options_releases.html" options = [ - ListOption("setting", "release_type_scores", _release_type_scores), - ListOption("setting", "preferred_release_countries", []), - ListOption("setting", "preferred_release_formats", []), + ListOption('setting', 'release_type_scores', _release_type_scores), + ListOption('setting', 'preferred_release_countries', []), + ListOption('setting', 'preferred_release_formats', []), ] def __init__(self, parent=None): @@ -230,14 +230,14 @@ def restore_defaults(self): def load(self): config = get_config() - scores = dict(config.setting["release_type_scores"]) + scores = dict(config.setting['release_type_scores']) for (release_type, release_type_slider) in self._release_type_sliders.items(): release_type_slider.setValue(scores.get(release_type, _DEFAULT_SCORE)) - self._load_list_items("preferred_release_countries", RELEASE_COUNTRIES, + self._load_list_items('preferred_release_countries', RELEASE_COUNTRIES, self.ui.country_list, self.ui.preferred_country_list) - self._load_list_items("preferred_release_formats", RELEASE_FORMATS, + self._load_list_items('preferred_release_formats', RELEASE_FORMATS, self.ui.format_list, self.ui.preferred_format_list) def save(self): @@ -245,10 +245,10 @@ def save(self): scores = [] for (release_type, release_type_slider) in self._release_type_sliders.items(): scores.append((release_type, release_type_slider.value())) - config.setting["release_type_scores"] = scores + config.setting['release_type_scores'] = scores - self._save_list_items("preferred_release_countries", self.ui.preferred_country_list) - self._save_list_items("preferred_release_formats", self.ui.preferred_format_list) + self._save_list_items('preferred_release_countries', self.ui.preferred_country_list) + self._save_list_items('preferred_release_formats', self.ui.preferred_format_list) def reset_preferred_types(self): for release_type_slider in self._release_type_sliders.values(): @@ -275,11 +275,11 @@ def _move_selected_items(self, list1, list2): list1.takeItem(list1.row(item)) def _load_list_items(self, setting, source, list1, list2): - if setting == "preferred_release_countries": + if setting == 'preferred_release_countries': source_list = [(c[0], gettext_countries(c[1])) for c in source.items()] - elif setting == "preferred_release_formats": - source_list = [(c[0], pgettext_attributes("medium_format", c[1])) for c + elif setting == 'preferred_release_formats': + source_list = [(c[0], pgettext_attributes('medium_format', c[1])) for c in source.items()] else: source_list = [(c[0], _(c[1])) for c in source.items()] diff --git a/picard/ui/options/renaming.py b/picard/ui/options/renaming.py index fbbcd71109..d42155fa7c 100644 --- a/picard/ui/options/renaming.py +++ b/picard/ui/options/renaming.py @@ -69,20 +69,20 @@ class RenamingOptionsPage(OptionsPage): - NAME = "filerenaming" + NAME = 'filerenaming' TITLE = N_("File Naming") PARENT = None SORT_ORDER = 40 ACTIVE = True - HELP_URL = '/config/options_filerenaming.html' + HELP_URL = "/config/options_filerenaming.html" options = [ - BoolOption("setting", "rename_files", False), - BoolOption("setting", "move_files", False), - TextOption("setting", "move_files_to", _default_music_dir), - BoolOption("setting", "move_additional_files", False), - TextOption("setting", "move_additional_files_pattern", "*.jpg *.png"), - BoolOption("setting", "delete_empty_dirs", True), + BoolOption('setting', 'rename_files', False), + BoolOption('setting', 'move_files', False), + TextOption('setting', 'move_files_to', _default_music_dir), + BoolOption('setting', 'move_additional_files', False), + TextOption('setting', 'move_additional_files_pattern', "*.jpg *.png"), + BoolOption('setting', 'delete_empty_dirs', True), ] def __init__(self, parent=None): @@ -231,15 +231,15 @@ def load(self): compat_page.options_changed.connect(self.on_compat_options_changed) config = get_config() - self.ui.rename_files.setChecked(config.setting["rename_files"]) - self.ui.move_files.setChecked(config.setting["move_files"]) - self.ui.move_files_to.setText(config.setting["move_files_to"]) + self.ui.rename_files.setChecked(config.setting['rename_files']) + self.ui.move_files.setChecked(config.setting['move_files']) + self.ui.move_files_to.setText(config.setting['move_files_to']) self.ui.move_files_to.setCursorPosition(0) - self.ui.move_additional_files.setChecked(config.setting["move_additional_files"]) - self.ui.move_additional_files_pattern.setText(config.setting["move_additional_files_pattern"]) - self.ui.delete_empty_dirs.setChecked(config.setting["delete_empty_dirs"]) - self.naming_scripts = config.setting["file_renaming_scripts"] - self.selected_naming_script_id = config.setting["selected_file_naming_script_id"] + self.ui.move_additional_files.setChecked(config.setting['move_additional_files']) + self.ui.move_additional_files_pattern.setText(config.setting['move_additional_files_pattern']) + self.ui.delete_empty_dirs.setChecked(config.setting['delete_empty_dirs']) + self.naming_scripts = config.setting['file_renaming_scripts'] + self.selected_naming_script_id = config.setting['selected_file_naming_script_id'] if self.script_editor_dialog: self.script_editor_dialog.load() else: @@ -267,15 +267,15 @@ def check_format(self): def save(self): config = get_config() - config.setting["rename_files"] = self.ui.rename_files.isChecked() - config.setting["move_files"] = self.ui.move_files.isChecked() - config.setting["move_files_to"] = os.path.normpath(self.ui.move_files_to.text()) - config.setting["move_additional_files"] = self.ui.move_additional_files.isChecked() - config.setting["move_additional_files_pattern"] = self.ui.move_additional_files_pattern.text() - config.setting["delete_empty_dirs"] = self.ui.delete_empty_dirs.isChecked() - config.setting["selected_file_naming_script_id"] = self.selected_naming_script_id - self.tagger.window.enable_renaming_action.setChecked(config.setting["rename_files"]) - self.tagger.window.enable_moving_action.setChecked(config.setting["move_files"]) + config.setting['rename_files'] = self.ui.rename_files.isChecked() + config.setting['move_files'] = self.ui.move_files.isChecked() + config.setting['move_files_to'] = os.path.normpath(self.ui.move_files_to.text()) + config.setting['move_additional_files'] = self.ui.move_additional_files.isChecked() + config.setting['move_additional_files_pattern'] = self.ui.move_additional_files_pattern.text() + config.setting['delete_empty_dirs'] = self.ui.delete_empty_dirs.isChecked() + config.setting['selected_file_naming_script_id'] = self.selected_naming_script_id + self.tagger.window.enable_renaming_action.setChecked(config.setting['rename_files']) + self.tagger.window.enable_moving_action.setChecked(config.setting['move_files']) self.tagger.window.make_script_selector_menu() def display_error(self, error): diff --git a/picard/ui/options/renaming_compat.py b/picard/ui/options/renaming_compat.py index 675959a59f..98c9ec17da 100644 --- a/picard/ui/options/renaming_compat.py +++ b/picard/ui/options/renaming_compat.py @@ -64,19 +64,19 @@ class RenamingCompatOptionsPage(OptionsPage): - NAME = "filerenaming_compat" + NAME = 'filerenaming_compat' TITLE = N_("Compatibility") - PARENT = "filerenaming" + PARENT = 'filerenaming' ACTIVE = True - HELP_URL = '/config/options_filerenaming_compat.html' + HELP_URL = "/config/options_filerenaming_compat.html" options = [ - BoolOption("setting", "windows_compatibility", True), - BoolOption("setting", "windows_long_paths", system_supports_long_paths() if IS_WIN else False), - BoolOption("setting", "ascii_filenames", False), - BoolOption("setting", "replace_spaces_with_underscores", False), - TextOption("setting", "replace_dir_separator", DEFAULT_REPLACEMENT), - Option("setting", "win_compat_replacements", { + BoolOption('setting', 'windows_compatibility', True), + BoolOption('setting', 'windows_long_paths', system_supports_long_paths() if IS_WIN else False), + BoolOption('setting', 'ascii_filenames', False), + BoolOption('setting', 'replace_spaces_with_underscores', False), + TextOption('setting', 'replace_dir_separator', DEFAULT_REPLACEMENT), + Option('setting', 'win_compat_replacements', { '*': DEFAULT_REPLACEMENT, ':': DEFAULT_REPLACEMENT, '<': DEFAULT_REPLACEMENT, @@ -92,7 +92,7 @@ class RenamingCompatOptionsPage(OptionsPage): def __init__(self, parent=None): super().__init__(parent) config = get_config() - self.win_compat_replacements = config.setting["win_compat_replacements"] + self.win_compat_replacements = config.setting['win_compat_replacements'] self.ui = Ui_RenamingCompatOptionsPage() self.ui.setupUi(self) self.ui.ascii_filenames.toggled.connect(self.on_options_changed) @@ -104,7 +104,7 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.win_compat_replacements = config.setting["win_compat_replacements"] + self.win_compat_replacements = config.setting['win_compat_replacements'] try: self.ui.windows_long_paths.toggled.disconnect(self.toggle_windows_long_paths) except TypeError: @@ -113,11 +113,11 @@ def load(self): self.ui.windows_compatibility.setChecked(True) self.ui.windows_compatibility.setEnabled(False) else: - self.ui.windows_compatibility.setChecked(config.setting["windows_compatibility"]) - self.ui.windows_long_paths.setChecked(config.setting["windows_long_paths"]) - self.ui.ascii_filenames.setChecked(config.setting["ascii_filenames"]) - self.ui.replace_spaces_with_underscores.setChecked(config.setting["replace_spaces_with_underscores"]) - self.ui.replace_dir_separator.setText(config.setting["replace_dir_separator"]) + self.ui.windows_compatibility.setChecked(config.setting['windows_compatibility']) + self.ui.windows_long_paths.setChecked(config.setting['windows_long_paths']) + self.ui.ascii_filenames.setChecked(config.setting['ascii_filenames']) + self.ui.replace_spaces_with_underscores.setChecked(config.setting['replace_spaces_with_underscores']) + self.ui.replace_dir_separator.setText(config.setting['replace_dir_separator']) self.ui.windows_long_paths.toggled.connect(self.toggle_windows_long_paths) def save(self): @@ -130,11 +130,11 @@ def toggle_windows_long_paths(self, state): if state and not system_supports_long_paths(): dialog = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Icon.Information, - _('Windows long path support'), + _("Windows long path support"), _( - 'Enabling long paths on Windows might cause files being saved with path names ' - 'exceeding the 259 character limit traditionally imposed by the Windows API. ' - 'Some software might not be able to properly access those files.' + "Enabling long paths on Windows might cause files being saved with path names " + "exceeding the 259 character limit traditionally imposed by the Windows API. " + "Some software might not be able to properly access those files." ), QtWidgets.QMessageBox.StandardButton.Ok, self) diff --git a/picard/ui/options/scripting.py b/picard/ui/options/scripting.py index 1a56f63b20..1b0e1900e7 100644 --- a/picard/ui/options/scripting.py +++ b/picard/ui/options/scripting.py @@ -96,17 +96,17 @@ def closeEvent(self, event): class ScriptingOptionsPage(OptionsPage): - NAME = "scripting" + NAME = 'scripting' TITLE = N_("Scripting") PARENT = None SORT_ORDER = 75 ACTIVE = True - HELP_URL = '/config/options_scripting.html' + HELP_URL = "/config/options_scripting.html" options = [ - BoolOption("setting", "enable_tagger_scripts", False), - ListOption("setting", "list_of_scripts", []), - IntOption("persist", "last_selected_script_pos", 0), + BoolOption('setting', 'enable_tagger_scripts', False), + ListOption('setting', 'list_of_scripts', []), + IntOption('persist', 'last_selected_script_pos', 0), ] default_script_directory = os.path.normpath(QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.StandardLocation.DocumentsLocation)) @@ -173,8 +173,8 @@ def import_script(self): self.output_file_error(error) return if script_item: - title = _("%s (imported)") % script_item["title"] - list_item = ScriptListWidgetItem(title, False, script_item["script"]) + title = _("%s (imported)") % script_item['title'] + list_item = ScriptListWidgetItem(title, False, script_item['script']) self.ui.script_list.addItem(list_item) self.ui.script_list.setCurrentRow(self.ui.script_list.count() - 1) @@ -250,14 +250,14 @@ def restore_defaults(self): def load(self): config = get_config() - self.ui.enable_tagger_scripts.setChecked(config.setting["enable_tagger_scripts"]) + self.ui.enable_tagger_scripts.setChecked(config.setting['enable_tagger_scripts']) self.ui.script_list.clear() - for pos, name, enabled, text in config.setting["list_of_scripts"]: + for pos, name, enabled, text in config.setting['list_of_scripts']: list_item = ScriptListWidgetItem(name, enabled, text) self.ui.script_list.addItem(list_item) # Select the last selected script item - last_selected_script_pos = config.persist["last_selected_script_pos"] + last_selected_script_pos = config.persist['last_selected_script_pos'] last_selected_script = self.ui.script_list.item(last_selected_script_pos) if last_selected_script: self.ui.script_list.setCurrentItem(last_selected_script) @@ -269,9 +269,9 @@ def _all_scripts(self): def save(self): config = get_config() - config.setting["enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked() - config.setting["list_of_scripts"] = list(self._all_scripts()) - config.persist["last_selected_script_pos"] = self.ui.script_list.currentRow() + config.setting['enable_tagger_scripts'] = self.ui.enable_tagger_scripts.isChecked() + config.setting['list_of_scripts'] = list(self._all_scripts()) + config.persist['last_selected_script_pos'] = self.ui.script_list.currentRow() def display_error(self, error): # Ignore scripting errors, those are handled inline diff --git a/picard/ui/options/tags.py b/picard/ui/options/tags.py index d94c7df878..f3ceafccf0 100644 --- a/picard/ui/options/tags.py +++ b/picard/ui/options/tags.py @@ -43,22 +43,22 @@ class TagsOptionsPage(OptionsPage): - NAME = "tags" + NAME = 'tags' TITLE = N_("Tags") PARENT = None SORT_ORDER = 30 ACTIVE = True - HELP_URL = '/config/options_tags.html' + HELP_URL = "/config/options_tags.html" options = [ - BoolOption("setting", "dont_write_tags", False), - BoolOption("setting", "preserve_timestamps", False), - BoolOption("setting", "clear_existing_tags", False), - BoolOption("setting", "preserve_images", False), - BoolOption("setting", "remove_id3_from_flac", False), - BoolOption("setting", "remove_ape_from_mp3", False), - BoolOption("setting", "fix_missing_seekpoints_flac", False), - ListOption("setting", "preserved_tags", []), + BoolOption('setting', 'dont_write_tags', False), + BoolOption('setting', 'preserve_timestamps', False), + BoolOption('setting', 'clear_existing_tags', False), + BoolOption('setting', 'preserve_images', False), + BoolOption('setting', 'remove_id3_from_flac', False), + BoolOption('setting', 'remove_ape_from_mp3', False), + BoolOption('setting', 'fix_missing_seekpoints_flac', False), + ListOption('setting', 'preserved_tags', []), ] def __init__(self, parent=None): @@ -68,30 +68,30 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.write_tags.setChecked(not config.setting["dont_write_tags"]) - self.ui.preserve_timestamps.setChecked(config.setting["preserve_timestamps"]) - self.ui.clear_existing_tags.setChecked(config.setting["clear_existing_tags"]) - self.ui.preserve_images.setChecked(config.setting["preserve_images"]) - self.ui.remove_ape_from_mp3.setChecked(config.setting["remove_ape_from_mp3"]) - self.ui.remove_id3_from_flac.setChecked(config.setting["remove_id3_from_flac"]) - self.ui.fix_missing_seekpoints_flac.setChecked(config.setting["fix_missing_seekpoints_flac"]) - self.ui.preserved_tags.update(config.setting["preserved_tags"]) + self.ui.write_tags.setChecked(not config.setting['dont_write_tags']) + self.ui.preserve_timestamps.setChecked(config.setting['preserve_timestamps']) + self.ui.clear_existing_tags.setChecked(config.setting['clear_existing_tags']) + self.ui.preserve_images.setChecked(config.setting['preserve_images']) + self.ui.remove_ape_from_mp3.setChecked(config.setting['remove_ape_from_mp3']) + self.ui.remove_id3_from_flac.setChecked(config.setting['remove_id3_from_flac']) + self.ui.fix_missing_seekpoints_flac.setChecked(config.setting['fix_missing_seekpoints_flac']) + self.ui.preserved_tags.update(config.setting['preserved_tags']) self.ui.preserved_tags.set_user_sortable(False) def save(self): config = get_config() - config.setting["dont_write_tags"] = not self.ui.write_tags.isChecked() - config.setting["preserve_timestamps"] = self.ui.preserve_timestamps.isChecked() + config.setting['dont_write_tags'] = not self.ui.write_tags.isChecked() + config.setting['preserve_timestamps'] = self.ui.preserve_timestamps.isChecked() clear_existing_tags = self.ui.clear_existing_tags.isChecked() - if clear_existing_tags != config.setting["clear_existing_tags"]: - config.setting["clear_existing_tags"] = clear_existing_tags + if clear_existing_tags != config.setting['clear_existing_tags']: + config.setting['clear_existing_tags'] = clear_existing_tags self.tagger.window.metadata_box.update() - config.setting["preserve_images"] = self.ui.preserve_images.isChecked() - config.setting["remove_ape_from_mp3"] = self.ui.remove_ape_from_mp3.isChecked() - config.setting["remove_id3_from_flac"] = self.ui.remove_id3_from_flac.isChecked() - config.setting["fix_missing_seekpoints_flac"] = self.ui.fix_missing_seekpoints_flac.isChecked() - config.setting["preserved_tags"] = list(self.ui.preserved_tags.tags) - self.tagger.window.enable_tag_saving_action.setChecked(not config.setting["dont_write_tags"]) + config.setting['preserve_images'] = self.ui.preserve_images.isChecked() + config.setting['remove_ape_from_mp3'] = self.ui.remove_ape_from_mp3.isChecked() + config.setting['remove_id3_from_flac'] = self.ui.remove_id3_from_flac.isChecked() + config.setting['fix_missing_seekpoints_flac'] = self.ui.fix_missing_seekpoints_flac.isChecked() + config.setting['preserved_tags'] = list(self.ui.preserved_tags.tags) + self.tagger.window.enable_tag_saving_action.setChecked(not config.setting['dont_write_tags']) register_options_page(TagsOptionsPage) diff --git a/picard/ui/options/tags_compatibility_aac.py b/picard/ui/options/tags_compatibility_aac.py index b50bc2aedb..ee58e4f0c8 100644 --- a/picard/ui/options/tags_compatibility_aac.py +++ b/picard/ui/options/tags_compatibility_aac.py @@ -37,16 +37,16 @@ class TagsCompatibilityAACOptionsPage(OptionsPage): - NAME = "tags_compatibility_aac" + NAME = 'tags_compatibility_aac' TITLE = N_("AAC") - PARENT = "tags" + PARENT = 'tags' SORT_ORDER = 40 ACTIVE = True - HELP_URL = '/config/options_tags_compatibility_aac.html' + HELP_URL = "/config/options_tags_compatibility_aac.html" options = [ - BoolOption("setting", "aac_save_ape", True), - BoolOption("setting", "remove_ape_from_aac", False), + BoolOption('setting', 'aac_save_ape', True), + BoolOption('setting', 'remove_ape_from_aac', False), ] def __init__(self, parent=None): @@ -57,17 +57,17 @@ def __init__(self, parent=None): def load(self): config = get_config() - if config.setting["aac_save_ape"]: + if config.setting['aac_save_ape']: self.ui.aac_save_ape.setChecked(True) else: self.ui.aac_no_tags.setChecked(True) - self.ui.remove_ape_from_aac.setChecked(config.setting["remove_ape_from_aac"]) - self.ui.remove_ape_from_aac.setEnabled(not config.setting["aac_save_ape"]) + self.ui.remove_ape_from_aac.setChecked(config.setting['remove_ape_from_aac']) + self.ui.remove_ape_from_aac.setEnabled(not config.setting['aac_save_ape']) def save(self): config = get_config() - config.setting["aac_save_ape"] = self.ui.aac_save_ape.isChecked() - config.setting["remove_ape_from_aac"] = self.ui.remove_ape_from_aac.isChecked() + config.setting['aac_save_ape'] = self.ui.aac_save_ape.isChecked() + config.setting['remove_ape_from_aac'] = self.ui.remove_ape_from_aac.isChecked() register_options_page(TagsCompatibilityAACOptionsPage) diff --git a/picard/ui/options/tags_compatibility_ac3.py b/picard/ui/options/tags_compatibility_ac3.py index ad2bb738c1..fb91b1cf20 100644 --- a/picard/ui/options/tags_compatibility_ac3.py +++ b/picard/ui/options/tags_compatibility_ac3.py @@ -37,16 +37,16 @@ class TagsCompatibilityAC3OptionsPage(OptionsPage): - NAME = "tags_compatibility_ac3" + NAME = 'tags_compatibility_ac3' TITLE = N_("AC3") - PARENT = "tags" + PARENT = 'tags' SORT_ORDER = 50 ACTIVE = True - HELP_URL = '/config/options_tags_compatibility_ac3.html' + HELP_URL = "/config/options_tags_compatibility_ac3.html" options = [ - BoolOption("setting", "ac3_save_ape", True), - BoolOption("setting", "remove_ape_from_ac3", False), + BoolOption('setting', 'ac3_save_ape', True), + BoolOption('setting', 'remove_ape_from_ac3', False), ] def __init__(self, parent=None): @@ -57,17 +57,17 @@ def __init__(self, parent=None): def load(self): config = get_config() - if config.setting["ac3_save_ape"]: + if config.setting['ac3_save_ape']: self.ui.ac3_save_ape.setChecked(True) else: self.ui.ac3_no_tags.setChecked(True) - self.ui.remove_ape_from_ac3.setChecked(config.setting["remove_ape_from_ac3"]) - self.ui.remove_ape_from_ac3.setEnabled(not config.setting["ac3_save_ape"]) + self.ui.remove_ape_from_ac3.setChecked(config.setting['remove_ape_from_ac3']) + self.ui.remove_ape_from_ac3.setEnabled(not config.setting['ac3_save_ape']) def save(self): config = get_config() - config.setting["ac3_save_ape"] = self.ui.ac3_save_ape.isChecked() - config.setting["remove_ape_from_ac3"] = self.ui.remove_ape_from_ac3.isChecked() + config.setting['ac3_save_ape'] = self.ui.ac3_save_ape.isChecked() + config.setting['remove_ape_from_ac3'] = self.ui.remove_ape_from_ac3.isChecked() register_options_page(TagsCompatibilityAC3OptionsPage) diff --git a/picard/ui/options/tags_compatibility_id3.py b/picard/ui/options/tags_compatibility_id3.py index 03785ba49f..ead7a08aa2 100644 --- a/picard/ui/options/tags_compatibility_id3.py +++ b/picard/ui/options/tags_compatibility_id3.py @@ -40,19 +40,19 @@ class TagsCompatibilityID3OptionsPage(OptionsPage): - NAME = "tags_compatibility_id3" + NAME = 'tags_compatibility_id3' TITLE = N_("ID3") - PARENT = "tags" + PARENT = 'tags' SORT_ORDER = 30 ACTIVE = True - HELP_URL = '/config/options_tags_compatibility_id3.html' + HELP_URL = "/config/options_tags_compatibility_id3.html" options = [ - BoolOption("setting", "write_id3v1", True), - BoolOption("setting", "write_id3v23", False), - TextOption("setting", "id3v2_encoding", "utf-8"), - TextOption("setting", "id3v23_join_with", "/"), - BoolOption("setting", "itunes_compatible_grouping", False), + BoolOption('setting', 'write_id3v1', True), + BoolOption('setting', 'write_id3v23', False), + TextOption('setting', 'id3v2_encoding', 'utf-8'), + TextOption('setting', 'id3v23_join_with', '/'), + BoolOption('setting', 'itunes_compatible_grouping', False), ] def __init__(self, parent=None): @@ -64,33 +64,33 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.write_id3v1.setChecked(config.setting["write_id3v1"]) - if config.setting["write_id3v23"]: + self.ui.write_id3v1.setChecked(config.setting['write_id3v1']) + if config.setting['write_id3v23']: self.ui.write_id3v23.setChecked(True) else: self.ui.write_id3v24.setChecked(True) - if config.setting["id3v2_encoding"] == "iso-8859-1": + if config.setting['id3v2_encoding'] == 'iso-8859-1': self.ui.enc_iso88591.setChecked(True) - elif config.setting["id3v2_encoding"] == "utf-16": + elif config.setting['id3v2_encoding'] == 'utf-16': self.ui.enc_utf16.setChecked(True) else: self.ui.enc_utf8.setChecked(True) - self.ui.id3v23_join_with.setEditText(config.setting["id3v23_join_with"]) - self.ui.itunes_compatible_grouping.setChecked(config.setting["itunes_compatible_grouping"]) + self.ui.id3v23_join_with.setEditText(config.setting['id3v23_join_with']) + self.ui.itunes_compatible_grouping.setChecked(config.setting['itunes_compatible_grouping']) self.update_encodings() def save(self): config = get_config() - config.setting["write_id3v1"] = self.ui.write_id3v1.isChecked() - config.setting["write_id3v23"] = self.ui.write_id3v23.isChecked() - config.setting["id3v23_join_with"] = self.ui.id3v23_join_with.currentText() + config.setting['write_id3v1'] = self.ui.write_id3v1.isChecked() + config.setting['write_id3v23'] = self.ui.write_id3v23.isChecked() + config.setting['id3v23_join_with'] = self.ui.id3v23_join_with.currentText() if self.ui.enc_iso88591.isChecked(): - config.setting["id3v2_encoding"] = "iso-8859-1" + config.setting['id3v2_encoding'] = 'iso-8859-1' elif self.ui.enc_utf16.isChecked(): - config.setting["id3v2_encoding"] = "utf-16" + config.setting['id3v2_encoding'] = 'utf-16' else: - config.setting["id3v2_encoding"] = "utf-8" - config.setting["itunes_compatible_grouping"] = self.ui.itunes_compatible_grouping.isChecked() + config.setting['id3v2_encoding'] = 'utf-8' + config.setting['itunes_compatible_grouping'] = self.ui.itunes_compatible_grouping.isChecked() def update_encodings(self, force_utf8=False): if self.ui.write_id3v23.isChecked(): diff --git a/picard/ui/options/tags_compatibility_wave.py b/picard/ui/options/tags_compatibility_wave.py index 3062295e6a..b513a1c7e8 100644 --- a/picard/ui/options/tags_compatibility_wave.py +++ b/picard/ui/options/tags_compatibility_wave.py @@ -39,17 +39,17 @@ class TagsCompatibilityWaveOptionsPage(OptionsPage): - NAME = "tags_compatibility_wave" + NAME = 'tags_compatibility_wave' TITLE = N_("WAVE") - PARENT = "tags" + PARENT = 'tags' SORT_ORDER = 60 ACTIVE = True - HELP_URL = '/config/options_tags_compatibility_wave.html' + HELP_URL = "/config/options_tags_compatibility_wave.html" options = [ - BoolOption("setting", "write_wave_riff_info", True), - BoolOption("setting", "remove_wave_riff_info", False), - TextOption("setting", "wave_riff_info_encoding", "windows-1252"), + BoolOption('setting', 'write_wave_riff_info', True), + BoolOption('setting', 'remove_wave_riff_info', False), + TextOption('setting', 'wave_riff_info_encoding', 'windows-1252'), ] def __init__(self, parent=None): @@ -59,21 +59,21 @@ def __init__(self, parent=None): def load(self): config = get_config() - self.ui.write_wave_riff_info.setChecked(config.setting["write_wave_riff_info"]) - self.ui.remove_wave_riff_info.setChecked(config.setting["remove_wave_riff_info"]) - if config.setting["wave_riff_info_encoding"] == "utf-8": + self.ui.write_wave_riff_info.setChecked(config.setting['write_wave_riff_info']) + self.ui.remove_wave_riff_info.setChecked(config.setting['remove_wave_riff_info']) + if config.setting['wave_riff_info_encoding'] == 'utf-8': self.ui.wave_riff_info_enc_utf8.setChecked(True) else: self.ui.wave_riff_info_enc_cp1252.setChecked(True) def save(self): config = get_config() - config.setting["write_wave_riff_info"] = self.ui.write_wave_riff_info.isChecked() - config.setting["remove_wave_riff_info"] = self.ui.remove_wave_riff_info.isChecked() + config.setting['write_wave_riff_info'] = self.ui.write_wave_riff_info.isChecked() + config.setting['remove_wave_riff_info'] = self.ui.remove_wave_riff_info.isChecked() if self.ui.wave_riff_info_enc_utf8.isChecked(): - config.setting["wave_riff_info_encoding"] = "utf-8" + config.setting['wave_riff_info_encoding'] = 'utf-8' else: - config.setting["wave_riff_info_encoding"] = "windows-1252" + config.setting['wave_riff_info_encoding'] = 'windows-1252' if WAVFile.supports_tag('artist'): diff --git a/picard/ui/passworddialog.py b/picard/ui/passworddialog.py index 43b32afc48..23f0c1f0f6 100644 --- a/picard/ui/passworddialog.py +++ b/picard/ui/passworddialog.py @@ -62,15 +62,15 @@ def __init__(self, authenticator, proxy, parent=None): self.ui.setupUi(self) config = get_config() self.ui.info_text.setText(_("The proxy %s requires you to login. Please enter your username and password.") - % config.setting["proxy_server_host"]) - self.ui.username.setText(config.setting["proxy_username"]) - self.ui.password.setText(config.setting["proxy_password"]) + % config.setting['proxy_server_host']) + self.ui.username.setText(config.setting['proxy_username']) + self.ui.password.setText(config.setting['proxy_password']) self.ui.buttonbox.accepted.connect(self.set_proxy_password) def set_proxy_password(self): config = get_config() - config.setting["proxy_username"] = self.ui.username.text() - config.setting["proxy_password"] = self.ui.password.text() + config.setting['proxy_username'] = self.ui.username.text() + config.setting['proxy_password'] = self.ui.password.text() self._authenticator.setUser(self.ui.username.text()) self._authenticator.setPassword(self.ui.password.text()) self.accept() diff --git a/picard/ui/playertoolbar.py b/picard/ui/playertoolbar.py index 76d26c4b83..6686833c87 100644 --- a/picard/ui/playertoolbar.py +++ b/picard/ui/playertoolbar.py @@ -88,14 +88,14 @@ def __init__(self, parent): self._toolbar = None self._selected_objects = [] if qt_multimedia_available: - log.debug('Internal player: QtMultimedia available, initializing QMediaPlayer') + log.debug("Internal player: QtMultimedia available, initializing QMediaPlayer") player = QtMultimedia.QMediaPlayer(parent) player.setAudioRole(QtMultimedia.QAudio.Role.MusicRole) self.state_changed = player.stateChanged self._logarithmic_volume = get_logarithmic_volume(player.volume()) availability = player.availability() if availability == QtMultimedia.QMultimedia.AvailabilityStatus.Available: - log.debug('Internal player: available, QMediaPlayer set up') + log.debug("Internal player: available, QMediaPlayer set up") self._player = player self._player.error.connect(self._on_error) elif availability == QtMultimedia.QMultimedia.AvailabilityStatus.ServiceMissing: @@ -187,7 +187,7 @@ def _on_error(self, error): class PlayerToolbar(QtWidgets.QToolBar): def __init__(self, parent, player): super().__init__(_("Player"), parent) - self.setObjectName("player_toolbar") + self.setObjectName('player_toolbar') self.setAllowedAreas(QtCore.Qt.ToolBarArea.TopToolBarArea | QtCore.Qt.ToolBarArea.BottomToolBarArea | QtCore.Qt.ToolBarArea.NoToolBarArea) @@ -218,14 +218,14 @@ def __init__(self, parent, player): self.addWidget(self.progress_widget) config = get_config() - volume = config.persist["mediaplayer_volume"] + volume = config.persist['mediaplayer_volume'] self.player.set_volume(volume) self.volume_button = VolumeControlButton(self, volume) self.volume_button.volume_changed.connect(self.player.set_volume) self.volume_button.setToolButtonStyle(self.toolButtonStyle()) self.addWidget(self.volume_button) - playback_rate = config.persist["mediaplayer_playback_rate"] + playback_rate = config.persist['mediaplayer_playback_rate'] self.player.set_playback_rate(playback_rate) self.playback_rate_button = PlaybackRateButton(self, playback_rate) self.playback_rate_button.playback_rate_changed.connect(self.player.set_playback_rate) @@ -273,7 +273,7 @@ def __init__(self, parent, player): self.player = player self._position_update = False - tool_font = QtWidgets.QApplication.font("QToolButton") + tool_font = QtWidgets.QApplication.font('QToolButton') self.progress_slider = ClickableSlider(self) self.progress_slider.setOrientation(QtCore.Qt.Orientation.Horizontal) @@ -340,20 +340,20 @@ class PlaybackRateButton(QtWidgets.QToolButton): def __init__(self, parent, playback_rate): super().__init__(parent) self.popover_position = 'bottom' - self.rate_fmt = N_('%1.1f ×') + self.rate_fmt = N_("%1.1f ×") button_margin = self.style().pixelMetric(QtWidgets.QStyle.PixelMetric.PM_ButtonMargin) min_width = get_text_width(self.font(), _(self.rate_fmt) % 8.8) self.setMinimumWidth(min_width + (2 * button_margin) + 2) self.set_playback_rate(playback_rate) self.clicked.connect(self.show_popover) - tooltip = _('Change playback speed') + tooltip = _("Change playback speed") self.setToolTip(tooltip) self.setStatusTip(tooltip) def show_popover(self): slider_value = self.playback_rate * self.multiplier popover = SliderPopover( - self, self.popover_position, _('Playback speed'), slider_value) + self, self.popover_position, _("Playback speed"), slider_value) # In 0.1 steps from 0.5 to 1.5 popover.slider.setMinimum(5) popover.slider.setMaximum(15) @@ -396,19 +396,19 @@ def __init__(self, parent, volume): super().__init__(parent) self.popover_position = 'bottom' self.step = 3 - self.volume_fmt = N_('%d%%') + self.volume_fmt = N_("%d%%") self.set_volume(volume) button_margin = self.style().pixelMetric(QtWidgets.QStyle.PixelMetric.PM_ButtonMargin) min_width = get_text_width(self.font(), _(self.volume_fmt) % 888) self.setMinimumWidth(min_width + (2 * button_margin) + 2) self.clicked.connect(self.show_popover) - tooltip = _('Change audio volume') + tooltip = _("Change audio volume") self.setToolTip(tooltip) self.setStatusTip(tooltip) def show_popover(self): popover = SliderPopover( - self, self.popover_position, _('Audio volume'), self.volume) + self, self.popover_position, _("Audio volume"), self.volume) popover.slider.setMinimum(0) popover.slider.setMaximum(100) popover.slider.setPageStep(self.step) diff --git a/picard/ui/ratingwidget.py b/picard/ui/ratingwidget.py index 4fd87e0440..5de3621cdf 100644 --- a/picard/ui/ratingwidget.py +++ b/picard/ui/ratingwidget.py @@ -39,9 +39,9 @@ def __init__(self, parent, track): super().__init__(parent) self._track = track config = get_config() - self._maximum = config.setting["rating_steps"] - 1 + self._maximum = config.setting['rating_steps'] - 1 try: - self._rating = int(track.metadata["~rating"] or 0) + self._rating = int(track.metadata['~rating'] or 0) except ValueError: self._rating = 0 self._highlight = 0 @@ -105,12 +105,12 @@ def _submitted(self, document, http, error): def _update_track(self): track = self._track rating = str(self._rating) - track.metadata["~rating"] = rating + track.metadata['~rating'] = rating for file in track.files: - file.metadata["~rating"] = rating + file.metadata['~rating'] = rating config = get_config() - if config.setting["submit_ratings"]: - ratings = {("recording", track.id): self._rating} + if config.setting['submit_ratings']: + ratings = {('recording', track.id): self._rating} try: self.tagger.mb_api.submit_ratings(ratings, self._submitted) except ValueError: # This should never happen as self._rating is always an integer diff --git a/picard/ui/scripteditor.py b/picard/ui/scripteditor.py index ed63318924..0e3faa92f8 100644 --- a/picard/ui/scripteditor.py +++ b/picard/ui/scripteditor.py @@ -137,7 +137,7 @@ def update_examples(self, override=None, script_text=None): if script_text and isinstance(script_text, str): self.script_text = script_text - if self.settings["move_files"] or self.settings["rename_files"]: + if self.settings['move_files'] or self.settings['rename_files']: if not self._sampled_example_files: self.update_sample_example_files() self.example_list = [self._example_to_filename(example) for example in self._sampled_example_files] @@ -159,14 +159,14 @@ def _example_to_filename(self, file): c_metadata.copy(file.metadata) try: # Only apply scripts if the original file metadata has not been changed. - if self.settings["enable_tagger_scripts"] and not c_metadata.diff(file.orig_metadata): - for s_pos, s_name, s_enabled, s_text in self.settings["list_of_scripts"]: + if self.settings['enable_tagger_scripts'] and not c_metadata.diff(file.orig_metadata): + for s_pos, s_name, s_enabled, s_text in self.settings['list_of_scripts']: if s_enabled and s_text: parser = ScriptParser() parser.eval(s_text, c_metadata) filename_before = file.filename filename_after = file.make_filename(filename_before, c_metadata, self.settings, self.script_text) - if not self.settings["move_files"]: + if not self.settings['move_files']: return os.path.basename(filename_before), os.path.basename(filename_after) return filename_before, filename_after except (ScriptError, TypeError, WinPathTooLong): @@ -316,7 +316,7 @@ def confirmation_dialog(parent, message): """ dialog = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Icon.Warning, - _('Confirm'), + _("Confirm"), message, QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel, parent @@ -395,15 +395,15 @@ class ScriptEditorDialog(PicardDialog, SingletonDialog): PROFILES_KEY = SettingConfigSection.PROFILES_KEY SETTINGS_KEY = SettingConfigSection.SETTINGS_KEY - SELECTED_SCRIPT_KEY = "selected_file_naming_script_id" - SCRIPTS_LIST_KEY = "file_renaming_scripts" + SELECTED_SCRIPT_KEY = 'selected_file_naming_script_id' + SCRIPTS_LIST_KEY = 'file_renaming_scripts' - help_url = PICARD_URLS["doc_naming_script_edit"] + help_url = PICARD_URLS['doc_naming_script_edit'] options = [ BoolOption('persist', 'script_editor_show_documentation', False), - Option("setting", SCRIPTS_LIST_KEY, {}), - TextOption("setting", SELECTED_SCRIPT_KEY, ""), + Option('setting', SCRIPTS_LIST_KEY, {}), + TextOption('setting', SELECTED_SCRIPT_KEY, ''), ] signal_save = QtCore.pyqtSignal() @@ -456,7 +456,7 @@ def __init__(self, parent=None, examples=None): self.installEventFilter(self) # Dialog buttons - self.reset_button = QtWidgets.QPushButton(_('Reset')) + self.reset_button = QtWidgets.QPushButton(_("Reset")) self.reset_button.setToolTip(self.reset_action.toolTip()) self.reset_button.clicked.connect(self.reload_from_config) self.ui.buttonbox.addButton(self.reset_button, QtWidgets.QDialogButtonBox.ButtonRole.ActionRole) @@ -530,7 +530,7 @@ def make_menu(self): main_menu = QtWidgets.QMenuBar() # File menu settings - file_menu = main_menu.addMenu(_('&File')) + file_menu = main_menu.addMenu(_("&File")) file_menu.setToolTipsVisible(True) self.import_action = QtWidgets.QAction(_("&Import a script file"), self) @@ -563,7 +563,7 @@ def make_menu(self): file_menu.addAction(self.close_action) # Script menu settings - script_menu = main_menu.addMenu(_('&Script')) + script_menu = main_menu.addMenu(_("&Script")) script_menu.setToolTipsVisible(True) self.details_action = QtWidgets.QAction(_("View/Edit Script &Metadata"), self) @@ -590,7 +590,7 @@ def make_menu(self): script_menu.addAction(self.delete_action) # Display menu settings - display_menu = main_menu.addMenu(_('&View')) + display_menu = main_menu.addMenu(_("&View")) display_menu.setToolTipsVisible(True) self.examples_action = QtWidgets.QAction(_("&Reload random example files"), self) @@ -611,7 +611,7 @@ def make_menu(self): display_menu.addAction(self.docs_action) # Help menu settings - help_menu = main_menu.addMenu(_('&Help')) + help_menu = main_menu.addMenu(_("&Help")) help_menu.setToolTipsVisible(True) self.help_action = QtWidgets.QAction(_("&Help…"), self) @@ -638,7 +638,7 @@ def _add_menu_item(title, script): self.add_action.addAction(script_action) # Add blank script template - _add_menu_item(_('Empty / blank script'), f"$noop( {_('New Script')} )") + _add_menu_item(_("Empty / blank script"), f"$noop( {_('New Script')} )") # Add preset script templates for script_item in get_file_naming_script_presets(): @@ -802,12 +802,12 @@ def scripts_in_profiles(self): profiles = config.profiles[self.PROFILES_KEY] profile_settings = config.profiles[self.SETTINGS_KEY] for profile in profiles: - settings = profile_settings[profile["id"]] + settings = profile_settings[profile['id']] if self.SELECTED_SCRIPT_KEY in settings: profiles_list.append( self.Profile( - profile["id"], - profile["title"], + profile['id'], + profile['title'], settings[self.SELECTED_SCRIPT_KEY] ) ) @@ -818,7 +818,7 @@ def update_script_text(self): """ selected = self.ui.preset_naming_scripts.currentIndex() script_item = self.ui.preset_naming_scripts.itemData(selected) - script_item["script"] = self.get_script() + script_item['script'] = self.get_script() self.update_combo_box_item(selected, script_item) def check_duplicate_script_title(self, new_title=None): @@ -849,7 +849,7 @@ def update_script_title(self): script_item = self.ui.preset_naming_scripts.itemData(selected) if title: if self.check_duplicate_script_title(new_title=title): - script_item["title"] = title + script_item['title'] = title self.update_combo_box_item(selected, script_item) self.save_script() self.signal_selection_changed.emit() @@ -858,7 +858,7 @@ def update_script_title(self): self.ui.script_title.setFocus() else: self.display_error(OptionsCheckError(_("Error"), _("The script title must not be empty."))) - self.ui.script_title.setText(script_item["title"]) + self.ui.script_title.setText(script_item['title']) self.ui.script_title.setFocus() def populate_script_selector(self): @@ -872,7 +872,7 @@ def toggle_documentation(self): """ checked = self.docs_action.isChecked() config = get_config() - config.persist["script_editor_show_documentation"] = checked + config.persist['script_editor_show_documentation'] = checked self.ui.documentation_frame.setVisible(checked) def view_script_details(self): @@ -916,7 +916,7 @@ def _insert_item(self, script_item): Args: script_item (dict): File naming script to insert as produced by FileNamingScript().to_dict() """ - self.selected_script_id = script_item["id"] + self.selected_script_id = script_item['id'] self.naming_scripts[self.selected_script_id] = script_item idx = populate_script_selection_combo_box( self.naming_scripts, @@ -958,11 +958,11 @@ def make_it_so(self): """Save the scripts and settings to configuration and exit. """ script_item = self.get_selected_item() - self.selected_script_id = script_item["id"] + self.selected_script_id = script_item['id'] self.naming_scripts = self.get_scripts_dict() config = get_config() config.setting[self.SCRIPTS_LIST_KEY] = self.naming_scripts - config.setting[self.SELECTED_SCRIPT_KEY] = script_item["id"] + config.setting[self.SELECTED_SCRIPT_KEY] = script_item['id'] self.close() def get_scripts_dict(self): @@ -974,7 +974,7 @@ def get_scripts_dict(self): naming_scripts = {} for idx in range(self.ui.preset_naming_scripts.count()): script_item = self.ui.preset_naming_scripts.itemData(idx) - naming_scripts[script_item["id"]] = script_item + naming_scripts[script_item['id']] = script_item return naming_scripts def get_selected_item(self, idx=None): @@ -999,7 +999,7 @@ def set_selected_script_id(self, id): idx = 0 for i in range(self.ui.preset_naming_scripts.count()): script_item = self.ui.preset_naming_scripts.itemData(i) - if script_item["id"] == id: + if script_item['id'] == id: idx = i break self.set_selected_script_index(idx) @@ -1119,7 +1119,7 @@ def delete_script(self): ).exec_() return - if confirmation_dialog(self, _('Are you sure that you want to delete the script?')): + if confirmation_dialog(self, _("Are you sure that you want to delete the script?")): widget = self.ui.preset_naming_scripts idx = widget.currentIndex() widget.blockSignals(True) @@ -1159,8 +1159,8 @@ def save_script(self): if title: script_item = self.ui.preset_naming_scripts.itemData(selected) if self.check_duplicate_script_title(new_title=title): - script_item["title"] = title - script_item["script"] = self.get_script() + script_item['title'] = title + script_item['script'] = self.get_script() self.update_combo_box_item(selected, script_item) else: self.display_error(OptionsCheckError(_("Error"), _("The script title must not be empty."))) @@ -1224,7 +1224,7 @@ def import_script(self): continue box = QtWidgets.QMessageBox() box.setIcon(QtWidgets.QMessageBox.Icon.Question) - box.setWindowTitle(_('Confirm')) + box.setWindowTitle(_("Confirm")) box.setText( _( "A script named \"{script_name}\" already exists.\n" @@ -1279,7 +1279,7 @@ def check_format(self): parser.eval(script_text) except Exception as e: raise ScriptCheckError("", str(e)) - if config.setting["rename_files"]: + if config.setting['rename_files']: if not self.get_script(): raise ScriptCheckError("", _("The file naming format must not be empty.")) @@ -1318,7 +1318,7 @@ class ScriptDetailsEditor(PicardDialog): """View / edit the metadata details for a script. """ NAME = 'scriptdetails' - TITLE = N_('Script Details') + TITLE = N_("Script Details") signal_save = QtCore.pyqtSignal() @@ -1401,12 +1401,12 @@ def save_changes(self): last_updated = self.ui.script_last_updated if not last_updated.isModified() or not last_updated.text().strip(): self.set_last_updated() - self.script_item["title"] = self.ui.script_title.text().strip() - self.script_item["author"] = self.ui.script_author.text().strip() - self.script_item["version"] = self.ui.script_version.text().strip() - self.script_item["license"] = self.ui.script_license.text().strip() - self.script_item["description"] = self.ui.script_description.toPlainText().strip() - self.script_item["last_updated"] = self.ui.script_last_updated.text().strip() + self.script_item['title'] = self.ui.script_title.text().strip() + self.script_item['author'] = self.ui.script_author.text().strip() + self.script_item['version'] = self.ui.script_version.text().strip() + self.script_item['license'] = self.ui.script_license.text().strip() + self.script_item['description'] = self.ui.script_description.toPlainText().strip() + self.script_item['last_updated'] = self.ui.script_last_updated.text().strip() self.signal_save.emit() self.skip_change_check = True self.close_window() diff --git a/picard/ui/searchdialog/__init__.py b/picard/ui/searchdialog/__init__.py index 23bd979635..cc69f65e65 100644 --- a/picard/ui/searchdialog/__init__.py +++ b/picard/ui/searchdialog/__init__.py @@ -51,7 +51,7 @@ def __init__(self, parent, force_advanced_search=None): if force_advanced_search is None: config = get_config() self.force_advanced_search = False - self.use_advanced_search = config.setting["use_adv_search_syntax"] + self.use_advanced_search = config.setting['use_adv_search_syntax'] else: self.force_advanced_search = True self.use_advanced_search = force_advanced_search @@ -118,7 +118,7 @@ def update_advanced_syntax_setting(self): self.use_advanced_search = self.use_adv_search_syntax.isChecked() if not self.force_advanced_search: config = get_config() - config.setting["use_adv_search_syntax"] = self.use_advanced_search + config.setting['use_adv_search_syntax'] = self.use_advanced_search def enable_search(self): if self.query: @@ -139,7 +139,7 @@ def set_query(self, query): query = property(get_query, set_query) -Retry = namedtuple("Retry", ["function", "query"]) +Retry = namedtuple('Retry', ['function', 'query']) class SearchDialog(TableBasedDialog): @@ -162,22 +162,22 @@ def use_advanced_search(self): return self.force_advanced_search else: config = get_config() - return config.setting["use_adv_search_syntax"] + return config.setting['use_adv_search_syntax'] def get_value_for_row_id(self, row, value): return row def setupUi(self): self.verticalLayout = QtWidgets.QVBoxLayout(self) - self.verticalLayout.setObjectName("vertical_layout") + self.verticalLayout.setObjectName('vertical_layout') if self.show_search: self.search_box = SearchBox(self, force_advanced_search=self.force_advanced_search) - self.search_box.setObjectName("search_box") + self.search_box.setObjectName('search_box') self.verticalLayout.addWidget(self.search_box) self.center_widget = QtWidgets.QWidget(self) - self.center_widget.setObjectName("center_widget") + self.center_widget.setObjectName('center_widget') self.center_layout = QtWidgets.QVBoxLayout(self.center_widget) - self.center_layout.setObjectName("center_layout") + self.center_layout.setObjectName('center_layout') self.center_layout.setContentsMargins(1, 1, 1, 1) self.center_widget.setLayout(self.center_layout) self.verticalLayout.addWidget(self.center_widget) @@ -205,7 +205,7 @@ def setupUi(self): def show_progress(self): progress_widget = QtWidgets.QWidget(self) - progress_widget.setObjectName("progress_widget") + progress_widget.setObjectName('progress_widget') layout = QtWidgets.QVBoxLayout(progress_widget) text_label = QtWidgets.QLabel(_('Loading…'), progress_widget) text_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter | QtCore.Qt.AlignmentFlag.AlignBottom) @@ -228,7 +228,7 @@ def show_error(self, error, show_retry_button=False): show_retry_button -- Whether to display retry button or not """ error_widget = QtWidgets.QWidget(self) - error_widget.setObjectName("error_widget") + error_widget.setObjectName('error_widget') layout = QtWidgets.QVBoxLayout(error_widget) error_label = QtWidgets.QLabel(error, error_widget) error_label.setWordWrap(True) diff --git a/picard/ui/searchdialog/album.py b/picard/ui/searchdialog/album.py index 8b15dc6597..83a85b19c2 100644 --- a/picard/ui/searchdialog/album.py +++ b/picard/ui/searchdialog/album.py @@ -133,17 +133,17 @@ def invalidate(self): class AlbumSearchDialog(SearchDialog): - dialog_header_state = "albumsearchdialog_header_state" + dialog_header_state = 'albumsearchdialog_header_state' options = [ - Option("persist", dialog_header_state, QtCore.QByteArray()) + Option('persist', dialog_header_state, QtCore.QByteArray()) ] def __init__(self, parent, force_advanced_search=None, existing_album=None): super().__init__( parent, accept_button_title=_("Load into Picard"), - search_type="album", + search_type='album', force_advanced_search=force_advanced_search) self.cluster = None self.existing_album = existing_album @@ -206,7 +206,7 @@ def show_similar_albums(self, cluster): if self.use_advanced_search: query_str = build_lucene_query(query) else: - query_str = query["release"] + query_str = query['release'] self.search(query_str) def retry(self): @@ -245,7 +245,7 @@ def fetch_coverart(self, cell): if not cell.is_visible(): return cell.fetched = True - mbid = cell.release["musicbrainz_albumid"] + mbid = cell.release['musicbrainz_albumid'] cell.fetch_task = self.tagger.webservice.get_url( url=f'{CAA_URL}/release/{mbid}', handler=partial(self._caa_json_downloaded, cell), @@ -264,14 +264,14 @@ def _caa_json_downloaded(self, cover_cell, data, http, error): front = None try: - for image in data["images"]: - if image["front"]: + for image in data['images']: + if image['front']: front = image break if front: cover_cell.fetch_task = self.tagger.webservice.download_url( - url=front["thumbnails"]["small"], + url=front['thumbnails']['small'], handler=partial(self._cover_downloaded, cover_cell) ) else: @@ -320,13 +320,13 @@ def parse_releases(self, releases): release['score'] = node['score'] rg_node = node['release-group'] release_group_to_metadata(rg_node, release) - if "media" in node: + if 'media' in node: media = node['media'] - release["format"] = media_formats_from_node(media) - release["tracks"] = node['track-count'] + release['format'] = media_formats_from_node(media) + release['tracks'] = node['track-count'] countries = countries_from_node(node) if countries: - release["country"] = countries_shortlist(countries) + release['country'] = countries_shortlist(countries) self.search_results.append(release) def display_results(self): @@ -335,19 +335,19 @@ def display_results(self): column = self.colpos('cover') for row, release in enumerate(self.search_results): self.table.insertRow(row) - self.set_table_item(row, 'name', release, "album") - self.set_table_item(row, 'artist', release, "albumartist") - self.set_table_item(row, 'format', release, "format") - self.set_table_item(row, 'tracks', release, "tracks") - self.set_table_item(row, 'date', release, "date") - self.set_table_item(row, 'country', release, "country") - self.set_table_item(row, 'labels', release, "label") - self.set_table_item(row, 'catnums', release, "catalognumber") - self.set_table_item(row, 'barcode', release, "barcode") - self.set_table_item(row, 'language', release, "~releaselanguage") - self.set_table_item(row, 'type', release, "releasetype") - self.set_table_item(row, 'status', release, "releasestatus") - self.set_table_item(row, 'score', release, "score") + self.set_table_item(row, 'name', release, 'album') + self.set_table_item(row, 'artist', release, 'albumartist') + self.set_table_item(row, 'format', release, 'format') + self.set_table_item(row, 'tracks', release, 'tracks') + self.set_table_item(row, 'date', release, 'date') + self.set_table_item(row, 'country', release, 'country') + self.set_table_item(row, 'labels', release, 'label') + self.set_table_item(row, 'catnums', release, 'catalognumber') + self.set_table_item(row, 'barcode', release, 'barcode') + self.set_table_item(row, 'language', release, '~releaselanguage') + self.set_table_item(row, 'type', release, 'releasetype') + self.set_table_item(row, 'status', release, 'releasestatus') + self.set_table_item(row, 'score', release, 'score') self.cover_cells.append(CoverCell(self.table, release, row, column, on_show=self.fetch_coverart)) if self.existing_album and release['musicbrainz_albumid'] == self.existing_album.id: @@ -360,12 +360,12 @@ def accept_event(self, rows): def load_selection(self, row): release = self.search_results[row] - release_mbid = release["musicbrainz_albumid"] + release_mbid = release['musicbrainz_albumid'] if self.existing_album: self.existing_album.switch_release_version(release_mbid) else: self.tagger.get_release_group_by_id( - release["musicbrainz_releasegroupid"]).loaded_albums.add( + release['musicbrainz_releasegroupid']).loaded_albums.add( release_mbid) album = self.tagger.load_album(release_mbid) if self.cluster: diff --git a/picard/ui/searchdialog/artist.py b/picard/ui/searchdialog/artist.py index e8b6ab1d11..4787cf379e 100644 --- a/picard/ui/searchdialog/artist.py +++ b/picard/ui/searchdialog/artist.py @@ -38,17 +38,17 @@ class ArtistSearchDialog(SearchDialog): - dialog_header_state = "artistsearchdialog_header_state" + dialog_header_state = 'artistsearchdialog_header_state' options = [ - Option("persist", dialog_header_state, QtCore.QByteArray()) + Option('persist', dialog_header_state, QtCore.QByteArray()) ] def __init__(self, parent): super().__init__( parent, accept_button_title=_("Show in browser"), - search_type="artist") + search_type='artist') self.setWindowTitle(_("Artist Search Dialog")) self.columns = [ ('name', _("Name")), @@ -102,15 +102,15 @@ def display_results(self): self.prepare_table() for row, artist in enumerate(self.search_results): self.table.insertRow(row) - self.set_table_item(row, 'name', artist, "name") - self.set_table_item(row, 'type', artist, "type") - self.set_table_item(row, 'gender', artist, "gender") - self.set_table_item(row, 'area', artist, "area") - self.set_table_item(row, 'begindate', artist, "begindate") - self.set_table_item(row, 'beginarea', artist, "beginarea") - self.set_table_item(row, 'enddate', artist, "enddate") - self.set_table_item(row, 'endarea', artist, "endarea") - self.set_table_item(row, 'score', artist, "score") + self.set_table_item(row, 'name', artist, 'name') + self.set_table_item(row, 'type', artist, 'type') + self.set_table_item(row, 'gender', artist, 'gender') + self.set_table_item(row, 'area', artist, 'area') + self.set_table_item(row, 'begindate', artist, 'begindate') + self.set_table_item(row, 'beginarea', artist, 'beginarea') + self.set_table_item(row, 'enddate', artist, 'enddate') + self.set_table_item(row, 'endarea', artist, 'endarea') + self.set_table_item(row, 'score', artist, 'score') self.show_table(sort_column='score') def accept_event(self, rows): @@ -118,4 +118,4 @@ def accept_event(self, rows): self.load_in_browser(row) def load_in_browser(self, row): - self.tagger.search(self.search_results[row]["musicbrainz_artistid"], "artist") + self.tagger.search(self.search_results[row]['musicbrainz_artistid'], 'artist') diff --git a/picard/ui/searchdialog/track.py b/picard/ui/searchdialog/track.py index f61d97a332..0489496d3f 100644 --- a/picard/ui/searchdialog/track.py +++ b/picard/ui/searchdialog/track.py @@ -51,17 +51,17 @@ class TrackSearchDialog(SearchDialog): - dialog_header_state = "tracksearchdialog_header_state" + dialog_header_state = 'tracksearchdialog_header_state' options = [ - Option("persist", dialog_header_state, QtCore.QByteArray()) + Option('persist', dialog_header_state, QtCore.QByteArray()) ] def __init__(self, parent, force_advanced_search=None): super().__init__( parent, accept_button_title=_("Load into Picard"), - search_type="track", + search_type='track', force_advanced_search=force_advanced_search) self.file_ = None self.setWindowTitle(_("Track Search Results")) @@ -108,7 +108,7 @@ def show_similar_tracks(self, file_): if self.use_advanced_search: query_str = build_lucene_query(query) else: - query_str = query["track"] + query_str = query['track'] self.search(query_str) def retry(self): @@ -142,19 +142,19 @@ def display_results(self): for row, obj in enumerate(self.search_results): track = obj[0] self.table.insertRow(row) - self.set_table_item(row, 'name', track, "title") - self.set_table_item(row, 'length', track, "~length", sortkey=track.length) - self.set_table_item(row, 'artist', track, "artist") - self.set_table_item(row, 'release', track, "album") - self.set_table_item(row, 'date', track, "date") - self.set_table_item(row, 'country', track, "country") - self.set_table_item(row, 'type', track, "releasetype") - self.set_table_item(row, 'score', track, "score") + self.set_table_item(row, 'name', track, 'title') + self.set_table_item(row, 'length', track, '~length', sortkey=track.length) + self.set_table_item(row, 'artist', track, 'artist') + self.set_table_item(row, 'release', track, 'album') + self.set_table_item(row, 'date', track, 'date') + self.set_table_item(row, 'country', track, 'country') + self.set_table_item(row, 'type', track, 'releasetype') + self.set_table_item(row, 'score', track, 'score') self.show_table(sort_column='score') def parse_tracks(self, tracks): for node in tracks: - if "releases" in node: + if 'releases' in node: for rel_node in node['releases']: track = Metadata() recording_to_metadata(node, track) @@ -164,7 +164,7 @@ def parse_tracks(self, tracks): release_group_to_metadata(rg_node, track) countries = countries_from_node(rel_node) if countries: - track["country"] = countries_shortlist(countries) + track['country'] = countries_shortlist(countries) self.search_results.append((track, node)) else: # This handles the case when no release is associated with a track @@ -186,30 +186,30 @@ def load_selection(self, row): """ track, node = self.search_results[row] - if track.get("musicbrainz_albumid"): + if track.get('musicbrainz_albumid'): # The track is not an NAT - self.tagger.get_release_group_by_id(track["musicbrainz_releasegroupid"]).loaded_albums.add( - track["musicbrainz_albumid"]) + self.tagger.get_release_group_by_id(track['musicbrainz_releasegroupid']).loaded_albums.add( + track['musicbrainz_albumid']) if self.file_: # Search is performed for a file. # Have to move that file from its existing album to the new one. if isinstance(self.file_.parent, Track): album = self.file_.parent.album - self.tagger.move_file_to_track(self.file_, track["musicbrainz_albumid"], track["musicbrainz_recordingid"]) + self.tagger.move_file_to_track(self.file_, track['musicbrainz_albumid'], track['musicbrainz_recordingid']) if album.get_num_total_files() == 0: # Remove album if it has no more files associated self.tagger.remove_album(album) else: - self.tagger.move_file_to_track(self.file_, track["musicbrainz_albumid"], track["musicbrainz_recordingid"]) + self.tagger.move_file_to_track(self.file_, track['musicbrainz_albumid'], track['musicbrainz_recordingid']) else: # No files associated. Just a normal search. - self.tagger.load_album(track["musicbrainz_albumid"]) + self.tagger.load_album(track['musicbrainz_albumid']) else: if self.file_ and getattr(self.file_.parent, 'album', None): album = self.file_.parent.album - self.tagger.move_file_to_nat(self.file_, track["musicbrainz_recordingid"], node) + self.tagger.move_file_to_nat(self.file_, track['musicbrainz_recordingid'], node) if album.get_num_total_files() == 0: self.tagger.remove_album(album) else: - self.tagger.load_nat(track["musicbrainz_recordingid"], node) - self.tagger.move_file_to_nat(self.file_, track["musicbrainz_recordingid"], node) + self.tagger.load_nat(track['musicbrainz_recordingid'], node) + self.tagger.move_file_to_nat(self.file_, track['musicbrainz_recordingid'], node) diff --git a/picard/ui/statusindicator.py b/picard/ui/statusindicator.py index 847946c305..4ce84d10fc 100644 --- a/picard/ui/statusindicator.py +++ b/picard/ui/statusindicator.py @@ -129,8 +129,8 @@ def __init__(self, bus, app_id): @property def current_progress(self): return { - "progress": self._progress, - "progress-visible": self._visible, + 'progress': self._progress, + 'progress-visible': self._visible, } @property diff --git a/picard/ui/tagsfromfilenames.py b/picard/ui/tagsfromfilenames.py index 570f33bd4b..3e3caedb3f 100644 --- a/picard/ui/tagsfromfilenames.py +++ b/picard/ui/tagsfromfilenames.py @@ -101,7 +101,7 @@ class TagsFromFileNamesDialog(PicardDialog): help_url = 'doc_tags_from_filenames' options = [ - TextOption("persist", "tags_from_filenames_format", ""), + TextOption('persist', 'tags_from_filenames_format', ''), ] def __init__(self, files, parent=None): @@ -118,7 +118,7 @@ def __init__(self, files, parent=None): "%artist% - %album%/%tracknumber% - %title%", ] config = get_config() - tff_format = config.persist["tags_from_filenames_format"] + tff_format = config.persist['tags_from_filenames_format'] if tff_format not in items: selected_index = 0 if tff_format: @@ -163,5 +163,5 @@ def accept(self): file.metadata.update(metadata) file.update() config = get_config() - config.persist["tags_from_filenames_format"] = self.ui.format.currentText() + config.persist['tags_from_filenames_format'] = self.ui.format.currentText() super().accept() diff --git a/picard/ui/theme.py b/picard/ui/theme.py index c445dafd8a..8714d80cab 100644 --- a/picard/ui/theme.py +++ b/picard/ui/theme.py @@ -178,7 +178,7 @@ def is_dark_theme(self): r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize") as key: dark_theme = winreg.QueryValueEx(key, "AppsUseLightTheme")[0] == 0 except OSError: - log.warning('Failed reading AppsUseLightTheme from registry') + log.warning("Failed reading AppsUseLightTheme from registry") return dark_theme @property @@ -190,7 +190,7 @@ def accent_color(self): accent_color_hex = '#{:06x}'.format(accent_color_dword & 0xffffff) accent_color = QtGui.QColor(accent_color_hex) except OSError: - log.warning('Failed reading ColorizationColor from registry') + log.warning("Failed reading ColorizationColor from registry") return accent_color def update_palette(self, palette, dark_theme, accent_color): diff --git a/picard/ui/util.py b/picard/ui/util.py index 8a164656ec..9db80f7616 100644 --- a/picard/ui/util.py +++ b/picard/ui/util.py @@ -46,10 +46,10 @@ class StandardButton(QtWidgets.QPushButton): CLOSE = 4 __types = { - OK: (N_('&Ok'), 'SP_DialogOkButton'), - CANCEL: (N_('&Cancel'), 'SP_DialogCancelButton'), - HELP: (N_('&Help'), 'SP_DialogHelpButton'), - CLOSE: (N_('Clos&e'), 'SP_DialogCloseButton'), + OK: (N_("&Ok"), 'SP_DialogOkButton'), + CANCEL: (N_("&Cancel"), 'SP_DialogCancelButton'), + HELP: (N_("&Help"), 'SP_DialogHelpButton'), + CLOSE: (N_("Clos&e"), 'SP_DialogCloseButton'), } def __init__(self, btntype): @@ -65,10 +65,10 @@ def __init__(self, btntype): def find_starting_directory(): config = get_config() - if config.setting["starting_directory"]: - path = config.setting["starting_directory_path"] + if config.setting['starting_directory']: + path = config.setting['starting_directory_path'] else: - path = config.persist["current_directory"] or QtCore.QDir.homePath() + path = config.persist['current_directory'] or QtCore.QDir.homePath() return find_existing_path(path) diff --git a/picard/ui/widgets/scriptdocumentation.py b/picard/ui/widgets/scriptdocumentation.py index 2a3756dc55..7897cb62a8 100644 --- a/picard/ui/widgets/scriptdocumentation.py +++ b/picard/ui/widgets/scriptdocumentation.py @@ -110,17 +110,17 @@ def process_html(html, function): self.verticalLayout = QtWidgets.QVBoxLayout(self) self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.verticalLayout.setObjectName("docs_verticalLayout") + self.verticalLayout.setObjectName('docs_verticalLayout') self.textBrowser = QtWidgets.QTextBrowser(self) self.textBrowser.setEnabled(True) self.textBrowser.setMinimumSize(QtCore.QSize(0, 0)) - self.textBrowser.setObjectName("docs_textBrowser") + self.textBrowser.setObjectName('docs_textBrowser') self.textBrowser.setHtml(html) self.textBrowser.show() self.verticalLayout.addWidget(self.textBrowser) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setContentsMargins(-1, 0, -1, -1) - self.horizontalLayout.setObjectName("docs_horizontalLayout") + self.horizontalLayout.setObjectName('docs_horizontalLayout') self.scripting_doc_link = QtWidgets.QLabel(self) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -132,7 +132,7 @@ def process_html(html, function): self.scripting_doc_link.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.scripting_doc_link.setWordWrap(True) self.scripting_doc_link.setOpenExternalLinks(True) - self.scripting_doc_link.setObjectName("docs_scripting_doc_link") + self.scripting_doc_link.setObjectName('docs_scripting_doc_link') self.scripting_doc_link.setText(link) self.scripting_doc_link.show() self.horizontalLayout.addWidget(self.scripting_doc_link) diff --git a/picard/util/__init__.py b/picard/util/__init__.py index a83d8b9d93..5f211c6fba 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -245,7 +245,7 @@ def system_supports_long_paths(): system_supports_long_paths._supported = supported return supported except OSError: - log.info('Failed reading LongPathsEnabled from registry') + log.info("Failed reading LongPathsEnabled from registry") return False @@ -257,7 +257,7 @@ def normpath(path): # realpath can fail if path does not exist or is not accessible # or on Windows if drives are mounted without mount manager # (see https://tickets.metabrainz.org/browse/PICARD-2425). - log.warning('Failed getting realpath for "%s": %s', path, why) + log.warning("Failed getting realpath for `%s`: %s", path, why) # If the path is longer than 259 characters on Windows, prepend the \\?\ # prefix. This enables access to long paths using the Windows API. See # https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation @@ -400,7 +400,7 @@ def translate_from_sortname(name, sortname): """'Translate' the artist name by reversing the sortname.""" for c in name: ctg = unicodedata.category(c) - if ctg[0] == "L" and unicodedata.name(c).find("LATIN") == -1: + if ctg[0] == "L" and unicodedata.name(c).find('LATIN') == -1: for separator in (" & ", "; ", " and ", " vs. ", " with ", " y "): if separator in sortname: parts = sortname.split(separator) @@ -749,11 +749,11 @@ def build_qurl(host, port=80, path=None, queryargs=None): url.setHost(host) if port == 443 or host in MUSICBRAINZ_SERVERS: - url.setScheme("https") + url.setScheme('https') elif port == 80: - url.setScheme("http") + url.setScheme('http') else: - url.setScheme("http") + url.setScheme('http') url.setPort(port) if path is not None: diff --git a/picard/util/bytes2human.py b/picard/util/bytes2human.py index 5794a5aa8f..a26a117fee 100644 --- a/picard/util/bytes2human.py +++ b/picard/util/bytes2human.py @@ -34,17 +34,17 @@ # used to force gettextization _BYTES_STRINGS_I18N = ( - N_('%(value)s B'), - N_('%(value)s kB'), - N_('%(value)s KiB'), - N_('%(value)s MB'), - N_('%(value)s MiB'), - N_('%(value)s GB'), - N_('%(value)s GiB'), - N_('%(value)s TB'), - N_('%(value)s TiB'), - N_('%(value)s PB'), - N_('%(value)s PiB'), + N_("%(value)s B"), + N_("%(value)s kB"), + N_("%(value)s KiB"), + N_("%(value)s MB"), + N_("%(value)s MiB"), + N_("%(value)s GB"), + N_("%(value)s GiB"), + N_("%(value)s TB"), + N_("%(value)s TiB"), + N_("%(value)s PB"), + N_("%(value)s PiB"), ) @@ -116,9 +116,9 @@ def calc_unit(number, multiple=1000): elif multiple == 1024: k, b = 'K', 'iB' else: - raise ValueError('multiple parameter has to be 1000 or 1024') + raise ValueError("multiple parameter has to be 1000 or 1024") - suffixes = ["B"] + [i + b for i in k + "MGTP"] + suffixes = ['B'] + [i + b for i in k + 'MGTP'] for suffix in suffixes: if n < multiple or suffix == suffixes[-1]: return (sign * n, suffix) diff --git a/picard/util/cdrom.py b/picard/util/cdrom.py index 8d8c31d0f2..d43b11046c 100644 --- a/picard/util/cdrom.py +++ b/picard/util/cdrom.py @@ -63,7 +63,7 @@ def _generic_iter_drives(): config = get_config() yield from ( device.strip() for device - in config.setting["cd_lookup_device"].split(",") + in config.setting['cd_lookup_device'].split(',') if device and not device.isspace() ) @@ -97,7 +97,7 @@ def _iter_drives(): mask = GetLogicalDrives() for i in range(26): if mask >> i & 1: - drive = chr(i + ord("A")) + ":" + drive = chr(i + ord('A')) + ':' if GetDriveType(drive) == DRIVE_TYPE_CDROM: yield drive diff --git a/picard/util/checkupdate.py b/picard/util/checkupdate.py index f2ac320cff..78593e1fa0 100644 --- a/picard/util/checkupdate.py +++ b/picard/util/checkupdate.py @@ -128,7 +128,7 @@ def _display_results(self): try: test_version = Version(*version_tuple) except (TypeError, VersionError): - log.error('Invalid version %r for update level %s.', version_tuple, update_level) + log.error("Invalid version %r for update level %s.", version_tuple, update_level) continue if self._update_level >= test_key and test_version > high_version: key = PROGRAM_UPDATE_LEVELS[test_key]['name'] @@ -153,7 +153,7 @@ def _display_results(self): if self._update_level in PROGRAM_UPDATE_LEVELS: update_level = PROGRAM_UPDATE_LEVELS[self._update_level]['title'] else: - update_level = N_('unknown') + update_level = N_("unknown") QMessageBox.information( self._parent, _("Picard Update"), diff --git a/picard/util/emptydir.py b/picard/util/emptydir.py index 48e1aa37bf..5edb4d86c8 100644 --- a/picard/util/emptydir.py +++ b/picard/util/emptydir.py @@ -84,8 +84,8 @@ def rm_empty_dir(path): or considered a special directory. """ if os.path.realpath(path) in PROTECTED_DIRECTORIES: - raise SkipRemoveDir('%s is a protected directory' % path) + raise SkipRemoveDir("%s is a protected directory" % path) elif not is_empty_dir(path): - raise SkipRemoveDir('%s is not empty' % path) + raise SkipRemoveDir("%s is not empty" % path) else: shutil.rmtree(path) diff --git a/picard/util/filenaming.py b/picard/util/filenaming.py index 11e4c28b4e..6f5ae72fa4 100644 --- a/picard/util/filenaming.py +++ b/picard/util/filenaming.py @@ -60,7 +60,7 @@ import pywintypes import win32api except ImportError as e: - log.warning('pywin32 not available: %s', e) + log.warning("pywin32 not available: %s", e) def _get_utf16_length(text): diff --git a/picard/util/imageinfo.py b/picard/util/imageinfo.py index 4795e74f5f..2fc20814fc 100644 --- a/picard/util/imageinfo.py +++ b/picard/util/imageinfo.py @@ -53,7 +53,7 @@ def __init__(self, data): self.data = data self.datalen = len(self.data) if self.datalen < 16: - raise NotEnoughData('Not enough data') + raise NotEnoughData("Not enough data") def read(self): self._read() @@ -176,7 +176,7 @@ def _read(self): index = data.find(b'\x9d\x01\x2a') if index != -1: if self.datalen < index + 7: - raise NotEnoughData('Not enough data for WebP VP8') + raise NotEnoughData("Not enough data for WebP VP8") self.w, self.h = struct.unpack(' str: self.__create_pipe() if message is not None: - message = message.decode("utf-8") + message = message.decode('utf-8') if exit_code == 0: return message # type: ignore else: diff --git a/picard/util/remotecommands.py b/picard/util/remotecommands.py index b61ac47f0d..4c9112b0ae 100644 --- a/picard/util/remotecommands.py +++ b/picard/util/remotecommands.py @@ -36,93 +36,93 @@ def __init__(self, method_name, help_text=None, help_args=None): REMOTE_COMMANDS = { - "CLEAR_LOGS": RemoteCommand( - "handle_command_clear_logs", + 'CLEAR_LOGS': RemoteCommand( + 'handle_command_clear_logs', help_text="Clear the Picard logs", ), - "CLUSTER": RemoteCommand( - "handle_command_cluster", + 'CLUSTER': RemoteCommand( + 'handle_command_cluster', help_text="Cluster all files in the cluster pane.", ), - "FINGERPRINT": RemoteCommand( - "handle_command_fingerprint", + 'FINGERPRINT': RemoteCommand( + 'handle_command_fingerprint', help_text="Calculate acoustic fingerprints for all (matched) files in the album pane.", ), - "FROM_FILE": RemoteCommand( - "handle_command_from_file", + 'FROM_FILE': RemoteCommand( + 'handle_command_from_file', help_text="Load commands from a file.", help_args="[Path to a file containing commands]", ), - "LOAD": RemoteCommand( - "handle_command_load", + 'LOAD': RemoteCommand( + 'handle_command_load', help_text="Load one or more files/MBIDs/URLs to Picard.", help_args="[supported MBID/URL or path to a file]", ), - "LOOKUP": RemoteCommand( - "handle_command_lookup", + 'LOOKUP': RemoteCommand( + 'handle_command_lookup', help_text="Lookup files in the clustering pane. Defaults to all files.", help_args="[clustered|unclustered|all]" ), - "LOOKUP_CD": RemoteCommand( - "handle_command_lookup_cd", + 'LOOKUP_CD': RemoteCommand( + 'handle_command_lookup_cd', help_text="Read CD from the selected drive and lookup on MusicBrainz. " "Without argument, it defaults to the first (alphabetically) available disc drive.", help_args="[device/log file]", ), - "PAUSE": RemoteCommand( - "handle_command_pause", + 'PAUSE': RemoteCommand( + 'handle_command_pause', help_text="Pause executable command processing.", help_args="[number of seconds to pause]", ), - "QUIT": RemoteCommand( - "handle_command_quit", + 'QUIT': RemoteCommand( + 'handle_command_quit', help_text="Exit the running instance of Picard. " "Use the argument 'FORCE' to bypass Picard's unsaved files check.", help_args="[FORCE]", ), - "REMOVE": RemoteCommand( - "handle_command_remove", + 'REMOVE': RemoteCommand( + 'handle_command_remove', help_text="Remove the file from Picard. Do nothing if no arguments provided.", help_args="[absolute path to one or more files]", ), - "REMOVE_ALL": RemoteCommand( - "handle_command_remove_all", + 'REMOVE_ALL': RemoteCommand( + 'handle_command_remove_all', help_text="Remove all files from Picard.", ), - "REMOVE_EMPTY": RemoteCommand( - "handle_command_remove_empty", + 'REMOVE_EMPTY': RemoteCommand( + 'handle_command_remove_empty', help_text="Remove all empty clusters and albums.", ), - "REMOVE_SAVED": RemoteCommand( - "handle_command_remove_saved", + 'REMOVE_SAVED': RemoteCommand( + 'handle_command_remove_saved', help_text="Remove all saved files from the album pane.", ), - "REMOVE_UNCLUSTERED": RemoteCommand( - "handle_command_remove_unclustered", + 'REMOVE_UNCLUSTERED': RemoteCommand( + 'handle_command_remove_unclustered', help_text="Remove all unclustered files from the cluster pane.", ), - "SAVE_MATCHED": RemoteCommand( - "handle_command_save_matched", + 'SAVE_MATCHED': RemoteCommand( + 'handle_command_save_matched', help_text="Save all matched files from the album pane." ), - "SAVE_MODIFIED": RemoteCommand( - "handle_command_save_modified", + 'SAVE_MODIFIED': RemoteCommand( + 'handle_command_save_modified', help_text="Save all modified files from the album pane.", ), - "SCAN": RemoteCommand( - "handle_command_scan", + 'SCAN': RemoteCommand( + 'handle_command_scan', help_text="Scan all files in the cluster pane.", ), - "SHOW": RemoteCommand( - "handle_command_show", + 'SHOW': RemoteCommand( + 'handle_command_show', help_text="Make the running instance the currently active window.", ), - "SUBMIT_FINGERPRINTS": RemoteCommand( - "handle_command_submit_fingerprints", + 'SUBMIT_FINGERPRINTS': RemoteCommand( + 'handle_command_submit_fingerprints', help_text="Submit outstanding acoustic fingerprints for all (matched) files in the album pane.", ), - "WRITE_LOGS": RemoteCommand( - "handle_command_write_logs", + 'WRITE_LOGS': RemoteCommand( + 'handle_command_write_logs', help_text="Write Picard logs to a given path.", help_args="[absolute path to one file]", ), diff --git a/picard/util/script_detector_weighted.py b/picard/util/script_detector_weighted.py index ee6118dfe5..13711418bb 100644 --- a/picard/util/script_detector_weighted.py +++ b/picard/util/script_detector_weighted.py @@ -40,16 +40,16 @@ class ScriptSelectionOrder(IntEnum): # characters to convey the same information as other characters sets. The factor is generally # based on the relative number of characters in the alphabet compared with the LATIN alphabet. SCRIPT_WEIGHTING_FACTORS = { - "LATIN": 1.0, - "CYRILLIC": 1.02, - "GREEK": 0.92, - "ARABIC": 1.08, - "HEBREW": 0.85, - "CJK": 2.5, - "HANGUL": 0.92, - "HIRAGANA": 1.77, - "KATAKANA": 1.77, - "THAI": 1.69, + 'LATIN': 1.0, + 'CYRILLIC': 1.02, + 'GREEK': 0.92, + 'ARABIC': 1.08, + 'HEBREW': 0.85, + 'CJK': 2.5, + 'HANGUL': 0.92, + 'HIRAGANA': 1.77, + 'KATAKANA': 1.77, + 'THAI': 1.69, } diff --git a/picard/util/scripttofilename.py b/picard/util/scripttofilename.py index 50a51a3091..f05194d5da 100644 --- a/picard/util/scripttofilename.py +++ b/picard/util/scripttofilename.py @@ -56,25 +56,25 @@ def script_to_filename_with_metadata(naming_format, metadata, file=None, setting config = get_config() settings = config.setting # make sure every metadata can safely be used in a path name - win_compat = IS_WIN or settings["windows_compatibility"] + win_compat = IS_WIN or settings['windows_compatibility'] new_metadata = Metadata() - replace_dir_separator = settings["replace_dir_separator"] + replace_dir_separator = settings['replace_dir_separator'] for name in metadata: new_metadata[name] = [ sanitize_filename(str(v), repl=replace_dir_separator, win_compat=win_compat) for v in metadata.getall(name) ] - naming_format = naming_format.replace("\t", "").replace("\n", "") + naming_format = naming_format.replace('\t', '').replace('\n', '') filename = ScriptParser().eval(naming_format, new_metadata, file) - if settings["ascii_filenames"]: + if settings['ascii_filenames']: filename = replace_non_ascii(filename, pathsave=True, win_compat=win_compat) # replace incompatible characters if win_compat: - filename = replace_win32_incompat(filename, replacements=settings["win_compat_replacements"]) - if settings["replace_spaces_with_underscores"]: + filename = replace_win32_incompat(filename, replacements=settings['win_compat_replacements']) + if settings['replace_spaces_with_underscores']: filename = _re_replace_underscores.sub('_', filename.strip()) # remove null characters - filename = filename.replace("\x00", "") + filename = filename.replace('\x00', '') return (filename, new_metadata) diff --git a/picard/util/versions.py b/picard/util/versions.py index a00a03b95e..9ff50df2c9 100644 --- a/picard/util/versions.py +++ b/picard/util/versions.py @@ -39,25 +39,25 @@ _versions = OrderedDict([ - ("version", PICARD_FANCY_VERSION_STR), - ("python-version", python_version()), - ("pyqt-version", pyqt_version), - ("qt-version", qVersion()), - ("mutagen-version", mutagen_version), - ("discid-version", discid_version), - ("astrcmp", astrcmp_implementation), - ("ssl-version", QSslSocket.sslLibraryVersionString()) + ('version', PICARD_FANCY_VERSION_STR), + ('python-version', python_version()), + ('pyqt-version', pyqt_version), + ('qt-version', qVersion()), + ('mutagen-version', mutagen_version), + ('discid-version', discid_version), + ('astrcmp', astrcmp_implementation), + ('ssl-version', QSslSocket.sslLibraryVersionString()) ]) _names = { - "version": "Picard", - "python-version": "Python", - "pyqt-version": "PyQt", - "qt-version": "Qt", - "mutagen-version": "Mutagen", - "discid-version": "Discid", - "astrcmp": "astrcmp", - "ssl-version": "SSL", + 'version': "Picard", + 'python-version': "Python", + 'pyqt-version': "PyQt", + 'qt-version': "Qt", + 'mutagen-version': "Mutagen", + 'discid-version': "Discid", + 'astrcmp': "astrcmp", + 'ssl-version': "SSL", } diff --git a/picard/webservice/__init__.py b/picard/webservice/__init__.py index e6942d2ff6..2488d2d0cc 100644 --- a/picard/webservice/__init__.py +++ b/picard/webservice/__init__.py @@ -210,7 +210,7 @@ def __init__( if self.data: if not self.request_mimetype: - self.request_mimetype = self.response_mimetype or "application/x-www-form-urlencoded" + self.request_mimetype = self.response_mimetype or 'application/x-www-form-urlencoded' self.setHeader(QNetworkRequest.KnownHeaders.ContentTypeHeader, self.request_mimetype) @property @@ -218,8 +218,8 @@ def has_auth(self): return self.mblogin and self.access_token def _update_authorization_header(self): - auth = "Bearer " + self.access_token if self.has_auth else "" - self.setRawHeader(b"Authorization", auth.encode('utf-8')) + auth = 'Bearer ' + self.access_token if self.has_auth else '' + self.setRawHeader(b'Authorization', auth.encode('utf-8')) @property def host(self): @@ -342,10 +342,10 @@ def __init__(self, parent=None): self.set_transfer_timeout(config.setting['network_transfer_timeout_seconds']) self.manager.finished.connect(self._process_reply) self._request_methods = { - "GET": self.manager.get, - "POST": self.manager.post, - "PUT": self.manager.put, - "DELETE": self.manager.deleteResource + 'GET': self.manager.get, + 'POST': self.manager.post, + 'PUT': self.manager.put, + 'DELETE': self.manager.deleteResource } self._init_queues() self._init_timers() @@ -414,17 +414,17 @@ def set_cache(self, cache_size_in_bytes=None): def setup_proxy(self): proxy = QtNetwork.QNetworkProxy() config = get_config() - if config.setting["use_proxy"]: - if config.setting["proxy_type"] == 'socks': + if config.setting['use_proxy']: + if config.setting['proxy_type'] == 'socks': proxy.setType(QtNetwork.QNetworkProxy.ProxyType.Socks5Proxy) else: proxy.setType(QtNetwork.QNetworkProxy.ProxyType.HttpProxy) - proxy.setHostName(config.setting["proxy_server_host"]) - proxy.setPort(config.setting["proxy_server_port"]) - if config.setting["proxy_username"]: - proxy.setUser(config.setting["proxy_username"]) - if config.setting["proxy_password"]: - proxy.setPassword(config.setting["proxy_password"]) + proxy.setHostName(config.setting['proxy_server_host']) + proxy.setPort(config.setting['proxy_server_port']) + if config.setting['proxy_username']: + proxy.setUser(config.setting['proxy_username']) + if config.setting['proxy_password']: + proxy.setPassword(config.setting['proxy_password']) self.manager.setProxy(proxy) def set_transfer_timeout(self, timeout): diff --git a/picard/webservice/api_helpers.py b/picard/webservice/api_helpers.py index 8911f72b66..9a7e83352d 100644 --- a/picard/webservice/api_helpers.py +++ b/picard/webservice/api_helpers.py @@ -143,24 +143,24 @@ def get_track_by_id(self, trackid, handler, inc=None, **kwargs): def lookup_discid(self, discid, handler, priority=True, important=True, refresh=False): inc = ('artist-credits', 'labels') - return self._get_by_id('discid', discid, handler, inc, queryargs={"cdstubs": "no"}, + return self._get_by_id('discid', discid, handler, inc, queryargs={'cdstubs': 'no'}, priority=priority, important=important, refresh=refresh) def _find(self, entitytype, handler, **kwargs): filters = {} - limit = kwargs.pop("limit") + limit = kwargs.pop('limit') if limit: filters['limit'] = limit - is_search = kwargs.pop("search", False) + is_search = kwargs.pop('search', False) if is_search: config = get_config() - use_advanced_search = kwargs.pop("advanced_search", config.setting["use_adv_search_syntax"]) + use_advanced_search = kwargs.pop('advanced_search', config.setting['use_adv_search_syntax']) if use_advanced_search: - query = kwargs["query"] + query = kwargs['query'] else: - query = escape_lucene_query(kwargs["query"]).strip().lower() + query = escape_lucene_query(kwargs['query']).strip().lower() filters['dismax'] = 'true' else: query = build_lucene_query(kwargs) @@ -195,14 +195,14 @@ def _browse(self, entitytype, handler, inc=None, queryargs=None, mblogin=False): if queryargs is None: queryargs = {} if inc: - queryargs["inc"] = self._make_inc_arg(inc) + queryargs['inc'] = self._make_inc_arg(inc) return self.get(f"/{entitytype}", handler, unencoded_queryargs=queryargs, priority=True, important=True, mblogin=mblogin, refresh=False) def browse_releases(self, handler, **kwargs): - inc = ("media", "labels") - return self._browse("release", handler, inc, queryargs=kwargs) + inc = ('media', 'labels') + return self._browse('release', handler, inc, queryargs=kwargs) def browse_recordings(self, handler, inc, **kwargs): return self._browse('recording', handler, inc, queryargs=kwargs) @@ -216,20 +216,20 @@ def _xml_ratings(ratings): return _wrap_xml_metadata('%s' % recordings) def submit_ratings(self, ratings, handler): - params = {"client": CLIENT_STRING} + params = {'client': CLIENT_STRING} data = self._xml_ratings(ratings) return self.post("/rating", data, handler, priority=True, - unencoded_queryargs=params, parse_response_type="xml", - request_mimetype="application/xml; charset=utf-8") + unencoded_queryargs=params, parse_response_type='xml', + request_mimetype='application/xml; charset=utf-8') def get_collection(self, collection_id, handler, limit=100, offset=0): if collection_id is not None: - inc = ("releases", "artist-credits", "media") + inc = ('releases', 'artist-credits', 'media') path = f"/collection/{collection_id}/releases" queryargs = { - "inc": self._make_inc_arg(inc), - "limit": limit, - "offset": offset, + 'inc': self._make_inc_arg(inc), + 'limit': limit, + 'offset': offset, } else: path = '/collection' @@ -243,12 +243,12 @@ def get_collection_list(self, handler): @staticmethod def _collection_request(collection_id, releases, batchsize=400): for i in range(0, len(releases), batchsize): - ids = ";".join(releases[i:i+batchsize]) + ids = ';'.join(releases[i:i+batchsize]) yield f"/collection/{collection_id}/releases/{ids}" @staticmethod def _get_client_queryarg(): - return {"client": CLIENT_STRING} + return {'client': CLIENT_STRING} def put_to_collection(self, collection_id, releases, handler): for path in self._collection_request(collection_id, releases): @@ -279,13 +279,13 @@ def query_acoustid(self, handler, **args): body = self._encode_acoustid_args(args) return self.post( "/lookup", body, handler, priority=False, important=False, - mblogin=False, request_mimetype="application/x-www-form-urlencoded" + mblogin=False, request_mimetype='application/x-www-form-urlencoded' ) @staticmethod def _submissions_to_args(submissions): config = get_config() - args = {'user': config.setting["acoustid_apikey"]} + args = {'user': config.setting['acoustid_apikey']} for i, submission in enumerate(submissions): for key, value in submission.args.items(): if value: @@ -297,5 +297,5 @@ def submit_acoustid_fingerprints(self, submissions, handler): body = self._encode_acoustid_args(args) return self.post( "/submit", body, handler, priority=True, important=False, - mblogin=False, request_mimetype="application/x-www-form-urlencoded" + mblogin=False, request_mimetype='application/x-www-form-urlencoded' )