|
28 | 28 | from flask.wrappers import Request, _missing, _get_data |
29 | 29 |
|
30 | 30 | from .utils import loads |
31 | | -from .frestq_app import FrestqApp, FrestqRequest |
| 31 | + |
| 32 | +logging.basicConfig(level=logging.DEBUG) |
| 33 | + |
| 34 | +class FrestqRequest(Request): |
| 35 | + ''' |
| 36 | + We have to customize request so that by default it can overload the json |
| 37 | + object_hook for json.loads() so that it auto-parses datetimes |
| 38 | + ''' |
| 39 | + |
| 40 | + def get_json(self, force=False, silent=False, cache=True): |
| 41 | + """Parses the incoming JSON request data and returns it. If |
| 42 | + parsing fails the :meth:`on_json_loading_failed` method on the |
| 43 | + request object will be invoked. By default this function will |
| 44 | + only load the json data if the mimetype is ``application/json`` |
| 45 | + but this can be overriden by the `force` parameter. |
| 46 | +
|
| 47 | + :param force: if set to `True` the mimetype is ignored. |
| 48 | + :param silent: if set to `False` this method will fail silently |
| 49 | + and return `False`. |
| 50 | + :param cache: if set to `True` the parsed JSON data is remembered |
| 51 | + on the request. |
| 52 | + """ |
| 53 | + rv = getattr(self, '_cached_json', _missing) |
| 54 | + if rv is not _missing: |
| 55 | + return rv |
| 56 | + |
| 57 | + if self.mimetype != 'application/json' and not force: |
| 58 | + return None |
| 59 | + |
| 60 | + # We accept a request charset against the specification as |
| 61 | + # certain clients have been using this in the past. This |
| 62 | + # fits our general approach of being nice in what we accept |
| 63 | + # and strict in what we send out. |
| 64 | + request_charset = self.mimetype_params.get('charset') |
| 65 | + try: |
| 66 | + data = _get_data(self, cache) |
| 67 | + if request_charset is not None: |
| 68 | + rv = loads(data, encoding=request_charset) |
| 69 | + else: |
| 70 | + rv = loads(data) |
| 71 | + except ValueError as e: |
| 72 | + if silent: |
| 73 | + rv = None |
| 74 | + else: |
| 75 | + rv = self.on_json_loading_failed(e) |
| 76 | + if cache: |
| 77 | + self._cached_json = rv |
| 78 | + return rv |
| 79 | + |
| 80 | +class FrestqApp(Flask): |
| 81 | + def __init__(self, *args, **kwargs): |
| 82 | + if 'parse_args' in kwargs: |
| 83 | + del kwargs['parse_args'] |
| 84 | + self.parse_args() |
| 85 | + super(FrestqApp, self).__init__(*args, **kwargs) |
| 86 | + |
| 87 | + request_class = FrestqRequest |
| 88 | + |
| 89 | + pargs = None |
| 90 | + |
| 91 | + def configure_app(self, config_object=None): |
| 92 | + ''' |
| 93 | + Configures the application. It's intended to do everything to be able to |
| 94 | + run the application except calling app.run, so that it can be reused when |
| 95 | + using gunicorn or similar. |
| 96 | + ''' |
| 97 | + self.config.from_object(__name__) |
| 98 | + if config_object: |
| 99 | + self.config.from_object(config_object) |
| 100 | + |
| 101 | + frestq_settings = os.environ.get('FRESTQ_SETTINGS', None) |
| 102 | + if frestq_settings is not None: |
| 103 | + if not os.path.isabs(frestq_settings): |
| 104 | + os.environ['FRESTQ_SETTINGS'] = os.path.abspath(frestq_settings) |
| 105 | + logging.debug("FRESTQ_SETTINGS = %s" % os.environ['FRESTQ_SETTINGS']) |
| 106 | + self.config.from_envvar('FRESTQ_SETTINGS', silent=False) |
| 107 | + else: |
| 108 | + logging.warning("FRESTQ_SETTINGS not set") |
| 109 | + |
| 110 | + # store cert in |
| 111 | + if self.config.get('SSL_CERT_PATH', None) and\ |
| 112 | + self.config.get('SSL_KEY_PATH', None): |
| 113 | + |
| 114 | + with open(self.config.get('SSL_CERT_PATH', ''), 'r') as f: |
| 115 | + self.config['SSL_CERT_STRING'] = f.read() |
| 116 | + else: |
| 117 | + self.config['SSL_CERT_STRING'] = '' |
| 118 | + logging.warning("You are NOT using SSL in this instance") |
| 119 | + |
| 120 | + if self.pargs.createdb or self.pargs.messages or self.pargs.tasks or\ |
| 121 | + self.pargs.tree or self.pargs.show_task or\ |
| 122 | + self.pargs.show_message or self.pargs.show_external or\ |
| 123 | + self.pargs.finish or self.pargs.show_activity: |
| 124 | + return |
| 125 | + |
| 126 | + logging.info("Launching with ROOT_URL = %s", self.config['ROOT_URL']) |
| 127 | + FScheduler.start_all_schedulers() |
| 128 | + |
| 129 | + def parse_args(self): |
| 130 | + parser = argparse.ArgumentParser() |
| 131 | + parser.add_argument("--createdb", help="create the database", |
| 132 | + action="store_true") |
| 133 | + parser.add_argument("--messages", help="list last messages", |
| 134 | + action="store_true") |
| 135 | + parser.add_argument("--tasks", help="list last tasks", |
| 136 | + action="store_true") |
| 137 | + parser.add_argument("--filters", nargs='+', |
| 138 | + help="filter items, with \"key=value\" ", default=[]) |
| 139 | + parser.add_argument("--tree", |
| 140 | + help="prints the tree of related tasks") |
| 141 | + parser.add_argument("--show-task", help="prints a task in detail") |
| 142 | + parser.add_argument("--console", help="frestq command line", |
| 143 | + action="store_true") |
| 144 | + parser.add_argument("--show-message", help="prints a task in detail") |
| 145 | + parser.add_argument("--show-external", help="prints an external task details") |
| 146 | + parser.add_argument("--show-activity", help="prints activity", |
| 147 | + action="store_true") |
| 148 | + parser.add_argument("--finish", help="finish an external task", |
| 149 | + nargs=2, default=None) |
| 150 | + parser.add_argument("--with-parents", |
| 151 | + help="show in the tree parent tasks too", |
| 152 | + action="store_true") |
| 153 | + parser.add_argument("-n", "--limit", help="limit number of results", |
| 154 | + type=int, default=20) |
| 155 | + parser.add_argument("-ll", "--log-level", default=None, |
| 156 | + help="show verbose output. set to ERROR by default", |
| 157 | + choices=["debug","info", "error"]) |
| 158 | + self.pargs = parser.parse_args() |
| 159 | + |
| 160 | + if self.pargs.limit < 1: |
| 161 | + print "limit must be >= 1" |
| 162 | + return |
| 163 | + |
| 164 | + if self.pargs.log_level != None: |
| 165 | + if self.pargs.log_level == "debug": |
| 166 | + logging.getLogger().setLevel(logging.DEBUG) |
| 167 | + elif self.pargs.log_level == "info": |
| 168 | + logging.getLogger().setLevel(logging.INFO) |
| 169 | + elif self.pargs.log_level == "error": |
| 170 | + logging.getLogger().setLevel(logging.ERROR) |
| 171 | + |
| 172 | + def run(self, *args, **kwargs): |
| 173 | + ''' |
| 174 | + Reimplemented the run function. |
| 175 | + ''' |
| 176 | + if self.pargs is not None: |
| 177 | + if self.pargs.createdb: |
| 178 | + print "creating the database: ", self.config.get('SQLALCHEMY_DATABASE_URI', '') |
| 179 | + db.create_all() |
| 180 | + return |
| 181 | + elif self.pargs.messages: |
| 182 | + list_messages(self.pargs) |
| 183 | + return |
| 184 | + elif self.pargs.tasks: |
| 185 | + list_tasks(self.pargs) |
| 186 | + return |
| 187 | + elif self.pargs.tree: |
| 188 | + task_tree(self.pargs) |
| 189 | + return |
| 190 | + elif self.pargs.show_task: |
| 191 | + show_task(self.pargs) |
| 192 | + return |
| 193 | + elif self.pargs.show_message: |
| 194 | + show_message(self.pargs) |
| 195 | + return |
| 196 | + elif self.pargs.show_external: |
| 197 | + show_external_task(self.pargs) |
| 198 | + elif self.pargs.finish: |
| 199 | + finish_task(self.pargs) |
| 200 | + return |
| 201 | + elif self.pargs.show_activity: |
| 202 | + show_activity(self.pargs) |
| 203 | + return |
| 204 | + elif self.pargs.console: |
| 205 | + import ipdb; ipdb.set_trace() |
| 206 | + return |
| 207 | + |
| 208 | + # ignore these threaded or use_reloader, we force those two |
| 209 | + if 'threaded' in kwargs: |
| 210 | + print "threaded provided but ignored (always set to True): ", kwargs['threaded'] |
| 211 | + del kwargs['threaded'] |
| 212 | + if 'use_reloader' in kwargs: |
| 213 | + print "use_reloader provided but ignored (always set to True): ", kwargs['use_reloader'] |
| 214 | + del kwargs['use_reloader'] |
| 215 | + |
| 216 | + if 'port' not in kwargs: |
| 217 | + kwargs['port'] = app.config.get('SERVER_PORT', None) |
| 218 | + |
| 219 | + return super(FrestqApp, self).run(threaded=True, use_reloader=False, |
| 220 | + *args, **kwargs) |
32 | 221 |
|
33 | 222 | app = FrestqApp(__name__, parse_args=True) |
34 | 223 |
|
|
0 commit comments