source: lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/appImageManager.py @ 7132

Last change on this file since 7132 was 7132, checked in by Juanma, 3 years ago

WIP on releases

File size: 22.2 KB
Line 
1#The name of the main class must match the file name in lowercase
2import re
3import urllib
4from urllib.request import Request
5from urllib.request import urlretrieve
6import shutil
7import json
8import os
9import sys
10import threading
11import queue
12import time
13import random
14import gi
15from gi.repository import Gio
16gi.require_version('AppStreamGlib', '1.0')
17from gi.repository import AppStreamGlib as appstream
18from bs4 import BeautifulSoup
19#from subprocess import call
20
21class appimagemanager:
22        def __init__(self):
23                self.dbg=True
24                self.progress=0
25                self.partial_progress=0
26                self.plugin_actions={'install':'appimage','remove':'appimage','pkginfo':'appimage','load':'appimage'}
27                self.result={}
28                self.result['data']={}
29                self.result['status']={}
30                self.conf_dir=os.getenv("HOME")+"/.cache/lliurex-store"
31                self.icons_dir=self.conf_dir+"/icons"
32                self.bundles_dir=self.conf_dir+"/bundles"
33                self.bundle_types=['appimg']
34                self.appimage_dir=os.getenv("HOME")+"/.lliurex-store/appimg"
35                #To get the description of an app we must go to a specific url defined in url_info.
36                #$(appname) we'll be replaced with the appname so the url matches the right one.
37                #If other site has other url naming convention it'll be mandatory to define it with the appropiate replacements
38                self.repos={'appimagehub':{'type':'json','url':'https://appimage.github.io/feed.json','url_info':''}}
39                #Appimges not stored in a repo must be listed in this file, providing the download url and the info url (if there's any)
40                self.external_appimages="/usr/share/lliurex-store/files/external_appimages.json"
41                #Queue pool
42                self.queue=queue.Queue()
43                self.disabled=False
44        #def __init__
45
46        def set_debug(self,dbg=True):
47                self.dbg=dbg
48                self._debug ("Debug enabled")
49        #def set_debug
50
51        def _debug(self,msg=''):
52                if self.dbg:
53                        print ('DEBUG appimage: %s'%msg)
54        #def debug
55
56        def register(self):
57                return(self.plugin_actions)
58
59        def enable(self,state=False):
60                self.disable=state
61
62        def execute_action(self,action,applist=None,store=None):
63                if store:
64                        self.store=store
65                else:
66                        self.store=appstream.Store()
67                self.progress=0
68                self.result['status']={'status':-1,'msg':''}
69                self.result['data']=''
70                dataList=[]
71                if self.disabled:
72                        self._set_status(9)
73                        self.result['data']=self.store
74                else:
75                        self._chk_installDir()
76                        if action=='load':
77                                self.result['data']=self._load_appimage_store(self.store)
78                        else:
79                                for app_info in applist:
80                                        self.partial_progress=0
81                                        if action=='install':
82                                                dataList.append(self._install_appimage(app_info))
83                                        if action=='remove':
84                                                dataList.append(self._remove_appimage(app_info))
85                                        if action=='pkginfo':
86                                                dataList.append(self._get_info(app_info))
87                                        self.progress+=int(self.partial_progress/len(applist))
88                                self.result['data']=list(dataList)
89                self.progress=100
90                return(self.result)
91
92        def _set_status(self,status,msg=''):
93                self.result['status']={'status':status,'msg':msg}
94        #def _set_status
95
96        def _callback(self,partial_size=0,total_size=0):
97                limit=99
98                if partial_size!=0 and total_size!=0:
99                        inc=round(partial_size/total_size,2)*100
100                        self.progress=inc
101                else:
102                        inc=1
103                        margin=limit-self.progress
104                        inc=round(margin/limit,3)
105                        self.progress=(self.progress+inc)
106                if (self.progress>limit):
107                        self.progress=limit
108
109        def _chk_installDir(self):
110                msg_status=True
111                if not os.path.isdir(self.appimage_dir):
112                        try:
113                                os.makedirs(self.appimage_dir)
114                        except:
115                                msg_status=False
116                return msg_status                               
117
118        def _install_appimage(self,app_info):
119                app_info=self._get_info(app_info)
120                self._debug("Installing %s"%app_info)
121                if app_info['state']=='installed':
122                        self._set_status(4)
123                else:
124                                #                       appimage_url=self.repository_url+'/'+app_info['package']
125                        appimage_url=app_info['homepage']+'/'+app_info['package']
126                        self._debug("Downloading "+appimage_url)
127                        dest_path=self.appimage_dir+'/'+app_info['package']
128                        if appimage_url:
129                                try:
130                                        req=Request(appimage_url, headers={'User-Agent':'Mozilla/5.0'})
131                                        with urllib.request.urlopen(req) as response, open(dest_path, 'wb') as out_file:
132                                                bf=16*1024
133                                                acumbf=0
134#                                               print("Response: %s"%response.info())
135                                                app_size=int(response.info()['Content-Length'])
136#                                               print("APP SIZE: %s"%app_size)
137                                                while True:
138                                                        if acumbf>=app_size:
139                                                            break
140                                                        shutil.copyfileobj(response, out_file,bf)
141                                                        acumbf=acumbf+bf
142                                                        self._callback(acumbf,app_size)
143                                        st = os.stat(dest_path)
144                                        os.chmod(dest_path, st.st_mode | 0o111)
145                                        self._set_status(0)
146                                except Exception as e:
147                                        print(e)
148                                        self._set_status(5)
149                        else:
150                                self._set_status(12)
151                return app_info
152        #def _install_appimage
153
154        def _remove_appimage(self,app_info):
155                self._debug("Removing "+app_info['package'])
156                if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
157                        try:
158                                call([self.appimage_dir+"/"+app_info['package'], "--remove-appimage-desktop-integration"])
159                        except:
160                                pass
161                        try:
162                                os.remove(self.appimage_dir+"/"+app_info['package'])
163                                self._set_status(0)
164                        except:
165                                self._set_status(6)
166                return(app_info)
167        #def _remove_appimage
168
169        def _load_appimage_store(self,store):
170                self._get_bundles_catalogue()
171                if os.path.exists(self.bundles_dir):
172                        for bundle_type in self.bundle_types:
173                                self._debug("Loading %s catalog"%bundle_type)
174                                store=self._generic_file_load(self.bundles_dir+'/'+bundle_type,store)
175                return(store)
176        #def load_bundles_catalog(self)
177       
178        def _generic_file_load(self,target_path,store):
179                icon_path='/usr/share/icons/hicolor/128x128'
180                if not os.path.isdir(target_path):
181                        os.makedirs(target_path)
182                files=os.listdir(target_path)
183                for target_file in os.listdir(target_path):
184                        if target_file.endswith('appdata.xml'):
185                                store_path=Gio.File.new_for_path(target_path+'/'+target_file)
186                                self._debug("Adding file "+target_path+'/'+target_file)
187                                try:
188                                        store.from_file(store_path,icon_path,None)
189                                except Exception as e:
190                                        self._debug("Couldn't add file "+target_file+" to store")
191                                        self._debug("Reason: "+str(e))
192                return(store)
193        #def _generic_file_load
194
195        def _get_bundles_catalogue(self):
196                applist=[]
197                appdict={}
198                all_apps=[]
199                outdir=self.bundles_dir+'/appimg/'
200                #Load repos
201                for repo_name,repo_info in self.repos.items():
202                        if not os.path.isdir(self.bundles_dir):
203                                try:
204                                        os.makedirs(self.bundles_dir)
205                                except:
206                                        self._debug("appImage catalogue could not be fetched: Permission denied")
207                        self._debug("Fetching repo %s"%repo_info['url'])
208                        if repo_info['type']=='json':
209                                applist=self._process_appimage_json(self._fetch_repo(repo_info['url']),repo_name)
210
211                        self._debug("Fetched repo "+repo_info['url'])
212                        self._th_generate_xml_catalog(applist,outdir,repo_info['url_info'],repo_info['url'],repo_name)
213                        all_apps.extend(applist)
214                #Load external apps
215                for app_name,app_info in self._get_external_appimages().items():
216                        if os.path.isdir(self.bundles_dir):
217                                appinfo=self._init_appinfo()
218                                appinfo['name']=app_info['url'].split('/')[-1]
219                                appinfo['package']=app_info['url'].split('/')[-1]
220                                appinfo['homepage']='/'.join(app_info['url'].split('/')[0:-1])
221                                self._debug("Fetching external appimage %s"%app_info['url'])
222                                appinfo['bundle']='appimage'
223                                applist=[appinfo]
224                                self._th_generate_xml_catalog(applist,outdir,app_info['url_info'],app_info['url'],app_name)
225                                self._debug("Fetched appimage "+app_info['url'])
226                                all_apps.extend(applist)
227                        else:
228                                self._debug("External appImage could not be fetched: Permission denied")
229                self._debug("Removing old entries...")
230#               self._clean_bundle_catalogue(all_apps,outdir)
231                return(True)
232        #def _get_bundles_catalogue
233       
234        def _fetch_repo(self,repo):
235                req=Request(repo, headers={'User-Agent':'Mozilla/5.0'})
236                with urllib.request.urlopen(req) as f:
237                        content=(f.read().decode('utf-8'))
238               
239                return(content)
240        #def _fetch_repo
241       
242        def _get_external_appimages(self):
243                external_appimages={}
244                if os.path.isfile(self.external_appimages):
245                        try:
246                                with open(self.external_appimages) as appimages:
247                                        external_appimages=json.load(appimages)
248                        except:
249                                self._debug("Can't load %s"%self.external_appimages)
250                self._debug(external_appimages)
251                return external_appimages
252        #def _get_external_appimages
253       
254        def _process_appimage_json(self,data,repo_name):
255                maxconnections = 10
256                semaphore = threading.BoundedSemaphore(value=maxconnections)
257                applist=[]
258                json_data=json.loads(data)
259                if 'items' in json_data.keys():
260                        for appimage in json_data['items']:
261                                appinfo=self._th_process_appimage(appimage,semaphore)
262                                if appinfo:
263                                        applist.append(appinfo)
264                                        #                               th=threading.Thread(target=self._th_process_appimage, args = (appimage,semaphore))
265#                               th.start()
266
267#               while threading.active_count()>1:
268#                       print("%s"%threading.active_count())
269#                       time.sleep(0.1)
270
271#               while not self.queue.empty():
272#                       applist.append(self.queue.get())
273#                       self._debug("Added %s"%applist[-1])
274#               self._debug("JSON: %s"%applist)
275                return (applist)
276        #_process_appimage_json
277
278        def _th_process_appimage(self,appimage,semaphore):
279                appinfo=None
280#               semaphore.acquire()
281#               lock=threading.Lock()
282                releases=[]
283                if 'links' in appimage.keys():
284                        if appimage['links']:
285                                appinfo=self.load_json_appinfo(appimage)
286#Deprecated. appImage releases will be load on the info stage
287#                       releases=self._get_releases_from_json(appimage)
288#                       if releases:
289#                               appinfo['releases']=releases
290#                               for release in releases:
291#                                       #Release has the direct download url
292#                                       tmp_release=release.split('/')
293#                                       tmp_appinfo=appinfo.copy()
294#                                       rel_number=tmp_release[-2]
295#                                       rel_name=tmp_release[-1].lower().replace('.appimage','')
296#                                       self._debug("Release: %s"%release)
297#                                       tmp_appinfo['name']=rel_name
298#                                       tmp_appinfo['package']=tmp_release[-1]
299#                                       tmp_appinfo['homepage']='/'.join(tmp_release[0:-1])
300#                                       self.queue.put(tmp_appinfo)
301#Threading disabled
302#                               self.queue.put(appinfo)
303                return(appinfo)
304        #def _th_process_appimage
305
306        def load_json_appinfo(self,appimage):
307                appinfo=self._init_appinfo()
308                appinfo['name']=appimage['name']
309                appinfo['package']=appimage['name']
310                if 'license' in appimage.keys():
311                        appinfo['license']=appimage['license']
312                appinfo['summary']=''
313                if 'description' in appimage.keys():
314                        appinfo['description']=appimage['description']
315                if 'categories' in appimage.keys():
316                        appinfo['categories']=appimage['categories']
317                if 'icon' in appimage.keys():
318                        appinfo['icon']=appimage['icon']
319                if 'screenshots' in appimage.keys():
320                        appinfo['thumbnails']=appimage['screenshots']
321                if 'links' in appimage.keys():
322                        if appimage['links']:
323                                for link in appimage['links']:
324                                        if 'url' in link.keys() and link['type']=='Download':
325                                                appinfo['homepage']=link['url']
326                elif 'authors' in appimage.keys():
327                        if appimage['authors']:
328                                for author in appimage['authors']:
329                                        if 'url' in author.keys():
330                                                appinfo['homepage']=author['url']
331                appinfo['bundle']=['appimage']
332                return appinfo
333        #def load_json_appinfo
334
335        def _get_releases_from_json(self,appimage):
336                releases=[]
337                if appimage['links']:
338                        for link in appimage['links']:
339                                if 'type' in link.keys():
340                                        if link['type']=='Download':
341                                                self._debug("Info url: %s"%link['url'])
342                                                try:
343                                                        sw_git=False
344                                                        with urllib.request.urlopen(link['url']) as f:
345                                                                if 'github' in link['url']:
346                                                                        sw_git=True
347                                                                content=(f.read().decode('utf-8'))
348                                                                soup=BeautifulSoup(content,"html.parser")
349                                                                package_a=soup.findAll('a', attrs={ "href" : re.compile(r'.*[aA]pp[iI]mage$')})
350                                                                for package_data in package_a:
351                                                                        package_name=package_data.findAll('strong', attrs={ "class" : "pl-1"})
352                                                                        package_link=package_data['href']
353                                                                        if sw_git:
354                                                                                package_link="https://github.com"+package_link
355                                                                                releases.append(package_link)
356                                                                                self._debug("Link: %s"%package_link)
357                                                except Exception as e:
358                                                        print(e)
359                return releases
360        #def _get_releases_from_json
361
362        def _th_generate_xml_catalog(self,applist,outdir,info_url,repo,repo_name):
363                maxconnections = 10
364                semaphore = threading.BoundedSemaphore(value=maxconnections)
365                random_applist = list(applist)
366                random.shuffle(random_applist)
367                for app in applist:
368                        th=threading.Thread(target=self._th_write_xml, args = (app,outdir,info_url,repo,repo_name,semaphore))
369                        th.start()
370        #def _th_generate_xml_catalog
371
372        def _th_write_xml(self,appinfo,outdir,info_url,repo,repo_name,semaphore):
373                semaphore.acquire()
374                lock=threading.Lock()
375#               self._debug("Populating %s"%appinfo)
376                package=appinfo['name'].lower().replace(".appimage","")
377                if len(package)>40:
378                        tmp_package=package.split('-')
379                        tam=0
380                        pos=1
381                        index=0
382                        banned=['linux32','linux64','i386','x86_64','ia32','amd64']
383                        for tmp_name in tmp_package:
384                                if (tam<len(tmp_name) and pos<index) and tmp_name not in banned:
385                                        tam=len(tmp_name)
386                                        pos=index
387                                index+=1
388                        print("Removed: %s"%tmp_package[pos])
389                        tmp_package[pos]=''
390                        package='-'.join(tmp_package)
391                        package=package.replace("--","-")
392                        package=package.replace("-.",".")
393
394#               filename=outdir+package.lower().replace('appimage',"appdata")+".xml"
395#               self._debug("checking if we need to download "+filename)
396#               if not os.path.isfile(filename):
397                repo_info={'info_url':info_url,'repo':repo,repo_name:'repo_name'}
398                self._write_xml_file(appinfo,repo_info,lock)
399                semaphore.release()
400        #def _th_write_xml
401
402        def _write_xml_file(self,appinfo,repo_info,lock):
403                #Search in local store for the app
404                app=self.store.get_app_by_pkgname(appinfo['package'].lower())
405                if not app:
406                        self._debug("Searching for %s"%appinfo['package'])
407                        app=self.store.get_app_by_id(appinfo['package'].lower()+".desktop")
408                sw_new=False
409                if not app:
410                        self._debug("Generating new %s"%appinfo['package'])
411                        app=appstream.App()
412                        sw_new=True
413                bundle=appstream.Bundle()
414                icon=appstream.Icon()
415                screenshot=appstream.Screenshot()
416                #F*****g appstream have kinds undefined but kind_from_string works... wtf?
417#               bundle.set_kind(appstream.BundleKind.SNAP)
418                bundle.set_kind(bundle.kind_from_string('APPIMAGE'))
419                bundle.set_id(appinfo['package']+'.appimage')
420                app.add_bundle(bundle)
421                app.add_keyword("C","appimage")
422                app.add_category("appimage")
423                if sw_new:
424                        app.set_name("C",appinfo['name'])
425#               app.add_pkgname(pkg.get_name()+'.snap')
426                        app.add_pkgname(appinfo['package'])
427#               release=appstream.Release()
428#               release.set_version(pkg.get_version())
429#               app.add_release(release)
430                        app.set_id("appimagehub.%s"%appinfo['name']+'.appimage')
431#               app.set_id(pkg.get_name()+'.snap')
432                        app.set_id_kind=appstream.IdKind.DESKTOP
433                        description="This is an AppImage bundle of app %s. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.\n%s"%(appinfo['name'],appinfo['description'])
434                        summary=' '.join(list(description.split(' ')[:8]))
435                        if len(description.split(' '))>8:
436                                summary+="... "
437                        app.set_description("C",description)
438                        app.set_comment("C",summary)
439                        for category in appinfo['categories']:
440                                app.add_category(category)
441                        self.store.add_app(app)
442
443#               app.add_keyword("C",pkg.get_name())
444#               for word in pkg.get_summary().split(' '):
445#                       app.add_keyword("C",word)
446
447#               if pkg.get_icon():
448#                       if self.icon_cache_enabled:
449#                               icon.set_kind(appstream.IconKind.LOCAL)
450#                               icon.set_name(self._download_file(pkg.get_icon(),pkg.get_name(),self.icons_folder))
451#                       else:
452#                               icon.set_kind(appstream.IconKind.REMOTE)
453#                               icon.set_name(pkg.get_icon())
454#                       app.add_icon(icon)
455
456#               if pkg.get_license():
457#                       app.set_project_license(pkg.get_license())
458
459#               if pkg.get_screenshots():
460#                       for snap_screen in pkg.get_screenshots():
461#                               img=appstream.Image()
462##                              img.load_filename(self._download_file(snap_screen.get_url(),pkg.get_name(),self.images_folder))
463#                               img.set_kind(appstream.ImageKind.SOURCE)
464#                               img.set_url(snap_screen.get_url())
465#                               break
466#                       screenshot.add_image(img)
467#                       app.add_screenshot(screenshot)
468                return(app)
469#                       name=appinfo['name'].lower().replace(".appimage","")
470#                       self._debug("Generating %s xml"%appinfo['package'])
471#                       f=open(filename,'w')
472#                       f.write('<?xml version="1.0" encoding="UTF-8"?>'+"\n")
473#                       f.write("<components version=\"0.10\">\n")
474#                       f.write("<component  type=\"desktop-application\">\n")
475#                       f.write("  <id>%s</id>\n"%appinfo['package'].lower())
476#                       f.write("  <pkgname>%s</pkgname>\n"%appinfo['package'])
477#                       f.write("  <name>%s</name>\n"%name)
478#                       f.write("  <metadata_license>CC0-1.0</metadata_license>\n")
479#                       f.write("  <provides><binary>%s</binary></provides>\n"%appinfo['package'])
480#                       if 'releases' in appinfo.keys():
481#                               f.write("  <releases>\n")
482#                               for release in appinfo['releases']:
483#                                       tmp_release=release.split('/')
484#                                       rel_number='/'.join(tmp_release[-2:])
485#                                       f.write("    <release version=\"%s\" urgency=\"medium\">"%rel_number)
486#                                       f.write("</release>\n")
487#                               f.write("  </releases>\n")
488#                       f.write("  <launchable type=\"desktop-id\">%s.desktop</launchable>\n"%name)
489#                       if appinfo['description']=='':
490#                               with lock:
491#                                       try:
492#                                               if appinfo['name'] in self.descriptions_dict.keys():
493#                                                       (description,icon)=self.descriptions_dict[appinfo['name']]
494#                                               else:
495#                                                       (description,icon)=self._get_description_icon(appinfo['name'],repo_info)
496#                                                       self.descriptions_dict.update({appinfo['name']:[description,icon]})
497#                                       except:
498#                                               description=''
499#                                               icon=''
500#                       else:
501#                               description=appinfo['description']
502#                       summary=' '.join(list(description.split(' ')[:8]))
503#                       if len(description.split(' '))>8:
504#                               summary+="... "
505#                       description="This is an AppImage bundle of app %s. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.\n%s"%(name,description)
506#                       if summary=='':
507#                               summary=' '.join(list(description.split(' ')[:8]))
508#                       f.write("  <description><p></p><p>%s</p></description>\n"%description)
509#                       f.write("  <summary>%s</summary>\n"%summary)
510##                      f.write("  <icon type=\"local\">%s</icon>\n"%appinfo['icon'])
511#                       f.write("<icon type=\"cached\">"+name+"_"+name+".png</icon>\n")
512#                       f.write("  <url type=\"homepage\">%s</url>\n"%appinfo['homepage'])
513#                       f.write("  <bundle type=\"appimage\">%s</bundle>\n"%appinfo['name'])
514#                       f.write("  <keywords>\n")
515#                       keywords=name.split("-")
516#                       banned_keywords=["linux","x86_64","i386","ia32","amd64"]
517#                       for keyword in keywords:
518#                               #Better than isalpha method for this purpose
519#                               if keyword.isidentifier() and keyword not in banned_keywords:
520#                                       f.write("       <keyword>%s</keyword>\n"%keyword)
521#                       f.write("       <keyword>appimage</keyword>\n")
522#                       f.write("  </keywords>\n")
523#                       f.write("  <categories>\n")
524#                       f.write("       <category>AppImage</category>\n")
525#                       if 'categories' in appinfo.keys():
526#                               for category in appinfo['categories']:
527#                                       f.write("       <category>%s</category>\n"%category)
528#                       f.write("  </categories>\n")
529#                       f.write("</component>\n")
530#                       f.write("</components>\n")
531#                       f.close()
532        #def _write_xml_file
533
534        def _get_description_icon(self,app_name,info_url,repo_name):
535                desc=''
536                icon=''
537                if info_url:
538                        if '$(appname)' in info_url:
539                                info_url=info_url.replace('$(appname)',app_name)
540                        self._debug("Getting description from repo/app %s - %s "%(repo_name,info_url))
541                        try:
542                                with urllib.request.urlopen(info_url) as f:
543                                        if repo_name=='probono':
544                                                content=(f.read().decode('utf-8'))
545                                                soup=BeautifulSoup(content,"html.parser")
546                                                description_div=soup.findAll('div', attrs={ "class" : "description-text"})
547                                                icon_div=soup.findAll('div', attrs={ "class" : "avatar-icon avatar-large description-icon "})
548                                if len(description_div)>0:
549                                        desc=description_div[0].text
550                                        desc=desc.replace(':','.')
551                                        desc=desc.replace('&','&amp;')
552                                if len(icon_div)>0:
553                                        icon_str=str(icon_div[0])
554                                        icon=icon_str.split(' ')[9]
555                                        icon=icon.lstrip('url(')
556                                        if icon.startswith('http'):
557                                                icon=icon.rstrip(');"></div>')
558                                                icon=self._download_file(icon,app_name)
559                                        print("Icon: %s"%icon)
560                        except Exception as e:
561                                print("Can't get description from "+info_url)
562                                print(str(e))
563                                pass
564                return([desc,icon])
565        #def _get_description
566
567        def _clean_bundle_catalogue(self,applist,outdir):
568                xml_files_list=[]
569                applist=[item.lower() for item in applist]
570                for xml_file in os.listdir(outdir):
571                        if xml_file.endswith('appdata.xml'):
572                                xml_files_list.append(xml_file.lower().replace('appdata.xml','appimage'))
573       
574                if xml_files_list:
575                        xml_discard_list=list(set(xml_files_list).difference(applist))
576                        for discarded_file in xml_discard_list:
577                                os.remove(outdir+'/'+discarded_file.replace('appimage','appdata.xml'))
578        #def _clean_bunlde_catalogue
579
580        def _download_file(self,url,app_name):
581#               target_file=self.icons_folder+'/'+app_name+".png"
582                target_file=self.icons_dir+'/'+app_name+".png"
583                if not os.path.isfile(target_file):
584#                       shutil.copy("/usr/share/icons/hicolor/128x128/apps/lliurex-store.png",target_file)
585#                       if not os.fork():
586                        if not os.path.isfile(target_file):
587                                self._debug("Downloading %s to %s"%(url,target_file))
588                                try:
589                                        with urllib.request.urlopen(url) as response, open(target_file, 'wb') as out_file:
590                                                bf=16*1024
591                                                acumbf=0
592                                                file_size=int(response.info()['Content-Length'])
593                                                while True:
594                                                        if acumbf>=file_size:
595                                                            break
596                                                        shutil.copyfileobj(response, out_file,bf)
597                                                        acumbf=acumbf+bf
598                                        st = os.stat(target_file)
599                                except Exception as e:
600                                        self._debug("Unable to download %s"%url)
601                                        self._debug("Reason: %s"%e)
602                                        target_file=url
603#                               os._exit(0)
604                return(target_file)
605        #def _download_file
606       
607        def _chk_bundle_dir(self,outdir):
608                msg_status=True
609                if not os.path.isdir(outdir):
610                        try:
611                                os.makedirs(outdir)
612                        except Exception as e:
613                                msg_status=False
614                                print(e)
615                return(os.access(outdir,os.W_OK|os.R_OK|os.X_OK|os.F_OK))
616        #def _chk_bundle_dir
617       
618        def _init_appinfo(self):
619                appInfo={'appstream_id':'',\
620                'id':'',\
621                'name':'',\
622                'version':'',\
623                'releases':[],\
624                'package':'',\
625                'license':'',\
626                'summary':'',\
627                'description':'',\
628                'categories':[],\
629                'icon':'',\
630                'screenshot':'',\
631                'thumbnails':[],\
632                'video':'',\
633                'homepage':'',\
634                'installerUrl':'',\
635                'state':'',\
636                'depends':'',\
637                'kudos':'',\
638                'suggests':'',\
639                'extraInfo':'',\
640                'size':'',\
641                'bundle':'',\
642                'updatable':'',\
643                }
644                return(appInfo)
645        #def _init_appinfo
646       
647        def _get_info(self,app_info):
648                app_info['state']='available'
649                if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
650                        app_info['state']='installed'
651                #Get size
652                appimage_url=app_info['homepage']+'/'+app_info['package']
653                dest_path=self.appimage_dir+'/'+app_info['package']
654                if appimage_url:
655                        try:
656                                with urllib.request.urlopen(appimage_url) as response:
657                                        app_info['size']=(response.info()['Content-Length'])
658                        except:
659                                app_info['size']=0
660                self._set_status(0)
661                self.partial_progress=100
662                return(app_info)
663        #def _get_info
664
Note: See TracBrowser for help on using the repository browser.