def test_help_doc_generated(self): app_svc = mock.MagicMock() route_svc = RouteService(app_svc, debug=False) routes = [("/route0", TestHandler), ("/route1", TestHandler)] route_svc.set_routes(routes) base_url = "http://self" help = route_svc.get_help(base_url).get("doc") self.assertEqual(len(help), len(routes)) for index, entry in enumerate(help): self.assertEqual(help[index]["route"], "{base_url}/route{index}".format(base_url=base_url, index=index)) methods = entry["methods"] self.assertEqual(len(methods), 2) actual = set([(key, value.split(":")[0] == "True") for key, value in methods.items()]) expected = set([("get", True), ("delete", True)]) self.assertEqual(actual, expected)
def __init__(self, config_svc, debug, port, logger=None): """Sets up the admin service and configures logging""" self.config_svc = config_svc self.route_svc = RouteService(self, debug) self._debug = debug if not port or (not type(port) is int): raise InvalidPortError("Invalid port: '{port}'".format(port=port)) self._port = port # Initialize the logger configuration: self._logger_config = config_svc.get_logger_config() logging.config.dictConfig(self._logger_config) self._logger = logger or logging.getLogger(__name__) self._logger.info("Logger initialized by AppService") self._tornado = None
def __init__(self, config_svc, debug, port, logger=None): """Sets up the admin service and configures logging""" self.config_svc = config_svc self.route_svc = RouteService(self, debug) self._debug = debug try: self._port = int(port) except ValueError: raise InvalidPortError("Invalid port: '{port}'. Could not be cast to int.".format(port=port)) # Initialize the logger configuration: self._logger_config = config_svc.get_logger_config() logging.config.dictConfig(self._logger_config) self._logger = logger or logging.getLogger(__name__) self._logger.info("Logger initialized by AppService") self._tornado = None
def test_help_doc_generated(self): app_svc = mock.MagicMock() route_svc = RouteService(app_svc, debug=False) routes = [("/route0", TestHandler), ("/route1", TestHandler)] route_svc.set_routes(routes) base_url = "http://self" help = route_svc.get_help(base_url) self.assertEqual(len(help), len(routes)) for index, entry in enumerate(help): self.assertEqual( help[index]["route"], "{base_url}/route{index}".format(base_url=base_url, index=index)) methods = entry["methods"] self.assertEqual(len(methods), 2) actual = set([(key, value.split(':')[0] == "True") for key, value in methods.items()]) expected = set([("get", True), ("delete", True)]) self.assertEqual(actual, expected)
class AppService: """ Core functionality for the application. Automatically sets up logging, given a config_svc that serves a logging config Usage example: def start(): # The following sets up a default AppService, reading # default arguments from the command line, in particular # --port and --product: app_svc = AppService.create() # The service is now set up to read config files from: # - /opt/product_name/etc/app.config # - /opt/product_name/etc/logger.config # Now set up Tornado routes args = dict(service1=Service1(), service2=Service2()) routes = [ (r"/api/1.0/endpoint1", Handler1, args), (r"/api/1.0/endpoint2", Handler2, args) ] # Now start the service. # The port will come from the command line argument --port app_svc.start(routes) """ def __init__(self, config_svc, debug, port, logger=None): """Sets up the admin service and configures logging""" self.config_svc = config_svc self.route_svc = RouteService(self, debug) self._debug = debug try: self._port = int(port) except ValueError: raise InvalidPortError( "Invalid port: '{port}'. Could not be cast to int.".format( port=port)) # Initialize the logger configuration: self._logger_config = config_svc.get_logger_config() logging.config.dictConfig(self._logger_config) self._logger = logger or logging.getLogger(__name__) self._logger.info("Logger initialized by AppService") self._tornado = None @staticmethod def create(product_name=None): """ Creates the default app service based on arguments sent from the command line and related services with defaults based on the product_name. If the product_name is specified via the command line, it will override the argument. Command line usage: <program> --port <port> [--product <product name>] [--debug] [--configroot path] These config files should be accessible: - /etc/arteria/<product_name>/app.config - /etc/arteria/<product_name>/logger.config You can override this by supplying config_root, in which case they should be found at <config_root>/*.config :param product_name: Should by convention be __package__. This value can be overriden by supplying the --product parameter on the command line. """ parser = OptionParser() parser.add_option("--product", dest="product", metavar="PRODUCT") parser.add_option("--port", dest="port", metavar="PORT") parser.add_option("--debug", dest="debug", action="store_true", default=False) parser.add_option("--configroot", dest="configroot", metavar="CONFIGROOT") (options, args) = parser.parse_args() if options.product: product_name = options.product if not options.port: parser.error("You have to specify a port.") if not product_name: raise ProductNameError( "No product name was supplied via the command line or as an argument to create" ) config_root = options.configroot or os.path.join( "/etc", "arteria", product_name) logger_config_path = os.path.join(config_root, "logger.config") app_config_path = os.path.join(config_root, "app.config") config_svc = ConfigurationService( logger_config_path=logger_config_path, app_config_path=app_config_path) app_svc = AppService(config_svc, options.debug, options.port) return app_svc def start(self, routes): # Add the default routes, such as the API handler routes.extend(self._get_default_routes()) self.route_svc.set_routes(routes) self._tornado = tornado.web.Application(self.route_svc.get_routes(), debug=self._debug) self._logger.info("Starting the service on {0} (debug={1})".format( self._port, self._debug)) self._tornado.listen(self._port) tornado.ioloop.IOLoop.current().start() def set_log_level(self, log_level): # TODO: Directly change via logging module if possible self._logger_config["handlers"]["file_handler"]["level"] = log_level logging.config.dictConfig(self._logger_config) def get_log_level(self): return self._logger_config["handlers"]["file_handler"]["level"] def _get_default_routes(self): """ Gets the default endpoints for a web service in the Arteria project """ return [(r"/api", ApiHelpHandler, dict(route_svc=self.route_svc)), (r"/api/1.0/admin/log_level", LogLevelHandler, dict(app_svc=self))]
class AppService: """ Core functionality for the application. Automatically sets up logging, given a config_svc that serves a logging config Usage example: def start(): # The following sets up a default AppService, reading # default arguments from the command line, in particular # --port and --product: app_svc = AppService.create() # The service is now set up to read config files from: # - /opt/product_name/etc/app.config # - /opt/product_name/etc/logger.config # Now set up Tornado routes args = dict(service1=Service1(), service2=Service2()) routes = [ (r"/api/1.0/endpoint1", Handler1, args), (r"/api/1.0/endpoint2", Handler2, args) ] # Now start the service. # The port will come from the command line argument --port app_svc.start(routes) """ def __init__(self, config_svc, debug, port, logger=None): """Sets up the admin service and configures logging""" self.config_svc = config_svc self.route_svc = RouteService(self, debug) self._debug = debug if not port or (not type(port) is int): raise InvalidPortError("Invalid port: '{port}'".format(port=port)) self._port = port # Initialize the logger configuration: self._logger_config = config_svc.get_logger_config() logging.config.dictConfig(self._logger_config) self._logger = logger or logging.getLogger(__name__) self._logger.info("Logger initialized by AppService") self._tornado = None @staticmethod def create(product_name=None): """ Creates the default app service based on arguments sent from the command line and related services with defaults based on the product_name. If the product_name is specified via the command line, it will override the argument. Command line usage: <program> --port <port> [--product <product name>] [--debug] [--configroot path] These config files should be accessible: - /opt/<product_name>/app.config - /opt/<product_name>/logger.config You can override this by supplying config_root, in which case they should be found at <config_root>/*.config :param product_name: Should by convention be __package__. This value can be overriden by supplying the --product parameter on the command line. """ parser = OptionParser() parser.add_option("--product", dest="product", metavar="PRODUCT") parser.add_option("--port", dest="port", metavar="PORT") parser.add_option("--debug", dest="debug", action="store_true", default=False) parser.add_option("--configroot", dest="configroot", metavar="CONFIGROOT") (options, args) = parser.parse_args() if options.product: product_name = options.product if not product_name: raise ProductNameError( "No product name was supplied via the command line or as an argument to create") config_root = options.configroot or os.path.join("/opt", product_name, "etc") logger_config_path = os.path.join(config_root, "logger.config") app_config_path = os.path.join(config_root, "app.config") config_svc = ConfigurationService(logger_config_path=logger_config_path, app_config_path=app_config_path) app_svc = AppService(config_svc, options.debug, int(options.port)) return app_svc def start(self, routes): # Add the default routes, such as the API handler routes.extend(self._get_default_routes()) self.route_svc.set_routes(routes) self._tornado = tornado.web.Application(self.route_svc.get_routes(), debug=self._debug) self._logger.info("Starting the service on {0} (debug={1})" .format(self._port, self._debug)) self._tornado.listen(self._port) tornado.ioloop.IOLoop.current().start() def set_log_level(self, log_level): # TODO: Directly change via logging module if possible self._logger_config["handlers"]["file_handler"]["level"] = log_level logging.config.dictConfig(self._logger_config) def get_log_level(self): return self._logger_config["handlers"]["file_handler"]["level"] def _get_default_routes(self): """ Gets the default endpoints for a web service in the Arteria project """ return [ (r"/api", ApiHelpHandler, dict(route_svc=self.route_svc)), (r"/api/1.0/admin/log_level", LogLevelHandler, dict(app_svc=self)) ]