exchange.py
Go to the documentation of this file.
1 #! /usr/bin/python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2011, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Willow Garage, Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 #
34 # Revision $Id: topics.py 11753 2010-10-25 06:23:19Z kwc $
35 
36 # author: pratkanis
37 
38 """
39 Implements exchange part of app_manager, which handles listing of
40 avialable and removable applications.
41 """
42 
43 import subprocess
44 import os
45 import sys
46 import yaml
47 import rospy
48 from std_msgs.msg import String
49 from .msg import ExchangeApp, Icon
50 
51 class Exchange():
52  def __init__(self, url, directory, on_error = lambda x: None):
53  self._url = url
54  self._directory = directory
55  self._on_error = on_error
56  self._installed_apps = []
57  self._available_apps = []
58  self._debs = {}
59 
60  self._exchange_local = os.path.join(self._directory, "exchange.yaml")
61  d = os.path.join(self._directory, "installed")
62  if (not os.path.exists(d)):
63  os.mkdir(d)
64  self._exchange_file = os.path.join(d, "app_exchange.installed")
65  rospy.loginfo("Directory: {}".format(self._directory))
66  rospy.loginfo("Local path: {}".format(self._exchange_local))
67  rospy.loginfo("Local file: {}".format(self._exchange_file))
68  rospy.loginfo(subprocess.Popen(["whoami"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate())
69 
70  def get_installed_version(self, deb):
71  data = subprocess.Popen(["dpkg", "-l", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
72  val = (data[0] or '').strip()
73  for i in val.split('\n'):
74  if (i.find(deb) > 0 and i.find("ii") == 0):
75  return [s for s in i.strip().split(" ") if s][2]
76  self._on_error("Failed to get installed version: " + str(data))
77  return "FAILED"
78 
79  def get_available_version(self, deb):
80  data = subprocess.Popen(["apt-cache", "showpkg", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
81  val = (data[0] or '').strip()
82  nearing = False
83  for i in val.split('\n'):
84  if (nearing):
85  return i.strip().split(" ")[0].strip()
86  if (i.strip() == "Versions:"):
87  nearing = True
88  self._on_error("Failed to get available version: " + str(data))
89  return "FAILED"
90 
91  def is_installed(self, deb):
92  data = subprocess.Popen(["dpkg", "-l", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
93  val = (data[0] or '').strip()
94  for i in val.split("\n"):
95  if (i.find(deb) > 0):
96  return (i.find("ii") == 0)
97  self._on_error("Error getting installed packages: " + str(data))
98  return False
99 
101  return self._installed_apps
102 
104  return self._available_apps
105 
106  def get_app_details(self, name):
107  local_path = os.path.join(self._directory, name)
108  if (not os.path.exists(local_path)):
109  os.makedirs(local_path)
110  data = subprocess.Popen(["wget", "-O", os.path.join(local_path, "app.yaml"), (self._url.strip('/') + "/" + name + ".yaml")], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
111  val = (data[0] or '').strip()
112  rospy.logwarn(val)
113  try:
114  data = yaml.load(open(os.path.join(local_path, "app.yaml")))
115  icon_url = data["icon_url"]
116  icon_format = data["icon_format"]
117  val = (subprocess.Popen(["wget", "-O", os.path.join(local_path, "icon" + icon_format), icon_url], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip()
118  rospy.logwarn(val)
119  except:
120  rospy.logerr("No icon")
121  self.update_local()
122  for i in self._available_apps:
123  if (i.name == name):
124  return i
125  for i in self._installed_apps:
126  if (i.name == name):
127  return i
128  self._on_error("Problem getting app details: " + str(data))
129  return None
130 
131  def install_app(self, app):
132  deb = False
133  for i in self._available_apps:
134  if (i.name == app):
135  if (deb):
136  return False #Somehow a dupe
137  deb = self._debs[i.name]
138  for i in self._installed_apps:
139  if (i.name == app):
140  if (deb):
141  return False #Somehow a dupe
142  deb = self._debs[i.name]
143  if (deb == False):
144  self._on_error("No debian found for install")
145  return False
146  rospy.loginfo("install app")
147  p = subprocess.Popen(["sudo", "rosget", "install", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
148  #data = p.communicate()
149  #data = "test string"
150  pub = rospy.Publisher('install_status', String)
151  l1 = []
152  for line in iter(p.stdout.readline, ''):
153  if line.rstrip() != '':
154  pub.publish(line.rstrip())
155  l1.append(line)
156  else:
157  break
158  l2 = []
159  for line in iter(p.stderr.readline, ''):
160  if line.rstrip() != '':
161  pub.publish(line.rstrip())
162  l2.append(line)
163  else:
164  break
165 
166  data = (''.join(l1), ''.join(l2))
167  val = (data[0] or '').strip()
168  rospy.logwarn(val)
169  self.update_local()
170  for i in self._installed_apps:
171  if (i.name == app):
172  return True
173  self._on_error("Invalid return for install: " + str(data))
174  return False
175 
176  def uninstall_app(self, app):
177  deb = False
178  for i in self._installed_apps:
179  if (i.name == app):
180  if (deb):
181  return False #Somehow a dupe
182  deb = self._debs[i.name]
183  if (deb == False):
184  self._on_error("No debian found for uninstall")
185  return False
186  rospy.loginfo("uninstall app")
187  data = subprocess.Popen(["sudo", "rosget", "remove", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
188  val = (data[0] or '').strip()
189  self.update_local()
190  for i in self._available_apps:
191  if (i.name == app):
192  return True
193  self._on_error("Invalid return for uninstall: " + str(data))
194  return False
195 
196  def update(self):
197  #Call server
198  val = (subprocess.Popen(["wget", "-O", self._exchange_local, self._url + "/applications.yaml"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip()
199  if (val != "" or not os.path.exists(self._exchange_local)):
200  rospy.logerr("Wget failed: {}".format(val))
201  return False
202 
203  p = subprocess.Popen(["sudo", "rosget", "update"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
204  data = p.communicate()
205  val = (data[0] or '').strip()
206  if (p.returncode != 0):
207  self._on_error("Invalid return of update: " + str(data))
208  self.update_local()
209  if (p.returncode != 0):
210  return False
211  return True
212 
213  def update_local(self):
214  installed_apps = []
215  file_apps = []
216  available_apps = []
217  try:
218  exchange_data = yaml.load(open(self._exchange_local))
219  except:
220  return
221  if (not exchange_data):
222  return
223  for app in exchange_data['apps']:
224  appc = ExchangeApp()
225  appc.name = app['app']
226  appc.display_name = app['display']
227  deb = app['debian']
228  self._debs[app['app']] = deb
229  appc.latest_version = self.get_available_version(deb)
230  appc.hidden = False
231  try:
232  if(app['hidden']):
233  appc.hidden = True
234  except:
235  pass
236 
237  local_path = os.path.join(self._directory, app['app'])
238  if (os.path.exists(local_path)):
239  format = ""
240  if (os.path.exists(os.path.join(local_path, "app.yaml"))):
241  rospy.logwarn(local_path)
242  data = yaml.load(open(os.path.join(local_path, "app.yaml")))
243  try:
244  appc.description = data['description']
245  except:
246  if (appc.hidden):
247  appc.description = "Descriptionless hidden app"
248  else:
249  appc.description = "No description set, likely an error in the yaml file"
250  try:
251  format = data['icon_format']
252  except:
253  pass
254  if (os.path.exists(os.path.join(local_path, "icon" + format)) and format != ""):
255  icon = Icon()
256  icon.format = format.strip(".")
257  if (icon.format == "jpg"): icon.format = "jpeg"
258  icon.data = open(os.path.join(local_path, "icon" + format), "rb").read()
259  appc.icon = icon
260  if (self.is_installed(deb)):
261  appc.version = self.get_installed_version(deb)
262  installed_apps.append(appc)
263  file_apps.append(app) #Should remove debian tag?
264  else:
265  available_apps.append(appc)
266 
267  f = open(self._exchange_file, "w")
268  yaml.dump({"apps": file_apps}, f)
269  f.close()
270  self._installed_apps = installed_apps
271  self._available_apps = available_apps
272 
273 
def __init__(self, url, directory, on_error=lambda x:None)
Definition: exchange.py:52
def get_available_version(self, deb)
Definition: exchange.py:79
def get_app_details(self, name)
Definition: exchange.py:106
def is_installed(self, deb)
Definition: exchange.py:91
def uninstall_app(self, app)
Definition: exchange.py:176
def install_app(self, app)
Definition: exchange.py:131
def get_installed_version(self, deb)
Definition: exchange.py:70


app_manager
Author(s): Jeremy Leibs, Ken Conley, Yuki Furuta
autogenerated on Fri Mar 5 2021 03:07:47