Преглед изворни кода

Fixed #30147 -- Simplified directory creation with os.makedirs(..., exist_ok=True).

Jon Dufresne пре 6 година
родитељ
комит
290d8471bb

+ 1 - 4
django/contrib/staticfiles/management/commands/collectstatic.py

@@ -310,10 +310,7 @@ class Command(BaseCommand):
         else:
             self.log("Linking '%s'" % source_path, level=2)
             full_path = self.storage.path(prefixed_path)
-            try:
-                os.makedirs(os.path.dirname(full_path))
-            except OSError:
-                pass
+            os.makedirs(os.path.dirname(full_path), exist_ok=True)
             try:
                 if os.path.lexists(full_path):
                     os.unlink(full_path)

+ 1 - 5
django/core/cache/backends/filebased.py

@@ -113,11 +113,7 @@ class FileBasedCache(BaseCache):
             self._delete(fname)
 
     def _createdir(self):
-        if not os.path.exists(self._dir):
-            try:
-                os.makedirs(self._dir, 0o700)
-            except FileExistsError:
-                pass
+        os.makedirs(self._dir, 0o700, exist_ok=True)
 
     def _key_to_file(self, key, version=None):
         """

+ 12 - 18
django/core/files/storage.py

@@ -228,24 +228,18 @@ class FileSystemStorage(Storage):
 
         # Create any intermediate directories that do not exist.
         directory = os.path.dirname(full_path)
-        if not os.path.exists(directory):
-            try:
-                if self.directory_permissions_mode is not None:
-                    # os.makedirs applies the global umask, so we reset it,
-                    # for consistency with file_permissions_mode behavior.
-                    old_umask = os.umask(0)
-                    try:
-                        os.makedirs(directory, self.directory_permissions_mode)
-                    finally:
-                        os.umask(old_umask)
-                else:
-                    os.makedirs(directory)
-            except FileExistsError:
-                # There's a race between os.path.exists() and os.makedirs().
-                # If os.makedirs() fails with FileExistsError, the directory
-                # was created concurrently.
-                pass
-        if not os.path.isdir(directory):
+        try:
+            if self.directory_permissions_mode is not None:
+                # os.makedirs applies the global umask, so we reset it,
+                # for consistency with file_permissions_mode behavior.
+                old_umask = os.umask(0)
+                try:
+                    os.makedirs(directory, self.directory_permissions_mode, exist_ok=True)
+                finally:
+                    os.umask(old_umask)
+            else:
+                os.makedirs(directory, exist_ok=True)
+        except FileExistsError:
             raise FileExistsError('%s exists and is not a directory.' % directory)
 
         # There's a potential race condition between get_available_name and

+ 7 - 10
django/core/mail/backends/filebased.py

@@ -21,19 +21,16 @@ class EmailBackend(ConsoleEmailBackend):
         if not isinstance(self.file_path, str):
             raise ImproperlyConfigured('Path for saving emails is invalid: %r' % self.file_path)
         self.file_path = os.path.abspath(self.file_path)
-        # Make sure that self.file_path is a directory if it exists.
-        if os.path.exists(self.file_path) and not os.path.isdir(self.file_path):
+        try:
+            os.makedirs(self.file_path, exist_ok=True)
+        except FileExistsError:
             raise ImproperlyConfigured(
                 'Path for saving email messages exists, but is not a directory: %s' % self.file_path
             )
-        # Try to create it, if it not exists.
-        elif not os.path.exists(self.file_path):
-            try:
-                os.makedirs(self.file_path)
-            except OSError as err:
-                raise ImproperlyConfigured(
-                    'Could not create directory for saving email messages: %s (%s)' % (self.file_path, err)
-                )
+        except OSError as err:
+            raise ImproperlyConfigured(
+                'Could not create directory for saving email messages: %s (%s)' % (self.file_path, err)
+            )
         # Make sure that self.file_path is writable.
         if not os.access(self.file_path, os.W_OK):
             raise ImproperlyConfigured('Could not write to directory: %s' % self.file_path)

+ 2 - 4
django/core/management/commands/makemessages.py

@@ -356,8 +356,7 @@ class Command(BaseCommand):
                 self.locale_paths.append(os.path.abspath('locale'))
             if self.locale_paths:
                 self.default_locale_path = self.locale_paths[0]
-                if not os.path.exists(self.default_locale_path):
-                    os.makedirs(self.default_locale_path)
+                os.makedirs(self.default_locale_path, exist_ok=True)
 
         # Build locale list
         looks_like_locale = re.compile(r'[a-z]{2}')
@@ -598,8 +597,7 @@ class Command(BaseCommand):
         Use msgmerge and msgattrib GNU gettext utilities.
         """
         basedir = os.path.join(os.path.dirname(potfile), locale, 'LC_MESSAGES')
-        if not os.path.isdir(basedir):
-            os.makedirs(basedir)
+        os.makedirs(basedir, exist_ok=True)
         pofile = os.path.join(basedir, '%s.po' % self.domain)
 
         if os.path.exists(pofile):

+ 1 - 2
django/core/management/commands/makemigrations.py

@@ -210,8 +210,7 @@ class Command(BaseCommand):
                     # Write the migrations file to the disk.
                     migrations_directory = os.path.dirname(writer.path)
                     if not directory_created.get(app_label):
