def _downloaded(self, msg: Soup.Message, result: Any, data: Tuple) -> None: path, song = data try: headers = msg.get_property('response-headers') size = int(headers.get('content-length')) content_type = headers.get('content-type') print_d( f"Downloaded {format_size(size)} of {content_type}: {song('title')}" ) _, ext = splitext(urlparse(song("~uri")).path) fn = (escape_filename(song("~artist~title")[:100], safe=b" ,';") or song("~basename") or f"download-{hash(song('~filename'))}") path = path / Path(fn + ext) if path.is_file() and path.stat(): print_w(f"{path!s} already exists. Skipping download") self.success(song) return with open(path, "wb") as f: f.write(result) self.success(song) print_d(f"Downloaded to {path} successfully!") except Exception as e: print_e(f"Failed download ({e})") self.failure(song)
def _rewrite_json(self, obj, path): try: with path.open('w+', encoding='utf-8') as f: json.dump(obj, f, indent=self._get_json_indent()) except (ValueError, OSError): self._error_msg(_("Couldn't write '%s'") % path) print_e(f"Couldn't write {path} due to:") print_exc()
def __item_for(self, view: BaseView, Item: Type[EditTagsPlugin], tag: str, text: str) -> Optional[EditTagsPlugin]: try: item = Item(tag, text) except Exception as e: print_e(f"Couldn't create menu item from {Item} ({e})") return None else: item.connect('activate', self.__menu_activate, view) return item
def _try_read_source_json(self, path: Path): try: with path.open(encoding="utf-8") as f: return json.load(f) except ValueError: print_e(f"Couldn't parse JSON in {path}.") self._error_msg(_("Couldn't parse JSON in %s") % path) return None except OSError: print_e(f"Couldn't read {path}") self._error_msg(_("Couldn't read %s") % path) return None
def apicall(method, **kwargs): """Performs Last.fm API call.""" real_args = {'api_key': API_KEY, 'format': 'json', 'method': method} real_args.update(kwargs) url = ''.join(["https://ws.audioscrobbler.com/2.0/?", urlencode(real_args)]) uobj = urlopen(url) json_text = uobj.read().decode("utf-8") resp = json.loads(json_text) if 'error' in resp: errmsg = f"Last.fm API error: {resp.get('message', '')}" print_e(errmsg) raise EnvironmentError(resp['error'], errmsg) return resp
def add_song_to_playlist(pl_name, song): pl_lib = app.library.playlists try: pl_lib[pl_name].append(song) except KeyError: try: pl = pl_lib.create(pl_name) pl.append(song) except ValueError: print_e( f'tried to add {song} to playlist {pl_name} but could not due to:' ) print_exc()
def update_files(self, songs, metadata, names, append=True, rename=False): for song, meta, name in zip(songs, metadata, names): for key, values in meta.items(): if append and key in song: values = song.list(key) + values song[key] = '\n'.join(values) if rename: path = song('~dirname') base = os.path.basename(name) newname = os.path.join(path, base) try: app.library.rename(song._song, newname) except ValueError: print_e("File {} already exists. Ignoring file " "rename.".format(newname)) app.library.changed(songs)
def open(self, ignore_lock=False): """Create the FIFO and listen to it. Raises: FIFOError in case another process is already using it. """ from quodlibet import qltk mkdir(os.path.dirname(self._path)) try: os.mkfifo(self._path, 0o600) except OSError: # maybe exists, we'll fail below otherwise pass try: fifo = os.open(self._path, os.O_NONBLOCK) except OSError: return while True: try: fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB) except InterruptedError: # EINTR continue except BlockingIOError: # EWOULDBLOCK if not ignore_lock: raise FIFOError("fifo already locked") except OSError as e: print_d(f"fifo locking failed: {e!r}") break try: f = os.fdopen(fifo, "rb", 4096) except OSError as e: print_e(f"Couldn't open FIFO ({e!r})") else: self._source_id = qltk.io_add_watch( f, GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP, self._process, )
def _write(self, _widget: Gtk.Widget, model: QueueModel, force=False): diff = time.time() - self._updated_time if not self._should_write(force, diff): self._pending += 1 return print_d(f"Saving play queue after {diff:.1f}s") filenames = [row[0]["~filename"] for row in model] try: with open(QUEUE, "wb") as f: for filename in filenames: try: line = fsn2bytes(filename, "utf-8") except ValueError as e: print_w(f"Ignoring queue save error ({e})") continue f.write(line + b"\n") except EnvironmentError as e: print_e(f"Error saving queue ({e})") self._updated_time = time.time() self._pending = 0
def _open(self, ignore_lock, *args): from quodlibet import qltk self._id = None mkdir(os.path.dirname(self._path)) try: os.mkfifo(self._path, 0o600) except OSError: # maybe exists, we'll fail below otherwise pass try: fifo = os.open(self._path, os.O_NONBLOCK) except OSError: return while True: try: fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError as e: # EINTR on linux if e.errno == errno.EINTR: continue if ignore_lock: break # OSX doesn't support FIFO locking, so check errno if e.errno == errno.EWOULDBLOCK: raise FIFOError("fifo already locked") else: print_d("fifo locking failed: %r" % e) break try: f = os.fdopen(fifo, "rb", 4096) except OSError as e: print_e("Couldn't open FIFO (%s)" % e) else: self._id = qltk.io_add_watch( f, GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP, self._process, *args)
def _open(self, ignore_lock, *args): from quodlibet import qltk self._id = None mkdir(os.path.dirname(self._path)) try: os.mkfifo(self._path, 0o600) except OSError: # maybe exists, we'll fail below otherwise pass try: fifo = os.open(self._path, os.O_NONBLOCK) except OSError: return while True: try: fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError as e: # EINTR on linux if e.errno == errno.EINTR: continue if ignore_lock: break # OSX doesn't support FIFO locking, so check errno if e.errno == errno.EWOULDBLOCK: raise FIFOError("fifo already locked") else: print_d("fifo locking failed: %r" % e) break try: f = os.fdopen(fifo, "rb", 4096) except OSError as e: print_e("Couldn't open FIFO (%s)" % e) else: self._id = qltk.io_add_watch( f, GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP, self._process, *args)
def _update_song(self, exported_data, song): file_stem = exported_data.pop(FILE_STEM_KEY, None) if file_stem is not None: file_ext = extension_of_file_name(song('~basename')) new_name = f'{file_stem}{file_ext}' new_song_path = os.path.join(song('~dirname'), new_name) try: app.library.rename(song._song, new_song_path) except ValueError: print_e(f'Could not rename {song._song} to {new_song_path}.') for pl_name in exported_data.pop(PLAYLISTS_KEY, []): add_song_to_playlist(pl_name, song) for tag_key, tag_value in exported_data.items(): if tag_key in song and song[tag_key] == tag_value: continue song[tag_key] = tag_value song._needs_write = True
def update_files(self, songs: List, metadata: List[Dict[str, List]], names: List, append=True, rename=False): for song, meta, name in zip(songs, metadata, names): for key, values in meta.items(): if append and key in song: values = song.list(key) + values song[key] = '\n'.join(values) if rename: origname = song['~filename'] path = os.path.dirname(origname) suffix_index = origname.rfind('.') suffix = origname[suffix_index:] if suffix_index >= 0 else '' newname = os.path.join(path, name + suffix) try: app.library.rename(song._song, newname) except ValueError: print_e("File {} already exists. Ignoring file " "rename.".format(newname)) app.library.changed(songs)
def set_tooltip_text(self, *args, **kwargs): print_e("Setting a tooltip on the view breaks tv hints. Set it" " on the parent scrolled window instead") return super(HintedTreeView, self).set_tooltip_text(*args, **kwargs)