00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 """
00038 Implements applist part of app_manager, which handles listing of
00039 currently installed applications.
00040 """
00041
00042 import os
00043 import sys
00044 import yaml
00045
00046 from .app import load_AppDefinition_by_name
00047 from .msg import App, ClientApp, KeyValue, Icon
00048 from .exceptions import AppException, InvalidAppException
00049
00050 def get_default_applist_directory():
00051 """
00052 Default directory where applist configuration is stored.
00053 """
00054 return "/etc/robot/apps"
00055
00056 def dict_to_KeyValue(d):
00057 l = []
00058 for k, v in d.iteritems():
00059 l.append(KeyValue(k, str(v)))
00060 return l
00061
00062 def read_Icon_file(filename):
00063 icon = Icon()
00064 if filename == None or filename == "":
00065 return icon
00066 basename, extension = os.path.splitext(filename)
00067 if extension.lower() == ".jpg" or extension.lower() == ".jpeg":
00068 icon.format = "jpeg"
00069 elif extension.lower() == ".png":
00070 icon.format = "png"
00071 else:
00072 icon.format = ""
00073 return icon
00074 icon.data = open(filename, "rb").read()
00075 return icon
00076
00077 def AppDefinition_to_App(app_definition):
00078 a = App(name=app_definition.name, display_name=app_definition.display_name, icon=read_Icon_file(app_definition.icon))
00079 a.client_apps = []
00080 for c in app_definition.clients:
00081 a.client_apps.append(ClientApp(c.client_type,
00082 dict_to_KeyValue(c.manager_data),
00083 dict_to_KeyValue(c.app_data)))
00084 return a
00085
00086 class InstalledFile(object):
00087 """
00088 Models data stored in a .installed file. These files are used to
00089 track installation of apps.
00090 """
00091
00092 def __init__(self, filename):
00093 self.filename = filename
00094
00095 self.available_apps = []
00096
00097 self._file_mtime = None
00098 self.update()
00099
00100 def _load(self):
00101 available_apps = []
00102 with open(self.filename) as f:
00103 installed_data = yaml.load(f)
00104 for reqd in ['apps']:
00105 if not reqd in installed_data:
00106 raise InvalidAppException("installed file [%s] is missing required key [%s]"%(self.filename, reqd))
00107 for app in installed_data['apps']:
00108 for areqd in ['app']:
00109 if not areqd in app:
00110 raise InvalidAppException("installed file [%s] app definition is missing required key [%s]"%(self.filename, areqd))
00111 available_apps.append(load_AppDefinition_by_name(app['app']))
00112
00113 self.available_apps = available_apps
00114
00115 def update(self):
00116 """
00117 Update app list
00118 """
00119 s = os.stat(self.filename)
00120 if s.st_mtime != self._file_mtime:
00121 self._load()
00122 self._file_mtime = s.st_mtime
00123
00124 class AppList(object):
00125
00126 def __init__(self, applist_directory):
00127 self.applist_directory = applist_directory
00128 self.installed_files = {}
00129 self.invalid_installed_files = []
00130 self.app_list = []
00131
00132 self._applist_directory_mtime = None
00133 self.update()
00134
00135 def _load(self):
00136 app_list = []
00137 invalid_installed_files = []
00138
00139 dir_list = os.listdir(self.applist_directory)
00140
00141 for f in set(self.installed_files.keys()) - set(dir_list):
00142 print "deleting installation data for [%s]"%(f)
00143 del self.installed_files[f]
00144
00145 for f in dir_list:
00146 if not f.endswith('.installed'):
00147 continue
00148 try:
00149 if f in self.installed_files:
00150 installed_file = self.installed_files[f]
00151 installed_file.update()
00152 else:
00153 print "loading installation data for [%s]"%(f)
00154 filename = os.path.join(self.applist_directory, f)
00155 installed_file = InstalledFile(filename)
00156 self.installed_files[f] = installed_file
00157
00158 app_list.extend(installed_file.available_apps)
00159
00160 except AppException as ae:
00161 print >> sys.stderr, "ERROR: %s"%(str(ae))
00162 invalid_installed_files.append((filename, ae))
00163 except Exception as e:
00164 print >> sys.stderr, "ERROR: %s"%(str(e))
00165 invalid_installed_files.append((filename, e))
00166
00167 self.app_list = app_list
00168 self.invalid_installed_files = invalid_installed_files
00169
00170 def get_app_list(self):
00171 return [AppDefinition_to_App(ad) for ad in self.app_list]
00172
00173 def update(self):
00174 """
00175 Update app list
00176 """
00177 s = os.stat(self.applist_directory)
00178 if s.st_mtime != self._applist_directory_mtime:
00179 self._load()
00180 self._applist_directory_mtime = s.st_mtime