Move acting on pgwui.routes setting from PGWUI_Server
authorKarl O. Pinc <kop@karlpinc.com>
Wed, 2 Dec 2020 03:22:57 +0000 (21:22 -0600)
committerKarl O. Pinc <kop@karlpinc.com>
Wed, 2 Dec 2020 03:22:57 +0000 (21:22 -0600)
README.rst
src/pgwui_common/exceptions.py
src/pgwui_common/routes.py [new file with mode: 0644]
tests/test_routes.py [new file with mode: 0644]

index 03b24060e85c8871f739eecd1bd2598d92e6c6e3..eff18f6f3aad1c5a93b47470f53311cfc606da50 100644 (file)
@@ -29,8 +29,8 @@ Short Documentation
 
 PGWUI_Common stands for `PostgreSQL`_ Web User Interface, Common files.
 
-Shared files used by the web interfaces which are a part of the PGWUI
-package suite.
+Shared files and functionality used by the web interfaces which are a
+part of the PGWUI package suite.
 
 The PGWUI package suite is a Python framework for creating
 `PostgreSQL`_ web user interfaces, and a collection of user interfaces
@@ -46,6 +46,9 @@ PGWUI_Common provides:
     database and credentials.  These forms are rendered using
     `Pyramid`_ views.
 
+  * Code used to establish `routes`_, called by PGWUI_Server
+    or whatever else is used to configure `Pyramid`_.
+
 The official PGWUI components based on PGWUI_Common are highly
 configurable.  The web page templates used to generate HTML files, the
 CSS files, the static HTML files, and the location of the web pages
@@ -137,6 +140,14 @@ Override API.  See:
 <https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/assets.html#overriding-assets>`_
 
 
+Establishing Routes
+^^^^^^^^^^^^^^^^^^^
+
+To establish `Pyramid`_ `routes`_ to the installed PGWUI components,
+after all components are configured, `pgwui_common.routes.add_routes()`
+must be called.
+
+
 Development Status
 ------------------
 
@@ -177,3 +188,4 @@ provided by `The Dian Fossey Gorilla Fund
 .. _PostgreSQL: https://www.postgresql.org/
 .. _Pyramid: https://trypyramid.com/
 .. _Pyramid's: `Pyramid`_
+.. _routes: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html
index 02122f0fb0d90e6f908a0cd3577af86c90c2aebd..b91e9c9a5e6ff409ec2decf01779a5228e7279dc 100644 (file)
@@ -32,6 +32,19 @@ class Error(core_ex.PGWUIError):
     pass
 
 
+class Info(core_ex.PGWUIError):
+    '''Informational exceptions
+    '''
+    pass
+
+
+class MenuPageInRoutes(Info):
+    def __init__(self):
+        super().__init__(
+            'The pgwui_menu in the pgwui.routes setting is ignored '
+            'and the pgwui.menu_page setting used instead')
+
+
 class UnknownSettingKeyError(Error):
     def __init__(self, key):
         super().__init__('Unknown PGWUI setting: {}'.format(key))
diff --git a/src/pgwui_common/routes.py b/src/pgwui_common/routes.py
new file mode 100644 (file)
index 0000000..f9db695
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (C) 2018, 2020 The Meme Factory, Inc.  http://www.karlpinc.com/
+
+# This file is part of PGWUI_Common.
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+# Karl O. Pinc <kop@karlpinc.com>
+
+'''Configure routing
+'''
+
+import logging
+import pgwui_common.exceptions as ex
+
+log = logging.getLogger(__name__)
+
+
+def add_routes(config, settings):
+    '''Add routes found in pgwui.routes setting
+
+    Because settings established with Pyramid's Configurator.include()
+    can be overridden by the caller, whatever configures PGWUI should
+    call add_routes() after configuring all PGWUI components.
+    '''
+    pgwui_settings = settings['pgwui']
+    if 'routes' in pgwui_settings:
+        have_menu_page = 'menu_page' in pgwui_settings
+        for name, route in pgwui_settings['routes'].items():
+            if have_menu_page and name == 'pgwui_menu':
+                log.info(ex.MenuPageInRoutes())
+            else:
+                config.add_route(name, route)
diff --git a/tests/test_routes.py b/tests/test_routes.py
new file mode 100644 (file)
index 0000000..d652688
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (C) 2018, 2019, 2020 The Meme Factory, Inc.
+# http://www.karlpinc.com/
+
+# This file is part of PGWUI_Common.
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+# Karl O. Pinc <kop@karlpinc.com>
+
+import pytest
+from pgwui_testing import testing
+
+import logging
+import pyramid.testing
+import pgwui_common.routes as routes
+
+mock_add_route = testing.instance_method_mock_fixture('add_route')
+
+
+# add_routes()
+
+@pytest.mark.unittest
+def test_add_routes_empty(mock_add_route):
+    '''When there is no pgwui.routes setting nothing gets added'''
+    with pyramid.testing.testConfig() as config:
+        mocked_add_route = mock_add_route(config)
+        routes.add_routes(config, {'pgwui': {}})
+
+    assert not mocked_add_route.called
+
+
+@pytest.mark.unittest
+def test_add_routes_notempty(mock_add_route):
+    '''When there is a pgwui.routes setting config.add_route() is called
+    for each route'''
+    test_routes = {'name1': 'route1',
+                   'name2': 'route2'}
+    with pyramid.testing.testConfig() as config:
+        mocked_add_route = mock_add_route(config)
+        routes.add_routes(config, {'pgwui': {'routes': test_routes}})
+
+    assert mocked_add_route.call_count == len(test_routes)
+
+
+@pytest.mark.unittest
+def test_add_routes_menu(mock_add_route, caplog):
+    '''When there is a a route for pgwui_menu, but there is a menu_page
+    setting, no route is added and an INFO message is logged
+    '''
+    caplog.set_level(logging.DEBUG)
+
+    test_routes = {'pgwui_menu': None, 'notused': None}
+    with pyramid.testing.testConfig() as config:
+        mocked_add_route = mock_add_route(config)
+        routes.add_routes(config, {'pgwui': {'routes': test_routes,
+                                             'menu_page': 'anything'}})
+
+    mocked_add_route.assert_called_once()
+
+    logs = caplog.record_tuples
+    assert len(logs) == 1
+    assert logs[0][1] == logging.INFO