Ckan: Run the development server using Werkzeug

Created on 12 Jun 2018  路  4Comments  路  Source: ckan/ckan

As we transition to Flask, besides migrating the controllers we need to start picking up other tools from its ecosystem. As it surfaced in #4257 in order to get the debugger pages working on requests served by Flask we will need to switch from the Paster development server (paster serve) to a Werkzeug-based one. This will enable the debugger on Flask requests (and is probably more performant that the Paster server).

To keep things simple and maintain a syntax close to the current one I propose adding a new paster command. At its simplest form (run from the ckan folder) it should look like:

paster devserver

Additional options could mimic as close as possible the current paster serve ones. The Paster serve command requires the path to config file as a positional parameter, we could probably implement that as well on the new command, but my preference is to align it to use the -c option that all other paster commands use.

Just to be clear the paster serve command is not going anywhere so any existing scripts will work, but it should be deprecated and documentation, CI, etc updated to reflect the new command.

The following was enough to get it working, enabling the debugger on Flask requests (the Pylons debugger still works when running under Werkzeug):

diff --git a/ckan/config/middleware/flask_app.py b/ckan/config/middleware/flask_app.py
index 1f9fa22..b6631cd 100644
--- a/ckan/config/middleware/flask_app.py
+++ b/ckan/config/middleware/flask_app.py
@@ -103,6 +103,10 @@ def make_flask_stack(conf, **app_conf):
         app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
         DebugToolbarExtension(app)

+        from werkzeug.debug import DebuggedApplication
+        app = DebuggedApplication(app, True)
+        app = app.app
+
     # Use Beaker as the Flask session interface
     class BeakerSessionInterface(SessionInterface):
         def open_session(self, app, request):
diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py
index c487b49..84155f1 100644
--- a/ckan/lib/cli.py
+++ b/ckan/lib/cli.py
@@ -330,6 +330,36 @@ class CkanCommand(paste.script.command.Command):
         self.site_user = load_config(self.options.config, load_site_user)


+class DevServerCommand(CkanCommand):
+    '''
+    Starts the development server
+
+    TODO: xx
+    '''
+
+    summary = __doc__.split('\n')[0]
+    usage = __doc__
+
+    # TODO: Options for debug , reload, port et al
+
+    def command(self):
+        self.serve()
+
+    def serve(self):
+        from werkzeug.serving import run_simple
+
+        conf = _get_config()
+
+        from ckan.config.environment import load_environment
+        load_environment(conf.global_conf, conf.local_conf)
+        app = make_app(conf.global_conf, **conf.local_conf)
+
+        # TODO: options
+        run_simple(
+            'localhost', 5000, app,
+            use_reloader=True, use_debugger=True, use_evalex=True)
+
+
 class ManageDb(CkanCommand):
     '''Perform various tasks on the database.

diff --git a/setup.py b/setup.py
index 4cc330e..2c54e5f 100644
--- a/setup.py
+++ b/setup.py
@@ -75,6 +75,7 @@ entry_points = {
         'views = ckan.lib.cli:ViewsCommand',
         'config-tool = ckan.lib.cli:ConfigToolCommand',
         'jobs = ckan.lib.cli:JobsCommand',
+        'devserver = ckan.lib.cli:DevServerCommand',
     ],
     'console_scripts': [
         'ckan-admin = bin.ckan_admin:Command',

Flask migration

Most helpful comment

Rather than using a paster command, use a new ckan serve command that we can keep going forward.

The ckan command will be fully based in click like the command mentioned by @wardi above.

This is for another issue, but perhaps we can find a way to fully wrap the current paster commands maintaining the syntax until we rewrite them to be click based.

paster db init

ckan db init

Probably not very useful, but the CKAN debian packages include a ckan command that is just a wrapper around paster.

All 4 comments

instead of inheriting from CkanCommand consider using the new cli.load_config() function and click for parsing args (like datastore's cli does now)

Rather than using a paster command, use a new ckan serve command that we can keep going forward.

The ckan command will be fully based in click like the command mentioned by @wardi above.

This is for another issue, but perhaps we can find a way to fully wrap the current paster commands maintaining the syntax until we rewrite them to be click based.

paster db init

ckan db init

Probably not very useful, but the CKAN debian packages include a ckan command that is just a wrapper around paster.

A minor related feature request too, before I forget.

One thing that frustrates me when using the dev server, is that I, without exception, always forget to update ckan_url whilst I'm debugging. Might it be possible for ckan serve to update the port number in ckan_url?

Does the solution for this issue help debugging Flask pages when using Apache httpd? I am asking to be clear, because my understanding is that it does not.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amercader picture amercader  路  4Comments

yagi815 picture yagi815  路  7Comments

joetsoi picture joetsoi  路  8Comments

TkTech picture TkTech  路  4Comments

juleskers picture juleskers  路  4Comments