From ca2e0e88a6e8e767b2d18a9c167830cf3cf5ce44 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sat, 13 Jul 2024 20:57:25 -0500 Subject: [PATCH 1/5] docs: add link to test coverage report --- docs/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index b012584..8a7bc0a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,6 +6,11 @@ This package provides a "web layer" for custom apps. It uses traditional server-side rendering with VueJS on the front-end. +Good documentation and 100% `test coverage`_ are priorities for this +project. + +.. _test coverage: https://buildbot.rattailproject.org/coverage/wuttaweb/ + .. toctree:: :maxdepth: 3 :caption: Contents: From 9c5320a31cb4e8812573bafbbd5e343f513d910b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 14 Jul 2024 08:47:34 -0500 Subject: [PATCH 2/5] docs: update project urls to wuttaproject.org --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a623b4c..7a59448 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,9 +53,9 @@ wuttaweb = "wuttaweb.app:WebAppProvider" [project.urls] -Homepage = "https://rattailproject.org/" -Repository = "https://kallithea.rattailproject.org/rattail-project/wuttaweb" -Changelog = "https://kallithea.rattailproject.org/rattail-project/wuttaweb/files/master/CHANGELOG.md" +Homepage = "https://wuttaproject.org/" +Repository = "https://forgejo.wuttaproject.org/wutta/wuttaweb" +Changelog = "https://forgejo.wuttaproject.org/wutta/wuttaweb/src/branch/master/CHANGELOG.md" [tool.commitizen] From 1d113da45aa4f3a8f70a4551f02f835b30da2f6c Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 14 Jul 2024 10:47:14 -0500 Subject: [PATCH 3/5] feat: add "web handler" feature; it must get the menu handler this makes more sense than (potentially) adding a whole bunch of methods to the app handler. also fix entry point for app provider, per wj changes --- docs/api/wuttaweb/handler.rst | 6 ++++ docs/api/wuttaweb/index.rst | 1 + pyproject.toml | 4 +-- src/wuttaweb/app.py | 24 +++++++-------- src/wuttaweb/handler.py | 57 +++++++++++++++++++++++++++++++++++ src/wuttaweb/menus.py | 12 +++++++- src/wuttaweb/subscribers.py | 7 ++++- tests/test_handler.py | 20 ++++++++++++ tests/test_menus.py | 6 ++++ 9 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 docs/api/wuttaweb/handler.rst create mode 100644 src/wuttaweb/handler.py create mode 100644 tests/test_handler.py diff --git a/docs/api/wuttaweb/handler.rst b/docs/api/wuttaweb/handler.rst new file mode 100644 index 0000000..0209473 --- /dev/null +++ b/docs/api/wuttaweb/handler.rst @@ -0,0 +1,6 @@ + +``wuttaweb.handler`` +==================== + +.. automodule:: wuttaweb.handler + :members: diff --git a/docs/api/wuttaweb/index.rst b/docs/api/wuttaweb/index.rst index 673a6df..2e49d4b 100644 --- a/docs/api/wuttaweb/index.rst +++ b/docs/api/wuttaweb/index.rst @@ -8,6 +8,7 @@ :maxdepth: 1 app + handler helpers menus static diff --git a/pyproject.toml b/pyproject.toml index 7a59448..673e0e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ dependencies = [ "pyramid_mako", "waitress", "WebHelpers2", - "WuttJamaican[db]>=0.6.1", + "WuttJamaican[db]>=0.7.0", ] @@ -48,7 +48,7 @@ tests = ["pytest-cov", "tox"] main = "wuttaweb.app:main" -[project.entry-points."wutta.providers"] +[project.entry-points."wutta.app.providers"] wuttaweb = "wuttaweb.app:WebAppProvider" diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index ff9d37f..18b07fb 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -34,28 +34,28 @@ from pyramid.config import Configurator class WebAppProvider(AppProvider): """ - The :term:`app provider` for WuttaWeb. This adds - some methods to get web-specific :term:`handlers`. + The :term:`app provider` for WuttaWeb. This adds some methods + specific to web apps. """ - def get_web_menu_handler(self, **kwargs): + def get_web_handler(self, **kwargs): """ - Get the configured "menu" handler for the web app. + Get the configured "web" handler for the app. Specify a custom handler in your config file like this: .. code-block:: ini - [wuttaweb] - menus.handler_spec = poser.web.menus:PoserMenuHandler + [wutta] + web.handler_spec = poser.web.handler:PoserWebHandler - :returns: Instance of :class:`~wuttaweb.menus.MenuHandler`. + :returns: Instance of :class:`~wuttaweb.handler.WebHandler`. """ - if 'web_menu_handler' not in self.__dict__: - spec = self.config.get('wuttaweb.menus.handler_spec', - default='wuttaweb.menus:MenuHandler') - self.web_menu_handler = self.app.load_object(spec)(self.config) - return self.web_menu_handler + if 'web_handler' not in self.__dict__: + spec = self.config.get(f'{self.appname}.web.handler_spec', + default='wuttaweb.handler:WebHandler') + self.web_handler = self.app.load_object(spec)(self.config) + return self.web_handler def make_wutta_config(settings): diff --git a/src/wuttaweb/handler.py b/src/wuttaweb/handler.py new file mode 100644 index 0000000..d0fa704 --- /dev/null +++ b/src/wuttaweb/handler.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# wuttaweb -- Web App for Wutta Framework +# Copyright © 2024 Lance Edgar +# +# This file is part of Wutta Framework. +# +# Wutta Framework is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Wutta Framework 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 General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# Wutta Framework. If not, see . +# +################################################################################ +""" +Web Handler + +This defines the :term:`handler` for the web layer. +""" + +from wuttjamaican.app import GenericHandler + + +class WebHandler(GenericHandler): + """ + Base class and default implementation for the "web" :term:`handler`. + + This is responsible for determining the "menu handler" and + (eventually) possibly other things. + """ + + def get_menu_handler(self, **kwargs): + """ + Get the configured "menu" handler for the web app. + + Specify a custom handler in your config file like this: + + .. code-block:: ini + + [wutta.web] + menus.handler_spec = poser.web.menus:PoserMenuHandler + + :returns: Instance of :class:`~wuttaweb.menus.MenuHandler`. + """ + if not hasattr(self, 'menu_handler'): + spec = self.config.get(f'{self.appname}.web.menus.handler_spec', + default='wuttaweb.menus:MenuHandler') + self.menu_handler = self.app.load_object(spec)(self.config) + return self.menu_handler diff --git a/src/wuttaweb/menus.py b/src/wuttaweb/menus.py index 37625a5..c0e7ae1 100644 --- a/src/wuttaweb/menus.py +++ b/src/wuttaweb/menus.py @@ -138,7 +138,7 @@ class MenuHandler(GenericHandler): The web app calls this method but you normally should not need to override it; you can override :meth:`make_menus()` instead. """ - raw_menus = self.make_menus(request, **kwargs) + raw_menus = self._make_raw_menus(request, **kwargs) # now we have "simple" (raw) menus definition, but must refine # that somewhat to produce our final menus @@ -209,6 +209,16 @@ class MenuHandler(GenericHandler): return final_menus + def _make_raw_menus(self, request, **kwargs): + """ + Construct the initial full set of "raw" menus. + + For now this just calls :meth:`make_menus()` which generally + means a "hard-coded" menu set. Eventually it may allow for + loading dynamic menus from config instead. + """ + return self.make_menus(request, **kwargs) + def _is_allowed(self, request, item): """ Logic to determine if a given menu item is "allowed" for diff --git a/src/wuttaweb/subscribers.py b/src/wuttaweb/subscribers.py index 860942f..314922b 100644 --- a/src/wuttaweb/subscribers.py +++ b/src/wuttaweb/subscribers.py @@ -36,12 +36,16 @@ hooks contained here, depending on the circumstance. """ import json +import logging from pyramid import threadlocal from wuttaweb import helpers +log = logging.getLogger(__name__) + + def new_request(event): """ Event hook called when processing a new request. @@ -129,6 +133,7 @@ def before_render(event): request = event.get('request') or threadlocal.get_current_request() config = request.wutta_config app = config.get_app() + web = app.get_web_handler() context = event context['app'] = app @@ -137,7 +142,7 @@ def before_render(event): context['url'] = request.route_url context['json'] = json - menus = app.get_web_menu_handler() + menus = web.get_menu_handler() context['menus'] = menus.do_make_menus(request) diff --git a/tests/test_handler.py b/tests/test_handler.py new file mode 100644 index 0000000..79a0a64 --- /dev/null +++ b/tests/test_handler.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8; -*- + +from unittest import TestCase + +from wuttjamaican.conf import WuttaConfig + +from wuttaweb import handler as mod +from wuttaweb.menus import MenuHandler + + +class TestWebHandler(TestCase): + + def setUp(self): + self.config = WuttaConfig() + self.app = self.config.get_app() + self.handler = mod.WebHandler(self.config) + + def test_menu_handler_default(self): + menus = self.handler.get_menu_handler() + self.assertIsInstance(menus, MenuHandler) diff --git a/tests/test_menus.py b/tests/test_menus.py index 68cec31..27d45b9 100644 --- a/tests/test_menus.py +++ b/tests/test_menus.py @@ -159,6 +159,12 @@ class TestMenuHandler(TestCase): self.assertTrue(entry['is_sep']) self.assertFalse(entry['is_menu']) + def test_make_raw_menus(self): + # minimal test to ensure it calls the other method + with patch.object(self.handler, 'make_menus') as make_menus: + self.handler._make_raw_menus(self.request, foo='bar') + make_menus.assert_called_once_with(self.request, foo='bar') + def test_do_make_menus_prune_unallowed_item(self): test_menus = [ { From 5197fa9ae92dcf31cb98052d779ff9931dc64bef Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 14 Jul 2024 11:09:15 -0500 Subject: [PATCH 4/5] =?UTF-8?q?bump:=20version=200.1.0=20=E2=86=92=200.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f28bedf..ba15691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to wuttaweb will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## v0.2.0 (2024-07-14) + +### Feat + +- add basic support for menu handler + +- add "web handler" feature; it must get the menu handler + ## v0.1.0 (2024-07-12) ### Feat diff --git a/pyproject.toml b/pyproject.toml index 673e0e2..985bef5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "WuttaWeb" -version = "0.1.0" +version = "0.2.0" description = "Web App for Wutta Framework" readme = "README.md" authors = [{name = "Lance Edgar", email = "lance@edbob.org"}] From 8ae140555a4b1e6d5fbadfefbef1e9bc009278c0 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 14 Jul 2024 11:10:54 -0500 Subject: [PATCH 5/5] build: just run pytest, avoid tox when building release --- tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index b6084de..4635a82 100644 --- a/tasks.py +++ b/tasks.py @@ -15,7 +15,7 @@ def release(c, skip_tests=False): Release a new version of WuttJamaican """ if not skip_tests: - c.run('tox') + c.run('pytest') # rebuild pkg if os.path.exists('dist'):