From 0cf3873cd17a7dd79702f5bda3c9dc276070bb30 Mon Sep 17 00:00:00 2001 From: BJ Dierkes Date: Fri, 9 May 2025 18:49:17 -0500 Subject: [PATCH] feat: support template_dirs config settings Resolves Issue #746 --- CHANGELOG.md | 3 ++- CONTRIBUTORS.md | 1 + cement/core/foundation.py | 29 ++++++++++++++++++----- tests/core/test_foundation.py | 43 +++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 011e6da4..06ea9f68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ Bugs: Features: -- None +- `[core.foundation]` Support for App.Meta.template_dirs. + - [Issue #746](https://github.com/datafolklabs/cement/issues/749) Refactoring: diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 11578bcf..bc72957d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -23,3 +23,4 @@ documentation, or testing: - Christian Hengl (rednar) - sigma67 - Blake Jameson (blakejameson) +- Tom Freudenberg (TomFreudenberg) diff --git a/cement/core/foundation.py b/cement/core/foundation.py index dab44b95..9e739a39 100644 --- a/cement/core/foundation.py +++ b/cement/core/foundation.py @@ -497,6 +497,7 @@ class App(meta.MetaMixin): 'plugin_dir', 'ignore_deprecation_warnings', 'template_dir', + 'template_dirs', 'mail_handler', 'cache_handler', 'log_handler', @@ -1521,6 +1522,17 @@ class App(meta.MetaMixin): 'home_dir': fs.HOME_DIR, } + # Check if template_dirs is overridden by config + config_template_dirs = [] + if 'template_dirs' in self.config.keys(self._meta.config_section): + config_template_dirs = self.config.get(self._meta.label, 'template_dirs') + + if isinstance(config_template_dirs, str): + config_template_dirs = [x.strip() for x in config_template_dirs.split(',')] + + # reverse it becuase it will be reverse again (keep user preference) + config_template_dirs.reverse() + # generate a final list of directories based on precedence (user level # paths take precedence). @@ -1529,7 +1541,17 @@ class App(meta.MetaMixin): if d not in template_dirs: template_dirs.append(d) - for d in self._meta.template_dirs: + # If config overrides template_dirs, use config instead of meta template_dirs + if config_template_dirs: + for d in config_template_dirs: + template_dirs.append(d) + else: + for d in self._meta.template_dirs: + d = d.format(**template_dict) + if d not in template_dirs: + template_dirs.append(d) + + for d in self._meta.core_user_template_dirs: d = d.format(**template_dict) if d not in template_dirs: template_dirs.append(d) @@ -1538,11 +1560,6 @@ class App(meta.MetaMixin): d = self._meta.template_dir.format(**template_dict) template_dirs.append(d) - for d in self._meta.core_user_template_dirs: - d = d.format(**template_dict) - if d not in template_dirs: - template_dirs.append(d) - # reset final list self._meta.template_dirs = [] diff --git a/tests/core/test_foundation.py b/tests/core/test_foundation.py index 53c19a35..e17eb962 100644 --- a/tests/core/test_foundation.py +++ b/tests/core/test_foundation.py @@ -779,6 +779,49 @@ def test_template_dirs(tmp, rando): assert tmp.dir in app._meta.template_dirs +def test_template_dirs_config_override(tmp, rando): + class ThisTestApp(TestApp): + class Meta: + label = rando + template_dirs = ['/original/path'] + + with ThisTestApp() as app: + # Set template_dirs in config - should override Meta.template_dirs + app.config.set(app._meta.config_section, 'template_dirs', [tmp.dir, '/config/path2']) + app._setup_template_handler() + assert tmp.dir in app._meta.template_dirs + assert '/config/path2' in app._meta.template_dirs + assert '/original/path' not in app._meta.template_dirs + + +def test_template_dirs_string_conversion(tmp, rando): + class ThisTestApp(TestApp): + class Meta: + label = rando + + with ThisTestApp() as app: + # Set template_dirs as comma-separated string - should convert to list + app.config.set(app._meta.config_section, 'template_dirs', f'{tmp.dir}, /path2 , /path3') + app._setup_template_handler() + assert tmp.dir in app._meta.template_dirs + assert '/path2' in app._meta.template_dirs + assert '/path3' in app._meta.template_dirs + + +def test_template_dir_and_dirs_interaction(tmp, rando): + class ThisTestApp(TestApp): + class Meta: + label = rando + template_dir = '/single/dir' + + with ThisTestApp() as app: + # Both template_dir and template_dirs should be processed + app.config.set(app._meta.config_section, 'template_dirs', [tmp.dir]) + app._setup_template_handler() + assert tmp.dir in app._meta.template_dirs + assert '/single/dir' in app._meta.template_dirs + + def test_core_system_plugin_dirs(tmp, rando): class ThisTestApp(TestApp): class Meta: