mirror of https://github.com/django/django.git
Refs #29983 -- Added support for using pathlib.Path in all settings.
This commit is contained in:
parent
367634f976
commit
77aa74cb70
|
@ -21,7 +21,7 @@ class Command(LabelCommand):
|
|||
if verbosity >= 2:
|
||||
searched_locations = (
|
||||
"\nLooking in the following locations:\n %s" %
|
||||
"\n ".join(finders.searched_locations)
|
||||
"\n ".join([str(loc) for loc in finders.searched_locations])
|
||||
)
|
||||
else:
|
||||
searched_locations = ''
|
||||
|
|
|
@ -174,7 +174,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
"settings.DATABASES is improperly configured. "
|
||||
"Please supply the NAME value.")
|
||||
kwargs = {
|
||||
'database': settings_dict['NAME'],
|
||||
# TODO: Remove str() when dropping support for PY36.
|
||||
# https://bugs.python.org/issue33496
|
||||
'database': str(settings_dict['NAME']),
|
||||
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
|
||||
**settings_dict['OPTIONS'],
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from django.db.backends.base.creation import BaseDatabaseCreation
|
||||
|
||||
|
@ -9,7 +10,9 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
|
||||
@staticmethod
|
||||
def is_in_memory_db(database_name):
|
||||
return database_name == ':memory:' or 'mode=memory' in database_name
|
||||
return not isinstance(database_name, Path) and (
|
||||
database_name == ':memory:' or 'mode=memory' in database_name
|
||||
)
|
||||
|
||||
def _get_test_db_name(self):
|
||||
test_database_name = self.connection.settings_dict['TEST']['NAME'] or ':memory:'
|
||||
|
|
|
@ -39,7 +39,7 @@ class EngineMixin:
|
|||
def engine(self):
|
||||
return self.backend({
|
||||
'APP_DIRS': True,
|
||||
'DIRS': [str(ROOT / self.backend.app_dirname)],
|
||||
'DIRS': [ROOT / self.backend.app_dirname],
|
||||
'NAME': 'djangoforms',
|
||||
'OPTIONS': {},
|
||||
})
|
||||
|
|
|
@ -99,7 +99,7 @@ def get_app_template_dirs(dirname):
|
|||
installed applications.
|
||||
"""
|
||||
template_dirs = [
|
||||
str(Path(app_config.path) / dirname)
|
||||
Path(app_config.path) / dirname
|
||||
for app_config in apps.get_app_configs()
|
||||
if app_config.path and (Path(app_config.path) / dirname).is_dir()
|
||||
]
|
||||
|
|
|
@ -96,7 +96,7 @@ Minor features
|
|||
:mod:`django.contrib.staticfiles`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* ...
|
||||
* The :setting:`STATICFILES_DIRS` setting now supports :class:`pathlib.Path`.
|
||||
|
||||
:mod:`django.contrib.syndication`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -226,6 +226,12 @@ Validators
|
|||
|
||||
* ...
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The SQLite backend now supports :class:`pathlib.Path` for the ``NAME``
|
||||
setting.
|
||||
|
||||
.. _backwards-incompatible-3.1:
|
||||
|
||||
Backwards incompatible changes in 3.1
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import os
|
||||
import re
|
||||
import tempfile
|
||||
import threading
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from sqlite3 import dbapi2
|
||||
from unittest import mock
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import connection, transaction
|
||||
from django.db import ConnectionHandler, connection, transaction
|
||||
from django.db.models import Avg, StdDev, Sum, Variance
|
||||
from django.db.models.aggregates import Aggregate
|
||||
from django.db.models.fields import CharField
|
||||
|
@ -89,6 +92,19 @@ class Tests(TestCase):
|
|||
value = bool(value) if value in {0, 1} else value
|
||||
self.assertIs(value, expected)
|
||||
|
||||
def test_pathlib_name(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
settings_dict = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': Path(tmp) / 'test.db',
|
||||
},
|
||||
}
|
||||
connections = ConnectionHandler(settings_dict)
|
||||
connections['default'].ensure_connection()
|
||||
connections['default'].close()
|
||||
self.assertTrue(os.path.isfile(os.path.join(tmp, 'test.db')))
|
||||
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'sqlite', 'SQLite tests')
|
||||
@isolate_apps('backends')
|
||||
|
|
|
@ -227,3 +227,12 @@ class AppCompilationTest(ProjectAndAppTests):
|
|||
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
||||
self.assertTrue(os.path.exists(self.PROJECT_MO_FILE))
|
||||
self.assertTrue(os.path.exists(self.APP_MO_FILE))
|
||||
|
||||
|
||||
class PathLibLocaleCompilationTests(MessageCompilationTests):
|
||||
work_subdir = 'exclude'
|
||||
|
||||
def test_locale_paths_pathlib(self):
|
||||
with override_settings(LOCALE_PATHS=[Path(self.test_dir) / 'canned_locale']):
|
||||
call_command('compilemessages', locale=['fr'], stdout=StringIO())
|
||||
self.assertTrue(os.path.exists('canned_locale/fr/LC_MESSAGES/django.mo'))
|
||||
|
|
|
@ -5,6 +5,7 @@ import tempfile
|
|||
import time
|
||||
import warnings
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from unittest import mock, skipIf, skipUnless
|
||||
|
||||
from admin_scripts.tests import AdminScriptTestCase
|
||||
|
@ -735,11 +736,17 @@ class CustomLayoutExtractionTests(ExtractorTests):
|
|||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
|
||||
def test_project_locale_paths(self):
|
||||
self._test_project_locale_paths(os.path.join(self.test_dir, 'project_locale'))
|
||||
|
||||
def test_project_locale_paths_pathlib(self):
|
||||
self._test_project_locale_paths(Path(self.test_dir) / 'project_locale')
|
||||
|
||||
def _test_project_locale_paths(self, locale_path):
|
||||
"""
|
||||
* translations for an app containing a locale folder are stored in that folder
|
||||
* translations outside of that app are in LOCALE_PATHS[0]
|
||||
"""
|
||||
with override_settings(LOCALE_PATHS=[os.path.join(self.test_dir, 'project_locale')]):
|
||||
with override_settings(LOCALE_PATHS=[locale_path]):
|
||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||
project_de_locale = os.path.join(
|
||||
self.test_dir, 'project_locale', 'de', 'LC_MESSAGES', 'django.po')
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.files import temp
|
||||
from django.core.files.base import ContentFile
|
||||
|
@ -94,3 +96,10 @@ class FileFieldTests(TestCase):
|
|||
# open() doesn't write to disk.
|
||||
d.myfile.file = ContentFile(b'', name='bla')
|
||||
self.assertEqual(d.myfile, d.myfile.open())
|
||||
|
||||
def test_media_root_pathlib(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
with override_settings(MEDIA_ROOT=Path(tmp_dir)):
|
||||
with TemporaryUploadedFile('foo.txt', 'text/plain', 1, 'utf-8') as tmp_file:
|
||||
Document.objects.create(myfile=tmp_file)
|
||||
self.assertTrue(os.path.exists(os.path.join(tmp_dir, 'unused', 'foo.txt')))
|
||||
|
|
|
@ -6,6 +6,7 @@ import tempfile
|
|||
import unittest
|
||||
from datetime import timedelta
|
||||
from http import cookies
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.backends.base import UpdateError
|
||||
|
@ -521,7 +522,7 @@ class FileSessionTests(SessionTestsMixin, unittest.TestCase):
|
|||
def setUp(self):
|
||||
# Do file session tests in an isolated directory, and kill it after we're done.
|
||||
self.original_session_file_path = settings.SESSION_FILE_PATH
|
||||
self.temp_session_store = settings.SESSION_FILE_PATH = tempfile.mkdtemp()
|
||||
self.temp_session_store = settings.SESSION_FILE_PATH = self.mkdtemp()
|
||||
# Reset the file session backend's internal caches
|
||||
if hasattr(self.backend, '_storage_path'):
|
||||
del self.backend._storage_path
|
||||
|
@ -532,6 +533,9 @@ class FileSessionTests(SessionTestsMixin, unittest.TestCase):
|
|||
settings.SESSION_FILE_PATH = self.original_session_file_path
|
||||
shutil.rmtree(self.temp_session_store)
|
||||
|
||||
def mkdtemp(self):
|
||||
return tempfile.mkdtemp()
|
||||
|
||||
@override_settings(
|
||||
SESSION_FILE_PATH='/if/this/directory/exists/you/have/a/weird/computer',
|
||||
)
|
||||
|
@ -598,6 +602,12 @@ class FileSessionTests(SessionTestsMixin, unittest.TestCase):
|
|||
self.assertEqual(1, count_sessions())
|
||||
|
||||
|
||||
class FileSessionPathLibTests(FileSessionTests):
|
||||
def mkdtemp(self):
|
||||
tmp_dir = super().mkdtemp()
|
||||
return Path(tmp_dir)
|
||||
|
||||
|
||||
class CacheSessionTests(SessionTestsMixin, unittest.TestCase):
|
||||
|
||||
backend = CacheSession
|
||||
|
|
|
@ -64,7 +64,7 @@ class CollectionTestCase(BaseStaticFilesMixin, SimpleTestCase):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
temp_dir = self.mkdtemp()
|
||||
# Override the STATIC_ROOT for all tests from setUp to tearDown
|
||||
# rather than as a context manager
|
||||
self.patched_settings = self.settings(STATIC_ROOT=temp_dir)
|
||||
|
@ -78,6 +78,9 @@ class CollectionTestCase(BaseStaticFilesMixin, SimpleTestCase):
|
|||
self.patched_settings.disable()
|
||||
super().tearDown()
|
||||
|
||||
def mkdtemp(self):
|
||||
return tempfile.mkdtemp()
|
||||
|
||||
def run_collectstatic(self, *, verbosity=0, **kwargs):
|
||||
call_command('collectstatic', interactive=False, verbosity=verbosity,
|
||||
ignore_patterns=['*.ignoreme'], **kwargs)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pathlib
|
|
@ -1,4 +1,5 @@
|
|||
import os.path
|
||||
from pathlib import Path
|
||||
|
||||
TEST_ROOT = os.path.dirname(__file__)
|
||||
|
||||
|
@ -10,6 +11,7 @@ TEST_SETTINGS = {
|
|||
'STATICFILES_DIRS': [
|
||||
os.path.join(TEST_ROOT, 'project', 'documents'),
|
||||
('prefix', os.path.join(TEST_ROOT, 'project', 'prefixed')),
|
||||
Path(TEST_ROOT) / 'project' / 'pathlib',
|
||||
],
|
||||
'STATICFILES_FINDERS': [
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
|
|
|
@ -4,6 +4,7 @@ import shutil
|
|||
import tempfile
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from admin_scripts.tests import AdminScriptTestCase
|
||||
|
@ -102,6 +103,7 @@ class TestFindStatic(TestDefaults, CollectionTestCase):
|
|||
# FileSystemFinder searched locations
|
||||
self.assertIn(TEST_SETTINGS['STATICFILES_DIRS'][1][1], searched_locations)
|
||||
self.assertIn(TEST_SETTINGS['STATICFILES_DIRS'][0], searched_locations)
|
||||
self.assertIn(str(TEST_SETTINGS['STATICFILES_DIRS'][2]), searched_locations)
|
||||
# DefaultStorageFinder searched locations
|
||||
self.assertIn(
|
||||
os.path.join('staticfiles_tests', 'project', 'site_media', 'media'),
|
||||
|
@ -174,6 +176,15 @@ class TestCollection(TestDefaults, CollectionTestCase):
|
|||
self.assertFileNotFound('test/backup~')
|
||||
self.assertFileNotFound('test/CVS')
|
||||
|
||||
def test_pathlib(self):
|
||||
self.assertFileContains('pathlib.txt', 'pathlib')
|
||||
|
||||
|
||||
class TestCollectionPathLib(TestCollection):
|
||||
def mkdtemp(self):
|
||||
tmp_dir = super().mkdtemp()
|
||||
return Path(tmp_dir)
|
||||
|
||||
|
||||
class TestCollectionVerbosity(CollectionTestCase):
|
||||
copying_msg = 'Copying '
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from pathlib import Path
|
||||
|
||||
from template_tests.test_response import test_processor_name
|
||||
|
||||
from django.template import Context, EngineHandler, RequestContext
|
||||
|
@ -164,3 +166,13 @@ class DjangoTemplatesTests(TemplateStringsTests):
|
|||
def test_debug_default_template_loaders(self):
|
||||
engine = DjangoTemplates({'DIRS': [], 'APP_DIRS': True, 'NAME': 'django', 'OPTIONS': {}})
|
||||
self.assertEqual(engine.engine.loaders, self.default_loaders)
|
||||
|
||||
def test_dirs_pathlib(self):
|
||||
engine = DjangoTemplates({
|
||||
'DIRS': [Path(__file__).parent / 'templates' / 'template_backends'],
|
||||
'APP_DIRS': False,
|
||||
'NAME': 'django',
|
||||
'OPTIONS': {},
|
||||
})
|
||||
template = engine.get_template('hello.html')
|
||||
self.assertEqual(template.render({'name': 'Joe'}), 'Hello Joe!\n')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from pathlib import Path
|
||||
from unittest import skipIf
|
||||
|
||||
from django.template import TemplateSyntaxError
|
||||
|
@ -85,3 +86,13 @@ class Jinja2Tests(TemplateStringsTests):
|
|||
with self.settings(STATIC_URL='/s/'):
|
||||
content = template.render(request=request)
|
||||
self.assertEqual(content, 'Static URL: /s/')
|
||||
|
||||
def test_dirs_pathlib(self):
|
||||
engine = Jinja2({
|
||||
'DIRS': [Path(__file__).parent / 'templates' / 'template_backends'],
|
||||
'APP_DIRS': False,
|
||||
'NAME': 'jinja2',
|
||||
'OPTIONS': {},
|
||||
})
|
||||
template = engine.get_template('hello.html')
|
||||
self.assertEqual(template.render({'name': 'Joe'}), 'Hello Joe!')
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
@ -52,3 +53,8 @@ class LocaleRegexDescriptorTests(SimpleTestCase):
|
|||
|
||||
def test_access_locale_regex_descriptor(self):
|
||||
self.assertIsInstance(RegexPattern.regex, LocaleRegexDescriptor)
|
||||
|
||||
|
||||
@override_settings(LOCALE_PATHS=[Path(here) / 'translations' / 'locale'])
|
||||
class LocaleRegexDescriptorPathLibTests(LocaleRegexDescriptorTests):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue