Exemple #1
0
def open_uri(uri):
    """Opens a local or remote URI with the default application"""
    system.reset_library_preloads()
    try:
        Gtk.show_uri(None, uri, Gdk.CURRENT_TIME)
    except GLib.Error as ex:
        logger.exception("Failed to open URI %s: %s", uri, ex)
Exemple #2
0
def fetch_icons(lutris_media, window):
    """Download missing icons from lutris.net"""
    if not lutris_media:
        return

    available_banners, available_icons = lutris_media
    downloads = [(slug, available_banners[slug], get_icon_path(slug, BANNER))
                 for slug in available_banners
                 ] + [(slug, available_icons[slug], get_icon_path(slug, ICON))
                      for slug in available_icons]
    with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
        future_downloads = {
            executor.submit(download_media, url, dest_path): slug
            for slug, url, dest_path in downloads
        }
        for future in concurrent.futures.as_completed(future_downloads):
            slug = future_downloads[future]
            try:
                future.result()
            except Exception as ex:  # pylint: disable=broad-except
                logger.exception('%r generated an exception: %s', slug, ex)
            else:
                GLib.idle_add(window.update_image_for_slug,
                              slug,
                              priority=GLib.PRIORITY_LOW)

    if bool(available_icons):
        udpate_desktop_icons()
Exemple #3
0
def open_uri(uri):
    """Opens a local or remote URI with the default application"""
    system.reset_library_preloads()
    try:
        Gtk.show_uri(None, uri, Gdk.CURRENT_TIME)
    except GLib.Error as ex:
        logger.exception("Failed to open URI %s: %s", uri, ex)
Exemple #4
0
 def sync_icons(self):
     try:
         resources.fetch_icons([game['slug'] for game in self.game_list],
                               callback=self.on_image_downloaded)
     except TypeError as ex:
         logger.exception("Invalid game list:\n%s\nException: %s",
                          self.game_list, ex)
Exemple #5
0
    def __init__(self):
        super().__init__(
            application_id="net.lutris.Lutris",
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
        )
        init_lutris()
        gettext.bindtextdomain("lutris", "/usr/share/locale")
        gettext.textdomain("lutris")

        GLib.set_application_name(_("Lutris"))
        self.running_games = Gio.ListStore.new(Game)
        self.window = None
        self.tray = None
        self.css_provider = Gtk.CssProvider.new()
        self.run_in_background = False

        if os.geteuid() == 0:
            ErrorDialog(
                "Running Lutris as root is not recommended and may cause unexpected issues"
            )

        try:
            self.css_provider.load_from_path(
                os.path.join(datapath.get(), "ui", "lutris.css"))
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, "add_main_option"):
            self.add_arguments()
        else:
            ErrorDialog(
                "Your Linux distribution is too old. Lutris won't function properly."
            )
Exemple #6
0
    def __init__(self):
        super().__init__(
            application_id="net.lutris.Lutris",
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
        )
        init_lutris()
        gettext.bindtextdomain("lutris", "/usr/share/locale")
        gettext.textdomain("lutris")

        GLib.set_application_name(_("Lutris"))
        self.running_games = Gio.ListStore.new(Game)
        self.window = None
        self.tray = None
        self.css_provider = Gtk.CssProvider.new()
        self.run_in_background = False

        if os.geteuid() == 0:
            ErrorDialog(
                "Running Lutris as root is not recommended and may cause unexpected issues"
            )

        try:
            self.css_provider.load_from_path(
                os.path.join(datapath.get(), "ui", "lutris.css")
            )
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, "add_main_option"):
            self.add_arguments()
        else:
            ErrorDialog(
                "Your Linux distribution is too old. Lutris won't function properly."
            )
Exemple #7
0
    def __init__(self):

        Gtk.Application.__init__(
            self,
            application_id='net.lutris.Lutris',
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)

        gettext.bindtextdomain("lutris", "/usr/share/locale")
        gettext.textdomain("lutris")

        check_config()
        migrate()
        update_platforms()

        GLib.set_application_name(_('Lutris'))
        self.window = None
        self.css_provider = Gtk.CssProvider.new()

        try:
            self.css_provider.load_from_path(
                os.path.join(datapath.get(), 'ui', 'lutris.css'))
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, 'add_main_option'):
            self.add_arguments()
        else:
            ErrorDialog(
                "Your Linux distribution is too old, Lutris won't function properly"
            )
