def run(self, result=None): # argv is rosargs but these have no effect on client, so no need to pass anything here with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) as node_ctx: self.node_ctx = node_ctx set_pyros_client(self.node_ctx.client) super(TestTopicsPyros, self).run(result)
def run(host, port, server, config, logfile, ros_args): """ Start rostful server. :param host: the local IP on which to serve rostful (0.0.0.0 for all) :param port: the local port on which to serve rostful :param server: the server to run our WSGI app (flask or tornado) :param config: the config file path, absolute, or relative to working directory :param logfile: the logfile path, absolute, or relative to working directory :param ros_args: the ros arguments (useful to absorb additional args when launched with roslaunch) TODO : get doctests to work here >>> run('127.0.0.1', '8888', False, 'flask', None, None) [] >>> run('127.0.0.1', '8888', True, 'flask', None, None) >>> run('127.0.0.1', '4444', False, 'tornado', None, None) >>> run() """ if port and isinstance(port, (str, unicode)): port = int(port) app = create_app(configfile_override=config, logfile=logfile) # Some logic for defaults value (might depend on config) server = server or app.config.get('SERVER_TYPE', 'tornado') app.logger.info( 'rostful started with : host {host} port {port} config {config} logfile {logfile} ros_args {ros_args}' .format(host=host, port=port, config=config, logfile=logfile, ros_args=ros_args)) # Starting pyros with latest config # TODO : move this out of here and let the user do it : # in ROS case : it should be done in launch file, and connect on user request (maybe even pass the zmq socket url) # in pyzmp case : it should be done dynamically, as much as possible outside of here. with pyros_start(config=app.config, ros_args=ros_args) as node_ctx: set_pyros_client(app, node_ctx.client) # configure logger # add log handler for warnings and more to sys.stderr. app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(logging.WARN) import socket # just to catch the "Address already in use" error port_retries = 5 while port_retries > 0: # keep trying try: # default server should be solid and production ready if server == 'flask': log = logging.getLogger('werkzeug') log.setLevel(logging.DEBUG) app.logger.info( 'Starting Flask server on port {0}'.format(port)) # debug is needed to investigate server errors. # use_reloader set to False => killing the ros node also kills the server child. app.run( host=host, port=port, debug=True, use_reloader=False, ) elif server == 'tornado': # Only import if needed from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.log import enable_pretty_logging port = port or '5000' # same default as flask host = host or '127.0.0.1' # same default as flask app.logger.info( 'Starting Tornado server on {0}:{1}'.format( host, port)) # enable_pretty_logging() # enable this for debugging during development http_server = HTTPServer(WSGIContainer(app)) http_server.listen(port) IOLoop.instance().start() # TODO : support more wsgi server setup : http://www.markjberger.com/flask-with-virtualenv-uwsgi-nginx/ break except socket.error as msg: port_retries -= 1 port += 1 app.logger.error('Socket Error : {0}'.format(msg))
def launch(self, host=None, port=None, ros_args='', serv_type='tornado', pyros_ctx_impl=None): """ Launch the current WSGI app in a web server (tornado or flask simple server) Will block until server is killed. :param host: the local ip to listen for connection on :param port: the local port to listen for connection on :param ros_args: the provided ros arguments that will be passed onto pyros node :param serv_type: the server type (tornado or flask) :param pyros_ctx_impl: the implementation of pyros context manager ( if different from normal module ). This is useful for mocking it. :return: None """ # default to real module, if no other implementation passed as parameter (used for mock) pyros_ctx_impl = pyros_ctx_impl or pyros_ctx if port and isinstance(port, (str, unicode)): port = int(port) # implementing Config.get_namespace() for flask version < 1.0: namespace = 'PYROS_' trim_namespace = True lowercase = False rv = {} for k, v in six.iteritems(self.app.config): if not k.startswith(namespace): continue if trim_namespace: key = k[len(namespace):] else: key = k if lowercase: key = key.lower() rv[key] = v # rv should now contain a dictionary of namespaced key:value from self.app.config # One PyrosNode is needed for Flask. # TODO : check everything works as expected, even if the WSGI app is used by multiple processes try: node_ctx_gen = pyros_ctx_impl(name='rostful', argv=ros_args, pyros_config=rv) except TypeError as te: # bwcompat trick node_ctx_gen = pyros_ctx_impl(name='rostful', argv=ros_args, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) with node_ctx_gen as node_ctx: set_pyros_client(node_ctx.client) # configure logger #if not debug: # add log handler for warnings and more to sys.stderr. # self.logger.addHandler(logging.StreamHandler()) # self.logger.setLevel(logging.WARN) import socket # just to catch the "Address already in use" error port_retries = 5 while port_retries > 0: # keep trying try: # default server should be solid and production ready serv_type = serv_type or self.app.config.get('SERVER_TYPE', 'tornado') if serv_type == 'flask': log = logging.getLogger('werkzeug') log.setLevel(logging.DEBUG) self.app.logger.info('Starting Flask server on port {0}'.format(port)) # debug is needed to investigate server errors. # use_reloader set to False => killing the ros node also kills the server child. self.app.run( host=host, port=port, debug=True, use_reloader=False, ) elif serv_type == 'tornado': port = port or '5000' # same default as flask host = host or '127.0.0.1' # same default as flask self.app.logger.info('Starting Tornado server on {0}:{1}'.format(host, port)) # enable_pretty_logging() # enable this for debugging during development http_server = HTTPServer(WSGIContainer(self.app)) http_server.listen(port) IOLoop.instance().start() # TODO : support more wsgi server setup : http://www.markjberger.com/flask-with-virtualenv-uwsgi-nginx/ break except socket.error as msg: port_retries -= 1 port += 1 self.app.logger.error('Socket Error : {0}'.format(msg))
def run(self, result=None): # argv is rosargs but these have no effect on client, so no need to pass anything here with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) as node_ctx: self.node_ctx = node_ctx set_pyros_client(self.node_ctx.client) super(TestServicesPyros, self).run(result)
def run(host, port, server, config, logfile, ros_args): """ Start rostful server. :param host: the local IP on which to serve rostful (0.0.0.0 for all) :param port: the local port on which to serve rostful :param server: the server to run our WSGI app (flask or tornado) :param config: the config file path, absolute, or relative to working directory :param logfile: the logfile path, absolute, or relative to working directory :param ros_args: the ros arguments (useful to absorb additional args when launched with roslaunch) TODO : get doctests to work here >>> run('127.0.0.1', '8888', False, 'flask', None, None) [] >>> run('127.0.0.1', '8888', True, 'flask', None, None) >>> run('127.0.0.1', '4444', False, 'tornado', None, None) >>> run() """ if port and isinstance(port, (str, unicode)): port = int(port) app = create_app(configfile_override=config, logfile=logfile) # Some logic for defaults value (might depend on config) server = server or app.config.get('SERVER_TYPE', 'tornado') app.logger.info( 'rostful started with : host {host} port {port} config {config} logfile {logfile} ros_args {ros_args}'.format( host=host, port=port, config=config, logfile=logfile, ros_args=ros_args)) # Starting pyros with latest config # TODO : move this out of here and let the user do it : # in ROS case : it should be done in launch file, and connect on user request (maybe even pass the zmq socket url) # in pyzmp case : it should be done dynamically, as much as possible outside of here. with pyros_start(config=app.config, ros_args=ros_args) as node_ctx: set_pyros_client(app, node_ctx.client) # configure logger # add log handler for warnings and more to sys.stderr. app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(logging.WARN) import socket # just to catch the "Address already in use" error port_retries = 5 while port_retries > 0: # keep trying try: # default server should be solid and production ready if server == 'flask': log = logging.getLogger('werkzeug') log.setLevel(logging.DEBUG) app.logger.info('Starting Flask server on port {0}'.format(port)) # debug is needed to investigate server errors. # use_reloader set to False => killing the ros node also kills the server child. app.run( host=host, port=port, debug=True, use_reloader=False, ) elif server == 'tornado': # Only import if needed from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.log import enable_pretty_logging port = port or '5000' # same default as flask host = host or '127.0.0.1' # same default as flask app.logger.info('Starting Tornado server on {0}:{1}'.format(host, port)) # enable_pretty_logging() # enable this for debugging during development http_server = HTTPServer(WSGIContainer(app)) http_server.listen(port) IOLoop.instance().start() # TODO : support more wsgi server setup : http://www.markjberger.com/flask-with-virtualenv-uwsgi-nginx/ break except socket.error as msg: port_retries -= 1 port += 1 app.logger.error('Socket Error : {0}'.format(msg))
def run(self, result=None): # argv is rosargs but these have no effect on client, so no need to pass anything here with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True) as node_ctx: self.node_ctx = node_ctx set_pyros_client(self.node_ctx.client) super(TestAppPyros, self).run(result)
def setUp(self): super(TestAppPyros, self).setUp() set_pyros_client(self.app, self.node_ctx.client)