def _init_python(): if PY2 or is_release(): MinVersions.PYTHON2.check(sys.version_info) else: # for non release builds we allow Python3 MinVersions.PYTHON3.check(sys.version_info) if is_osx(): # We build our own openssl on OSX and need to make sure that # our own ca file is used in all cases as the non-system openssl # doesn't use the system certs install_urllib2_ca_file() if is_windows(): # Not really needed on Windows as pygi-aio seems to work fine, but # wine doesn't have certs which we use for testing. install_urllib2_ca_file() if is_windows() and os.sep != "\\": # In the MSYS2 console MSYSTEM is set, which breaks os.sep/os.path.sep # If you hit this do a "setup.py clean -all" to get rid of the # bytecode cache then start things with "MSYSTEM= ..." raise AssertionError("MSYSTEM is set (%r)" % environ.get("MSYSTEM")) if is_windows(): # gdbm is broken under msys2, this makes shelve use another backend sys.modules["gdbm"] = None sys.modules["_gdbm"] = None logging.getLogger().addHandler(PrintHandler())
def test_constrains(self): if is_py2exe(): self.assertEqual(is_py2exe_console(), not is_py2exe_window()) self.assertTrue(is_windows()) if is_windows(): self.assertFalse(is_osx()) if is_osx(): self.assertFalse(is_windows())
class TOperonPrint(TOperonBase): # [-p <pattern>] <file> [<files>] def test_print(self): self.check_false(["print"], False, True) o, e = self.check_true(["print", self.f], True, False) self.failUnlessEqual( o.splitlines()[0], "piman, jzig - Quod Libet Test Data - 02/10 - Silence") o, e = self.check_true(["print", "-p", "<title>", self.f], True, False) self.failUnlessEqual(o.splitlines()[0], "Silence") o, e = self.check_true(["print", "-p", "<title>", self.f, self.f], True, False) self.failUnlessEqual(o.splitlines(), ["Silence", "Silence"]) def test_print_invalid(self): # passing a song which can't be loaded results in fail self.check_false(["print", self.f3], False, True) # in case some fail and some don't, print the error messages for # the failed ones, the patterns for the working ones and return # an error status o, e = self.check_false(["print", self.f3, self.f2], True, True) self.assertTrue("Quod Libet Test Data" in o) @skipIf(is_windows(), "doesn't prevent reading under wine...") def test_permissions(self): os.chmod(self.f, 0o000) self.check_false(["print", "-p", "<title>", self.f], False, True)
def create_pool(): if is_wine() or(PY3 and is_windows()): # ProcessPoolExecutor is broken under wine, and under py3+msys2 # https://github.com/Alexpux/MINGW-packages/issues/837 return ThreadPoolExecutor(1) else: return ProcessPoolExecutor(None)
def test_basic(self): if is_windows(): res = split_scan_dirs(u":Z:\\foo:C:/windows:") self.assertEquals(res, [u"Z:\\foo", u"C:/windows"]) else: res = split_scan_dirs(":%s:%s:" % (STANDARD_PATH, OTHER_PATH)) self.assertEquals(res, [STANDARD_PATH, OTHER_PATH])
def _get_chooser(accept_label, cancel_label): """ Args: accept_label (str) cancel_label (str) Returns: Gtk.FileChooser """ if hasattr(Gtk, "FileChooserNative"): FileChooser = Gtk.FileChooserNative else: FileChooser = Gtk.FileChooserDialog # https://github.com/quodlibet/quodlibet/issues/2406 if is_windows() and gtk_version < (3, 22, 16): FileChooser = Gtk.FileChooserDialog chooser = FileChooser() if hasattr(chooser, "set_accept_label"): chooser.set_accept_label(accept_label) else: chooser.add_button(accept_label, Gtk.ResponseType.ACCEPT) chooser.set_default_response(Gtk.ResponseType.ACCEPT) if hasattr(chooser, "set_cancel_label"): chooser.set_cancel_label(cancel_label) else: chooser.add_button(cancel_label, Gtk.ResponseType.CANCEL) return chooser
def test_all(self): self.assertTrue(isinstance(is_unity(), bool)) self.assertTrue(isinstance(is_windows(), bool)) self.assertTrue(isinstance(is_osx(), bool)) self.assertTrue(isinstance(is_py2exe(), bool)) self.assertTrue(isinstance(is_py2exe_console(), bool)) self.assertTrue(isinstance(is_py2exe_window(), bool))
def find_audio_sink(): """Get the best audio sink available. Returns (element, description) or raises PlayerError. """ if is_windows(): sinks = [ "directsoundsink", "autoaudiosink", ] elif is_linux() and pulse_is_running(): sinks = [ "pulsesink", ] else: sinks = [ "autoaudiosink", # plugins-good "pulsesink", # plugins-good "alsasink", # plugins-base ] for name in sinks: element = Gst.ElementFactory.make(name, None) if element is not None: return (element, name) else: details = " (%s)" % ", ".join(sinks) if sinks else "" raise PlayerError(_("No GStreamer audio sink found") + details)
def test_parse(self): if is_windows(): return data = (b'file:///foo/bar\nfile:///home/user\n' b'file:///home/user/Downloads Downloads\n') paths = parse_gtk_bookmarks(data) assert all(isinstance(p, fsnative) for p in paths)
class TDragScroll(TestCase): def setUp(self): class ScrollClass(BaseView, DragScroll): pass self.c = ScrollClass() _fill_view(self.c) @skipIf(is_windows(), "fixme") def test_basic(self): self.c.scroll_motion(0, 0) self.c.scroll_motion(42, 42) self.c.scroll_motion(999, 999) self.c.scroll_disable()
def set_scan_dirs(dirs): """Saves a list of fs paths which should be scanned Args: list """ assert all(isinstance(d, fsnative) for d in dirs) if is_windows(): joined = fsnative(u":").join(dirs) else: joined = join_escape(dirs, fsnative(u":")) config.setbytes("settings", "scan", fsn2bytes(joined, "utf-8"))
def init_devices(): global devices load_pyc = util.is_windows() or util.is_osx() modules = load_dir_modules(dirname(__file__), package=__package__, load_compiled=load_pyc) for mod in modules: try: devices.extend(mod.devices) except AttributeError: print_w("%r doesn't contain any devices." % mod.__name__) devices.sort()
def sink_options(): # People with Jack running probably want it more than any other options if config.getboolean("player", "gst_use_jack") and jack_is_running(): print_d("Using JACK output via Gstreamer") return [AudioSinks.JACK] elif is_windows(): return [AudioSinks.DIRECTSOUND] elif is_linux() and pulse_is_running(): return [AudioSinks.PULSE] else: return [ AudioSinks.AUTO, AudioSinks.PULSE, AudioSinks.ALSA, ]
def init_devices(): global devices load_pyc = util.is_windows() or util.is_osx() modules = load_dir_modules(dirname(__file__), package=__package__, load_compiled=load_pyc) for mod in modules: try: devices.extend(mod.devices) except AttributeError: print_w("%r doesn't contain any devices." % mod.__name__) devices.sort(key=lambda d: repr(d))
def split_scan_dirs(joined_paths): """Returns a list of paths Args: joined_paths (fsnative) Return: list """ assert isinstance(joined_paths, fsnative) if is_windows(): # we used to separate this config with ":", so this is tricky return filter(None, re.findall(r"[a-zA-Z]:[\\/][^:]*", joined_paths)) else: return filter(None, split_escape(joined_paths, ":"))
def split_scan_dirs(joined_paths): """Returns a list of paths Args: joined_paths (fsnative) Return: list """ assert isinstance(joined_paths, fsnative) if is_windows(): # we used to separate this config with ":", so this is tricky return list(filter(None, re.findall(r"[a-zA-Z]:[\\/][^:]*", joined_paths))) else: return list(filter(None, split_escape(joined_paths, ":")))
def _py3_to_py2(items): is_win = is_windows() new_list = [] for i in items: inst = dict.__new__(i.__class__) for key, value in i.items(): if key in ("~filename", "~mountpoint") and not is_win: value = fsn2bytes(value, None) try: key = key.encode("ascii") except UnicodeEncodeError: pass dict.__setitem__(inst, key, value) new_list.append(inst) return new_list
def init(): """Import all browsers from this package and from the user directory. After this is called the global `browers` list will contain all classes sorted by priority. Can be called multiple times. """ global browsers, default # ignore double init (for the test suite) if browsers: return this_dir = os.path.dirname(__file__) load_pyc = util.is_windows() or util.is_osx() modules = load_dir_modules(this_dir, package=__package__, load_compiled=load_pyc) user_dir = os.path.join(quodlibet.get_user_dir(), "browsers") if os.path.isdir(user_dir): modules += load_dir_modules(user_dir, package="quodlibet.fake.browsers", load_compiled=load_pyc) for browser in modules: try: browsers.extend(browser.browsers) except AttributeError: print_w("%r doesn't contain any browsers." % browser.__name__) def is_browser(Kind): return isinstance(Kind, type) and issubclass(Kind, Browser) browsers = list(filter(is_browser, browsers)) if not browsers: raise SystemExit("No browsers found!") browsers.sort(key=lambda Kind: Kind.priority) try: default = get("SearchBar") except ValueError: raise SystemExit("Default browser not found!")
def _init_python(): if PY2 or is_release(): MinVersions.PYTHON2.check(sys.version_info) else: # for non release builds we allow Python3 MinVersions.PYTHON3.check(sys.version_info) if is_osx(): # We build our own openssl on OSX and need to make sure that # our own ca file is used in all cases as the non-system openssl # doesn't use the system certs util.install_urllib2_ca_file() if is_windows(): # Not really needed on Windows as pygi-aio seems to work fine, but # wine doesn't have certs which we use for testing. util.install_urllib2_ca_file()
def init(): """Load/Import all formats. Before this is called loading a file and unpickling will not work. """ global mimes, loaders, types MinVersions.MUTAGEN.check(mutagen.version) base = util.get_module_dir() load_pyc = util.is_windows() or util.is_osx() formats = load_dir_modules(base, package=__package__, load_compiled=load_pyc) module_names = [] for format in formats: name = format.__name__ for ext in format.extensions: loaders[ext] = format.loader types.update(format.types) if format.extensions: for type_ in format.types: mimes.update(type_.mimes) module_names.append(name.split(".")[-1]) # Migrate pre-0.16 library, which was using an undocumented "feature". sys.modules[name.replace(".", "/")] = format # Migrate old layout if name.startswith("quodlibet."): sys.modules[name.split(".", 1)[1]] = format # This can be used for the quodlibet.desktop file desktop_mime_types = "MimeType=" + \ ";".join(sorted({m.split(";")[0] for m in mimes})) + ";" print_d(desktop_mime_types) s = ", ".join(sorted(module_names)) print_d("Supported formats: %s" % s) if not loaders: raise SystemExit("No formats found!")
def init(): """Import all browsers from this package and from the user directory. After this is called the global `browers` list will contain all classes sorted by priority. Can be called multiple times. """ global browsers, default # ignore double init (for the test suite) if browsers: return this_dir = os.path.dirname(__file__) load_pyc = util.is_windows() or util.is_osx() modules = load_dir_modules(this_dir, package=__package__, load_compiled=load_pyc) user_dir = os.path.join(quodlibet.get_user_dir(), "browsers") if os.path.isdir(user_dir): modules += load_dir_modules(user_dir, package="quodlibet.fake.browsers", load_compiled=load_pyc) for browser in modules: try: browsers.extend(browser.browsers) except AttributeError: print_w("%r doesn't contain any browsers." % browser.__name__) def is_browser(Kind): return isinstance(Kind, type) and issubclass(Kind, Browser) browsers = filter(is_browser, browsers) if not browsers: raise SystemExit("No browsers found!") browsers.sort(key=lambda Kind: Kind.priority) try: default = get("SearchBar") except ValueError: raise SystemExit("Default browser not found!")
def init(): global mimes, _infos, modules, names import mutagen if mutagen.version < MinVersions.MUTAGEN: raise ImportError( "Mutagen %s required. %s found." % (MinVersions.MUTAGEN, mutagen.version_string)) base = os.path.dirname(__file__) load_pyc = util.is_windows() or util.is_osx() formats = load_dir_modules(base, package=__package__, load_compiled=load_pyc) for format in formats: name = format.__name__ for ext in format.extensions: _infos[ext] = format.info types.extend(format.types) if format.extensions: for type_ in format.types: mimes.update(type_.mimes) names.append(type_.format) modules.append(name.split(".")[-1]) # Migrate pre-0.16 library, which was using an undocumented "feature". sys.modules[name.replace(".", "/")] = format # Migrate old layout if name.startswith("quodlibet."): sys.modules[name.split(".", 1)[1]] = format modules.sort() names.sort() # This can be used for the quodlibet.desktop file desktop_mime_types = "MimeType=" + \ ";".join(sorted({m.split(";")[0] for m in mimes})) + ";" print_d(desktop_mime_types) if not _infos: raise SystemExit("No formats found!")
def init(): global mimes, _infos, modules, names, _extensions import mutagen MinVersions.MUTAGEN.check(mutagen.version) base = os.path.dirname(__file__) load_pyc = util.is_windows() or util.is_osx() formats = load_dir_modules(base, package=__package__, load_compiled=load_pyc) for format in formats: name = format.__name__ for ext in format.extensions: _infos[ext] = format.info types.extend(format.types) if format.extensions: for type_ in format.types: mimes.update(type_.mimes) names.append(type_.format) modules.append(name.split(".")[-1]) # Migrate pre-0.16 library, which was using an undocumented "feature". sys.modules[name.replace(".", "/")] = format # Migrate old layout if name.startswith("quodlibet."): sys.modules[name.split(".", 1)[1]] = format modules.sort() names.sort() # This can be used for the quodlibet.desktop file desktop_mime_types = "MimeType=" + \ ";".join(sorted({m.split(";")[0] for m in mimes})) + ";" print_d(desktop_mime_types) if not _infos: raise SystemExit("No formats found!") _extensions = tuple(_infos.keys())
def _init_dbus(): """Setup dbus mainloop integration. Call before using dbus""" # To make GDBus fail early and we don't have to wait for a timeout if is_osx() or is_windows(): os.environ["DBUS_SYSTEM_BUS_ADDRESS"] = "something-invalid" os.environ["DBUS_SESSION_BUS_ADDRESS"] = "something-invalid" try: from dbus.mainloop.glib import DBusGMainLoop, threads_init except ImportError: try: import dbus.glib dbus.glib except ImportError: return else: threads_init() DBusGMainLoop(set_as_default=True)
def _show_files_win32(dirname, entries): if not is_windows(): raise BrowseError("windows only") if not entries: # open_folder_and_select_items will open the parent if no items # are passed, so execute explorer directly for that case try: if subprocess.call(["explorer", dirname]) != 0: raise EnvironmentError("explorer error return status") except EnvironmentError as e: raise BrowseError(e) else: from quodlibet.util.windows import open_folder_and_select_items try: open_folder_and_select_items(dirname, []) except WindowsError as e: raise BrowseError(e)
def _show_files_win32(dirname, entries): if not is_windows(): raise BrowseError("windows only") if not entries: # open_folder_and_select_items will open the parent if no items # are passed, so execute explorer directly for that case try: if subprocess.call(["explorer", dirname]) != 0: raise EnvironmentError("explorer error return status") except EnvironmentError as e: raise BrowseError(e) else: from quodlibet.util.windows import open_folder_and_select_items try: open_folder_and_select_items(dirname, entries) except WindowsError as e: raise BrowseError(e)
def show_uri(label, uri): """Shows a uri. The uri can be anything handled by GIO or a quodlibet specific one. Currently handled quodlibet uris: - quodlibet:///prefs/plugins/<plugin id> Args: label (str) uri (str) the uri to show Returns: True on success, False on error """ parsed = urlparse(uri) if parsed.scheme == "quodlibet": if parsed.netloc != "": print_w("Unknown QuodLibet URL format (%s)" % uri) return False else: return __show_quodlibet_uri(parsed) elif parsed.scheme == "file" and (is_windows() or is_osx()): # Gio on non-Linux can't handle file URIs for some reason, # fall back to our own implementation for now from quodlibet.qltk.showfiles import show_files try: filepath = uri2fsn(uri) except ValueError: return False else: return show_files(filepath, []) else: # Gtk.show_uri_on_window exists since 3.22 try: if hasattr(Gtk, "show_uri_on_window"): from quodlibet.qltk import get_top_parent return Gtk.show_uri_on_window(get_top_parent(label), uri, 0) else: return Gtk.show_uri(None, uri, 0) except GLib.Error: return False
def show_files(dirname, entries=[]): """Shows the directory in the default file browser and if passed a list of directory entries will highlight those. Depending on the system/platform this might highlight all files passed, or only one of them, or none at all. Args: dirname (fsnative): Path to the directory entries (List[fsnative]): List of (relative) filenames in the directory entries (List[fsnative]): List of (relative) filenames in the directory Returns: bool: if the action was successful or not """ assert isinstance(dirname, fsnative) assert all(isinstance(e, fsnative) and os.path.basename(e) == e for e in entries) dirname = os.path.abspath(dirname) if is_windows(): implementations = [_show_files_win32] elif is_osx(): implementations = [_show_files_finder] else: implementations = [ _show_files_fdo, _show_files_thunar, _show_files_xdg_open, _show_files_gnome_open, ] for impl in implementations: try: impl(dirname, entries) except BrowseError as e: print_d("Couldn't show files with %s (%s), ignoring." % (impl, e)) continue else: return True return False
def show_files(dirname, entries=[]): """Shows the directory in the default file browser and if passed a list of directory entries will highlight those. Depending on the system/platform this might highlight all files passed, or only one of them, or none at all. Args: dirname (fsnative): Path to the directory entries (List[fsnative]): List of (relative) filenames in the directory entries (List[fsnative]): List of (relative) filenames in the directory Returns: bool: if the action was successful or not """ assert isinstance(dirname, fsnative) assert all(isinstance(e, fsnative) and os.path.basename(e) == e for e in entries) dirname = os.path.abspath(dirname) if is_windows(): implementations = [_show_files_win32] elif is_osx(): implementations = [_show_files_finder] else: implementations = [ _show_files_fdo, _show_files_thunar, _show_files_xdg_open, _show_files_gnome_open, ] for impl in implementations: try: impl(dirname, entries) except BrowseError: continue else: return True return False
def _py2_to_py3(items): assert PY3 for i in items: try: l = list(i.items()) except AttributeError: raise SerializationError i.clear() for k, v in l: if isinstance(k, bytes): k = k.decode("utf-8", "replace") else: # strip surrogates try: k.encode("utf-8") except UnicodeEncodeError: k = k.encode("utf-8", "replace").decode("utf-8") if k == "~filename" or k == "~mountpoint": if isinstance(v, bytes): try: v = bytes2fsn(v, "utf-8") except ValueError: # just in case, only on Windows assert is_windows() v = v.decode("utf-8", "replace") elif isinstance(v, bytes): v = v.decode("utf-8", "replace") elif isinstance(v, text_type): # strip surrogates try: v.encode("utf-8") except UnicodeEncodeError: v = v.encode("utf-8", "replace").decode("utf-8") i[k] = v return items
from quodlibet.util import is_windows QLPATH = str(Path(quodlibet.__file__).resolve().parent.parent) class Mock: def __init__(self, resp=None): self.lines = [] self.resp = resp def handle_line(self, app, line): self.lines.append(line) return self.resp @skipIf(is_windows(), "unix only") class TUnixRemote(TestCase): def test_fifo(self): mock = Mock() remote = QuodLibetUnixRemote(None, mock) remote._callback(b"foo\n") remote._callback(b"bar\nbaz") self.assertEqual( mock.lines, [bytes2fsn(b, None) for b in [b"foo", b"bar", b"baz"]]) def test_response(self): with temp_filename() as fn: mock = Mock(resp=bytes2fsn(b"resp", None)) remote = QuodLibetUnixRemote(None, mock) remote._callback(b"\x00foo\x00" + fsn2bytes(fn, None) + b"\x00") self.assertEqual(mock.lines, [bytes2fsn(b"foo", None)])
def _init_gtk(): """Call before using Gtk/Gdk""" import gi # pygiaio 3.14rev16 switched to fontconfig for PangoCairo. As this results # in 100% CPU under win7 revert it. Maybe we need to update the # cache in the windows installer for it to work... but for now revert. if is_windows(): os.environ['PANGOCAIRO_BACKEND'] = 'win32' # disable for consistency and trigger events seem a bit flaky here if is_osx(): os.environ["GTK_OVERLAY_SCROLLING"] = "0" # make sure GdkX11 doesn't get used under Windows if os.name == "nt": sys.modules["gi.repository.GdkX11"] = None try: # not sure if this is available under Windows gi.require_version("GdkX11", "3.0") from gi.repository import GdkX11 GdkX11 except (ValueError, ImportError): pass gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") gi.require_version("Pango", "1.0") gi.require_version('Soup', '2.4') from gi.repository import Gtk, Gdk # PyGObject doesn't fail anymore when init fails, so do it ourself initialized, argv = Gtk.init_check(sys.argv) if not initialized: raise SystemExit("Gtk.init failed") sys.argv = list(argv) # add Gtk.TreePath.__getitem__/__len__ for PyGObject 3.2 try: Gtk.TreePath()[0] except TypeError: Gtk.TreePath.__getitem__ = lambda self, index: list(self)[index] Gtk.TreePath.__len__ = lambda self: self.get_depth() # GTK+ 3.4+ constants if not hasattr(Gdk, "BUTTON_PRIMARY"): Gdk.BUTTON_PRIMARY = 1 Gdk.BUTTON_MIDDLE = 2 Gdk.BUTTON_SECONDARY = 3 if not hasattr(Gdk, "EVENT_PROPAGATE"): Gdk.EVENT_PROPAGATE = 0 Gdk.EVENT_STOP = 1 # include our own icon theme directory theme = Gtk.IconTheme.get_default() theme_search_path = get_image_dir() assert os.path.exists(theme_search_path) theme.append_search_path(theme_search_path) # Force menu/button image related settings. We might show too many atm # but this makes sure we don't miss cases where we forgot to force them # per widget. # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # some day... but not now warnings.filterwarnings( 'ignore', '.*Stock items are deprecated.*', Warning) warnings.filterwarnings( 'ignore', '.*:use-stock.*', Warning) warnings.filterwarnings( 'ignore', '.*The property GtkAlignment:[^\s]+ is deprecated.*', Warning) settings = Gtk.Settings.get_default() with warnings.catch_warnings(): warnings.simplefilter("ignore") settings.set_property("gtk-button-images", True) settings.set_property("gtk-menu-images", True) if hasattr(settings.props, "gtk_primary_button_warps_slider"): # https://bugzilla.gnome.org/show_bug.cgi?id=737843 settings.set_property("gtk-primary-button-warps-slider", True) # Make sure PyGObject includes support for foreign cairo structs try: gi.require_foreign("cairo") except AttributeError: # older pygobject pass except ImportError: print_e("PyGObject is missing cairo support") exit(1) # CSS overrides if os.name == "nt": # somehow borders are missing under Windows & Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(""" .menu { border: 1px solid @borders; } """) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) if sys.platform == "darwin": # fix duplicated shadows for popups with Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(""" GtkWindow { box-shadow: none; } .tooltip { border-radius: 0; padding: 0; } .tooltip.background { background-clip: border-box; } """) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # blacklist some modules, simply loading can cause segfaults sys.modules["gtk"] = None sys.modules["gpod"] = None sys.modules["gnome"] = None from quodlibet.qltk import pygobject_version, gtk_version MinVersions.GTK.check(gtk_version) MinVersions.PYGOBJECT.check(pygobject_version)
def test_urllib(self): if is_windows(): # FXIME return urlopen(self.URI).close()
def test_set_scan_dirs_colons(self): set_scan_dirs([STANDARD_PATH, GVFS_PATH]) expected = GVFS_PATH if is_windows() else GVFS_PATH_ESCAPED self.assertEqual(self.scan_dirs, "%s:%s" % (STANDARD_PATH, expected))
def test_colon_paths(self): if not is_windows(): res = split_scan_dirs( ":%s:%s" % (STANDARD_PATH, GVFS_PATH_ESCAPED)) self.assertEquals(res, [STANDARD_PATH, GVFS_PATH])
[(b"a", b"/dev/null"), (b"b", b"/dev/foo")]) # mixed self.assertEqual(func(b"foo\x00a\x00/dev\x00"), [(b"foo", None), (b"a", b"/dev")]) self.assertEqual(func(b"\x00a\x00/dev\x00foo"), [(b"a", b"/dev"), (b"foo", None)]) self.assertEqual(func(b"\x00a\x00/dev\x00foo\x00b\x00/arg\x00bla"), [(b"a", b"/dev"), (b"foo", None), (b"b", b"/arg"), (b"bla", None)]) # inval self.assertRaises(ValueError, func, b"foo\x00bar") @skipIf(is_windows(), "not on Windows") class TFIFO(TestCase): def test_creation_destruction(self): def cb(bs, _): print_d(bs) with temp_filename() as fn: fifo = FIFO(fn, cb) self.failIf(fifo_exists(fifo._path)) fifo.open() self.failUnless(fifo_exists(fifo._path)) # Should *not* error if file is gone fifo.destroy()
# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. from tests import TestCase, skipUnless from gi.repository import Gio, Soup from quodlibet.util import is_osx, is_windows from quodlibet.compat import urlopen @skipUnless(is_osx() or is_windows(), "not on linux") class Thttps(TestCase): """For Windows/OSX to check if we can create a TLS connection using both openssl and whatever backend soup/gio uses. """ URI = "https://www.google.com" def test_urllib(self): if is_windows(): # FXIME return urlopen(self.URI).close() def test_gio(self): if is_osx():
def _init_gtk(): """Call before using Gtk/Gdk""" import gi # pygiaio 3.14rev16 switched to fontconfig for PangoCairo. As this results # in 100% CPU under win7 revert it. Maybe we need to update the # cache in the windows installer for it to work... but for now revert. if is_windows(): environ['PANGOCAIRO_BACKEND'] = 'win32' environ["GTK_CSD"] = "0" # disable for consistency and trigger events seem a bit flaky here if is_osx(): environ["GTK_OVERLAY_SCROLLING"] = "0" # make sure GdkX11 doesn't get used under Windows if os.name == "nt": sys.modules["gi.repository.GdkX11"] = None try: # not sure if this is available under Windows gi.require_version("GdkX11", "3.0") from gi.repository import GdkX11 GdkX11 except (ValueError, ImportError): pass gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") gi.require_version("Pango", "1.0") gi.require_version('Soup', '2.4') from gi.repository import Gtk, Soup from quodlibet.qltk import ThemeOverrider, gtk_version # Work around missing annotation in older libsoup (Ubuntu 14.04 at least) message = Soup.Message() try: message.set_request(None, Soup.MemoryUse.COPY, b"") except TypeError: orig = Soup.Message.set_request def new_set_request(self, content_type, req_use, req_body): return orig(self, content_type, req_use, req_body, len(req_body)) Soup.Message.set_request = new_set_request # PyGObject doesn't fail anymore when init fails, so do it ourself initialized, argv[:] = Gtk.init_check(argv) if not initialized: raise SystemExit("Gtk.init failed") # include our own icon theme directory theme = Gtk.IconTheme.get_default() theme_search_path = get_image_dir() assert os.path.exists(theme_search_path) theme.append_search_path(theme_search_path) # Force menu/button image related settings. We might show too many atm # but this makes sure we don't miss cases where we forgot to force them # per widget. # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # some day... but not now warnings.filterwarnings( 'ignore', '.*Stock items are deprecated.*', Warning) warnings.filterwarnings( 'ignore', '.*:use-stock.*', Warning) warnings.filterwarnings( 'ignore', '.*The property GtkAlignment:[^\s]+ is deprecated.*', Warning) settings = Gtk.Settings.get_default() with warnings.catch_warnings(): warnings.simplefilter("ignore") settings.set_property("gtk-button-images", True) settings.set_property("gtk-menu-images", True) if hasattr(settings.props, "gtk_primary_button_warps_slider"): # https://bugzilla.gnome.org/show_bug.cgi?id=737843 settings.set_property("gtk-primary-button-warps-slider", True) # Make sure PyGObject includes support for foreign cairo structs try: gi.require_foreign("cairo") except AttributeError: # older pygobject pass except ImportError: print_e("PyGObject is missing cairo support") exit(1) css_override = ThemeOverrider() # CSS overrides if os.name == "nt": # somehow borders are missing under Windows & Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" .menu { border: 1px solid @borders; } """) css_override.register_provider("", style_provider) if sys.platform == "darwin": # fix duplicated shadows for popups with Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" GtkWindow { box-shadow: none; } .tooltip { border-radius: 0; padding: 0; } .tooltip.background { background-clip: border-box; } """) css_override.register_provider("", style_provider) if gtk_version[:2] >= (3, 20): # https://bugzilla.gnome.org/show_bug.cgi?id=761435 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" spinbutton, button { min-height: 1.8rem; } .view button { min-height: 2.0rem; } entry { min-height: 2.4rem; } entry.cell { min-height: 0; } """) css_override.register_provider("Adwaita", style_provider) css_override.register_provider("HighContrast", style_provider) # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # blacklist some modules, simply loading can cause segfaults sys.modules["gtk"] = None sys.modules["gpod"] = None sys.modules["gnome"] = None from quodlibet.qltk import pygobject_version, gtk_version MinVersions.GTK.check(gtk_version) MinVersions.PYGOBJECT.check(pygobject_version)
import threading from xml.dom import minidom from urllib.parse import quote import queue from quodlibet import _, print_d from quodlibet.plugins.gui import UserInterfacePlugin from quodlibet.util import gi_require_versions, is_windows, is_osx from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import (PluginImportException, PluginConfig, ConfProp, BoolConfProp, FloatConfProp, PluginNotSupportedError) try: gi_require_versions("WebKit2", ["4.0", "3.0"]) except ValueError as e: if is_windows() or is_osx(): raise PluginNotSupportedError raise PluginImportException("GObject Introspection: " + str(e)) from gi.repository import WebKit2, Gtk, GLib from quodlibet import qltk from quodlibet.util import escape, cached_property, connect_obj from quodlibet.qltk import Icons, Align from quodlibet.qltk.entry import UndoEntry from quodlibet.pattern import URLFromPattern from quodlibet.util.urllib import urlopen # for the mobile version USER_AGENT = ("Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) "
# osx implementation might be buggy so let users disable it "disable_mmkeys": "false", # the UI language to use, empty means system default "language": "", # the pattern for the main window title "window_title_pattern": "~title~version~~people", # the format of the timestamps in DateColumn "datecolumn_timestamp_format": "", # scrollbar does not fade out when inactive "scrollbar_always_visible": "true" if (is_osx() or is_windows()) else "false", # Force fontconfig as PangoCairo backend "pangocairo_force_fontconfig": "false", # Whether the plugin window appears on top of others "plugins_window_on_top": "false", # search bar font style (#3647) "monospace_query": "false", # size to apply to query box, in any Pango CSS units (e.g. '100%', '1rem') "query_font_size": "100%", # Amount of colour to apply to validating text entries # (0.0 = no colour, 1.0 = full colour)
from xml.dom import minidom from urllib.parse import quote import queue from quodlibet import _, print_d from quodlibet.plugins.gui import UserInterfacePlugin from quodlibet.util import gi_require_versions, is_windows, is_osx from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import (PluginImportException, PluginConfig, ConfProp, BoolConfProp, FloatConfProp, PluginNotSupportedError) try: gi_require_versions("WebKit2", ["4.0", "3.0"]) except ValueError as e: if is_windows() or is_osx(): raise PluginNotSupportedError raise PluginImportException("GObject Introspection: " + str(e)) from gi.repository import WebKit2, Gtk, GLib from quodlibet import qltk from quodlibet.util import escape, cached_property, connect_obj from quodlibet.qltk import Icons, Align from quodlibet.qltk.entry import UndoEntry from quodlibet.pattern import URLFromPattern from quodlibet.util.urllib import urlopen # for the mobile version USER_AGENT = ("Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) " "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0"
def _init_gtk(): """Call before using Gtk/Gdk""" import gi # pygiaio 3.14rev16 switched to fontconfig for PangoCairo. As this results # in 100% CPU under win7 revert it. Maybe we need to update the # cache in the windows installer for it to work... but for now revert. if is_windows(): os.environ['PANGOCAIRO_BACKEND'] = 'win32' os.environ["GTK_CSD"] = "0" # disable for consistency and trigger events seem a bit flaky here if is_osx(): os.environ["GTK_OVERLAY_SCROLLING"] = "0" # make sure GdkX11 doesn't get used under Windows if os.name == "nt": sys.modules["gi.repository.GdkX11"] = None try: # not sure if this is available under Windows gi.require_version("GdkX11", "3.0") from gi.repository import GdkX11 GdkX11 except (ValueError, ImportError): pass gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") gi.require_version("Pango", "1.0") gi.require_version('Soup', '2.4') from gi.repository import Gtk, Soup from quodlibet.qltk import ThemeOverrider, gtk_version # Work around missing annotation in older libsoup (Ubuntu 14.04 at least) message = Soup.Message() try: message.set_request(None, Soup.MemoryUse.COPY, b"") except TypeError: orig = Soup.Message.set_request def new_set_request(self, content_type, req_use, req_body): return orig(self, content_type, req_use, req_body, len(req_body)) Soup.Message.set_request = new_set_request # PyGObject doesn't fail anymore when init fails, so do it ourself initialized, argv = Gtk.init_check(sys.argv) if not initialized: raise SystemExit("Gtk.init failed") sys.argv = list(argv) # include our own icon theme directory theme = Gtk.IconTheme.get_default() theme_search_path = get_image_dir() assert os.path.exists(theme_search_path) theme.append_search_path(theme_search_path) # Force menu/button image related settings. We might show too many atm # but this makes sure we don't miss cases where we forgot to force them # per widget. # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # some day... but not now warnings.filterwarnings( 'ignore', '.*Stock items are deprecated.*', Warning) warnings.filterwarnings( 'ignore', '.*:use-stock.*', Warning) warnings.filterwarnings( 'ignore', '.*The property GtkAlignment:[^\s]+ is deprecated.*', Warning) settings = Gtk.Settings.get_default() with warnings.catch_warnings(): warnings.simplefilter("ignore") settings.set_property("gtk-button-images", True) settings.set_property("gtk-menu-images", True) if hasattr(settings.props, "gtk_primary_button_warps_slider"): # https://bugzilla.gnome.org/show_bug.cgi?id=737843 settings.set_property("gtk-primary-button-warps-slider", True) # Make sure PyGObject includes support for foreign cairo structs try: gi.require_foreign("cairo") except AttributeError: # older pygobject pass except ImportError: print_e("PyGObject is missing cairo support") exit(1) css_override = ThemeOverrider() # CSS overrides if os.name == "nt": # somehow borders are missing under Windows & Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" .menu { border: 1px solid @borders; } """) css_override.register_provider("", style_provider) if sys.platform == "darwin": # fix duplicated shadows for popups with Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" GtkWindow { box-shadow: none; } .tooltip { border-radius: 0; padding: 0; } .tooltip.background { background-clip: border-box; } """) css_override.register_provider("", style_provider) if gtk_version[:2] >= (3, 20): # https://bugzilla.gnome.org/show_bug.cgi?id=761435 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" spinbutton, button { min-height: 1.8rem; } .view button { min-height: 2.0rem; } entry { min-height: 2.4rem; } """) css_override.register_provider("Adwaita", style_provider) css_override.register_provider("HighContrast", style_provider) # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # blacklist some modules, simply loading can cause segfaults sys.modules["gtk"] = None sys.modules["gpod"] = None sys.modules["gnome"] = None from quodlibet.qltk import pygobject_version, gtk_version MinVersions.GTK.check(gtk_version) MinVersions.PYGOBJECT.check(pygobject_version)
import configparser as ConfigParser from os.path import dirname, basename from quodlibet.util.dprint import print_d, print_w from gi.repository import GObject from quodlibet.util.path import xdg_get_system_data_dirs import quodlibet from quodlibet import util from quodlibet.devices import _udev as udev from quodlibet.util.importhelper import load_dir_modules try: import dbus except ImportError: if not util.is_osx() and not util.is_windows(): print_w(_("Could not import %s, which is needed for " "device support.") % "dbus-python") dbus = None devices = [] def init_devices(): global devices load_pyc = util.is_windows() or util.is_osx() modules = load_dir_modules(dirname(__file__), package=__package__, load_compiled=load_pyc)
from tests import TestCase, skipUnless from gi.repository import Gio, Soup from quodlibet.util import is_osx, is_windows from quodlibet.compat import urlopen # this is fixed in 3.6, but we currently still use 3.5 bundles on travis if is_osx(): glib_net_fixed = "GTLS_SYSTEM_CA_FILE" in os.environ else: glib_net_fixed = True @skipUnless(is_osx() or is_windows()) class Thttps(TestCase): """For Windows/OSX to check if we can create a TLS connection using both openssl and whatever backend soup/gio uses. """ URI = "https://www.google.com" def test_urllib(self): if is_windows(): # FXIME return urlopen(self.URI).close() def test_gio(self): if not glib_net_fixed: