def update_description(self): # I have become GTK - Destroyer Of Children for child in self.description_box.get_children(): child.destroy() id = self.item.get_id() fallback = self.item.get_description() store = self.item.get_store() desc = self.context.appsystem.get_description(id, fallback, store) plain = As.markup_convert(desc, As.MarkupConvertFormat.MARKDOWN) lines = [] try: self.parser.consume(plain) lines = self.parser.emit() except Exception as e: print("Parsing error: {}".format(e)) plain = As.markup_convert_simple(desc) lines = plain.split("\n") for line in lines: lab = Gtk.Label(line) lab.set_use_markup(True) lab.set_halign(Gtk.Align.START) lab.set_line_wrap(True) lab.set_property("xalign", 0.0) lab.set_property("margin", 2) lab.set_margin_bottom(4) self.description_box.pack_start(lab, False, False, 0) lab.show_all()
def update_description(self): # I have become GTK - Destroyer Of Children for child in self.description_box.get_children(): child.destroy() id = self.item.get_id() fallback = self.item.get_description() desc = self.context.appsystem.get_description(id, fallback) plain = As.markup_convert(desc, As.MarkupConvertFormat.MARKDOWN) lines = [] try: self.parser.consume(plain) lines = self.parser.emit() except Exception as e: print("Parsing error: {}".format(e)) plain = As.markup_convert_simple(desc) lines = plain.split("\n") for line in lines: lab = Gtk.Label(line) lab.set_use_markup(True) lab.set_halign(Gtk.Align.START) lab.set_line_wrap(True) lab.set_property("xalign", 0.0) lab.set_property("margin", 2) lab.set_margin_bottom(4) self.description_box.pack_start(lab, False, False, 0) lab.show_all()
def update_app(self, app, content_app_id=''): app_id = content_app_id or app.get_id() metadata = self._get_app_metadata(app_id) if not metadata: app_id = app_id.rsplit('.desktop', 1)[0] metadata = self._get_app_metadata(app_id) if not metadata: raise NoMetadataException(app_id) app.set_name('C', metadata['title']) app.set_comment('C', metadata['subtitle']) description = metadata['description'] app.set_description('C', description) categories = metadata.get('category') for category in categories.split(';'): app.add_category(category) # Screenshots in the metadata are arranged as 'language' -> ['image', ...] # but we need to group the same images in the same screenshot (with a # different language each), so we invert the arrangement as: # 'image' -> ['language', ...] # # Use an OrderedDict so we maintain the order of the screenshots as found # in the metadata which can be important. screenshots = collections.OrderedDict() for locale, images in metadata.get('screenshots', {}).items(): for image in images: screenshots.setdefault(image, []).append(locale) for image, locales in screenshots.items(): screenshot = AppStreamGlib.Screenshot() for locale in locales: as_img = AppStreamGlib.Image() # We need to add the screenshots as source, otherwise, without a # caption and other elements, AppStreamGlib discards the screenshots # as duplicates... as_img.set_kind(AppStreamGlib.ImageKind.SOURCE) as_img.set_url(self._get_screenshot_url(app_id, locale, image)) if locale != 'C': as_img.set_locale(locale) screenshot.add_image(as_img) app.add_screenshot(screenshot) self._translate_app(app) # We only format the description now otherwise it would not # match the translations app.set_description('C', self._add_paragraph_tags_if_needed(description))
def __init__(self): self.store = As.Store() self.store.load(As.StoreLoadFlags.APP_INFO_SYSTEM) itheme = Gtk.IconTheme.get_default() try: self.default_pixbuf = self.scaled_icon(itheme.load_icon( "package-x-generic", 64, Gtk.IconLookupFlags.GENERIC_FALLBACK)) self.security_pixbuf = self.scaled_icon(itheme.load_icon( "network-vpn", 64, Gtk.IconLookupFlags.GENERIC_FALLBACK)) self.mandatory_pixbuf = self.scaled_icon(itheme.load_icon( "computer", 64, Gtk.IconLookupFlags.GENERIC_FALLBACK)) self.other_pixbuf = self.scaled_icon(itheme.load_icon( "folder-download", 64, Gtk.IconLookupFlags.GENERIC_FALLBACK)) self.addon_pixbuf = self.scaled_icon(itheme.load_icon( "application-x-addon", 64, Gtk.IconLookupFlags.GENERIC_FALLBACK)) except Exception as e: print(e)
def matches(self, value): if self.compare == 'eq': return value == self.value if self.compare == 'lt': return AppStreamGlib.utils_vercmp(value, self.value) < 0 if self.compare == 'le': return AppStreamGlib.utils_vercmp(value, self.value) <= 0 if self.compare == 'gt': return AppStreamGlib.utils_vercmp(value, self.value) > 0 if self.compare == 'ge': return AppStreamGlib.utils_vercmp(value, self.value) >= 0 if self.compare == 'glob': return fnmatch.fnmatch(value, self.value) if self.compare == 'regex': return re.search(self.value, value) return False
def execute_action(self,action,applist=None,store=None,results=0): if store: self.store=store else: self.store=appstream.Store() self.progress=0 self.result['status']={'status':-1,'msg':''} self.result['data']='' if self.disabled==True: self._set_status(9) self.result['data']=self.store else: self._check_dirs() dataList=[] if action=='load': self.result['data']=self._loadStore(self.store) else: for app_info in applist: self.partial_progress=0 if action=='install': dataList.append(self._install(app_info)) if action=='remove': dataList.append(self._remove(app_info)) if action=='pkginfo': dataList.append(self._get_info(app_info)) #dataList.append((app_info)) self.progress+=round(self.partial_progress/len(applist),1) if self.progress>98: self.progress=98 self.result['data']=list(dataList) self.progress=100 return(self.result)
def render_plain(self, input_string): """ Render a plain version of the description, no markdown """ plain = As.markup_convert_simple(input_string) plain = plain.replace(""", "\"").replace("'", "'").replace("&", "&") return plain
def _load_appstream_pool(pools, remote): pool = AppStreamGlib.Store() path = remote.get_appstream_dir().get_path() with open(os.path.join(path, "appstream.xml")) as f: pool.from_xml(f.read(), path) pools[remote.get_name()] = pool
def _searchPackage(self,package): self._debug("Searching %s"%package) pklist=None package=package.replace("_","-") apps=appstream.Store() searchStore=[] for app in self.store.get_apps(): if app.search_matches(package)>90: apps.add_app(app) searchResults=rebostHelper.appstream_to_rebost(apps) return(searchResults)
def _user_agent_safe_for_requirement(user_agent): # very early versions of fwupd used 'fwupdmgr' as the user agent if user_agent == 'fwupdmgr': return False # gnome-software/3.26.5 (Linux x86_64 4.14.0) fwupd/1.0.4 sections = user_agent.split(' ') for chunk in sections: toks = chunk.split('/') if len(toks) == 2 and toks[0] == 'fwupd': return AppStreamGlib.utils_vercmp(toks[1], '0.8.0') >= 0 # this is a heuristic; the logic is that it's unlikely that a distro would # ship a very new gnome-software and a very old fwupd for chunk in sections: toks = chunk.split('/') if len(toks) == 2 and toks[0] == 'gnome-software': return AppStreamGlib.utils_vercmp(toks[1], '3.26.0') >= 0 # is is probably okay return True
def firmware_modify(firmware_id): """ Modifies the update urgency and release notes for the update """ if request.method != 'POST': return redirect(url_for('.firmware')) # find firmware fw = db.session.query(Firmware).filter( Firmware.firmware_id == firmware_id).first() if not fw: return _error_internal("No firmware %s" % firmware_id) # security check for md in fw.mds: if not md.check_acl('@modify-updateinfo'): return _error_permission_denied( 'Insufficient permissions to modify firmware') # set new metadata values for md in fw.mds: if 'urgency' in request.form: md.release_urgency = request.form['urgency'] if 'description' in request.form: txt = request.form['description'] if txt: if txt.find('<p>') == -1: txt = AppStreamGlib.markup_import( txt, AppStreamGlib.MarkupConvertFormat.SIMPLE) try: AppStreamGlib.markup_validate(txt) except GLib.Error as e: # pylint: disable=catching-non-exception return _error_internal("Failed to parse %s: %s" % (txt, str(e))) md.release_description = unicode(txt) # modify db.session.commit() flash('Update text updated', 'info') return redirect(url_for('.firmware_show', firmware_id=firmware_id))
def cache_icons(self): for release in self.active_fedora_releases: fname = 'fedora-%s.xml.gz' % release target = join(self.icons_path, 'tmp', str(release), fname) if not os.path.exists(target): return metadata = AppStreamGlib.Store() with gzip.open(target, 'rb') as f: metadata.from_xml(f.read(), '') for app in metadata.get_apps(): # Other types are 'stock' and 'unknown' icons = app.get_icons() pkgname = app.get_pkgnames()[0] # Pick the biggest one.. icon = None for candidate in icons: if not icon: if candidate.get_kind().value_nick == 'cached': icon = candidate continue if int(icon.get_width()) < int(candidate.get_width()): icon = candidate if not icon: continue # Move the file out of the temp dir and into place s = join(self.icons_path, 'tmp', str(release), '{width}x{height}', '{value}') d = join(self.icons_path, '{value}') source = s.format(width=icon.get_width(), height=icon.get_height(), value=icon.get_name()) destination = d.format(value=icon.get_name()) try: shutil.copy(source, destination) # And hang the name in the dict for other code to find it # ... but only if we succeeded at placing the icon file. self.icon_cache[pkgname] = icon.get_name() except IOError as e: log.warning("appstream metadata lied: %s %r" % (source, e)) except OSError as e: log.warning("fail %r->%r. %r" % (source, destination, e)) shutil.rmtree(join(self.icons_path, 'tmp'))
def execute_action(self, action, applist=None, store=None): if store: self.store = store else: self.store = appstream.Store() self.appimage_store = appstream.Store() self.progress = 0 self.result['status'] = {'status': -1, 'msg': ''} self.result['data'] = [] self.threads = [] dataList = [] if self.disabled: self._set_status(9) self.result['data'] = self.store else: self._chk_installDir() if action == 'load': self._load_appimage_store(self.store) self._debug("Ending threads...") while not self.apps_for_store.empty(): app = self.apps_for_store.get() self.store.add_app(app) self.result['data'] = self.store else: for app_info in applist: self.partial_progress = 0 if action == 'install': dataList.append(self._install_appimage(app_info)) if action == 'remove': dataList.append(self._remove_appimage(app_info)) if action == 'pkginfo': dataList.append(self._get_info(app_info)) self.progress += int( self.partial_progress / len(applist)) - 1 self.result['data'] = list(dataList) self.progress = 100 return (self.result)
def _th_load_store(self,store,pkg,semaphore): semaphore.acquire() app=self.store.get_app_by_pkgname(pkg.get_name()) if not app: #self._debug("Searching for %s"%pkg.get_name()) app=self.store.get_app_by_id(pkg.get_name().lower()+".desktop") if app: bundle=appstream.Bundle() bundle.set_kind(bundle.kind_from_string('SNAP')) bundle.set_id(pkg.get_name()+'.snap') app.add_bundle(bundle) app.add_category("Snap") store.put(self._generate_appstream_app_from_snap(pkg)) else: store.put(self._generate_appstream_app_from_snap(pkg)) semaphore.release()
def __init__(self): # /usr/share/gir-1.0/AppStreamGlib-1.0.gir try: if not USE_APPSTREAM: raise ValueError import gi gi.require_version('AppStreamGlib', '1.0') from gi.repository import AppStreamGlib app_store = AppStreamGlib.Store() app_store.load(flags=AppStreamGlib.StoreLoadFlags.APP_INFO_SYSTEM); app_store.set_search_match(AppStreamGlib.AppSearchMatch.PKGNAME | AppStreamGlib.AppSearchMatch.NAME | AppStreamGlib.AppSearchMatch.KEYWORD); except ValueError: app_store = None def _app_store_ico(tofind): """ find app in store It's very slow ... """ default = "package" for app in app_store.get_apps(): if app.get_kind() != AppStreamGlib.AppKind.DESKTOP: continue if app.get_pkgname_default() == tofind: #print(f"-- AppStream trouvé -- {tofind}") # FIX entries errors iname = app.get_icon_default().get_name() if not ".png" in iname: iname = f"{app.get_pkgname_default()}_{iname}.png" icon = f"{app.get_icon_path()}/64x64/{iname}" if not Path(icon).exists(): print(f" bad ico ? {icon} {app.get_icon_default().get_name()}") icon = default return icon return default #self.handle = Handle('/', '/var/lib/pacman') self.handle = config.init_with_config("/etc/pacman.conf") self.pkgs = [] for i, pkg in enumerate(self.handle.get_localdb().pkgcache): pkg_repo = self._find(pkg.name) afile = AlpmFile(pkg, i, pkg_repo) if app_store: afile.ico = _app_store_ico(pkg.name) self.pkgs.append(afile) print(f"end scan {len(self.pkgs)} packages")
def execute_action(self, appstreamStore, action, tokens, exact_match_for_search=False, max_results=0): self._debug("Executing action %s" % action) self._debug("Tokens: %s" % tokens) self.progress = 0 if type(tokens) == type([]): tokens = ' '.join(tokens) if type(tokens) is str: tokens = tokens.lower() else: tokens = '' if len(tokens.split(' ')) > 1: if action == 'search': #self._debug("Tokenizing search items") tokens = appstream.utils_search_tokenize(tokens) else: tokens = tokens.split(' ') else: if len(tokens) >= 1: tokens = [tokens] else: tokens = [] self.store = appstreamStore self.result['status'] = {'status': -1, 'msg': ''} self.result['data'] = [] if self.store: if action == 'list': self._list_category(tokens, max_results) if action == 'list_sections': self._list_sections() if (action == 'search' or action == 'info'): self._search_app(tokens, exact_match_for_search) else: #self._debug("Search needs a store") pass self.progress = 100 return (self.result)
def execute_action(self,action,applist=None,store=None,results=0): if store: self.store=store else: self.store=appstream.Store() self.progress=0 self.result['status']={'status':-1,'msg':''} self.result['data']='' self.snap_client=Snapd.Client() try: self.snap_client.connect_sync(None) except Exception as e: self.disabled=True #self._debug("Disabling snap %s"%e) if self.disabled==True: self._set_status(9) self.result['data']=self.store else: self._check_dirs() dataList=[] if action=='load': self.result['data']=self._load_snap_store(self.store) else: for app_info in applist: self.partial_progress=0 if action=='install': dataList.append(self._install_snap(app_info)) if action=='remove': dataList.append(self._remove_snap(app_info)) if action=='pkginfo': dataList.append(self._get_info(app_info)) self.progress+=round(self.partial_progress/len(applist),1) if self.progress>98: self.progress=98 self.result['data']=list(dataList) self.progress=100 return(self.result)
def update_appdata_from_file(self, file_path, content_app_id=''): app = load_as_app_from_appdata(file_path) self.update_app(app, content_app_id) # Add a special metadata item in order to easily check if this app-data # file has been merged by eos-shell-content app.add_metadata('Endless::EosShellContent::Merged', 'true') store = AppStreamGlib.Store() store.add_app(app) xml_str = store.to_xml(AppStreamGlib.NodeToXmlFlags.NONE).str root = ET.fromstring(xml_str) if root.tag == 'components': root = root.find('component') # We do not want to display screenshots from 3rd parties when we have # provided some from the Shell Content, so we need to remove them. # The removal should be done in the app object but this cannot be # accomplished until there is API to do it in libappstream-glib. self._remove_unneeded_screenshots(root) node = xml.dom.minidom.parseString(ET.tostring(root, encoding='utf-8')) return node.toprettyxml(indent=' ')
#!/usr/bin/env python2.7 import gi.repository gi.require_version('AppStreamGlib', '1.0') from gi.repository import AppStreamGlib as AS store = AS.Store() store.load(AS.StoreLoadFlags.APP_INFO_SYSTEM) def test_markup(desc): m = AS.markup_convert(desc, -1, AS.MarkupConvertFormat.SIMPLE) return m app = store.get_app_by_pkgname("pitivi") desc = app.get_description("C") print test_markup(desc)
def _generate_appstream_app_from_snap(self,pkg): bundle=appstream.Bundle() app=appstream.App() icon=appstream.Icon() screenshot=appstream.Screenshot() # bundle.set_kind(appstream.BundleKind.SNAP) bundle.set_kind(bundle.kind_from_string('SNAP')) bundle.set_id(pkg.get_name()+'.snap') app.add_bundle(bundle) app.set_name("C",pkg.get_name()+'.snap') app.add_pkgname(pkg.get_name()+'.snap') app.add_category("Snap") release=appstream.Release() release.set_version(pkg.get_version()) app.add_release(release) app.set_id("io.snapcraft.%s"%pkg.get_name()+'.snap') app.set_id_kind=appstream.IdKind.DESKTOP app.set_metadata_license("CC0-1.0") description="" #This is an Snap bundle. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully." pkg_description=pkg.get_description() pkg_description=html.escape(pkg_description,quote=True) pkg_description=pkg_description.replace("<",">") app.set_description("C","<p>%s</p><p>%s</p>"%(description,pkg_description)) app.set_comment("C",pkg.get_summary().rstrip('.')) app.add_keyword("C",pkg.get_name()) for word in pkg.get_summary().split(' '): if len(word)>3: app.add_keyword("C",word) if pkg.get_icon(): if self.icon_cache_enabled: icon.set_kind(appstream.IconKind.LOCAL) icon.set_filename(self._download_file(pkg.get_icon(),pkg.get_name(),self.icons_folder)) else: icon.set_kind(appstream.IconKind.REMOTE) icon.set_name(pkg.get_icon()) icon.set_url(pkg.get_icon()) app.add_icon(icon) if pkg.get_license(): app.set_project_license(pkg.get_license()) if pkg.get_screenshots(): for snap_screen in pkg.get_screenshots(): img=appstream.Image() img.set_kind(appstream.ImageKind.SOURCE) img.set_url(snap_screen.get_url()) break screenshot.add_image(img) app.add_screenshot(screenshot) if not os.path.isfile(self.cache_xmls+'/'+app.get_id_filename()): xml_path='%s/%s.xml'%(self.cache_xmls,app.get_id_filename()) gioFile=Gio.File.new_for_path(xml_path) app.to_file(gioFile) #Fix some things in app_file... with open(xml_path,'r',encoding='utf-8') as f: xml_data=f.readlines() #self._debug("fixing %s"%xml_path) try: xml_data[0]=xml_data[0]+"<components>\n" xml_data[-1]=xml_data[-1]+"\n"+"</components>" except: pass with open(xml_path,'w') as f: f.writelines(xml_data) return(app)
def _generate_metadata_kind(filename, fws, firmware_baseuri=''): """ Generates AppStream metadata of a specific kind """ store = AppStreamGlib.Store.new() store.set_origin('lvfs') store.set_api_version(0.9) for fw in fws: # add each component for md in fw.mds: component = AppStreamGlib.App.new() component.set_id(md.appstream_id) component.set_kind(AppStreamGlib.AppKind.FIRMWARE) component.set_name(None, md.name) component.set_comment(None, md.summary) component.set_description(None, md.description) if md.url_homepage: component.add_url(AppStreamGlib.UrlKind.HOMEPAGE, md.url_homepage) component.set_metadata_license(md.metadata_license) component.set_project_license(md.project_license) component.set_developer_name(None, md.developer_name) # add provide for guid in md.guids: prov = AppStreamGlib.Provide.new() prov.set_kind(AppStreamGlib.ProvideKind.FIRMWARE_FLASHED) prov.set_value(guid.value) component.add_provide(prov) # add release if md.version: rel = AppStreamGlib.Release.new() rel.set_version(md.version) if md.release_description: rel.set_description(None, md.release_description) if md.release_timestamp: rel.set_timestamp(md.release_timestamp) rel.checksums = [] rel.add_location(firmware_baseuri + fw.filename) rel.set_size(AppStreamGlib.SizeKind.INSTALLED, md.release_installed_size) rel.set_size(AppStreamGlib.SizeKind.DOWNLOAD, md.release_download_size) if md.release_urgency: rel.set_urgency(AppStreamGlib.urgency_kind_from_string(md.release_urgency)) component.add_release(rel) # add container checksum if fw.checksum_signed: csum = AppStreamGlib.Checksum.new() csum.set_kind(GLib.ChecksumType.SHA1) csum.set_target(AppStreamGlib.ChecksumTarget.CONTAINER) csum.set_value(fw.checksum_signed) csum.set_filename(fw.filename) rel.add_checksum(csum) # add content checksum if md.checksum_contents: csum = AppStreamGlib.Checksum.new() csum.set_kind(GLib.ChecksumType.SHA1) csum.set_target(AppStreamGlib.ChecksumTarget.CONTENT) csum.set_value(md.checksum_contents) csum.set_filename(md.filename_contents) rel.add_checksum(csum) # add screenshot if md.screenshot_caption: ss = AppStreamGlib.Screenshot.new() ss.set_caption(None, md.screenshot_caption) if md.screenshot_url: im = AppStreamGlib.Image.new() im.set_url(md.screenshot_url) ss.add_image(im) component.add_screenshot(ss) # add requires for each allowed vendor_ids vendor = db.session.query(Vendor).filter(Vendor.vendor_id == fw.vendor_id).first() if vendor and vendor.restrictions: vendor_ids = [] for res in vendor.restrictions: vendor_ids.append(res.value) req = AppStreamGlib.Require.new() req.set_kind(AppStreamGlib.RequireKind.FIRMWARE) req.set_value('vendor-id') if len(vendor_ids) == 1: req.set_compare(AppStreamGlib.RequireCompare.EQ) else: req.set_compare(AppStreamGlib.RequireCompare.REGEX) req.set_version('|'.join(vendor_ids)) component.add_require(req) # add manual firmware or fwupd version requires for rq in md.requirements: if rq.kind == 'hardware': continue req = AppStreamGlib.Require.new() req.set_kind(AppStreamGlib.Require.kind_from_string(rq.kind)) if rq.value: req.set_value(rq.value) if rq.compare: req.set_compare(AppStreamGlib.Require.compare_from_string(rq.compare)) if rq.version: req.set_version(rq.version) component.add_require(req) # add hardware requirements rq_hws = [] for rq in md.requirements: if rq.kind == 'hardware': rq_hws.append(rq.value) if rq_hws: req = AppStreamGlib.Require.new() req.set_kind(AppStreamGlib.RequireKind.HARDWARE) req.set_value('|'.join(rq_hws)) component.add_require(req) # add any shared metadata if md.inhibit_download: component.add_metadata('LVFS::InhibitDownload') if md.version_format: component.add_metadata('LVFS::VersionFormat', md.version_format) # add component store.add_app(component) # dump to file store.to_file(Gio.file_new_for_path(filename), AppStreamGlib.NodeToXmlFlags.ADD_HEADER | AppStreamGlib.NodeToXmlFlags.FORMAT_INDENT | AppStreamGlib.NodeToXmlFlags.FORMAT_MULTILINE)
def __init__(self): self.store = As.Store() self.store.load(As.StoreLoadFlags.APP_INFO_SYSTEM)
def _create_fw_from_uploaded_file(ufile): # create empty firmware fw = Firmware() fw.filename = ufile.filename_new fw.checksum_upload = ufile.checksum_upload if ufile.version_display: fw.version_display = ufile.version_display # create child metadata object for the components for component in ufile.get_components(): md = Component() md.appstream_id = component.get_id() md.name = unicode(component.get_name()) md.summary = unicode(component.get_comment()) md.developer_name = unicode(component.get_developer_name()) md.metadata_license = component.get_metadata_license() md.project_license = component.get_project_license() md.url_homepage = unicode( component.get_url_item(AppStreamGlib.UrlKind.HOMEPAGE)) md.description = unicode(component.get_description()) # fix up the vendor if md.developer_name == 'LenovoLtd.': md.developer_name = u'Lenovo Ltd.' # add manually added keywords for keyword in component.get_keywords(): md.add_keywords_from_string(unicode(keyword), priority=5) # add from the provided free text if md.developer_name: md.add_keywords_from_string(md.developer_name, priority=10) if md.name: md.add_keywords_from_string(md.name, priority=3) if md.summary: md.add_keywords_from_string(md.summary, priority=1) # from the provide for prov in component.get_provides(): if prov.get_kind() != AppStreamGlib.ProvideKind.FIRMWARE_FLASHED: continue md.guids.append(Guid(md.component_id, prov.get_value())) # from the release rel = component.get_release_default() md.version = rel.get_version() md.release_description = unicode(rel.get_description()) md.release_timestamp = rel.get_timestamp() md.release_installed_size = rel.get_size( AppStreamGlib.SizeKind.INSTALLED) md.release_download_size = rel.get_size( AppStreamGlib.SizeKind.DOWNLOAD) md.release_urgency = AppStreamGlib.urgency_kind_to_string( rel.get_urgency()) # from requires for req in component.get_requires(): rq = Requirement( md.component_id, AppStreamGlib.Require.kind_to_string(req.get_kind()), req.get_value(), AppStreamGlib.Require.compare_to_string(req.get_compare()), req.get_version()) md.requirements.append(rq) # from the first screenshot if len(component.get_screenshots()) > 0: ss = component.get_screenshots()[0] md.screenshot_caption = ss.get_caption(None) if len(ss.get_images()) > 0: im = ss.get_images()[0] md.screenshot_url = unicode(im.get_url()) # from the content checksum csum = rel.get_checksum_by_target(AppStreamGlib.ChecksumTarget.CONTENT) md.checksum_contents = csum.get_value() md.filename_contents = csum.get_filename() # allows OEM to hide the direct download link on the LVFS metadata = component.get_metadata() if 'LVFS::InhibitDownload' in metadata: md.inhibit_download = True # allows OEM to change the triplet (AA.BB.CCDD) to quad (AA.BB.CC.DD) if 'LVFS::VersionFormat' in metadata: md.version_format = metadata['LVFS::VersionFormat'] fw.mds.append(md) return fw
def _add_appimage(self, appinfo): #Search in local store for the app sw_new = True app = appstream.App() app_orig = self.store.get_app_by_pkgname(appinfo['name'].lower()) if not app_orig: app_orig = self.store.get_app_by_id(appinfo['name'].lower() + ".desktop") if app_orig: self._debug("Extending app %s" % appinfo['package']) if appinfo['icon']: #self._debug("Icon: %s"%appinfo['icon']) app = self._copy_app_from_appstream(app_orig, app, copy_icon=False) else: app = self._copy_app_from_appstream(app_orig, app, copy_icon=True) sw_new = False else: self._debug("Generating new %s" % appinfo['package']) pass if appinfo['name'].lower().endswith('.appimage'): app.set_id("appimagehub.%s" % appinfo['name'].lower()) app.set_name("C", appinfo['name']) else: app.set_id("appimagehub.%s" % appinfo['name'].lower() + '.appimage') app.set_name("C", appinfo['name'] + ".appimage") if appinfo['package'].lower().endswith('.appimage'): app.add_pkgname(appinfo['package'].lower()) else: app.add_pkgname(appinfo['package'].lower() + ".appimage") app.set_id_kind = appstream.IdKind.DESKTOP if appinfo['license']: app.set_project_license(appinfo['license']) bundle = appstream.Bundle() bundle.set_kind(bundle.kind_from_string('APPIMAGE')) if appinfo['package'].endswith('.appimage'): bundle.set_id(appinfo['package']) else: bundle.set_id(appinfo['package'] + '.appimage') app.add_bundle(bundle) if 'keywords' in appinfo.keys(): for keyword in appinfo['keywords']: app.add_keyword("C", keyword) if 'appimage' not in appinfo['keywords']: app.add_keyword("C", "appimage") else: app.add_keyword("C", "appimage") app.add_url(appstream.UrlKind.UNKNOWN, appinfo['installerUrl']) app.add_url(appstream.UrlKind.HOMEPAGE, appinfo['homepage']) if sw_new: app.add_keyword("C", appinfo['package']) if not appinfo['name'].endswith('.appimage'): app.set_name("C", appinfo['name'] + ".appimage") desc_header = "" #This is an AppImage bundle. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully." if appinfo['description']: for lang, desc in appinfo['description'].items(): desc = desc.replace('&', '&') description = "<p>%s</p><p>%s</p>" % (desc_header, desc) summary = ' '.join(list(desc.split(' ')[:10])) app.set_description(lang, description) app.set_comment(lang, summary) else: description = "<p>%s</p>" % (desc_header) summary = ' '.join(list(desc_header.split(' ')[:8])) app.set_description("C", description) app.set_comment("C", summary) if 'categories' in appinfo.keys(): for category in appinfo['categories']: if category: app.add_category(category) if 'appimage' not in appinfo['categories']: app.add_category("appimage") else: app.add_category("appimage") if appinfo['icon']: icon = appstream.Icon() if self.icon_cache_enabled: icon.set_kind(appstream.IconKind.LOCAL) icon_fn = self._download_file(appinfo['icon'], appinfo['name'], self.icons_dir) icon.set_filename(icon_fn) else: icon.set_kind(appstream.IconKind.REMOTE) icon.set_name(pkg.get_icon()) icon.set_url(pkg.get_icon()) app.add_icon(icon) if appinfo['thumbnails']: screenshot = appstream.Screenshot() img = appstream.Image() if not appinfo['thumbnails'][0].startswith('http'): appinfo['screenshot'] = appinfo['thumbnails'][0] appinfo[ 'screenshot'] = "https://appimage.github.io/database/%s" % appinfo[ 'screenshot'] img.set_kind(appstream.ImageKind.SOURCE) img.set_url(appinfo['screenshot']) screenshot.add_image(img) app.add_screenshot(screenshot) #Adds the app to the store self.apps_for_store.put(app) xml_path = '%s/%s.xml' % (self.cache_xmls, app.get_id_filename()) gioFile = Gio.File.new_for_path(xml_path) app.to_file(gioFile) #Fix some things in app_file... xml_file = open(xml_path, 'r', encoding='utf-8') xml_data = xml_file.readlines() xml_file.close() self._debug("fixing %s" % xml_path) try: xml_data[0] = xml_data[ 0] + "<components origin=\"%s\">\n" % app.get_origin() xml_data[-1] = xml_data[-1] + "\n" + "</components>" except: pass xml_file = open(xml_path, 'w') xml_file.writelines(xml_data) xml_file.close()
def _get_flatpak_catalogue(self): action="load" rebostPkgList=[] sections=[] progress=0 inc=0 flInst='' store=appstream.Store() store2=appstream.Store() #metadata=appstream.Metadata() try: #Get all the remotes, copy appstream to wrkdir flInst=Flatpak.get_system_installations() for installer in flInst: flRemote=installer.list_remotes() for remote in flRemote: srcDir=remote.get_appstream_dir().get_path() installer.update_appstream_sync(remote.get_name()) #sections=self.snap_client.get_sections_sync() except Exception as e: print(e) #self._on_error("load",e) try: store.from_file(Gio.File.parse_name(os.path.join(srcDir,"appstream.xml"))) except Exception as e: print(e) pass added=[] for pkg in store.get_apps(): idx=pkg.get_id() idxList=idx.split(".") if len(idxList)>2: idxList[0]="org" idxList[1]="flathub" newId=".".join(idxList).lower() else: newId="org.flathub.{}".format(idx[-1]) #pkg.set_id(newId) state="available" for installer in flInst: installed=False try: installed=installer.get_installed_ref(0,pkg.get_name()) except: try: installed=installer.get_installed_ref(1,pkg.get_name()) except: pass if installed: state="installed" break #flatpak has his own cache dir for icons so if present use it iconPath='' icon64=os.path.join(srcDir,"icons/64x64") icon128=os.path.join(srcDir,"icons/128x128") idx=idx.replace(".desktop","") if os.path.isfile(os.path.join(icon128,"{}.png".format(idx))): iconPath=os.path.join(icon128,"{}.png".format(idx)) elif os.path.isfile(os.path.join(icon64,"{}.png".format(idx))): iconPath=os.path.join(icon64,"{}.png".format(idx)) if iconPath!='': icon=appstream.Icon() icon.set_kind(appstream.IconKind.LOCAL) icon.set_filename(iconPath) pkg.add_icon(icon) add=False if not pkg.get_bundles(): bundle=appstream.Bundle() bundle.set_id("{};amd64;{}".format(pkg.get_id(),state)) bundle.set_kind(appstream.BundleKind.FLATPAK) pkg.add_bundle(bundle) add=True else: for bundle in pkg.get_bundles(): bundle.set_id("{};amd64;{}".format(pkg.get_id(),state)) bundle.set_kind(appstream.BundleKind.FLATPAK) add=True if add and pkg.get_id() not in added: try: # if not (app.validate()): pkg.set_name("C",pkg.get_name().lower().replace(" ","_")+'.flatpak') pkg.add_pkgname(pkg.get_name()) store2.add_app(pkg) # else: # pass # print(app.validate()) except: pass added.append(pkg.get_id()) self._debug("Loaded flatpak metadata") return(store2)
def render_plain(input_string): """ Render a plain version of the description, no markdown """ plain = As.markup_convert_simple(input_string) plain = plain.replace(""", "\"").replace("'", "'").replace("&", "&") return plain
def load_as_app_from_appdata(appdata_file): app = AppStreamGlib.App() app.parse_file(appdata_file, AppStreamGlib.AppParseFlags.NONE) return app
def test_markup(desc): m = AS.markup_convert_simple(desc) return m
def test_markup(desc): m = AS.markup_convert(desc, -1, AS.MarkupConvertFormat.SIMPLE) return m
def render_plain(self, input_string): """ Render a plain version of the description, no markdown """ plain = As.markup_convert(input_string, -1, As.MarkupConvertFormat.SIMPLE) plain = plain.replace(""", "\"").replace("'", "'") return plain
def render_plain(self, input_string): """ Render a plain version of the description, no markdown """ plain = As.markup_convert(input_string, -1, As.MarkupConvertFormat.SIMPLE) plain = plain.replace(""", "\"") return plain