Exemple #8
0
    def __init__(self):

        Gtk.Application.__init__(self, application_id='net.lutris.Lutris',
                                 flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)

        gettext.bindtextdomain("lutris", "/usr/share/locale")
        gettext.textdomain("lutris")

        check_config()
        migrate()
        update_platforms()

        GLib.set_application_name(_('Lutris'))
        self.window = None
        self.css_provider = Gtk.CssProvider.new()

        try:
            self.css_provider.load_from_path(os.path.join(datapath.get(), 'ui', 'lutris.css'))
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, 'add_main_option'):
            self.add_arguments()
        else:
            ErrorDialog("Your Linux distribution is too old, Lutris won't function properly")
Exemple #9
0
    def __init__(self):
        super().__init__(
            application_id="net.lutris.Lutris",
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
        )

        GObject.add_emission_hook(Game, "game-launch", self.on_game_launch)
        GObject.add_emission_hook(Game, "game-start", self.on_game_start)
        GObject.add_emission_hook(Game, "game-stop", self.on_game_stop)
        GObject.add_emission_hook(Game, "game-install", self.on_game_install)

        GLib.set_application_name(_("Lutris"))
        self.window = None

        self.running_games = Gio.ListStore.new(Game)
        self.app_windows = {}
        self.tray = None
        self.css_provider = Gtk.CssProvider.new()
        self.run_in_background = False

        if os.geteuid() == 0:
            ErrorDialog(_("Running Lutris as root is not recommended and may cause unexpected issues"))

        try:
            self.css_provider.load_from_path(os.path.join(datapath.get(), "ui", "lutris.css"))
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, "add_main_option"):
            self.add_arguments()
        else:
            ErrorDialog(_("Your Linux distribution is too old. Lutris won't function properly."))
Exemple #10
0
 def setup_defaults(self):
     """Sets the defaults for newly created prefixes"""
     self.override_dll("winemenubuilder.exe", "")
     try:
         self.desktop_integration()
     except OSError as ex:
         logger.error("Failed to setup desktop integration, the prefix may not be valid.")
         logger.exception(ex)
Exemple #11
0
 def setup_defaults(self):
     """Sets the defaults for newly created prefixes"""
     for dll, value in DEFAULT_DLL_OVERRIDES.items():
         self.override_dll(dll, value)
     try:
         self.desktop_integration()
     except OSError as ex:
         logger.error("Failed to setup desktop integration, the prefix may not be valid.")
         logger.exception(ex)
Exemple #12
0
 def setup_defaults(self):
     """Sets the defaults for newly created prefixes"""
     self.override_dll("winemenubuilder.exe", "")
     self.override_dll("steamwebhelper.exe", "")
     try:
         self.desktop_integration()
     except OSError as ex:
         logger.error("Failed to setup desktop integration, the prefix may not be valid.")
         logger.exception(ex)
Exemple #13
0
def get_appid(app):
    """Get the appid for the game"""
    try:
        return os.path.splitext(app.get_id())[0]
    except UnicodeDecodeError:
        logger.exception(
            "Failed to read ID for app %s (non UTF-8 encoding). Reverting to executable name.",
            app,
        )
        return app.get_executable()
Exemple #14
0
def get_appid(app):
    """Get the appid for the game"""
    try:
        return os.path.splitext(app.get_id())[0]
    except UnicodeDecodeError:
        logger.exception(
            "Failed to read ID for app %s (non UTF-8 encoding). Reverting to executable name.",
            app,
        )
        return app.get_executable()
Exemple #15
0
 def execute_process(self, command, env=None):
     try:
         if self.cwd and not system.path_exists(self.cwd):
             os.makedirs(self.cwd)
         return subprocess.Popen(command, bufsize=1,
                                 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                 cwd=self.cwd, env=env)
     except OSError as ex:
         logger.exception("Failed to execute %s: %s", ' '.join(command), ex)
         self.error = ex.strerror
Exemple #16
0
 def stop(self):
     """The kill command runs wineserver -k."""
     wine_path = self.get_executable()
     wine_root = os.path.dirname(wine_path)
     env = self.get_env(full=True)
     command = [os.path.join(wine_root, "wineserver"), " -k"]
     logger.debug("Killing all wine processes: %s" % command)
     try:
         subprocess.Popen(command, env=env)
     except OSError:
         logger.exception('Could not terminate wineserver %s', command)
