webapp: have an AppMaker object to ease customisation

It turns out people may want to extend api points etc.
Providing extension hooks using a class will make that approchable.

The tswatch package is now provided by refinery_pro.
M conftest.py +3 -4
@@ 80,13 80,12 @@ class NonSuckingWebTester(webtest.TestAp
 def client(engine):
     return NonSuckingWebTester(
         nosecurity(
-            webapp.make_app(
+            webapp.AppMaker(
                 str(engine.url),
                 sources={
                     'remote': (f'{engine.url}', 'remote')
-                },
-                httpapi=webapp.httpapi
-            )
+                }
+            ).app()
         )
     )
 

          
M test/test_webapi.py +0 -30
@@ 1,5 1,4 @@ 
 import io
-import json
 from pathlib import Path
 
 import pandas as pd

          
@@ 485,32 484,3 @@ def test_edit_policy(client, engine):
          }
     ]
 
-
-# stores
-
-def test_basic_kvstore(client, engine):
-    res = client.get('/api/kvstore/keys', params={'namespace': 'tswatch'})
-    assert res.json == [
-        'catalog-models',
-        'catalog-scrapers',
-        'namespaces'
-    ]
-
-    res = client.get('/api/kvstore/keys', params={'namespace': 'dashboards'})
-    assert res.json == []
-
-    res = client.get('/api/kvstore/keys', params={'namespace': 'balances'})
-    assert res.json == []
-
-    res = client.put(
-        '/api/kvstore/item',
-        params={
-            'namespace': 'tswatch',
-            'key': 'test',
-            'value': json.dumps('Hello')
-        }
-    )
-    assert res.status_code == 204
-
-    res = client.get('/api/kvstore/all', params={'namespace': 'tswatch'})
-    assert res.json['test'] == 'Hello'

          
M tshistory_refinery/blueprint.py +0 -1
@@ 91,7 91,6 @@ def refinery_bp(tsa, more_sections=None)
             },
             'Monitoring': {
                 'Tasks': url_for('reworkui.home'),
-                'Series': url_for('tswatch.watchseries')
             }
         }
 

          
M tshistory_refinery/migrate.py +0 -3
@@ 16,6 16,3 @@ class Migrator(_Migrator):
         print('initial migration')
         migrate_metadata(self.engine, f'{self.namespace}-cache', self.interactive)
         fix_user_metadata(self.engine, f'{self.namespace}-cache', self.interactive)
-
-        from tswatch.utils import tswatch_init
-        tswatch_init(self.engine, drop=False)

          
M tshistory_refinery/schema.py +1 -3
@@ 8,7 8,6 @@ from rework_ui.schema import init as rew
 from tshistory.schema import tsschema
 from tshistory_supervision.schema import supervision_schema
 from tshistory_formula.schema import formula_schema
-from tswatch.utils import tswatch_init
 
 
 CACHE_POLICY = Path(__file__).parent / 'schema.sql'

          
