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  print "Directory:", self._directory
66  print "Local path:", self._exchange_local
67  print "Local file:", self._exchange_file
68  print 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  print 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  print val
119  except:
120  print "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  print "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  print 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  print "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  print sys.stderr >> val
201  print sys.stderr >> "Wget failed"
202  return False
203 
204  p = subprocess.Popen(["sudo", "rosget", "update"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
205  data = p.communicate()
206  val = (data[0] or '').strip()
207  if (p.returncode != 0):
208  self._on_error("Invalid return of update: " + str(data))
209  self.update_local()
210  if (p.returncode != 0):
211  return False
212  return True
213 
214  def update_local(self):
215  installed_apps = []
216  file_apps = []
217  available_apps = []
218  try:
219  exchange_data = yaml.load(open(self._exchange_local))
220  except:
221  return
222  if (not exchange_data):
223  return
224  for app in exchange_data['apps']:
225  appc = ExchangeApp()
226  appc.name = app['app']
227  appc.display_name = app['display']
228  deb = app['debian']
229  self._debs[app['app']] = deb
230  appc.latest_version = self.get_available_version(deb)
231  appc.hidden = False
232  try:
233  if(app['hidden']):
234  appc.hidden = True
235  except:
236  pass
237 
238  local_path = os.path.join(self._directory, app['app'])
239  if (os.path.exists(local_path)):
240  format = ""
241  if (os.path.exists(os.path.join(local_path, "app.yaml"))):
242  print local_path
243  data = yaml.load(open(os.path.join(local_path, "app.yaml")))
244  try:
245  appc.description = data['description']
246  except:
247  if (appc.hidden):
248  appc.description = "Descriptionless hidden app"
249  else:
250  appc.description = "No description set, likely an error in the yaml file"
251  try:
252  format = data['icon_format']
253  except:
254  pass
255  if (os.path.exists(os.path.join(local_path, "icon" + format)) and format != ""):
256  icon = Icon()
257  icon.format = format.strip(".")
258  if (icon.format == "jpg"): icon.format = "jpeg"
259  icon.data = open(os.path.join(local_path, "icon" + format), "rb").read()
260  appc.icon = icon
261  if (self.is_installed(deb)):
262  appc.version = self.get_installed_version(deb)
263  installed_apps.append(appc)
264  file_apps.append(app) #Should remove debian tag?
265  else:
266  available_apps.append(appc)
267 
268  f = open(self._exchange_file, "w")
269  yaml.dump({"apps": file_apps}, f)
270  f.close()
271  self._installed_apps = installed_apps
272  self._available_apps = available_apps
273 
274 
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 __init__(self, url, directory, on_error=lambda(x):None)
Definition: exchange.py:52
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 Tue Apr 2 2019 02:58:24