diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69b842c..90fc273 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,18 +5,6 @@ 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.4.0 (2024-08-05)
-
-### Feat
-
-- add basic App Info view (index only)
-- add initial `MasterView` support
-
-### Fix
-
-- add `notfound()` View method; auto-append trailing slash
-- bump min version for wuttjamaican
-
## v0.3.0 (2024-08-05)
### Feat
diff --git a/docs/api/wuttaweb/index.rst b/docs/api/wuttaweb/index.rst
index 5afd18b..204864e 100644
--- a/docs/api/wuttaweb/index.rst
+++ b/docs/api/wuttaweb/index.rst
@@ -23,5 +23,3 @@
views.base
views.common
views.essential
- views.master
- views.settings
diff --git a/docs/api/wuttaweb/views.master.rst b/docs/api/wuttaweb/views.master.rst
deleted file mode 100644
index a1e5d5b..0000000
--- a/docs/api/wuttaweb/views.master.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttaweb.views.master``
-=========================
-
-.. automodule:: wuttaweb.views.master
- :members:
diff --git a/docs/api/wuttaweb/views.settings.rst b/docs/api/wuttaweb/views.settings.rst
deleted file mode 100644
index 7923331..0000000
--- a/docs/api/wuttaweb/views.settings.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttaweb.views.settings``
-===========================
-
-.. automodule:: wuttaweb.views.settings
- :members:
diff --git a/pyproject.toml b/pyproject.toml
index 1708f3b..2c921be 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
[project]
name = "WuttaWeb"
-version = "0.4.0"
+version = "0.3.0"
description = "Web App for Wutta Framework"
readme = "README.md"
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
diff --git a/src/wuttaweb/menus.py b/src/wuttaweb/menus.py
index 0fe780d..c0e7ae1 100644
--- a/src/wuttaweb/menus.py
+++ b/src/wuttaweb/menus.py
@@ -118,9 +118,8 @@ class MenuHandler(GenericHandler):
'type': 'menu',
'items': [
{
- 'title': "App Info",
- 'route': 'appinfo',
- 'perm': 'appinfo.list',
+ 'title': "TODO!",
+ 'url': '#',
},
],
}
diff --git a/src/wuttaweb/subscribers.py b/src/wuttaweb/subscribers.py
index 92d40d9..63fe428 100644
--- a/src/wuttaweb/subscribers.py
+++ b/src/wuttaweb/subscribers.py
@@ -249,7 +249,6 @@ def before_render(event):
context['h'] = helpers
context['url'] = request.route_url
context['json'] = json
- context['b'] = 'o' if request.use_oruga else 'b' # for buefy
# TODO: this should be avoided somehow, for non-traditional web
# apps, esp. "API" web apps. (in the meantime can configure the
diff --git a/src/wuttaweb/templates/appinfo/index.mako b/src/wuttaweb/templates/appinfo/index.mako
deleted file mode 100644
index 7354514..0000000
--- a/src/wuttaweb/templates/appinfo/index.mako
+++ /dev/null
@@ -1,56 +0,0 @@
-## -*- coding: utf-8; -*-
-<%inherit file="/master/index.mako" />
-
-<%def name="page_content()">
-
-
-
-
-
-%def>
-
-<%def name="modify_this_page_vars()">
- ${parent.modify_this_page_vars()}
-
-%def>
-
-
-${parent.body()}
diff --git a/src/wuttaweb/templates/master/index.mako b/src/wuttaweb/templates/master/index.mako
deleted file mode 100644
index fd3d573..0000000
--- a/src/wuttaweb/templates/master/index.mako
+++ /dev/null
@@ -1,13 +0,0 @@
-## -*- coding: utf-8; -*-
-<%inherit file="/page.mako" />
-
-<%def name="title()">${index_title}%def>
-
-<%def name="content_title()">%def>
-
-<%def name="page_content()">
-
TODO: index page content
-%def>
-
-
-${parent.body()}
diff --git a/src/wuttaweb/views/__init__.py b/src/wuttaweb/views/__init__.py
index 845ff49..68fdd77 100644
--- a/src/wuttaweb/views/__init__.py
+++ b/src/wuttaweb/views/__init__.py
@@ -27,11 +27,9 @@ For convenience, from this ``wuttaweb.views`` namespace you can access
the following:
* :class:`~wuttaweb.views.base.View`
-* :class:`~wuttaweb.views.master.MasterView`
"""
from .base import View
-from .master import MasterView
def includeme(config):
diff --git a/src/wuttaweb/views/base.py b/src/wuttaweb/views/base.py
index 94e22b2..e412ed2 100644
--- a/src/wuttaweb/views/base.py
+++ b/src/wuttaweb/views/base.py
@@ -73,14 +73,6 @@ class View:
"""
return forms.Form(self.request, **kwargs)
- def notfound(self):
- """
- Convenience method, to raise a HTTP 404 Not Found exception::
-
- raise self.notfound()
- """
- return httpexceptions.HTTPNotFound()
-
def redirect(self, url, **kwargs):
"""
Convenience method to return a HTTP 302 response.
diff --git a/src/wuttaweb/views/common.py b/src/wuttaweb/views/common.py
index b5c108e..153bc5c 100644
--- a/src/wuttaweb/views/common.py
+++ b/src/wuttaweb/views/common.py
@@ -53,10 +53,7 @@ class CommonView(View):
@classmethod
def _defaults(cls, config):
- # auto-correct URLs which require trailing slash
- config.add_notfound_view(cls, attr='notfound', append_slash=True)
-
- # home page
+ # home
config.add_route('home', '/')
config.add_view(cls, attr='home',
route_name='home',
diff --git a/src/wuttaweb/views/essential.py b/src/wuttaweb/views/essential.py
index 0d4ec35..93c8149 100644
--- a/src/wuttaweb/views/essential.py
+++ b/src/wuttaweb/views/essential.py
@@ -39,7 +39,6 @@ def defaults(config, **kwargs):
config.include(mod('wuttaweb.views.auth'))
config.include(mod('wuttaweb.views.common'))
- config.include(mod('wuttaweb.views.settings'))
def includeme(config):
diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py
deleted file mode 100644
index 9ba1572..0000000
--- a/src/wuttaweb/views/master.py
+++ /dev/null
@@ -1,443 +0,0 @@
-# -*- 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 .
-#
-################################################################################
-"""
-Base Logic for Master Views
-"""
-
-from pyramid.renderers import render_to_response
-
-from wuttaweb.views import View
-
-
-class MasterView(View):
- """
- Base class for "master" views.
-
- Master views typically map to a table in a DB, though not always.
- They essentially are a set of CRUD views for a certain type of
- data record.
-
- Many attributes may be overridden in subclass. For instance to
- define :attr:`model_class`::
-
- from wuttaweb.views import MasterView
- from wuttjamaican.db.model import Person
-
- class MyPersonView(MasterView):
- model_class = Person
-
- def includeme(config):
- MyPersonView.defaults(config)
-
- .. note::
-
- Many of these attributes will only exist if they have been
- explicitly defined in a subclass. There are corresponding
- ``get_xxx()`` methods which should be used instead of accessing
- these attributes directly.
-
- .. attribute:: model_class
-
- Optional reference to a data model class. While not strictly
- required, most views will set this to a SQLAlchemy mapped
- class,
- e.g. :class:`wuttjamaican:wuttjamaican.db.model.auth.User`.
-
- Code should not access this directly but instead call
- :meth:`get_model_class()`.
-
- .. attribute:: model_name
-
- Optional override for the view's data model name,
- e.g. ``'WuttaWidget'``.
-
- Code should not access this directly but instead call
- :meth:`get_model_name()`.
-
- .. attribute:: model_name_normalized
-
- Optional override for the view's "normalized" data model name,
- e.g. ``'wutta_widget'``.
-
- Code should not access this directly but instead call
- :meth:`get_model_name_normalized()`.
-
- .. attribute:: model_title
-
- Optional override for the view's "humanized" (singular) model
- title, e.g. ``"Wutta Widget"``.
-
- Code should not access this directly but instead call
- :meth:`get_model_title()`.
-
- .. attribute:: model_title_plural
-
- Optional override for the view's "humanized" (plural) model
- title, e.g. ``"Wutta Widgets"``.
-
- Code should not access this directly but instead call
- :meth:`get_model_title_plural()`.
-
- .. attribute:: route_prefix
-
- Optional override for the view's route prefix,
- e.g. ``'wutta_widgets'``.
-
- Code should not access this directly but instead call
- :meth:`get_route_prefix()`.
-
- .. attribute:: url_prefix
-
- Optional override for the view's URL prefix,
- e.g. ``'/widgets'``.
-
- Code should not access this directly but instead call
- :meth:`get_url_prefix()`.
-
- .. attribute:: template_prefix
-
- Optional override for the view's template prefix,
- e.g. ``'/widgets'``.
-
- Code should not access this directly but instead call
- :meth:`get_template_prefix()`.
-
- .. attribute:: listable
-
- Boolean indicating whether the view model supports "listing" -
- i.e. it should have an :meth:`index()` view.
- """
-
- ##############################
- # attributes
- ##############################
-
- listable = True
-
- ##############################
- # view methods
- ##############################
-
- def index(self):
- """
- View to "list" (filter/browse) the model data.
-
- This is the "default" view for the model and is what user sees
- when visiting the "root" path under the :attr:`url_prefix`,
- e.g. ``/widgets/``.
- """
- return self.render_to_response('index', {})
-
- ##############################
- # support methods
- ##############################
-
- def get_index_title(self):
- """
- Returns the main index title for the master view.
-
- By default this returns the value from
- :meth:`get_model_title_plural()`. Subclass may override as
- needed.
- """
- return self.get_model_title_plural()
-
- def render_to_response(self, template, context):
- """
- Locate and render an appropriate template, with the given
- context, and return a :term:`response`.
-
- The specified ``template`` should be only the "base name" for
- the template - e.g. ``'index'`` or ``'edit'``. This method
- will then try to locate a suitable template file, based on
- values from :meth:`get_template_prefix()` and
- :meth:`get_fallback_templates()`.
-
- In practice this *usually* means two different template paths
- will be attempted, e.g. if ``template`` is ``'edit'`` and
- :attr:`template_prefix` is ``'/widgets'``:
-
- * ``/widgets/edit.mako``
- * ``/master/edit.mako``
-
- The first template found to exist will be used for rendering.
- It then calls
- :func:`pyramid:pyramid.renderers.render_to_response()` and
- returns the result.
-
- :param template: Base name for the template.
-
- :param context: Data dict to be used as template context.
-
- :returns: Response object containing the rendered template.
- """
- defaults = {
- 'index_title': self.get_index_title(),
- }
-
- # merge defaults + caller-provided context
- defaults.update(context)
- context = defaults
-
- # first try the template path most specific to this view
- template_prefix = self.get_template_prefix()
- mako_path = f'{template_prefix}/{template}.mako'
- try:
- return render_to_response(mako_path, context, request=self.request)
- except IOError:
-
- # failing that, try one or more fallback templates
- for fallback in self.get_fallback_templates(template):
- try:
- return render_to_response(fallback, context, request=self.request)
- except IOError:
- pass
-
- # if we made it all the way here, then we found no
- # templates at all, in which case re-attempt the first and
- # let that error raise on up
- return render_to_response(mako_path, context, request=self.request)
-
- def get_fallback_templates(self, template):
- """
- Returns a list of "fallback" template paths which may be
- attempted for rendering a view. This is used within
- :meth:`render_to_response()` if the "first guess" template
- file was not found.
-
- :param template: Base name for a template (without prefix), e.g.
- ``'custom'``.
-
- :returns: List of full template paths to be tried, based on
- the specified template. For instance if ``template`` is
- ``'custom'`` this will (by default) return::
-
- ['/master/custom.mako']
- """
- return [f'/master/{template}.mako']
-
- ##############################
- # class methods
- ##############################
-
- @classmethod
- def get_model_class(cls):
- """
- Returns the model class for the view (if defined).
-
- A model class will *usually* be a SQLAlchemy mapped class,
- e.g. :class:`wuttjamaican:wuttjamaican.db.model.base.Person`.
-
- There is no default value here, but a subclass may override by
- assigning :attr:`model_class`.
-
- Note that the model class is not *required* - however if you
- do not set the :attr:`model_class`, then you *must* set the
- :attr:`model_name`.
- """
- if hasattr(cls, 'model_class'):
- return cls.model_class
-
- @classmethod
- def get_model_name(cls):
- """
- Returns the model name for the view.
-
- A model name should generally be in the format of a Python
- class name, e.g. ``'WuttaWidget'``. (Note this is
- *singular*, not plural.)
-
- The default logic will call :meth:`get_model_class()` and
- return that class name as-is. A subclass may override by
- assigning :attr:`model_name`.
- """
- if hasattr(cls, 'model_name'):
- return cls.model_name
-
- return cls.get_model_class().__name__
-
- @classmethod
- def get_model_name_normalized(cls):
- """
- Returns the "normalized" model name for the view.
-
- A normalized model name should generally be in the format of a
- Python variable name, e.g. ``'wutta_widget'``. (Note this is
- *singular*, not plural.)
-
- The default logic will call :meth:`get_model_name()` and
- simply lower-case the result. A subclass may override by
- assigning :attr:`model_name_normalized`.
- """
- if hasattr(cls, 'model_name_normalized'):
- return cls.model_name_normalized
-
- return cls.get_model_name().lower()
-
- @classmethod
- def get_model_title(cls):
- """
- Returns the "humanized" (singular) model title for the view.
-
- The model title will be displayed to the user, so should have
- proper grammar and capitalization, e.g. ``"Wutta Widget"``.
- (Note this is *singular*, not plural.)
-
- The default logic will call :meth:`get_model_name()` and use
- the result as-is. A subclass may override by assigning
- :attr:`model_title`.
- """
- if hasattr(cls, 'model_title'):
- return cls.model_title
-
- return cls.get_model_name()
-
- @classmethod
- def get_model_title_plural(cls):
- """
- Returns the "humanized" (plural) model title for the view.
-
- The model title will be displayed to the user, so should have
- proper grammar and capitalization, e.g. ``"Wutta Widgets"``.
- (Note this is *plural*, not singular.)
-
- The default logic will call :meth:`get_model_title()` and
- simply add a ``'s'`` to the end. A subclass may override by
- assigning :attr:`model_title_plural`.
- """
- if hasattr(cls, 'model_title_plural'):
- return cls.model_title_plural
-
- model_title = cls.get_model_title()
- return f"{model_title}s"
-
- @classmethod
- def get_route_prefix(cls):
- """
- Returns the "route prefix" for the master view. This prefix
- is used for all named routes defined by the view class.
-
- For instance if route prefix is ``'widgets'`` then a view
- might have these routes:
-
- * ``'widgets'``
- * ``'widgets.create'``
- * ``'widgets.edit'``
- * ``'widgets.delete'``
-
- The default logic will call
- :meth:`get_model_name_normalized()` and simply add an ``'s'``
- to the end, making it plural. A subclass may override by
- assigning :attr:`route_prefix`.
- """
- if hasattr(cls, 'route_prefix'):
- return cls.route_prefix
-
- model_name = cls.get_model_name_normalized()
- return f'{model_name}s'
-
- @classmethod
- def get_url_prefix(cls):
- """
- Returns the "URL prefix" for the master view. This prefix is
- used for all URLs defined by the view class.
-
- Using the same example as in :meth:`get_route_prefix()`, the
- URL prefix would be ``'/widgets'`` and the view would have
- defined routes for these URLs:
-
- * ``/widgets/``
- * ``/widgets/new``
- * ``/widgets/XXX/edit``
- * ``/widgets/XXX/delete``
-
- The default logic will call :meth:`get_route_prefix()` and
- simply add a ``'/'`` to the beginning. A subclass may
- override by assigning :attr:`url_prefix`.
- """
- if hasattr(cls, 'url_prefix'):
- return cls.url_prefix
-
- route_prefix = cls.get_route_prefix()
- return f'/{route_prefix}'
-
- @classmethod
- def get_template_prefix(cls):
- """
- Returns the "template prefix" for the master view. This
- prefix is used to guess which template path to render for a
- given view.
-
- Using the same example as in :meth:`get_url_prefix()`, the
- template prefix would also be ``'/widgets'`` and the templates
- assumed for those routes would be:
-
- * ``/widgets/index.mako``
- * ``/widgets/create.mako``
- * ``/widgets/edit.mako``
- * ``/widgets/delete.mako``
-
- The default logic will call :meth:`get_url_prefix()` and
- return that value as-is. A subclass may override by assigning
- :attr:`template_prefix`.
- """
- if hasattr(cls, 'template_prefix'):
- return cls.template_prefix
-
- return cls.get_url_prefix()
-
- ##############################
- # configuration
- ##############################
-
- @classmethod
- def defaults(cls, config):
- """
- Provide default Pyramid configuration for a master view.
-
- This is generally called from within the module's
- ``includeme()`` function, e.g.::
-
- from wuttaweb.views import MasterView
-
- class WidgetView(MasterView):
- model_name = 'Widget'
-
- def includeme(config):
- WidgetView.defaults(config)
-
- :param config: Reference to the app's
- :class:`pyramid:pyramid.config.Configurator` instance.
- """
- cls._defaults(config)
-
- @classmethod
- def _defaults(cls, config):
- route_prefix = cls.get_route_prefix()
- url_prefix = cls.get_url_prefix()
-
- # index view
- if cls.listable:
- config.add_route(route_prefix, f'{url_prefix}/')
- config.add_view(cls, attr='index',
- route_name=route_prefix)
diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py
deleted file mode 100644
index 42ce834..0000000
--- a/src/wuttaweb/views/settings.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- 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 .
-#
-################################################################################
-"""
-Views for app settings
-"""
-
-from wuttaweb.views import MasterView
-
-
-class AppInfoView(MasterView):
- """
- Master view for the overall app, to show/edit config etc.
- """
- model_name = 'AppInfo'
- model_title_plural = "App Info"
- route_prefix = 'appinfo'
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- AppInfoView = kwargs.get('AppInfoView', base['AppInfoView'])
- AppInfoView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/tests/forms/test_base.py b/tests/forms/test_base.py
index 5e29ad6..27e2109 100644
--- a/tests/forms/test_base.py
+++ b/tests/forms/test_base.py
@@ -46,10 +46,8 @@ class TestFieldList(TestCase):
class TestForm(TestCase):
def setUp(self):
- self.config = WuttaConfig(defaults={
- 'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
- })
- self.request = testing.DummyRequest(wutta_config=self.config, use_oruga=False)
+ self.config = WuttaConfig()
+ self.request = testing.DummyRequest(wutta_config=self.config)
self.pyramid_config = testing.setUp(request=self.request, settings={
'mako.directories': ['wuttaweb:templates'],
diff --git a/tests/test_subscribers.py b/tests/test_subscribers.py
index c991383..419e130 100644
--- a/tests/test_subscribers.py
+++ b/tests/test_subscribers.py
@@ -214,12 +214,10 @@ class TestNewRequestSetUser(TestCase):
class TestBeforeRender(TestCase):
def setUp(self):
- self.config = WuttaConfig(defaults={
- 'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
- })
+ self.config = WuttaConfig()
def make_request(self):
- request = testing.DummyRequest(use_oruga=False)
+ request = testing.DummyRequest()
request.registry.settings = {'wutta_config': self.config}
request.wutta_config = self.config
return request
diff --git a/tests/utils.py b/tests/utils.py
deleted file mode 100644
index ed66cc1..0000000
--- a/tests/utils.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8; -*-
-
-from wuttaweb.menus import MenuHandler
-
-
-class NullMenuHandler(MenuHandler):
- """
- Dummy menu handler for testing.
- """
- def make_menus(self, request, **kwargs):
- return []
diff --git a/tests/views/test_base.py b/tests/views/test_base.py
index 6e2f126..103e005 100644
--- a/tests/views/test_base.py
+++ b/tests/views/test_base.py
@@ -3,7 +3,7 @@
from unittest import TestCase
from pyramid import testing
-from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
+from pyramid.httpexceptions import HTTPFound, HTTPForbidden
from wuttjamaican.conf import WuttaConfig
from wuttaweb.views import base
@@ -31,10 +31,6 @@ class TestView(TestCase):
form = self.view.make_form()
self.assertIsInstance(form, Form)
- def test_notfound(self):
- error = self.view.notfound()
- self.assertIsInstance(error, HTTPNotFound)
-
def test_redirect(self):
error = self.view.redirect('/')
self.assertIsInstance(error, HTTPFound)
diff --git a/tests/views/test_master.py b/tests/views/test_master.py
deleted file mode 100644
index 8fe4c47..0000000
--- a/tests/views/test_master.py
+++ /dev/null
@@ -1,282 +0,0 @@
-# -*- coding: utf-8; -*-
-
-from unittest import TestCase
-from unittest.mock import MagicMock
-
-from pyramid import testing
-from pyramid.response import Response
-
-from wuttjamaican.conf import WuttaConfig
-from wuttaweb.views import master
-from wuttaweb.subscribers import new_request_set_user
-
-
-class TestMasterView(TestCase):
-
- def setUp(self):
- self.config = WuttaConfig(defaults={
- 'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
- })
- self.app = self.config.get_app()
- self.request = testing.DummyRequest(wutta_config=self.config, use_oruga=False)
- self.pyramid_config = testing.setUp(request=self.request, settings={
- 'wutta_config': self.config,
- 'mako.directories': ['wuttaweb:templates'],
- })
- self.pyramid_config.include('pyramid_mako')
- self.pyramid_config.include('wuttaweb.static')
- self.pyramid_config.include('wuttaweb.views.essential')
- self.pyramid_config.add_subscriber('wuttaweb.subscribers.before_render',
- 'pyramid.events.BeforeRender')
-
- event = MagicMock(request=self.request)
- new_request_set_user(event)
-
- def tearDown(self):
- testing.tearDown()
-
- def test_defaults(self):
- master.MasterView.model_name = 'Widget'
- # TODO: should inspect pyramid routes after this, to be certain
- master.MasterView.defaults(self.pyramid_config)
- del master.MasterView.model_name
-
- ##############################
- # class methods
- ##############################
-
- def test_get_model_class(self):
-
- # no model class by default
- self.assertIsNone(master.MasterView.get_model_class())
-
- # subclass may specify
- MyModel = MagicMock()
- master.MasterView.model_class = MyModel
- self.assertIs(master.MasterView.get_model_class(), MyModel)
- del master.MasterView.model_class
-
- def test_get_model_name(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_model_name)
-
- # subclass may specify model name
- master.MasterView.model_name = 'Widget'
- self.assertEqual(master.MasterView.get_model_name(), 'Widget')
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Blaster')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_model_name(), 'Blaster')
- del master.MasterView.model_class
-
- def test_get_model_name_normalized(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_model_name_normalized)
-
- # subclass may specify *normalized* model name
- master.MasterView.model_name_normalized = 'widget'
- self.assertEqual(master.MasterView.get_model_name_normalized(), 'widget')
- del master.MasterView.model_name_normalized
-
- # or it may specify *standard* model name
- master.MasterView.model_name = 'Blaster'
- self.assertEqual(master.MasterView.get_model_name_normalized(), 'blaster')
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Dinosaur')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_model_name_normalized(), 'dinosaur')
- del master.MasterView.model_class
-
- def test_get_model_title(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_model_title)
-
- # subclass may specify model title
- master.MasterView.model_title = 'Wutta Widget'
- self.assertEqual(master.MasterView.get_model_title(), "Wutta Widget")
- del master.MasterView.model_title
-
- # or it may specify model name
- master.MasterView.model_name = 'Blaster'
- self.assertEqual(master.MasterView.get_model_title(), "Blaster")
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Dinosaur')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_model_title(), "Dinosaur")
- del master.MasterView.model_class
-
- def test_get_model_title_plural(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_model_title_plural)
-
- # subclass may specify *plural* model title
- master.MasterView.model_title_plural = 'People'
- self.assertEqual(master.MasterView.get_model_title_plural(), "People")
- del master.MasterView.model_title_plural
-
- # or it may specify *singular* model title
- master.MasterView.model_title = 'Wutta Widget'
- self.assertEqual(master.MasterView.get_model_title_plural(), "Wutta Widgets")
- del master.MasterView.model_title
-
- # or it may specify model name
- master.MasterView.model_name = 'Blaster'
- self.assertEqual(master.MasterView.get_model_title_plural(), "Blasters")
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Dinosaur')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_model_title_plural(), "Dinosaurs")
- del master.MasterView.model_class
-
- def test_get_route_prefix(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_route_prefix)
-
- # subclass may specify route prefix
- master.MasterView.route_prefix = 'widgets'
- self.assertEqual(master.MasterView.get_route_prefix(), 'widgets')
- del master.MasterView.route_prefix
-
- # subclass may specify *normalized* model name
- master.MasterView.model_name_normalized = 'blaster'
- self.assertEqual(master.MasterView.get_route_prefix(), 'blasters')
- del master.MasterView.model_name_normalized
-
- # or it may specify *standard* model name
- master.MasterView.model_name = 'Dinosaur'
- self.assertEqual(master.MasterView.get_route_prefix(), 'dinosaurs')
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Truck')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_route_prefix(), 'trucks')
- del master.MasterView.model_class
-
- def test_get_url_prefix(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_url_prefix)
-
- # subclass may specify url prefix
- master.MasterView.url_prefix = '/widgets'
- self.assertEqual(master.MasterView.get_url_prefix(), '/widgets')
- del master.MasterView.url_prefix
-
- # or it may specify route prefix
- master.MasterView.route_prefix = 'trucks'
- self.assertEqual(master.MasterView.get_url_prefix(), '/trucks')
- del master.MasterView.route_prefix
-
- # or it may specify *normalized* model name
- master.MasterView.model_name_normalized = 'blaster'
- self.assertEqual(master.MasterView.get_url_prefix(), '/blasters')
- del master.MasterView.model_name_normalized
-
- # or it may specify *standard* model name
- master.MasterView.model_name = 'Dinosaur'
- self.assertEqual(master.MasterView.get_url_prefix(), '/dinosaurs')
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Machine')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_url_prefix(), '/machines')
- del master.MasterView.model_class
-
- def test_get_template_prefix(self):
-
- # error by default (since no model class)
- self.assertRaises(AttributeError, master.MasterView.get_template_prefix)
-
- # subclass may specify template prefix
- master.MasterView.template_prefix = '/widgets'
- self.assertEqual(master.MasterView.get_template_prefix(), '/widgets')
- del master.MasterView.template_prefix
-
- # or it may specify url prefix
- master.MasterView.url_prefix = '/trees'
- self.assertEqual(master.MasterView.get_template_prefix(), '/trees')
- del master.MasterView.url_prefix
-
- # or it may specify route prefix
- master.MasterView.route_prefix = 'trucks'
- self.assertEqual(master.MasterView.get_template_prefix(), '/trucks')
- del master.MasterView.route_prefix
-
- # or it may specify *normalized* model name
- master.MasterView.model_name_normalized = 'blaster'
- self.assertEqual(master.MasterView.get_template_prefix(), '/blasters')
- del master.MasterView.model_name_normalized
-
- # or it may specify *standard* model name
- master.MasterView.model_name = 'Dinosaur'
- self.assertEqual(master.MasterView.get_template_prefix(), '/dinosaurs')
- del master.MasterView.model_name
-
- # or it may specify model class
- MyModel = MagicMock(__name__='Machine')
- master.MasterView.model_class = MyModel
- self.assertEqual(master.MasterView.get_template_prefix(), '/machines')
- del master.MasterView.model_class
-
- ##############################
- # support methods
- ##############################
-
- def test_get_index_title(self):
- master.MasterView.model_title_plural = "Wutta Widgets"
- view = master.MasterView(self.request)
- self.assertEqual(view.get_index_title(), "Wutta Widgets")
- del master.MasterView.model_title_plural
-
- def test_render_to_response(self):
-
- # basic sanity check using /master/index.mako
- # (nb. it skips /widgets/index.mako since that doesn't exist)
- master.MasterView.model_name = 'Widget'
- view = master.MasterView(self.request)
- response = view.render_to_response('index', {})
- self.assertIsInstance(response, Response)
- del master.MasterView.model_name
-
- # basic sanity check using /appinfo/index.mako
- master.MasterView.model_name = 'AppInfo'
- master.MasterView.template_prefix = '/appinfo'
- view = master.MasterView(self.request)
- response = view.render_to_response('index', {})
- self.assertIsInstance(response, Response)
- del master.MasterView.model_name
- del master.MasterView.template_prefix
-
- # bad template name causes error
- master.MasterView.model_name = 'Widget'
- self.assertRaises(IOError, view.render_to_response, 'nonexistent', {})
- del master.MasterView.model_name
-
- ##############################
- # view methods
- ##############################
-
- def test_index(self):
-
- # basic sanity check using /appinfo
- master.MasterView.model_name = 'AppInfo'
- master.MasterView.template_prefix = '/appinfo'
- view = master.MasterView(self.request)
- response = view.index()
- del master.MasterView.model_name
- del master.MasterView.template_prefix
diff --git a/tests/views/test_settings.py b/tests/views/test_settings.py
deleted file mode 100644
index 321364b..0000000
--- a/tests/views/test_settings.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8; -*-
-
-from tests.views.utils import WebTestCase
-
-from wuttaweb.views import settings
-
-
-class TestAppInfoView(WebTestCase):
-
- def test_index(self):
- # just a sanity check
- view = settings.AppInfoView(self.request)
- response = view.index()
diff --git a/tests/views/utils.py b/tests/views/utils.py
deleted file mode 100644
index 495f5cb..0000000
--- a/tests/views/utils.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- coding: utf-8; -*-
-
-from unittest import TestCase
-from unittest.mock import MagicMock
-
-from pyramid import testing
-
-from wuttjamaican.conf import WuttaConfig
-from wuttaweb import subscribers
-
-
-class WebTestCase(TestCase):
- """
- Base class for test suites requiring a full (typical) web app.
- """
-
- def setUp(self):
- self.setup_web()
-
- def setup_web(self):
- self.config = WuttaConfig(defaults={
- 'wutta.db.default.url': 'sqlite://',
- 'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
- })
-
- self.request = testing.DummyRequest()
-
- self.pyramid_config = testing.setUp(request=self.request, settings={
- 'wutta_config': self.config,
- 'mako.directories': ['wuttaweb:templates'],
- })
-
- # init db
- self.app = self.config.get_app()
- model = self.app.model
- model.Base.metadata.create_all(bind=self.config.appdb_engine)
- self.session = self.app.make_session()
-
- # init web
- self.pyramid_config.include('pyramid_mako')
- self.pyramid_config.include('wuttaweb.static')
- self.pyramid_config.include('wuttaweb.views.essential')
- self.pyramid_config.add_subscriber('wuttaweb.subscribers.before_render',
- 'pyramid.events.BeforeRender')
-
- # setup new request w/ anonymous user
- event = MagicMock(request=self.request)
- subscribers.new_request(event)
- def user_getter(request, **kwargs): pass
- subscribers.new_request_set_user(event, db_session=self.session,
- user_getter=user_getter)
-
- def tearDown(self):
- self.teardown_web()
-
- def teardown_web(self):
- testing.tearDown()