9578053 Jan 22 2022 distfiles.gentoo.org/distfiles/gajim-1.3.3-2.tar.gz
This commit is contained in:
parent
a5b3822651
commit
4c1b226bff
1045 changed files with 753037 additions and 18 deletions
195
gajim/data/plugins/plugin_installer/utils.py
Normal file
195
gajim/data/plugins/plugin_installer/utils.py
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
import logging
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from zipfile import ZipFile
|
||||
import configparser
|
||||
from configparser import ConfigParser
|
||||
from packaging.version import Version as V
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
import gajim
|
||||
from gajim.common import app
|
||||
from gajim.common import configpaths
|
||||
|
||||
from plugin_installer.remote import PLUGINS_DIR_URL
|
||||
|
||||
log = logging.getLogger('gajim.p.installer.utils')
|
||||
|
||||
MANDATORY_FIELDS = {'name', 'short_name', 'version',
|
||||
'description', 'authors', 'homepage'}
|
||||
FALLBACK_ICON = Gtk.IconTheme.get_default().load_icon(
|
||||
'preferences-system', Gtk.IconSize.MENU, 0)
|
||||
|
||||
|
||||
class PluginInfo:
|
||||
def __init__(self, config, icon):
|
||||
self.icon = icon
|
||||
self.name = config.get('info', 'name')
|
||||
self.short_name = config.get('info', 'short_name')
|
||||
self.version = V(config.get('info', 'version'))
|
||||
self._installed_version = None
|
||||
self.min_gajim_version = V(config.get('info', 'min_gajim_version'))
|
||||
self.max_gajim_version = V(config.get('info', 'max_gajim_version'))
|
||||
self.description = config.get('info', 'description')
|
||||
self.authors = config.get('info', 'authors')
|
||||
self.homepage = config.get('info', 'homepage')
|
||||
|
||||
|
||||
@classmethod
|
||||
def from_zip_file(cls, zip_file, manifest_path):
|
||||
config = ConfigParser()
|
||||
# ZipFile can only handle posix paths
|
||||
with zip_file.open(manifest_path.as_posix()) as manifest_file:
|
||||
try:
|
||||
config.read_string(manifest_file.read().decode())
|
||||
except configparser.Error as error:
|
||||
log.warning(error)
|
||||
raise ValueError('Invalid manifest: %s' % manifest_path)
|
||||
|
||||
if not is_manifest_valid(config):
|
||||
raise ValueError('Invalid manifest: %s' % manifest_path)
|
||||
|
||||
short_name = config.get('info', 'short_name')
|
||||
png_filename = '%s.png' % short_name
|
||||
png_path = manifest_path.parent / png_filename
|
||||
icon = load_icon_from_zip(zip_file, png_path) or FALLBACK_ICON
|
||||
|
||||
return cls(config, icon)
|
||||
|
||||
@classmethod
|
||||
def from_path(cls, manifest_path):
|
||||
config = ConfigParser()
|
||||
with open(manifest_path, encoding='utf-8') as conf_file:
|
||||
try:
|
||||
config.read_file(conf_file)
|
||||
except configparser.Error as error:
|
||||
log.warning(error)
|
||||
raise ValueError('Invalid manifest: %s' % manifest_path)
|
||||
|
||||
if not is_manifest_valid(config):
|
||||
raise ValueError('Invalid manifest: %s' % manifest_path)
|
||||
|
||||
return cls(config, None)
|
||||
|
||||
@property
|
||||
def remote_uri(self):
|
||||
return '%s/%s.zip' % (PLUGINS_DIR_URL, self.short_name)
|
||||
|
||||
@property
|
||||
def download_path(self):
|
||||
return Path(configpaths.get('PLUGINS_DOWNLOAD'))
|
||||
|
||||
@property
|
||||
def installed_version(self):
|
||||
if self._installed_version is None:
|
||||
self._installed_version = self._get_installed_version()
|
||||
return self._installed_version
|
||||
|
||||
def has_valid_version(self):
|
||||
gajim_version = V(gajim.__version__)
|
||||
return self.min_gajim_version <= gajim_version <= self.max_gajim_version
|
||||
|
||||
def _get_installed_version(self):
|
||||
for plugin in app.plugin_manager.plugins:
|
||||
if plugin.name == self.name:
|
||||
return V(plugin.version)
|
||||
|
||||
# Fallback:
|
||||
# If the plugin has errors and is not loaded by the
|
||||
# PluginManager. Look in the Gajim config if the plugin is
|
||||
# known and active, if yes load the manifest from the Plugin
|
||||
# dir and parse the version
|
||||
plugin_settings = app.settings.get_plugins()
|
||||
if self.short_name not in plugin_settings:
|
||||
return None
|
||||
|
||||
active = app.settings.get_plugin_setting(self.short_name, 'active')
|
||||
if not active:
|
||||
return None
|
||||
|
||||
manifest_path = (Path(configpaths.get('PLUGINS_USER')) /
|
||||
self.short_name /
|
||||
'manifest.ini')
|
||||
if not manifest_path.exists():
|
||||
return None
|
||||
try:
|
||||
return PluginInfo.from_path(manifest_path).version
|
||||
except Exception as error:
|
||||
log.warning(error)
|
||||
return None
|
||||
|
||||
def needs_update(self):
|
||||
if self.installed_version is None:
|
||||
return False
|
||||
return self.installed_version < self.version
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
return [self.icon,
|
||||
self.name,
|
||||
str(self.installed_version or ''),
|
||||
str(self.version),
|
||||
self.needs_update(),
|
||||
self]
|
||||
|
||||
|
||||
def parse_manifests_zip(bytes_):
|
||||
plugins = []
|
||||
with ZipFile(BytesIO(bytes_)) as zip_file:
|
||||
files = list(map(Path, zip_file.namelist()))
|
||||
for manifest_path in filter(is_manifest, files):
|
||||
try:
|
||||
plugin = PluginInfo.from_zip_file(zip_file, manifest_path)
|
||||
except Exception as error:
|
||||
log.warning(error)
|
||||
continue
|
||||
|
||||
if not plugin.has_valid_version():
|
||||
continue
|
||||
plugins.append(plugin)
|
||||
|
||||
return plugins
|
||||
|
||||
|
||||
def is_manifest(path):
|
||||
if path.name == 'manifest.ini':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_manifest_valid(config):
|
||||
if not config.has_section('info'):
|
||||
log.warning('Manifest is missing INFO section')
|
||||
return False
|
||||
|
||||
opts = config.options('info')
|
||||
if not MANDATORY_FIELDS.issubset(opts):
|
||||
log.warning('Manifest is missing mandatory fields %s.',
|
||||
MANDATORY_FIELDS.difference(opts))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def load_icon_from_zip(zip_file, icon_path):
|
||||
# ZipFile can only handle posix paths
|
||||
try:
|
||||
zip_file.getinfo(icon_path.as_posix())
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
with zip_file.open(icon_path.as_posix()) as png_file:
|
||||
data = png_file.read()
|
||||
|
||||
pixbuf = GdkPixbuf.PixbufLoader()
|
||||
pixbuf.set_size(16, 16)
|
||||
try:
|
||||
pixbuf.write(data)
|
||||
except Exception:
|
||||
log.exception('Can\'t load icon: %s', icon_path)
|
||||
pixbuf.close()
|
||||
return None
|
||||
|
||||
pixbuf.close()
|
||||
return pixbuf.get_pixbuf()
|
||||
Loading…
Add table
Add a link
Reference in a new issue