-                        if not os.path.isdir(migrations_directory):
-                            os.mkdir(migrations_directory)
+                        os.makedirs(migrations_directory, exist_ok=True)
                         init_path = os.path.join(migrations_directory, "__init__.py")
                         if not os.path.isfile(init_path):
                             open(init_path, "w").close()

+ 1 - 2
django/core/management/templates.py

@@ -120,8 +120,7 @@ class TemplateCommand(BaseCommand):
             relative_dir = path_rest.replace(base_name, name)
             if relative_dir:
                 target_dir = path.join(top_dir, relative_dir)
-                if not path.exists(target_dir):
-                    os.mkdir(target_dir)
+                os.makedirs(target_dir, exist_ok=True)
 
             for dirname in dirs[:]:
                 if dirname.startswith('.') or dirname == '__pycache__':

+ 2 - 2
django/db/migrations/writer.py

@@ -1,3 +1,4 @@
+
 import os
 import re
 from importlib import import_module
@@ -249,8 +250,7 @@ class MigrationWriter:
                 migrations_package_name)
 
         final_dir = os.path.join(base_dir, *missing_dirs)
-        if not os.path.isdir(final_dir):
-            os.makedirs(final_dir)
+        os.makedirs(final_dir, exist_ok=True)
         for missing_dir in missing_dirs:
             base_dir = os.path.join(base_dir, missing_dir)
             with open(os.path.join(base_dir, "__init__.py"), "w"):

+ 8 - 9
django/utils/archive.py

@@ -157,8 +157,8 @@ class TarArchive(BaseArchive):
                 name = self.split_leading_dir(name)[1]
             filename = os.path.join(to_path, name)
             if member.isdir():
-                if filename and not os.path.exists(filename):
-                    os.makedirs(filename)
+                if filename:
+                    os.makedirs(filename, exist_ok=True)
             else:
                 try:
                     extracted = self._archive.extractfile(member)
@@ -169,8 +169,8 @@ class TarArchive(BaseArchive):
                           (name, member.name, exc))
                 else:
                     dirname = os.path.dirname(filename)
-                    if dirname and not os.path.exists(dirname):
-                        os.makedirs(dirname)
+                    if dirname:
+                        os.makedirs(dirname, exist_ok=True)
                     with open(filename, 'wb') as outfile:
                         shutil.copyfileobj(extracted, outfile)
                         self._copy_permissions(member.mode, filename)
@@ -199,14 +199,13 @@ class ZipArchive(BaseArchive):
             if leading:
                 name = self.split_leading_dir(name)[1]
             filename = os.path.join(to_path, name)
-            dirname = os.path.dirname(filename)
-            if dirname and not os.path.exists(dirname):
-                os.makedirs(dirname)
             if filename.endswith(('/', '\\')):
                 # A directory
-                if not os.path.exists(filename):
-                    os.makedirs(filename)
+                os.makedirs(filename, exist_ok=True)
             else:
+                dirname = os.path.dirname(filename)
+                if dirname:
+                    os.makedirs(dirname, exist_ok=True)
                 with open(filename, 'wb') as outfile:
                     outfile.write(data)
                 # Convert ZipInfo.external_attr to mode

+ 1 - 2
tests/admin_scripts/tests.py

@@ -48,8 +48,7 @@ class AdminScriptTestCase(SimpleTestCase):
             cls.__name__,
             'test_project',
         ))
-        if not os.path.exists(cls.test_dir):
-            os.makedirs(cls.test_dir)
+        os.makedirs(cls.test_dir)
         with open(os.path.join(cls.test_dir, '__init__.py'), 'w'):
             pass
 

+ 5 - 4
tests/file_storage/tests.py

@@ -410,12 +410,13 @@ class FileStorageTests(SimpleTestCase):
 
         # Monkey-patch os.makedirs, to simulate a normal call, a raced call,
         # and an error.
-        def fake_makedirs(path):
+        def fake_makedirs(path, mode=0o777, exist_ok=False):
             if path == os.path.join(self.temp_dir, 'normal'):
-                real_makedirs(path)
+                real_makedirs(path, mode, exist_ok)
             elif path == os.path.join(self.temp_dir, 'raced'):
-                real_makedirs(path)
-                raise FileExistsError()
+                real_makedirs(path, mode, exist_ok)
+                if not exist_ok:
+                    raise FileExistsError()
             elif path == os.path.join(self.temp_dir, 'error'):
                 raise PermissionError()
             else:

+ 2 - 4
tests/file_uploads/tests.py

@@ -29,8 +29,7 @@ class FileUploadTests(TestCase):
     @classmethod
     def setUpClass(cls):
         super().setUpClass()
-        if not os.path.isdir(MEDIA_ROOT):
-            os.makedirs(MEDIA_ROOT)
+        os.makedirs(MEDIA_ROOT, exist_ok=True)
 
     @classmethod
     def tearDownClass(cls):
@@ -528,8 +527,7 @@ class DirectoryCreationTests(SimpleTestCase):
     @classmethod
     def setUpClass(cls):
         super().setUpClass()
-        if not os.path.isdir(MEDIA_ROOT):
-            os.makedirs(MEDIA_ROOT)
+        os.makedirs(MEDIA_ROOT, exist_ok=True)
 
     @classmethod
     def tearDownClass(cls):