@@ 23,11 22,10 @@ class refinery_schema(supervision_schema
             rework_init(engine, drop=reset)
             rework_ui_init(engine)
 
-        for store_ns in ('tswatch', 'dashboards', 'balances'):
+        for store_ns in ('dashboards', 'balances'):
             stores_schema.init(engine, ns=store_ns, drop=reset)
 
         with engine.begin() as cn:
             cn.execute(sqlfile(CACHE_POLICY, ns=self.namespace))
 
         tsschema(f'{self.namespace}-cache').create(engine)
-        tswatch_init(engine, drop=True)

          
M tshistory_refinery/webapp.py +65 -65
@@ 11,7 11,6 @@ from rework_ui.blueprint import reworkui
 
 from tshistory.api import timeseries
 from tshistory_xl.blueprint import blueprint as excel
-from tswatch.webapp import make_blueprint as tswatch
 
 from tshistory_refinery import http, blueprint
 

          
@@ 34,76 33,77 @@ class httpapi(http.refinery_httpapi,
         )
 
 
-def make_app(dburi=None, sources=None, httpapi=None, more_sections=None):
-    if dburi:
-        # that will typically for the tests
-        # or someone doing something fancy
-        tsa = timeseries(dburi, sources=sources)
-    else:
-        # this will take everything from `tshistory.cfg`
-        tsa = timeseries()
-        dburi = str(tsa.engine.url)
+class AppMaker:
 
-    app = Flask('refinery')
-    engine = create_engine(dburi)
+    def __init__(self, dburi=None, sources=None, more_sections=None):
+        if dburi:
+            # that will typically for the tests
+            # or someone doing something fancy
+            self.tsa = timeseries(dburi, sources=sources)
+        else:
+            # this will take everything from `tshistory.cfg`
+            self.tsa = timeseries()
+            dburi = str(self.tsa.engine.url)
 
-    # tsview
-    app.register_blueprint(
-        tsview(tsa)
-    )
+        self.dburi = dburi
+        self.sources = sources
+        self.more_sections = more_sections
+        self.engine = create_engine(dburi)
 
-    # rework-ui
-    app.register_blueprint(
-        reworkui(engine),
-        url_prefix='/tasks'
-    )
-
-    # history (tsview)
-    historic(
-        app,
-        tsa,
-        request_pathname_prefix='/'
-    )
+    def app(self):
+        app = Flask('refinery')
+        self.tsview(app)
+        self.reworkui(app)
+        self.excel(app)
+        self.api(app)
+        self.refinery(app)
+        return app
 
-    # editor (tsview)
-    editor(
-        app,
-        tsa,
-        request_pathname_prefix='/'
-    )
+    def tsview(self, app):
+        app.register_blueprint(
+            tsview(self.tsa)
+        )
+        historic(
+            app,
+            self.tsa,
+            request_pathname_prefix='/'
+        )
+        editor(
+            app,
+            self.tsa,
+            request_pathname_prefix='/'
+        )
 
-    # tswatch
-    app.register_blueprint(
-        tswatch(tsa),
-        url_prefix='/tswatch',
-    )
-
-    # excel
-    app.register_blueprint(
-        excel(tsa)
-    )
+    def reworkui(self, app):
+        app.register_blueprint(
+            reworkui(self.engine),
+            url_prefix='/tasks'
+        )
 
-    # refinery api
-    app.register_blueprint(
-        httpapi(
-            tsa,
-            dburi,
-            {
-                'tswatch': kvstore(dburi, 'tswatch'),
-                'dashboards': kvstore(dburi, 'dashboards'),
-                'balances': kvstore(dburi, 'balances')
-             },
-            {}  # no vkvstore yet
-        ).bp,
-        url_prefix='/api'
-    )
+    def excel(self, app):
+        app.register_blueprint(
+            excel(self.tsa)
+        )
 
-    # refinery web ui
-    app.register_blueprint(
-        blueprint.refinery_bp(
-            tsa,
-            more_sections=more_sections
+    def api(self, app):
+        # refinery api
+        app.register_blueprint(
+            httpapi(
+                self.tsa,
+                self.dburi,
+                {
+                    'dashboards': kvstore(self.dburi, 'dashboards'),
+                    'balances': kvstore(self.dburi, 'balances')
+                 },
+                {}  # no vkvstore yet
+            ).bp,
+            url_prefix='/api'
         )
-    )
 
-    return app
+    def refinery(self, app):
+        app.register_blueprint(
+            blueprint.refinery_bp(
+                self.tsa,
+                more_sections=self.more_sections
+            )
+        )

          
M tshistory_refinery/wsgi.py +3 -5
@@ 1,9 1,7 @@ 
 from tshistory.http.util import nosecurity
 
-from tshistory_refinery.webapp import (
-    httpapi,
-    make_app
-)
+from tshistory_refinery.webapp import AppMaker
+
 
-app = make_app(httpapi=httpapi)
+app = AppMaker().app()
 app.wsgi_app = nosecurity(app.wsgi_app)