Exemple #17
0
def _trigger_early_poll():
    global _timeout_set
    try:
        # prevent changes to size during iteration
        for command in set(_commands):
            command.watch_children()
    except Exception:
        logger.exception("Signal handler exception")
    finally:
        _timeout_set = False
    return False
Exemple #18
0
 def stop(self):
     """The kill command runs wineserver -k."""
     wine_path = self.get_executable()
     wine_root = os.path.dirname(wine_path)
     env = self.get_env(full=True)
     command = [os.path.join(wine_root, "wineserver"), " -k"]
     logger.debug("Killing all wine processes: %s" % command)
     try:
         subprocess.Popen(command, env=env)
     except OSError:
         logger.exception('Could not terminate wineserver %s', command)
Exemple #19
0
 def __init__(self, steamapps_paths, callback=None):
     self.monitors = []
     self.callback = callback
     for steam_path in steamapps_paths:
         path = Gio.File.new_for_path(steam_path)
         try:
             monitor = path.monitor_directory(Gio.FileMonitorFlags.NONE)
             logger.debug('Watching Steam folder %s', steam_path)
             monitor.connect('changed', self._on_directory_changed)
             self.monitors.append(monitor)
         except GLib.Error as e:
             logger.exception(e)
Exemple #20
0
 def __init__(self, steamapps_paths, callback=None):
     self.monitors = []
     self.callback = callback
     for steam_path in steamapps_paths:
         path = Gio.File.new_for_path(steam_path)
         try:
             monitor = path.monitor_directory(Gio.FileMonitorFlags.NONE)
             logger.debug('Watching Steam folder %s', steam_path)
             monitor.connect('changed', self._on_directory_changed)
             self.monitors.append(monitor)
         except GLib.Error as e:
             logger.exception(e)
Exemple #21
0
    def get_raw_registry(reg_filename):
        """Return an array of the unprocessed contents of a registry file"""
        if not system.path_exists(reg_filename):
            return []
        with open(reg_filename, "r", encoding='utf-8') as reg_file:

            try:
                registry_content = reg_file.readlines()
            except Exception:  # pylint: disable=broad-except
                logger.exception("Failed to registry read %s", reg_filename)
                registry_content = []
        return registry_content
Exemple #22
0
 def sync_icons(self):
     """Download missing icons"""
     game_slugs = [game['slug'] for game in self.game_list]
     if not game_slugs:
         return
     logger.debug("Syncing %d icons", len(game_slugs))
     try:
         GLib.idle_add(resources.fetch_icons, game_slugs,
                       self.on_image_downloaded)
     except TypeError as ex:
         logger.exception("Invalid game list:\n%s\nException: %s",
                          self.game_list, ex)
Exemple #23
0
 def execute_process(self, command, env=None):
     try:
         if self.cwd and not system.path_exists(self.cwd):
             os.makedirs(self.cwd)
         return subprocess.Popen(command,
                                 bufsize=1,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT,
                                 cwd=self.cwd,
                                 env=env)
     except OSError as ex:
         logger.exception("Failed to execute %s: %s", ' '.join(command), ex)
         self.error = ex.strerror
Exemple #24
0
 def ensure_discord_disconnected(self):
     """Ensure we are definitely disconnected and fix broken event loop from pypresence"""
     logger.debug("Ensuring disconnected.")
     if self.rpc_client is not None:
         try:
             self.rpc_client.close()
         except Exception as e:
             logger.exception("Unable to close Discord RPC connection: %s",
                              e)
         if self.rpc_client.sock_writer is not None:
             try:
                 logger.debug("Forcefully closing sock writer.")
                 self.rpc_client.sock_writer.close()
             except Exception:
                 logger.exception("Sock writer could not be closed.")
         try:
             logger.debug("Forcefully closing event loop.")
             self.rpc_client.loop.close()
         except Exception:
             logger.debug("Could not close event loop.")
         try:
             logger.debug("Forcefully replacing event loop.")
             self.rpc_client.loop = None
             asyncio.set_event_loop(asyncio.new_event_loop())
         except Exception as e:
             logger.exception("Could not replace event loop: %s", e)
         try:
             logger.debug("Forcefully deleting RPC client.")
             self.rpc_client = None
         except Exception as ex:
             logger.exception(ex)
     self.rpc_client = None
     self.presence_connected = False
