diff --git a/pyproject.toml b/pyproject.toml index 0aa3e33..a90fbe1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dependencies = [ "pyramid>=2", "pyramid_beaker", "pyramid_deform", + "pyramid_fanstatic", "pyramid_mako", "pyramid_tm", "waitress", diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index 8b4a610..bafc921 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -114,6 +114,7 @@ def make_pyramid_config(settings): :returns: Instance of :class:`pyramid:pyramid.config.Configurator`. """ + settings.setdefault('fanstatic.versioning', 'true') settings.setdefault('mako.directories', ['wuttaweb:templates']) settings.setdefault('pyramid_deform.template_search_path', 'wuttaweb:templates/deform') @@ -130,6 +131,7 @@ def make_pyramid_config(settings): pyramid_config.include('pyramid_beaker') pyramid_config.include('pyramid_deform') + pyramid_config.include('pyramid_fanstatic') pyramid_config.include('pyramid_mako') pyramid_config.include('pyramid_tm') diff --git a/src/wuttaweb/util.py b/src/wuttaweb/util.py index 61614ad..6d1d5f2 100644 --- a/src/wuttaweb/util.py +++ b/src/wuttaweb/util.py @@ -248,40 +248,73 @@ def get_liburl( version = get_libver(request, key, prefix=prefix) + static = config.get('wuttaweb.static_libcache.module') + if static: + static = importlib.import_module(static) + needed = request.environ['fanstatic.needed'] + liburl = needed.library_url(static.libcache) + '/' + # nb. add custom url prefix if needed, e.g. /wutta + if request.script_name: + liburl = request.script_name + liburl + if key == 'buefy': + if static and hasattr(static, 'buefy_js'): + return liburl + static.buefy_js.relpath return f'https://unpkg.com/buefy@{version}/dist/buefy.min.js' elif key == 'buefy.css': + if static and hasattr(static, 'buefy_css'): + return liburl + static.buefy_css.relpath return f'https://unpkg.com/buefy@{version}/dist/buefy.min.css' elif key == 'vue': + if static and hasattr(static, 'vue_js'): + return liburl + static.vue_js.relpath return f'https://unpkg.com/vue@{version}/dist/vue.min.js' elif key == 'vue_resource': + if static and hasattr(static, 'vue_resource_js'): + return liburl + static.vue_resource_js.relpath return f'https://cdn.jsdelivr.net/npm/vue-resource@{version}' elif key == 'fontawesome': + if static and hasattr(static, 'fontawesome_js'): + return liburl + static.fontawesome_js.relpath return f'https://use.fontawesome.com/releases/v{version}/js/all.js' elif key == 'bb_vue': + if static and hasattr(static, 'bb_vue_js'): + return liburl + static.bb_vue_js.relpath return f'https://unpkg.com/vue@{version}/dist/vue.esm-browser.prod.js' elif key == 'bb_oruga': + if static and hasattr(static, 'bb_oruga_js'): + return liburl + static.bb_oruga_js.relpath return f'https://unpkg.com/@oruga-ui/oruga-next@{version}/dist/oruga.mjs' elif key == 'bb_oruga_bulma': + if static and hasattr(static, 'bb_oruga_bulma_js'): + return liburl + static.bb_oruga_bulma_js.relpath return f'https://unpkg.com/@oruga-ui/theme-bulma@{version}/dist/bulma.mjs' elif key == 'bb_oruga_bulma_css': + if static and hasattr(static, 'bb_oruga_bulma_css'): + return liburl + static.bb_oruga_bulma_css.relpath return f'https://unpkg.com/@oruga-ui/theme-bulma@{version}/dist/bulma.css' elif key == 'bb_fontawesome_svg_core': + if static and hasattr(static, 'bb_fontawesome_svg_core_js'): + return liburl + static.bb_fontawesome_svg_core_js.relpath return f'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@{version}/+esm' elif key == 'bb_free_solid_svg_icons': + if static and hasattr(static, 'bb_free_solid_svg_icons_js'): + return liburl + static.bb_free_solid_svg_icons_js.relpath return f'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@{version}/+esm' elif key == 'bb_vue_fontawesome': + if static and hasattr(static, 'bb_vue_fontawesome_js'): + return liburl + static.bb_vue_fontawesome_js.relpath return f'https://cdn.jsdelivr.net/npm/@fortawesome/vue-fontawesome@{version}/+esm' diff --git a/tests/libcache/bb_fontawesome_svg_core.js b/tests/libcache/bb_fontawesome_svg_core.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_free_solid_svg_icons.js b/tests/libcache/bb_free_solid_svg_icons.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_oruga.js b/tests/libcache/bb_oruga.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_oruga_bulma.css b/tests/libcache/bb_oruga_bulma.css new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_oruga_bulma.js b/tests/libcache/bb_oruga_bulma.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_vue.js b/tests/libcache/bb_vue.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/bb_vue_fontawesome.js b/tests/libcache/bb_vue_fontawesome.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/buefy.css b/tests/libcache/buefy.css new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/buefy.js b/tests/libcache/buefy.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/fontawesome.js b/tests/libcache/fontawesome.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/vue.js b/tests/libcache/vue.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/libcache/vue_resource.js b/tests/libcache/vue_resource.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_util.py b/tests/test_util.py index 44817e5..4d779c3 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,8 +1,9 @@ # -*- coding: utf-8; -*- from unittest import TestCase -from unittest.mock import patch +from unittest.mock import patch, MagicMock +from fanstatic import Library, Resource from pyramid import testing from wuttjamaican.conf import WuttaConfig @@ -162,12 +163,40 @@ class TestGetLibVer(TestCase): self.assertEqual(version, '3.0.8') +libcache = Library('testing', 'libcache') +vue_js = Resource(libcache, 'vue.js') +vue_resource_js = Resource(libcache, 'vue_resource.js') +buefy_js = Resource(libcache, 'buefy.js') +buefy_css = Resource(libcache, 'buefy.css') +fontawesome_js = Resource(libcache, 'fontawesome.js') +bb_vue_js = Resource(libcache, 'bb_vue.js') +bb_oruga_js = Resource(libcache, 'bb_oruga.js') +bb_oruga_bulma_js = Resource(libcache, 'bb_oruga_bulma.js') +bb_oruga_bulma_css = Resource(libcache, 'bb_oruga_bulma.css') +bb_fontawesome_svg_core_js = Resource(libcache, 'bb_fontawesome_svg_core.js') +bb_free_solid_svg_icons_js = Resource(libcache, 'bb_free_solid_svg_icons.js') +bb_vue_fontawesome_js = Resource(libcache, 'bb_vue_fontawesome.js') + + class TestGetLibUrl(TestCase): def setUp(self): self.config = WuttaConfig() - self.request = testing.DummyRequest() - self.request.wutta_config = self.config + self.request = testing.DummyRequest(wutta_config=self.config) + self.pyramid_config = testing.setUp(request=self.request) + + def tearDown(self): + testing.tearDown() + + def setup_fanstatic(self): + self.pyramid_config.include('pyramid_fanstatic') + self.config.setdefault('wuttaweb.static_libcache.module', + 'tests.test_util') + + needed = MagicMock() + needed.library_url = MagicMock(return_value='/fanstatic') + self.request.environ['fanstatic.needed'] = needed + self.request.script_name = '/wutta' def test_buefy_default(self): url = util.get_liburl(self.request, 'buefy') @@ -187,6 +216,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'buefy', configured_only=True) self.assertIsNone(url) + def test_buefy_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'buefy') + self.assertEqual(url, '/wutta/fanstatic/buefy.js') + def test_buefy_css_default(self): url = util.get_liburl(self.request, 'buefy.css') self.assertEqual(url, 'https://unpkg.com/buefy@latest/dist/buefy.min.css') @@ -196,6 +230,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'buefy.css') self.assertEqual(url, '/lib/buefy.css') + def test_buefy_css_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'buefy.css') + self.assertEqual(url, '/wutta/fanstatic/buefy.css') + def test_vue_default(self): url = util.get_liburl(self.request, 'vue') self.assertEqual(url, 'https://unpkg.com/vue@2.6.14/dist/vue.min.js') @@ -205,6 +244,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'vue') self.assertEqual(url, '/lib/vue.js') + def test_vue_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'vue') + self.assertEqual(url, '/wutta/fanstatic/vue.js') + def test_vue_resource_default(self): url = util.get_liburl(self.request, 'vue_resource') self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/vue-resource@latest') @@ -214,6 +258,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'vue_resource') self.assertEqual(url, '/lib/vue-resource.js') + def test_vue_resource_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'vue_resource') + self.assertEqual(url, '/wutta/fanstatic/vue_resource.js') + def test_fontawesome_default(self): url = util.get_liburl(self.request, 'fontawesome') self.assertEqual(url, 'https://use.fontawesome.com/releases/v5.3.1/js/all.js') @@ -223,6 +272,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'fontawesome') self.assertEqual(url, '/lib/fontawesome.js') + def test_fontawesome_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'fontawesome') + self.assertEqual(url, '/wutta/fanstatic/fontawesome.js') + def test_bb_vue_default(self): url = util.get_liburl(self.request, 'bb_vue') self.assertEqual(url, 'https://unpkg.com/vue@3.4.31/dist/vue.esm-browser.prod.js') @@ -232,6 +286,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_vue') self.assertEqual(url, '/lib/vue.js') + def test_bb_vue_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_vue') + self.assertEqual(url, '/wutta/fanstatic/bb_vue.js') + def test_bb_oruga_default(self): url = util.get_liburl(self.request, 'bb_oruga') self.assertEqual(url, 'https://unpkg.com/@oruga-ui/oruga-next@0.8.12/dist/oruga.mjs') @@ -241,6 +300,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_oruga') self.assertEqual(url, '/lib/oruga.js') + def test_bb_oruga_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_oruga') + self.assertEqual(url, '/wutta/fanstatic/bb_oruga.js') + def test_bb_oruga_bulma_default(self): url = util.get_liburl(self.request, 'bb_oruga_bulma') self.assertEqual(url, 'https://unpkg.com/@oruga-ui/theme-bulma@0.3.0/dist/bulma.mjs') @@ -250,6 +314,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_oruga_bulma') self.assertEqual(url, '/lib/oruga_bulma.js') + def test_bb_oruga_bulma_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_oruga_bulma') + self.assertEqual(url, '/wutta/fanstatic/bb_oruga_bulma.js') + def test_bb_oruga_bulma_css_default(self): url = util.get_liburl(self.request, 'bb_oruga_bulma_css') self.assertEqual(url, 'https://unpkg.com/@oruga-ui/theme-bulma@0.3.0/dist/bulma.css') @@ -259,6 +328,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_oruga_bulma_css') self.assertEqual(url, '/lib/oruga-bulma.css') + def test_bb_oruga_bulma_css_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_oruga_bulma_css') + self.assertEqual(url, '/wutta/fanstatic/bb_oruga_bulma.css') + def test_bb_fontawesome_svg_core_default(self): url = util.get_liburl(self.request, 'bb_fontawesome_svg_core') self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@6.5.2/+esm') @@ -268,6 +342,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_fontawesome_svg_core') self.assertEqual(url, '/lib/fontawesome-svg-core.js') + def test_bb_fontawesome_svg_core_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_fontawesome_svg_core') + self.assertEqual(url, '/wutta/fanstatic/bb_fontawesome_svg_core.js') + def test_bb_free_solid_svg_icons_default(self): url = util.get_liburl(self.request, 'bb_free_solid_svg_icons') self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@6.5.2/+esm') @@ -277,6 +356,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_free_solid_svg_icons') self.assertEqual(url, '/lib/free-solid-svg-icons.js') + def test_bb_free_solid_svg_icons_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_free_solid_svg_icons') + self.assertEqual(url, '/wutta/fanstatic/bb_free_solid_svg_icons.js') + def test_bb_vue_fontawesome_default(self): url = util.get_liburl(self.request, 'bb_vue_fontawesome') self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/vue-fontawesome@3.0.6/+esm') @@ -286,6 +370,11 @@ class TestGetLibUrl(TestCase): url = util.get_liburl(self.request, 'bb_vue_fontawesome') self.assertEqual(url, '/lib/vue-fontawesome.js') + def test_bb_vue_fontawesome_fanstatic(self): + self.setup_fanstatic() + url = util.get_liburl(self.request, 'bb_vue_fontawesome') + self.assertEqual(url, '/wutta/fanstatic/bb_vue_fontawesome.js') + class TestGetFormData(TestCase):