app.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2011, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 #
33 # Revision $Id: app.py 14667 2011-08-12 23:55:04Z pratkanis $
34 
35 # author: leibs, kwc
36 
37 import os
38 import errno
39 import yaml
40 
41 import roslib.names
42 from rospkg import ResourceNotFound
43 from .exceptions import AppException, InvalidAppException, NotFoundException, InternalAppException
44 
45 class Interface(object):
46  def __init__(self, subscribed_topics, published_topics):
47  self.subscribed_topics = subscribed_topics
48  self.published_topics = published_topics
49 
50  def __eq__(self, other):
51  if not isinstance(other, Interface):
52  return False
53  return self.subscribed_topics == other.subscribed_topics and \
54  self.published_topics == other.published_topics
55 
56 class Client(object):
57  __slots__ = ['client_type', 'manager_data', 'app_data']
58  def __init__(self, client_type, manager_data, app_data):
59  self.client_type = client_type
60  self.manager_data = manager_data
61  self.app_data = app_data
62 
63  def as_dict(self):
64  return {'client_type': self.client_type, 'manager_data': self.manager_data, 'app_data': self.app_data}
65 
66  def __eq__(self, other):
67  if not isinstance(other, Client):
68  return False
69  return self.client_type == other.client_type and \
70  self.manager_data == other.manager_data and \
71  self.app_data == other.app_data
72 
73  def __repr__(self):
74  return yaml.dump(self.as_dict())
75 
76 class AppDefinition(object):
77  __slots__ = ['name', 'display_name', 'description', 'platform',
78  'launch', 'interface', 'clients', 'icon']
79  def __init__(self, name, display_name, description, platform,
80  launch, interface, clients, icon=None):
81  self.name = name
82  self.display_name = display_name
83  self.description = description
84  self.platform=platform
85  self.launch = launch
86  self.interface = interface
87  self.clients = clients
88  self.icon = icon
89 
90  def __repr__(self):
91  d = {}
92  for s in self.__slots__:
93  if s == 'clients':
94  d[s] = [c.as_dict() for c in self.clients]
95  else:
96  d[s] = getattr(self, s)
97  return yaml.dump(d)
98  # return "name: %s\ndisplay: %s\ndescription: %s\nplatform: %s\nlaunch: %s\ninterface: %s\nclients: %s"%(self.name, self.display_name, self.description, self.platform, self.launch, self.interface, self.clients)
99 
100  def __eq__(self, other):
101  if not isinstance(other, AppDefinition):
102  return False
103  return self.name == other.name and \
104  self.display_name == other.display_name and \
105  self.description == other.description and \
106  self.platform == other.platform and \
107  self.launch == other.launch and \
108  self.interface == other.interface and \
109  self.clients == other.clients and \
110  self.icon == other.icon
111 
112 def find_resource(resource):
113  """
114  @return: filepath of resource. Does not validate if filepath actually exists.
115 
116  @raise ValueError: if resource is not a valid resource name.
117  @raise rospkg.ResourceNotFound: if package referred
118  to in resource name cannot be found.
119  @raise NotFoundException: if resource does not exist.
120  """
121  p, a = roslib.names.package_resource_name(resource)
122  if not p:
123  raise ValueError("Resource is missing package name: %s"%(resource))
124  matches = roslib.packages.find_resource(p, a)
125  # TODO: convert ValueError to better type for better error messages
126  if len(matches) == 1:
127  return matches[0]
128  elif not matches:
129  raise NotFoundException("No resource [%s]"%(resource))
130  else:
131  raise ValueError("Multiple resources named [%s]"%(resource))
132 
134  """
135  @raise IOError: I/O error reading file (e.g. does not exist)
136  @raise InvalidAppException: if app file is invalid
137  """
138  with open(filename,'r') as f:
139  y = yaml.load(f.read())
140  y = y or {} #coerce to dict
141  try:
142  subscribed_topics = y.get('subscribed_topics', {})
143  published_topics = y.get('published_topics', {})
144  except KeyError:
145  raise InvalidAppException("Malformed interface, missing keys")
146  return Interface(published_topics=published_topics, subscribed_topics=subscribed_topics)
147 
148 def _AppDefinition_load_icon_entry(app_data, appfile="UNKNOWN"):
149  """
150  @raise InvalidAppExcetion: if app definition is invalid.
151  """
152  # load/validate launch entry
153  try:
154  icon_resource = app_data.get('icon', '')
155  if icon_resource == '':
156  return None
157  icon_filename = find_resource(icon_resource)
158  if not icon_filename or not os.path.exists(icon_filename):
159  return None
160  return icon_filename
161  except ValueError as e:
162  raise InvalidAppException("Malformed appfile [%s]: bad icon entry: %s"%(appfile, e))
163  except NotFoundException:
164  # TODO: make this a soft fail?
165  raise InvalidAppException("App file [%s] refers to icon that cannot be found"%(appfile))
166  except ResourceNotFound as e:
167  raise InvalidAppException("App file [%s] refers to package that is not installed: %s"%(appfile, str(e)))
168 
169 def _AppDefinition_load_launch_entry(app_data, appfile="UNKNOWN"):
170  """
171  @raise InvalidAppExcetion: if app definition is invalid.
172  """
173  # load/validate launch entry
174  try:
175  launch = find_resource(app_data['launch'])
176  if not os.path.exists(launch):
177  raise InvalidAppException("Malformed appfile [%s]: refers to launch that does not exist."%(appfile))
178  return launch
179  except ValueError as e:
180  raise InvalidAppException("Malformed appfile [%s]: bad launch entry: %s"%(appfile, e))
181  except NotFoundException:
182  raise InvalidAppException("App file [%s] refers to launch that is not installed"%(appfile))
183  except ResourceNotFound as e:
184  raise InvalidAppException("App file [%s] refers to package that is not installed: %s"%(appfile, str(e)))
185 
186 def _AppDefinition_load_interface_entry(app_data, appfile="UNKNOWN"):
187  """
188  @raise InvalidAppExcetion: if app definition is invalid.
189  """
190  # load/validate interface entry
191  try:
192  return load_Interface_from_file(find_resource(app_data['interface']))
193  except IOError as e:
194  if e.errno == errno.ENOENT:
195  raise InvalidAppException("Malformed appfile [%s]: refers to interface file that does not exist"%(appfile))
196  else:
197  raise InvalidAppException("Error with appfile [%s]: cannot read interface file"%(appfile))
198  except ValueError:
199  raise InvalidAppException("Malformed appfile [%s]: bad interface entry"%(appfile))
200  except ResourceNotFound as e:
201  raise InvalidAppException("App file [%s] refers to package that is not installed: %s"%(appfile, str(e)))
202 
203 def _AppDefinition_load_clients_entry(app_data, appfile="UNKNOWN"):
204  """
205  @raise InvalidAppExcetion: if app definition is invalid.
206  """
207  clients_data = app_data.get('clients', [])
208  clients = []
209  for c in clients_data:
210  for reqd in ['type', 'manager']:
211  if not reqd in c:
212  raise InvalidAppException("Malformed appfile [%s], missing required key [%s]"%(appfile, reqd))
213  client_type = c['type']
214  manager_data = c['manager']
215  if not type(manager_data) == dict:
216  raise InvalidAppException("Malformed appfile [%s]: manager data must be a map"%(appfile))
217 
218  app_data = c.get('app', {})
219  if not type(app_data) == dict:
220  raise InvalidAppException("Malformed appfile [%s]: app data must be a map"%(appfile))
221 
222  clients.append(Client(client_type, manager_data, app_data))
223  return clients
224 
225 def load_AppDefinition_from_file(appfile, appname):
226  """
227  @raise InvalidAppExcetion: if app definition is invalid.
228  @raise IOError: I/O error reading appfile (e.g. file does not exist).
229  """
230  with open(appfile,'r') as f:
231  app_data = yaml.load(f.read())
232  for reqd in ['launch', 'interface', 'platform']:
233  if not reqd in app_data:
234  raise InvalidAppException("Malformed appfile [%s], missing required key [%s]"%(appfile, reqd))
235 
236  display_name = app_data.get('display', appname)
237  description = app_data.get('description', '')
238  platform = app_data['platform']
239 
240 
241  launch = _AppDefinition_load_launch_entry(app_data, appfile)
242  interface = _AppDefinition_load_interface_entry(app_data, appfile)
243  clients = _AppDefinition_load_clients_entry(app_data, appfile)
244  icon = _AppDefinition_load_icon_entry(app_data, appfile)
245 
246  return AppDefinition(appname, display_name, description, platform,
247  launch, interface, clients, icon)
248 
250  """
251  @raise InvalidAppExcetion: if app definition is invalid.
252  @raise NotFoundExcetion: if app definition is not installed.
253  @raise ValueError: if appname is invalid.
254  """
255  if not appname:
256  raise ValueError("app name is empty")
257 
258  try:
259  appfile = find_resource(appname + '.app')
260  except ResourceNotFound as e:
261  raise NotFoundException("Cannot locate app file for %s: package is not installed."%(appname))
262 
263  try:
264  return load_AppDefinition_from_file(appfile, appname)
265  except IOError as e:
266  if e.errno == errno.ENOENT:
267  raise NotFoundException("Cannot locate app file for %s."%(appname))
268  else:
269  raise InternalAppException("I/O error loading AppDefinition file: %s."%(e.errno))
def _AppDefinition_load_launch_entry(app_data, appfile="UNKNOWN")
Definition: app.py:169
def load_AppDefinition_from_file(appfile, appname)
Definition: app.py:225
def find_resource(resource)
Definition: app.py:112
def __init__(self, name, display_name, description, platform, launch, interface, clients, icon=None)
Definition: app.py:80
def as_dict(self)
Definition: app.py:63
def __eq__(self, other)
Definition: app.py:100
def __init__(self, subscribed_topics, published_topics)
Definition: app.py:46
def _AppDefinition_load_interface_entry(app_data, appfile="UNKNOWN")
Definition: app.py:186
def _AppDefinition_load_icon_entry(app_data, appfile="UNKNOWN")
Definition: app.py:148
def __eq__(self, other)
Definition: app.py:50
def _AppDefinition_load_clients_entry(app_data, appfile="UNKNOWN")
Definition: app.py:203
def __repr__(self)
Definition: app.py:73
def __init__(self, client_type, manager_data, app_data)
Definition: app.py:58
def load_AppDefinition_by_name(appname)
Definition: app.py:249
def load_Interface_from_file(filename)
Definition: app.py:133
def __eq__(self, other)
Definition: app.py:66


app_manager
Author(s): Jeremy Leibs, Ken Conley, Yuki Furuta
autogenerated on Tue Apr 2 2019 02:58:24