Exemple #25
0
 def ensure_discord_disconnected(self):
     """Ensure we are definitely disconnected and fix broken event loop from pypresence"""
     logger.debug("Ensuring disconnected.")
     if self.rpc_client is not None:
         try:
             self.rpc_client.close()
         except Exception as e:
             logger.exception("Unable to close Discord RPC connection: %s", e)
         if self.rpc_client.sock_writer is not None:
             try:
                 logger.debug("Forcefully closing sock writer.")
                 self.rpc_client.sock_writer.close()
             except Exception:
                 logger.exception("Sock writer could not be closed.")
         try:
             logger.debug("Forcefully closing event loop.")
             self.rpc_client.loop.close()
         except Exception:
             logger.debug("Could not close event loop.")
         try:
             logger.debug("Forcefully replacing event loop.")
             self.rpc_client.loop = None
             asyncio.set_event_loop(asyncio.new_event_loop())
         except Exception as e:
             logger.exception("Could not replace event loop: %s", e)
         try:
             logger.debug("Forcefully deleting RPC client.")
             self.rpc_client = None
         except Exception as ex:
             logger.exception(ex)
     self.rpc_client = None
     self.presence_connected = False
Exemple #26
0
def get_display_manager():
    """Return the appropriate display manager instance.
    Defaults to Mutter if available. This is the only one to support Wayland.
    """
    try:
        return MutterDisplayManager()
    except DBusException as ex:
        logger.debug("Mutter DBus service not reachable: %s", ex)
    except Exception as ex:  # pylint: disable=broad-except
        logger.exception("Failed to instanciate MutterDisplayConfig. Please report with exception: %s", ex)
    try:
        return DisplayManager()
    except (GLib.Error, NoScreenDetected):
        return LegacyDisplayManager()
Exemple #27
0
 def disconnect(self):
     """Ensure we are definitely disconnected and fix broken event loop from pypresence
     That method is a huge mess of non-deterministic bs and should be nuked from orbit.
     """
     logger.debug("Disconnecting from Discord")
     if self.rpc_client:
         try:
             self.rpc_client.close()
         except Exception as e:
             logger.exception("Unable to close Discord RPC connection: %s", e)
         if self.rpc_client.sock_writer is not None:
             try:
                 logger.debug("Forcefully closing sock writer.")
                 self.rpc_client.sock_writer.close()
             except Exception:
                 logger.exception("Sock writer could not be closed.")
         try:
             logger.debug("Forcefully closing event loop.")
             self.rpc_client.loop.close()
         except Exception:
             logger.debug("Could not close event loop.")
         try:
             logger.debug("Forcefully replacing event loop.")
             self.rpc_client.loop = None
             asyncio.set_event_loop(asyncio.new_event_loop())
         except Exception as e:
             logger.exception("Could not replace event loop: %s", e)
         try:
             logger.debug("Forcefully deleting RPC client.")
             self.rpc_client = None
         except Exception as ex:
             logger.exception(ex)
     self.rpc_client = None
     self.presence_connected = False
Exemple #28
0
    def get_raw_registry(reg_filename):
        """Return an array of the unprocessed contents of a registry file"""
        if not system.path_exists(reg_filename):
            return []
        with open(reg_filename, "r") as reg_file:

            try:
                registry_content = reg_file.readlines()
            except Exception:  # pylint: disable=broad-except
                logger.exception(
                    "Failed to registry read %s, please send attach this file in a bug report",
                    reg_filename)
                registry_content = []
        return registry_content
Exemple #29
0
    def get_raw_registry(reg_filename):
        """Return an array of the unprocessed contents of a registry file"""
        if not system.path_exists(reg_filename):
            return []
        with open(reg_filename, "r") as reg_file:

            try:
                registry_content = reg_file.readlines()
            except Exception:  # pylint: disable=broad-except
                logger.exception(
                    "Failed to registry read %s, please send attach this file in a bug report",
                    reg_filename
                )
                registry_content = []
        return registry_content
Exemple #30
0
 def get_installer_files(self, installer, installer_file_id):
     """Replace the user provided file with download links from Humble Bundle"""
     try:
         link = get_humble_download_link(installer.service_appid, installer.runner)
     except Exception as ex:
         logger.exception("Failed to get Humble Bundle game: %s", ex)
         raise UnavailableGame
     if not link:
         raise UnavailableGame("No game found on Humble Bundle")
     filename = link.split("?")[0].split("/")[-1]
     return [
         InstallerFile(installer.game_slug, installer_file_id, {
             "url": link,
             "filename": filename
         })
     ]
