From a83778a5fc6233d0679cbe3c6b773cae2546bc83 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:21:16 -0600 Subject: [PATCH 01/12] Avoid "File name too long" error Any file error will be ignored and jump straight to treating var as CSS text. fixes tethysplatform/tethys#1127 --- tethys_apps/templatetags/site_settings.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index c8b7120f4..1007bb6a7 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -17,12 +17,14 @@ def load_custom_css(var): if var.startswith("/"): var = var.lstrip("/") - if (Path(settings.STATIC_ROOT) / var).is_file() or static_finder.find(var): - return f'' + try: + if (Path(settings.STATIC_ROOT) / var).is_file() or static_finder.find(var): + return f'' - else: for path in settings.STATICFILES_DIRS: if (Path(path) / var).is_file(): return f'' + except OSError: + pass return "" From 08352218a7080d9a1d66204f89ffceaa3333e6b6 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:28:53 -0600 Subject: [PATCH 02/12] Add docstring and update import order --- tethys_apps/templatetags/site_settings.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 1007bb6a7..ba096bd0b 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -1,9 +1,9 @@ +from pathlib import Path + from django import template from django.template.defaultfilters import stringfilter from django.conf import settings -from pathlib import Path - from ..static_finders import TethysStaticFinder static_finder = TethysStaticFinder() @@ -14,6 +14,14 @@ @register.filter @stringfilter def load_custom_css(var): + """Load Custom Styles defined in Tethys Portal -> Site Settings + + Args: + var: a filename of CSS to load or CSS text to embed into the page + + Returns: a string of HTML that either embeds CSS text or points to a file + + """ if var.startswith("/"): var = var.lstrip("/") From d84423369cf7c63fc0c483a2c4c07e8b45a8666d Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:19:54 -0600 Subject: [PATCH 03/12] Add unit test --- .../test_templatetags/test_site_settings.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py index fb7042e1f..23b16559a 100644 --- a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py +++ b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py @@ -44,3 +44,19 @@ def test_get_css_is_code(self, mock_isfile, mock_settings): ret = ss.load_custom_css("test.css") self.assertEqual(ret, "") + + def test_long_css_text(self): + long_css_text = """ + .site-header { margin: 0 50px 0 0; background-color: red; } + .site-header .navbar-brand { + background-color: darkred; + color: black; + font-style: italic; + font-variant: small-caps; + font-family: cursive; + font-size: 24px; + } + """ + + ret = ss.load_custom_css(long_css_text) + self.assertEqual(ret, f"") From a59c7a3d43719c189281cbc870e0e2eccb53893a Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:26:41 -0600 Subject: [PATCH 04/12] Remove trailing whitespace --- .../test_templatetags/test_site_settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py index 23b16559a..81dbd34f3 100644 --- a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py +++ b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py @@ -48,9 +48,9 @@ def test_get_css_is_code(self, mock_isfile, mock_settings): def test_long_css_text(self): long_css_text = """ .site-header { margin: 0 50px 0 0; background-color: red; } - .site-header .navbar-brand { - background-color: darkred; - color: black; + .site-header .navbar-brand { + background-color: darkred; + color: black; font-style: italic; font-variant: small-caps; font-family: cursive; From 921c6da54805376f7dc8dfdfa4e04f3ab1aa4b39 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Fri, 27 Dec 2024 12:04:50 -0600 Subject: [PATCH 05/12] Log a warning if var looks like a filename but can't load The login page calls load_custom_css() twice with an empty var, so this now returns early for that. --- tethys_apps/templatetags/site_settings.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index ba096bd0b..7f22df93f 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -1,3 +1,4 @@ +import logging from pathlib import Path from django import template @@ -10,6 +11,8 @@ register = template.Library() +log = logging.getLogger(f"tethys.{__name__}") + @register.filter @stringfilter @@ -19,9 +22,12 @@ def load_custom_css(var): Args: var: a filename of CSS to load or CSS text to embed into the page - Returns: a string of HTML that either embeds CSS text or points to a file + Returns: + a string of HTML that either embeds CSS text or points to a file """ + if not var.strip(): + return "" if var.startswith("/"): var = var.lstrip("/") @@ -32,7 +38,18 @@ def load_custom_css(var): for path in settings.STATICFILES_DIRS: if (Path(path) / var).is_file(): return f'' - except OSError: + except OSError as e: + oserror_exception = ": " + str(e) pass + else: + oserror_exception = "" + + common_css_chars = "{};," + if not any(c in var for c in common_css_chars): + # This appears to be a filename and not a CSS string + log.warning( + "Could not load file '%s' for custom styles%s", var, oserror_exception + ) + return "" return "" From ca7a2d1058dd772f6c4109a68671976a251df8a5 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Fri, 27 Dec 2024 13:59:33 -0600 Subject: [PATCH 06/12] Update code style test load_custom_css() now returns an empty string for a file that does not exist, so test_get_css_is_code() has been updated to test CSS code. --- .../test_tethys_apps/test_templatetags/test_site_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py index 81dbd34f3..a1ea00175 100644 --- a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py +++ b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py @@ -42,8 +42,8 @@ def test_get_css_is_code(self, mock_isfile, mock_settings): mock_settings.STATIC_ROOT = "test_base_path1" mock_settings.STATICFILES_DIRS = ["test_base_path2"] - ret = ss.load_custom_css("test.css") - self.assertEqual(ret, "") + ret = ss.load_custom_css(".navbar-brand { background-color: darkred; }") + self.assertEqual(ret, "") def test_long_css_text(self): long_css_text = """ From 9dd9c5899c3ae971bbccf3bca0b2a229f759ff53 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Fri, 27 Dec 2024 14:37:45 -0600 Subject: [PATCH 07/12] Apply black formatting --- .../test_tethys_apps/test_templatetags/test_site_settings.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py index a1ea00175..fe6b11fe6 100644 --- a/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py +++ b/tests/unit_tests/test_tethys_apps/test_templatetags/test_site_settings.py @@ -43,7 +43,9 @@ def test_get_css_is_code(self, mock_isfile, mock_settings): mock_settings.STATICFILES_DIRS = ["test_base_path2"] ret = ss.load_custom_css(".navbar-brand { background-color: darkred; }") - self.assertEqual(ret, "") + self.assertEqual( + ret, "" + ) def test_long_css_text(self): long_css_text = """ From 1e246d62982e95a6717dbaa3c67325a1b17dfb79 Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:48:08 -0600 Subject: [PATCH 08/12] Remove unnecessary pass statement Co-authored-by: Nathan Swain --- tethys_apps/templatetags/site_settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 7f22df93f..6d2c493ef 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -40,7 +40,6 @@ def load_custom_css(var): return f'' except OSError as e: oserror_exception = ": " + str(e) - pass else: oserror_exception = "" From 4b1989153b1a587259119025ee446ab34a6ca41c Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:48:56 -0600 Subject: [PATCH 09/12] Add comment for is_file Co-authored-by: Nathan Swain --- tethys_apps/templatetags/site_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 6d2c493ef..61ce24644 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -32,6 +32,7 @@ def load_custom_css(var): var = var.lstrip("/") try: + # Check if var is a path to a file, if so return a link tag to the file if (Path(settings.STATIC_ROOT) / var).is_file() or static_finder.find(var): return f'' From ce756b8cf02a9581f707ed9c005c19b015c9782b Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:49:23 -0600 Subject: [PATCH 10/12] Add comment about long CSS string causing OSError Co-authored-by: Nathan Swain --- tethys_apps/templatetags/site_settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 61ce24644..37022e8d0 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -39,6 +39,9 @@ def load_custom_css(var): for path in settings.STATICFILES_DIRS: if (Path(path) / var).is_file(): return f'' + # If the string is too long for a file path, which could happen if it is CSS, + # an OSError will be raised during the file path checks. This could also happen + # if a lengthy file path is given or is otherwise invalid. except OSError as e: oserror_exception = ": " + str(e) else: From ba22cee77ee11df79c4d6019c874b57ca8cd563f Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:49:57 -0600 Subject: [PATCH 11/12] Add comment about determining if it is a CSS string Co-authored-by: Nathan Swain --- tethys_apps/templatetags/site_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 37022e8d0..2971e8eca 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -47,6 +47,7 @@ def load_custom_css(var): else: oserror_exception = "" + # Verify the string is CSS and log warning if it is not common_css_chars = "{};," if not any(c in var for c in common_css_chars): # This appears to be a filename and not a CSS string From 5cb1046f602c1a057c7c6d2587fcb2d60ce385cf Mon Sep 17 00:00:00 2001 From: Mark Lugar <14322382+araglu@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:14:39 -0600 Subject: [PATCH 12/12] Apply black/flake8 formatting --- tethys_apps/templatetags/site_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tethys_apps/templatetags/site_settings.py b/tethys_apps/templatetags/site_settings.py index 2971e8eca..b85e315aa 100644 --- a/tethys_apps/templatetags/site_settings.py +++ b/tethys_apps/templatetags/site_settings.py @@ -39,7 +39,7 @@ def load_custom_css(var): for path in settings.STATICFILES_DIRS: if (Path(path) / var).is_file(): return f'' - # If the string is too long for a file path, which could happen if it is CSS, + # If the string is too long for a file path, which could happen if it is CSS, # an OSError will be raised during the file path checks. This could also happen # if a lengthy file path is given or is otherwise invalid. except OSError as e: