def test_any_filenames(path): if isinstance(path, fsnative): assert path2fsn(path) == fsn2norm(path) fsn = path2fsn(path) assert path2fsn(fsn) == fsn assert isinstance(fsn, fsnative) try: # never raises ValueError/TypError with open(fsn): pass except EnvironmentError: pass fsn2text(fsn).encode("utf-8") try: t = fsn2text(fsn, strict=True) except ValueError: pass else: assert fsn2norm(text2fsn(t)) == fsn2norm(fsn) data = fsn2bytes(fsn, "utf-8") assert fsn2bytes(bytes2fsn(data, "utf-8"), "utf-8") == data
def test_any_normalize(path): fsn = path2fsn(path) assert path2fsn(path) == fsn2norm(fsn) assert bytes2fsn(fsn2bytes(fsn, "utf-8"), "utf-8") == fsn2norm(fsn) if isinstance(path, text_type): assert text2fsn(path) == fsn2norm(text2fsn(path))
def call(args): args = [path2fsn(a) for a in args] with capture_output() as (out, err): try: return_code = operon_main([path2fsn("operon.py")] + args) except SystemExit as e: return_code = e.code return (return_code, out.getvalue(), err.getvalue())
def _dir_for(filelike): try: if isinstance(filelike, addinfourl): # if the "filelike" was created via urlopen # it is wrapped in an addinfourl object return os.path.dirname(path2fsn(filelike.fp.name)) else: return os.path.dirname(path2fsn(filelike.name)) except AttributeError: # Probably a URL return text2fsn(u'')
def test_path2fsn_pathlike(): # basic tests for os.fspath with pytest.raises(TypeError): os.fspath(PathLike(None)) assert os.fspath(PathLike(fsnative(u"foo"))) == fsnative(u"foo") assert os.fspath(PathLike(u"\u1234")) == u"\u1234" # now support in path2fsn pathlike = PathLike(fsnative(u"foo")) assert path2fsn(pathlike) == fsnative(u"foo") # pathlib should also work.. from pathlib import Path assert path2fsn(Path(".")) == fsnative(u".")
def print_exc(exc_info=None, context=None): """Prints the stack trace of the current exception or the passed one. Depending on the configuration will either print a short summary or the whole stacktrace. """ if exc_info is None: exc_info = sys.exc_info() etype, value, tb = exc_info if const.DEBUG: string = u"".join(format_exception(etype, value, tb)) else: # try to get a short error message pointing at the cause of # the exception text = u"".join(format_exception_only(etype, value)) try: filename, lineno, name, line = extract_tb(tb)[-1] except IndexError: # no stack string = text else: string = u"%s:%s:%s: %s" % (fsn2text( path2fsn(os.path.basename(filename))), lineno, name, text) _print_message(string, context, False, "E", "red", "errors")
def get_available_languages(domain): """Returns a list of available translations for a given gettext domain. Args: domain (str) Returns: List[text_type] """ locale_dir = gettext.bindtextdomain(domain) if locale_dir is None: return [] try: entries = os.listdir(locale_dir) except OSError: return [] langs = [u"C"] for lang in entries: mo_path = os.path.join(locale_dir, lang, "LC_MESSAGES", "%s.mo" % domain) if os.path.exists(mo_path): langs.append(fsn2text(path2fsn(lang))) return langs
def print_exc(exc_info=None, context=None): """Prints the stack trace of the current exception or the passed one. Depending on the configuration will either print a short summary or the whole stacktrace. """ if exc_info is None: exc_info = sys.exc_info() etype, value, tb = exc_info if const.DEBUG: string = u"".join(format_exception(etype, value, tb)) else: # try to get a short error message pointing at the cause of # the exception text = u"".join(format_exception_only(etype, value)) try: filename, lineno, name, line = extract_tb(tb)[-1] except IndexError: # no stack string = text else: string = u"%s:%s:%s: %s" % ( fsn2text(path2fsn(os.path.basename(filename))), lineno, name, text) _print_message(string, context, False, "E", "red", "errors")
def get_user_dir(): """Place where QL saves its state, database, config etc.""" if os.name == "nt": USERDIR = os.path.join(windows.get_appdata_dir(), "Quod Libet") elif is_osx(): USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet") else: USERDIR = os.path.join(xdg_get_config_home(), "quodlibet") if not os.path.exists(USERDIR): tmp = os.path.join(os.path.expanduser("~"), ".quodlibet") if os.path.exists(tmp): USERDIR = tmp if 'QUODLIBET_USERDIR' in environ: USERDIR = environ['QUODLIBET_USERDIR'] if build.BUILD_TYPE == u"windows-portable": USERDIR = os.path.normpath(os.path.join( os.path.dirname(path2fsn(sys.executable)), "..", "..", "config")) # XXX: users shouldn't assume the dir is there, but we currently do in # some places mkdir(USERDIR, 0o750) return USERDIR
def get_user_dir(): """Place where QL saves its state, database, config etc.""" if os.name == "nt": USERDIR = os.path.join(windows.get_appdata_dir(), "Quod Libet") elif is_osx(): USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet") else: USERDIR = os.path.join(xdg_get_config_home(), "quodlibet") if not os.path.exists(USERDIR): tmp = os.path.join(os.path.expanduser("~"), ".quodlibet") if os.path.exists(tmp): USERDIR = tmp if 'QUODLIBET_USERDIR' in environ: USERDIR = environ['QUODLIBET_USERDIR'] if build.BUILD_TYPE == u"windows-portable": USERDIR = os.path.normpath( os.path.join(os.path.dirname(path2fsn(sys.executable)), "..", "..", "config")) # XXX: users shouldn't assume the dir is there, but we currently do in # some places mkdir(USERDIR, 0o750) return USERDIR
def test_uri_roundtrip(): if os.name == "nt": for path in [ u"C:\\foo-\u1234", u"C:\\bla\\quux ha", u"\\\\\u1234\\foo\\\u1423", u"\\\\foo;\\f" ]: path = fsnative(path) assert uri2fsn(fsn2uri(path)) == path assert isinstance(uri2fsn(fsn2uri(path)), fsnative) else: path = path2fsn(b"/foo-\xe1\x88\xb4") assert uri2fsn(fsn2uri(path2fsn(b"/\x80"))) == path2fsn(b"/\x80") assert uri2fsn(fsn2uri(fsnative(u"/foo"))) == "/foo" assert uri2fsn(fsn2uri(path)) == path assert isinstance(uri2fsn(fsn2uri(path)), fsnative)
def get_available_languages(domain): """Returns a list of available translations for a given gettext domain. Args: domain (str) Returns: List[text_type] """ locale_dir = gettext.bindtextdomain(domain) if locale_dir is None: return [] try: entries = os.listdir(locale_dir) except OSError: return [] langs = [u"C"] for lang in entries: mo_path = os.path.join( locale_dir, lang, "LC_MESSAGES", "%s.mo" % domain) if os.path.exists(mo_path): langs.append(fsn2text(path2fsn(lang))) return langs
def test_any_pathnames(path): fsn = path2fsn(path) abspath = os.path.abspath(fsn) if os.path.isabs(abspath): if is_wine: # FIXME: fails on native Windows assert uri2fsn(fsn2uri(abspath)) == abspath
def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: header = h.read(64) if len(header) != 64 or header[:4] != b"Vgm ": # filename useful to show (helps w/ faulty VGM files.) raise Exception(filename + " not a VGM file") samples_to_sec = lambda s: s / 44100. samples = struct.unpack('<i', header[24:28])[0] loop_offset = struct.unpack('<i', header[28:32])[0] loop_samples = struct.unpack('<i', header[32:36])[0] # this should match libgme length = samples_to_sec(samples) if length <= 0: length = 150 elif loop_offset: # intro + 2 loops length += samples_to_sec(loop_samples) self["~#length"] = length gd3_position = struct.unpack( '<i', header[GD3_TAG_PTR_POS:GD3_TAG_PTR_POS + GD3_TAG_PTR_SIZE])[0] h.seek(GD3_TAG_PTR_POS + gd3_position) self.update(parse_gd3(h.read())) self.setdefault("title", fsn2text(path2fsn(os.path.basename(filename)[:-4]))) self.sanitize(filename)
def iter_paths(root: fsnative, exclude: Optional[Iterable[fsnative]] = None, skip_hidden: bool = True) -> Generator[fsnative, None, None]: """Yields paths contained in root (symlinks dereferenced) Any path starting with any of the path parts included in exclude are ignored (before and after dereferencing symlinks) Directory symlinks are not followed (except root itself) Args: root: start here exclude: ignore any of these skip_hidden: Ignore files which are hidden or where any of the parent directories are hidden. Yields: fsnative: absolute dereferenced paths """ assert isinstance(root, fsnative) exclude = exclude or [] assert all((isinstance(p, fsnative) for p in exclude)) assert os.path.abspath(root) def skip(path): if skip_hidden and is_hidden(path): return True # FIXME: normalize paths.. return any((path.startswith(p) for p in exclude)) if skip_hidden and is_hidden(root): return for path, dnames, fnames in os.walk(root): if skip_hidden: dnames[:] = [ d for d in dnames if not is_hidden(path2fsn(os.path.join(path, d))) ] for filename in fnames: full_filename = path2fsn(os.path.join(path, filename)) if skip(full_filename): continue full_filename = path2fsn(os.path.realpath(full_filename)) if skip(full_filename): continue yield full_filename # type: ignore
def __getitem__(self, key): # we used to save them with the wrong type value = super(RemoteFile, self).__getitem__(key) if key in ("~filename", "~mountpoint") and \ not isinstance(value, fsnative): value = path2fsn(value) return value
def get_devices_from_path(udev_ctx, path): """A list of device attribute dicts for the given device path and all its parents. Either returns a non empty list or raises EnvironmentError. """ path = fsn2bytes(path2fsn(path), None) enum = udev.UdevEnumerate.new(udev_ctx) if not enum: raise EnvironmentError # only match the device we want if enum.add_match_property(b"DEVNAME", path) != 0: enum.unref() raise EnvironmentError # search for it if enum.scan_devices() != 0: enum.unref() raise EnvironmentError # take the first entry entry = enum.get_list_entry() if not entry: enum.unref() raise EnvironmentError sys_path = entry.get_name() enum.unref() device = udev.UdevDevice.new_from_syspath(udev_ctx, sys_path) if not device: raise EnvironmentError devices = [] while device: devices.append(device) device = device.get_parent() device_attrs = [] for device in devices: entry = device.get_properties_list_entry() if not entry: continue attrs = {} for e in entry: name = e.get_name() value = e.get_value() attrs[name] = escape_decode(value) device_attrs.append(attrs) # the first device owns its parents devices[0].unref() return device_attrs
def _normalize_path(filename, canonicalise=False): """Normalize a path on Windows / Linux If `canonicalise` is True, dereference symlinks etc by calling `os.path.realpath` """ filename = path2fsn(filename) if canonicalise: filename = os.path.realpath(filename) filename = os.path.normpath(filename) return os.path.normcase(filename)
def get_module_dir(module=None): """Returns the absolute path of a module. If no module is given the one this is called from is used. """ if module is None: file_path = sys._getframe(1).f_globals["__file__"] else: file_path = getattr(module, "__file__") file_path = path2fsn(file_path) return os.path.dirname(os.path.realpath(file_path))
def __init__(self, parent, path): title = _("File exists") fn_format = "<b>%s</b>" % util.escape(fsn2text(path2fsn(path))) description = _("Replace %(file-name)s?") % {"file-name": fn_format} super(ConfirmFileReplace, self).__init__( parent, title, description, buttons=Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Replace File"), Icons.DOCUMENT_SAVE, self.RESPONSE_REPLACE) self.set_default_response(Gtk.ResponseType.CANCEL)
def save_image(self, fsn): fsn = path2fsn(fsn) if self.config.re_encode: quality = str(self.config.jpg_quality) print_d(f"Converting image to JPEG @ {quality}%") ret = self._pixbuf.savev(fsn, "jpeg", ["quality"], [quality]) if not ret: raise IOError("Couldn't save to %s" % fsn) else: print_d("Saving original image to %s" % fsn) with open(fsn, "wb") as f: f.write(self._original)
def test_uri2fsn(): if os.name != "nt": with pytest.raises(ValueError): assert uri2fsn(u"file:///%00") with pytest.raises(ValueError): assert uri2fsn("file:///%00") assert uri2fsn("file:///foo") == fsnative(u"/foo") assert uri2fsn(u"file:///foo") == fsnative(u"/foo") assert isinstance(uri2fsn("file:///foo"), fsnative) assert isinstance(uri2fsn(u"file:///foo"), fsnative) assert \ uri2fsn("file:///foo-%E1%88%B4") == path2fsn(b"/foo-\xe1\x88\xb4") assert uri2fsn("file:NOPE") == fsnative(u"/NOPE") assert uri2fsn("file:/NOPE") == fsnative(u"/NOPE") with pytest.raises(ValueError): assert uri2fsn("file://NOPE") assert uri2fsn("file:///bla:[email protected]") == \ fsnative(u"/bla:[email protected]") assert uri2fsn("file:///bla?x#b") == fsnative(u"/bla?x#b") else: assert uri2fsn("file:///C:/%ED%A0%80") == fsnative(u"C:\\\ud800") assert uri2fsn("file:///C:/%20") == "C:\\ " assert uri2fsn("file:NOPE") == "\\NOPE" assert uri2fsn("file:/NOPE") == "\\NOPE" with pytest.raises(ValueError): assert uri2fsn(u"file:///C:/%00") with pytest.raises(ValueError): assert uri2fsn("file:///C:/%00") assert uri2fsn("file:///C:/foo") == fsnative(u"C:\\foo") assert uri2fsn(u"file:///C:/foo") == fsnative(u"C:\\foo") assert isinstance(uri2fsn("file:///C:/foo"), fsnative) assert isinstance(uri2fsn(u"file:///C:/foo"), fsnative) assert uri2fsn(u"file:///C:/foo-\u1234") == fsnative(u"C:\\foo-\u1234") assert \ uri2fsn("file:///C:/foo-%E1%88%B4") == fsnative(u"C:\\foo-\u1234") assert uri2fsn(u"file://UNC/foo/bar") == u"\\\\UNC\\foo\\bar" assert uri2fsn(u"file://\u1234/\u4321") == u"\\\\\u1234\\\u4321" with pytest.raises(TypeError): uri2fsn(object()) with pytest.raises(ValueError): uri2fsn("http://www.foo.bar") if os.name == "nt": with pytest.raises(ValueError): uri2fsn(u"\u1234") if PY3: with pytest.raises(TypeError): uri2fsn(b"file:///foo")
def parse_m3u(filename, library=None): plname = fsn2text(path2fsn(os.path.basename( os.path.splitext(filename)[0]))) filenames = [] with open(filename, "rb") as h: for line in h: line = line.strip() if line.startswith("#"): continue else: filenames.append(line) return __parse_playlist(plname, filename, filenames, library)
def open_chooser(self, action): if action.get_name() == "AddFolders": fns = choose_folders(self, _("Add Music"), _("_Add Folders")) if fns: # scan them copool.add(self.__library.scan, fns, cofuncid="library", funcid="library") else: patterns = ["*" + path2fsn(k) for k in formats.loaders.keys()] choose_filter = create_chooser_filter(_("Music Files"), patterns) fns = choose_files( self, _("Add Music"), _("_Add Files"), choose_filter) if fns: for filename in fns: self.__library.add_filename(filename)
def _normalize_darwin_path(filename, canonicalise=False): filename = path2fsn(filename) if canonicalise: filename = os.path.realpath(filename) filename = os.path.normpath(filename) data = fsn2bytes(filename, "utf-8") decoded = data.decode("utf-8", "quodlibet-osx-path-decode") try: return bytes2fsn(NSString.fileSystemRepresentation(decoded), "utf-8") except ValueError: return filename
def test_argv_change(): with preserve_argv(): argv.append(fsnative(u"\u1234")) assert argv[-1] == fsnative(u"\u1234") assert len(sys.argv) == len(argv) assert sys.argv[-1] in (fsnative(u"\u1234"), "?") argv[-1] = fsnative(u"X") assert path2fsn(sys.argv[-1]) == argv[-1] del argv[-1] assert len(sys.argv) == len(argv) with preserve_argv(): sys.argv[0] = sys.argv[0] + sys.argv[0] if path2fsn(sys.argv[0]) != argv[0]: del sys.argv[:] argv[0] = fsnative(u"") del argv[0] with preserve_argv(): argv[:] = [fsnative(u"foo")] assert repr(argv).replace("u'", "'") == repr(sys.argv) assert argv[:] == argv with preserve_argv(): del argv[:] assert not argv assert argv == [] assert argv == argv assert not argv != argv argv.append("") assert len(argv) == 1 assert isinstance(argv[-1], fsnative) argv.insert(0, "") assert isinstance(argv[0], fsnative) assert len(argv) == 2 assert not argv > argv
def create_chooser_filter(name, patterns): """Create a Gtk.FileFilter that also works on Windows Args: name (str): The name of the filter patterns (List[pathlike]): A list of glob patterns Returns: Gtk.FileFilter """ # The Windows FileChooserNative implementation only supports patterns filter_ = Gtk.FileFilter() filter_.set_name(name) for pattern in sorted(set(patterns)): filter_.add_pattern(fsn2glib(path2fsn(pattern))) return filter_
def _normalize_darwin_path(filename, canonicalise=False): filename = path2fsn(filename) if canonicalise: filename = os.path.realpath(filename) filename = os.path.normpath(filename) data = fsn2bytes(filename, "utf-8") decoded = data.decode("utf-8", "quodlibet-osx-path-decode") try: return bytes2fsn( NSString.fileSystemRepresentation(decoded), "utf-8") except ValueError: return filename
def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: head = h.read(46) if len(head) != 46 or \ head[:27] != b'SNES-SPC700 Sound File Data': raise IOError("Not a valid SNES-SPC700 file") if getbyte(head, 35) == b'\x1a': data = h.read(210) if len(data) == 210: self.update(parse_id666(data)) self.setdefault( "title", fsn2text(path2fsn(os.path.basename(filename)[:-4]))) self.sanitize(filename)
def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: head = h.read(46) if len(head) != 46 or \ head[:27] != b'SNES-SPC700 Sound File Data': raise IOError("Not a valid SNES-SPC700 file") if head[35:35 + 1] == b'\x1a': data = h.read(210) if len(data) == 210: self.update(parse_id666(data)) self.setdefault( "title", fsn2text(path2fsn(os.path.basename(filename)[:-4]))) self.sanitize(filename)
def parse_m3u(filename, library=None): plname = fsn2text(path2fsn(os.path.basename( os.path.splitext(filename)[0]))) filenames = [] with open(filename, "rb") as h: for line in h: line = line.strip() if line.startswith(b"#"): continue else: try: filenames.append(bytes2fsn(line, "utf-8")) except ValueError: continue return __parse_playlist(plname, filename, filenames, library)
def extract_tb(*args, **kwargs): """Returns a list of tuples containing (fsnative, int, text_type, text_type) """ tp = traceback.extract_tb(*args, **kwargs) if not PY2: return tp result = [] for filename, line_number, function_name, text in tp: filename = path2fsn(filename) function_name = decode(function_name) text = decode(text or u"") result.append((filename, line_number, function_name, text)) return result
def parse_pls(filename, name="", library=None): plname = fsn2text(path2fsn(os.path.basename( os.path.splitext(filename)[0]))) filenames = [] with open(filename) as h: for line in h: line = line.strip() if not line.lower().startswith("file"): continue else: try: line = line[line.index("=") + 1:].strip() except ValueError: pass else: filenames.append(line) return __parse_playlist(plname, filename, filenames, library)
def print_exc(): """Prints the stack trace of the current exception. Depending on the configuration will either print a short summary or the whole stacktrace. """ if const.DEBUG: string = format_exc() else: # try to get a short error message pointing at the cause of # the exception tp = traceback.extract_tb(sys.exc_info()[2])[-1] filename, lineno, name, line = tp text = os.linesep.join(format_exc(0).splitlines()[1:]) string = u"%s:%s:%s: %s" % (fsn2text( path2fsn(os.path.basename(filename))), lineno, name, text) _print_message(string, None, False, "E", "red", "errors")
def __setitem__(self, key, value): # validate key if not isinstance(key, str): raise TypeError("key has to be str") # validate value if key.startswith("~#"): if not isinstance(value, (int, float)): raise TypeError elif key in FILESYSTEM_TAGS: if not isinstance(value, fsnative): value = path2fsn(value) else: value = str(value) dict.__setitem__(self, key, value) pop = self.__dict__.pop pop("album_key", None) pop("sort_key", None)
def get_available_languages(domain): """Returns a set of available translations for a given gettext domain. Args: domain (str) Returns: Set[text_type] """ langs = set(["C"]) for locale_dir in iter_locale_dirs(): try: entries = os.listdir(locale_dir) except OSError: continue for lang in entries: mo_path = os.path.join( locale_dir, lang, "LC_MESSAGES", "%s.mo" % domain) if os.path.exists(mo_path): langs.add(fsn2text(path2fsn(lang))) return langs
def __setitem__(self, key, value): # validate key if PY3: if not isinstance(key, text_type): raise TypeError("key has to be str") else: if isinstance(key, text_type): # we try to save keys as encoded ASCII to save memory # under PY2. Everything else besides ASCII combined with # unicode breaks hashing even if the default encoding # it utf-8. try: key = key.encode("ascii") except UnicodeEncodeError: pass elif isinstance(key, bytes): # make sure we set ascii keys only key.decode("ascii") else: raise TypeError("key needs to be unicode or ASCII str") # validate value if key.startswith("~#"): if not isinstance(value, number_types): raise TypeError elif key in FILESYSTEM_TAGS: if not isinstance(value, fsnative): value = path2fsn(value) else: value = text_type(value) dict.__setitem__(self, key, value) pop = self.__dict__.pop pop("album_key", None) pop("sort_key", None)
def send_message(cls, message): data = fsn2bytes(path2fsn(message), "utf-8") try: winpipe.write_pipe(cls._NAME, data) except EnvironmentError as e: raise RemoteError(e)
def get_data_path(filename): return os.path.join(_DATA_DIR, path2fsn(filename))
def _dir_for(filelike): try: return os.path.dirname(path2fsn(filelike.name)) except AttributeError: # Probably a URL return text2fsn(u'')
def _name_for(filename): if not filename: return _("New Playlist") name = os.path.basename(os.path.splitext(filename)[0]) return fsn2text(path2fsn(name))
def format_exception(etype, value, tb, limit=None): """Returns a list of text_type""" result_lines = traceback.format_exception(etype, value, tb, limit) return [fsn2text(path2fsn(l)) for l in result_lines]
def format_exception_only(etype, value): """Returns a list of text_type""" result_lines = traceback.format_exception_only(etype, value) return [fsn2text(path2fsn(l)) for l in result_lines]