Exemple #31
0
 def ensure_discord_connected(self):
     """Make sure we are actually connected before trying to send requests"""
     logger.debug("Ensuring connected.")
     if self.presence_connected:
         logger.debug("Already connected!")
     else:
         logger.debug("Creating Presence object.")
         self.rpc_client = PyPresence(self.client_id)
         try:
             logger.debug("Attempting to connect.")
             self.rpc_client.connect()
             self.presence_connected = True
         except Exception as ex:
             logger.exception("Unable to reach Discord.  Skipping update: %s", ex)
             self.ensure_discord_disconnected()
     return self.presence_connected
Exemple #32
0
def db_insert(db_path, table, fields):
    columns = ", ".join(list(fields.keys()))
    placeholders = ("?, " * len(fields))[:-2]
    field_values = tuple(fields.values())
    with db_cursor(db_path) as cursor:
        try:
            cursor_execute(
                cursor,
                "insert into {0}({1}) values ({2})".format(table, columns, placeholders),
                field_values,
            )
        except sqlite3.IntegrityError:
            logger.exception("Uh oh, an integrity error has occurred!")
            raise
        inserted_id = cursor.lastrowid
    return inserted_id
Exemple #33
0
    def update_row(self, game_id, game_year, game_playtime):
        """Update game informations."""
        row = self.get_row_by_id(game_id)
        if row:
            row[COL_YEAR] = str(game_year)
            if game_playtime:
                try:
                    game_playtime = "%.1f hrs" % float(game_playtime)
                except TypeError:
                    logger.exception("Failed to parse playtime %s", game_playtime)
                    game_playtime = "-"
            else:
                game_playtime = "-"
            row[COL_PLAYTIME_TEXT] = game_playtime

            self.update_image(game_id, row[COL_INSTALLED])
Exemple #34
0
 def ensure_discord_connected(self):
     """Make sure we are actually connected before trying to send requests"""
     logger.debug("Ensuring connected.")
     if self.presence_connected:
         logger.debug("Already connected!")
     else:
         logger.debug("Creating Presence object.")
         self.rpc_client = PyPresence(self.client_id)
         try:
             logger.debug("Attempting to connect.")
             self.rpc_client.connect()
             self.presence_connected = True
         except Exception as ex:
             logger.exception(
                 "Unable to reach Discord.  Skipping update: %s", ex)
             self.ensure_discord_disconnected()
     return self.presence_connected
Exemple #35
0
 def execute_process(self, command, env=None):
     """Execute and return a subprocess"""
     if self.cwd and not system.path_exists(self.cwd):
         try:
             os.makedirs(self.cwd)
         except OSError:
             logger.error("Failed to create working directory, falling back to %s", self.fallback_cwd)
             self.cwd = "/tmp"
     try:
         return subprocess.Popen(  # pylint: disable=consider-using-with
             command,
             stdout=subprocess.PIPE,
             stderr=subprocess.STDOUT,
             cwd=self.cwd,
             env=env,
         )
     except OSError as ex:
         logger.exception("Failed to execute %s: %s", " ".join(command), ex)
         self.error = ex.strerror
Exemple #36
0
def get_display_manager():
    """Return the appropriate display manager instance.
    Defaults to Mutter if available. This is the only one to support Wayland.
    """
    if DBUS_AVAILABLE:
        try:
            return MutterDisplayManager()
        except DBusException as ex:
            logger.debug("Mutter DBus service not reachable: %s", ex)
        except Exception as ex:  # pylint: disable=broad-except
            logger.exception("Failed to instanciate MutterDisplayConfig. Please report with exception: %s", ex)
    else:
        logger.error("DBus is not available, lutris was not properly installed.")
    if LIB_GNOME_DESKTOP_AVAILABLE:
        try:
            return DisplayManager()
        except (GLib.Error, NoScreenDetected):
            pass
    return LegacyDisplayManager()
Exemple #37
0
    def __init__(self):
        super().__init__(
            application_id="net.lutris.Lutris",
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
        )
        logger.info("Running Lutris %s", settings.VERSION)
        set_child_subreaper()
        gettext.bindtextdomain("lutris", "/usr/share/locale")
        gettext.textdomain("lutris")

        check_config()
        migrate()
        update_platforms()
        check_driver()
        check_libs()
        check_vulkan()

        GLib.set_application_name(_("Lutris"))
        self.running_games = []
        self.window = None
        self.help_overlay = None
        self.tray = None
        self.css_provider = Gtk.CssProvider.new()

        if os.geteuid() == 0:
            ErrorDialog(
                "Running Lutris as root is not recommended and may cause unexpected issues"
            )

        try:
            self.css_provider.load_from_path(
                os.path.join(datapath.get(), "ui", "lutris.css")
            )
        except GLib.Error as e:
            logger.exception(e)

        if hasattr(self, "add_main_option"):
            self.add_arguments()
        else:
            ErrorDialog(
                "Your Linux distribution is too old, Lutris won't function properly"
            )
Exemple #38
0
def get_system_wine_version(wine_path="wine"):
    """Return the version of Wine installed on the system."""
    if wine_path != "wine" and not system.path_exists(wine_path):
        return
    if wine_path == "wine" and not system.find_executable("wine"):
        return
    if os.path.isabs(wine_path):
        wine_stats = os.stat(wine_path)
        if wine_stats.st_size < 2000:
            # This version is a script, ignore it
            return
    try:
        version = subprocess.check_output([wine_path, "--version"]).decode().strip()
    except (OSError, subprocess.CalledProcessError) as ex:
        logger.exception("Error reading wine version for %s: %s", wine_path, ex)
        return
    else:
        if version.startswith("wine-"):
            version = version[5:]
        return version
def migrate():
    dest_dir = settings.BANNER_PATH
    src_dir = os.path.join(settings.DATA_DIR, "banners")

    try:
        # init_lutris() creates the new banners directrory
        if os.path.isdir(src_dir) and os.path.isdir(dest_dir):
            for filename in os.listdir(src_dir):
                src_file = os.path.join(src_dir, filename)
                dest_file = os.path.join(dest_dir, filename)

                if not os.path.exists(dest_file):
                    os.rename(src_file, dest_file)
                else:
                    os.unlink(src_file)

            if not os.listdir(src_dir):
                os.rmdir(src_dir)
    except OSError as ex:
        logger.exception("Failed to migrate banners: %s", ex)
Exemple #40
0
    def parse(self, line):
        """Parse a registry line, populating meta and subkeys"""
        if len(line) < 4:
            # Line is too short, nothing to parse
            return

        if line.startswith("#"):
            self.add_meta(line)
        elif line.startswith('"'):
            try:
                key, value = re.split(re.compile(r"(?<![^\\]\\\")="), line, maxsplit=1)
            except ValueError as ex:
                logger.error("Unable to parse line %s", line)
                logger.exception(ex)
                return
            key = key[1:-1]
            self.subkeys[key] = value
        elif line.startswith("@"):
            key, value = line.split("=", 1)
            self.subkeys["default"] = value
Exemple #41
0
def get_system_wine_version(wine_path="wine"):
    """Return the version of Wine installed on the system."""
    if wine_path != "wine" and not system.path_exists(wine_path):
        return
    if wine_path == "wine" and not system.find_executable("wine"):
        return
    if os.path.isabs(wine_path):
        wine_stats = os.stat(wine_path)
        if wine_stats.st_size < 2000:
            # This version is a script, ignore it
            return
    try:
        version = subprocess.check_output([wine_path, "--version"]).decode().strip()
    except (OSError, subprocess.CalledProcessError) as ex:
        logger.exception("Error reading wine version for %s: %s", wine_path, ex)
        return
    else:
        if version.startswith("wine-"):
            version = version[5:]
        return version
    def download_icons(self, media_urls, service_media):
        """Download a list of media files concurrently.

        Limits the number of simultaneous downloads to avoid API throttling
        and UI being overloaded with signals.
        """
        with concurrent.futures.ThreadPoolExecutor(
                max_workers=self.num_workers) as executor:
            future_downloads = {
                executor.submit(service_media.download, slug, url): slug
                for slug, url in media_urls.items()
            }
            for future in concurrent.futures.as_completed(future_downloads):
                slug = future_downloads[future]
                try:
                    path = future.result()
                except Exception as ex:  # pylint: disable=broad-except
                    logger.exception('%r failed: %s', slug, ex)
                else:
                    self.emit("icon-loaded", slug, path)