/usr/lib/python2.7/dist-packages/quodlibet/update.py is in exfalso 3.7.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | # -*- coding: utf-8 -*-
# Copyright 2016 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
"""Check for new versions of the application
For each "build type" (basically each bundle/installer) we host
an (sparkle appcast) rss feed on quodlibet.github.io.
We download it and compare versions...
Since there can be multiple builds per release for the same release type
(e.g. the installer was broken and had to be redone) the build version
is used and not the release version.
"""
from gi.repository import Gtk
import quodlibet
from quodlibet.build import BUILD_TYPE
from quodlibet.compat import text_type, urlopen
from quodlibet.qltk.window import Dialog
from quodlibet.util.dprint import print_exc
from quodlibet.util import escape
from quodlibet.util.thread import call_async, Cancellable
class UpdateError(Exception):
pass
def parse_version(version_string):
"""Might raise ValueError"""
return tuple(map(int, version_string.split(".")))
def format_version(version_tuple):
return u".".join(map(text_type, version_tuple))
def fetch_versions(build_type, timeout=5.0):
"""Fetches the list of available releases and returns a list
of version tuples. Sorted and oldest version first. The list
might be empty. Also returns an URL to the download page.
Args:
build_type (text): the build type. e.g. "default" or "windows"
timeout (float): timeout in seconds
Thread safe.
Raises UpdateError
"""
# TODO: we currently don't depend on feedparser.. maybe we should?
try:
import feedparser
except ImportError as error:
raise UpdateError(error)
try:
content = urlopen(
u"https://quodlibet.github.io/appcast/%s.rss" % build_type,
timeout=timeout).read()
except Exception as error:
raise UpdateError(error)
d = feedparser.parse(content)
if d.bozo:
raise UpdateError(d.bozo_exception)
try:
link = d.feed.link
enclosures = [e for entry in d.entries for e in entry.enclosures]
except AttributeError as error:
raise UpdateError(error)
try:
versions = [parse_version(en.version) for en in enclosures]
except ValueError as error:
raise UpdateError(error)
return sorted(versions), link
class UpdateDialog(Dialog):
def __init__(self, parent):
super(UpdateDialog, self).__init__(
title=_("Checking for Updates"), use_header_bar=True,
modal=True)
self.set_default_size(380, 110)
self.set_transient_for(parent)
self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL)
self.set_default_response(Gtk.ResponseType.CANCEL)
content = self.get_content_area()
self._stack = Gtk.Stack(border_width=10)
self._stack.set_transition_duration(500)
self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
content.pack_start(self._stack, True, True, 0)
content.show_all()
spinner = Gtk.Spinner()
spinner.start()
self._set_widget(spinner)
def run(self):
def do_fetch_versions():
try:
return fetch_versions(BUILD_TYPE)
except UpdateError:
print_exc()
return None
cancel = Cancellable()
self.connect("response", self._on_response, cancel)
call_async(do_fetch_versions, cancel, self._on_result)
return super(UpdateDialog, self).run()
def _on_result(self, args):
if args is None or not args[0]:
text = _("Connection failed")
else:
versions, url = args
version = quodlibet.get_build_version()
def f(v):
return "<b>%s</b>" % escape(format_version(v))
if version >= versions[-1]:
text = (_("You are already using the newest version "
"%(version)s") % {"version": f(version)})
else:
text = (_("A new version %(new-version)s is available\n\n"
"You are currently using version %(old-version)s\n\n"
"Visit the <a href='%(url)s'>website</a>") % {
"new-version": f(versions[-1]),
"old-version": f(version),
"url": escape(url)})
self._set_widget(
Gtk.Label(label=text, use_markup=True, wrap=True,
justify=Gtk.Justification.CENTER))
def _set_widget(self, widget):
old = self._stack.get_visible_child()
self._stack.add(widget)
widget.show()
self._stack.set_visible_child(widget)
if old:
old.destroy()
def _on_response(self, dialog, response_id, cancel):
cancel.cancel()
|