This commit is contained in:
Eduardo Cuducos 2022-08-05 16:43:24 +02:00 committed by GitHub
commit abff70bac1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 9 deletions

View file

@ -3,6 +3,7 @@ import copy
import decimal
import os
import sys
from pathlib import Path
from django.core import validators
from django.core.exceptions import ValidationError, ImproperlyConfigured
@ -389,16 +390,20 @@ class RegexValue(ValidationMixin, Value):
class PathValue(Value):
use_pathlib = False
def __init__(self, *args, **kwargs):
self.check_exists = kwargs.pop('check_exists', True)
self.use_pathlib = kwargs.pop('use_pathlib', PathValue.use_pathlib)
super().__init__(*args, **kwargs)
def setup(self, name):
value = super().setup(name)
value = os.path.expanduser(value)
if self.check_exists and not os.path.exists(value):
value = Path(value).expanduser()
if self.check_exists and not value.exists():
raise ValueError('Path {0!r} does not exist.'.format(value))
return os.path.abspath(value)
value = value.absolute()
return value if self.use_pathlib else str(value)
class SecretValue(Value):

View file

@ -407,20 +407,25 @@ Validator values
DEFAULT_SKU = values.RegexValue('000-000-00', regex=r'\d{3}-\d{3}-\d{2}')
.. class:: PathValue(default, [check_exists=True, environ=True, environ_name=None, environ_prefix='DJANGO'])
.. class:: PathValue(default, [check_exists=True, use_pathlib=False, environ=True, environ_name=None, environ_prefix='DJANGO'])
A :class:`~Value` subclass that normalizes the given path using
:func:`os.path.expanduser` and checks if it exists on the file system.
:func:`pathlib.Path.expanduser` and checks if it exists on the file system.
Takes an optional ``check_exists`` parameter to disable the check with
:func:`os.path.exists`.
:func:`pathlib.Path.exists`, and an optional ``use_pathlib`` to return the
path as a :class:`pathlib.Path` instance. The default return value is a
:func:`str`.
:param check_exists: toggle the file system check
:param use_pathlib: return the path as a :class:`pathlib.Path` instance
::
BASE_DIR = values.PathValue('/opt/mysite/')
STATIC_ROOT = values.PathValue('/var/www/static', checks_exists=False)
STATICFILES_DIRS = values.PathValue('assets/', use_pathlib=True)
URL-based values
^^^^^^^^^^^^^^^^

View file

@ -1,6 +1,7 @@
import decimal
import os
from contextlib import contextmanager
from pathlib import Path
from django import VERSION as DJANGO_VERSION
from django.test import TestCase
@ -347,12 +348,33 @@ class ValueTests(TestCase):
with env(DJANGO_TEST='/'):
self.assertEqual(value.setup('TEST'), '/')
with env(DJANGO_TEST='~/spam/eggs'):
self.assertEqual(value.setup('TEST'),
os.path.join(os.path.expanduser('~'),
'spam', 'eggs'))
self.assertEqual(
value.setup('TEST'),
os.path.join(os.path.expanduser('~'), 'spam', 'eggs'),
)
with env(DJANGO_TEST='/does/not/exist'):
self.assertEqual(value.setup('TEST'), '/does/not/exist')
def test_path_values_use_pathlib(self):
value = PathValue(use_pathlib=True)
with env(DJANGO_TEST='/'):
self.assertEqual(value.setup('TEST'), Path('/'))
with env(DJANGO_TEST='~/'):
self.assertEqual(value.setup('TEST'), Path.home())
with env(DJANGO_TEST='/does/not/exist'):
self.assertRaises(ValueError, value.setup, 'TEST')
def test_path_values_use_pathlib_global(self):
PathValue.use_pathlib = True
try:
value = PathValue()
self.assertTrue(value.use_pathlib)
with env(DJANGO_TEST='/'):
self.assertEqual(value.setup('TEST'), Path('/'))
finally:
# Reset global state
PathValue.use_pathlib = False
def test_secret_value(self):
# no default allowed, only environment values are
self.assertRaises(ValueError, SecretValue, 'default')