Refs #23919 -- Replaced errno checking with PEP 3151 exceptions.

This commit is contained in:
Tim Graham 2017-01-25 10:13:08 -05:00 committed by GitHub
parent 3f0c4fe18f
commit 632c4ffd9c
12 changed files with 55 additions and 87 deletions

View File

@ -1,5 +1,4 @@
import datetime import datetime
import errno
import logging import logging
import os import os
import shutil import shutil
@ -133,13 +132,12 @@ class SessionStore(SessionBase):
flags |= os.O_EXCL | os.O_CREAT flags |= os.O_EXCL | os.O_CREAT
fd = os.open(session_file_name, flags) fd = os.open(session_file_name, flags)
os.close(fd) os.close(fd)
except FileNotFoundError:
except OSError as e: if not must_create:
if must_create and e.errno == errno.EEXIST:
raise CreateError
if not must_create and e.errno == errno.ENOENT:
raise UpdateError raise UpdateError
raise except FileExistsError:
if must_create:
raise CreateError
# Write the session file without interfering with other threads # Write the session file without interfering with other threads
# or processes. By writing to an atomically generated temporary # or processes. By writing to an atomically generated temporary

View File

@ -1,5 +1,4 @@
"File-based cache backend" "File-based cache backend"
import errno
import glob import glob
import hashlib import hashlib
import os import os
@ -34,9 +33,8 @@ class FileBasedCache(BaseCache):
with open(fname, 'rb') as f: with open(fname, 'rb') as f:
if not self._is_expired(f): if not self._is_expired(f):
return pickle.loads(zlib.decompress(f.read())) return pickle.loads(zlib.decompress(f.read()))
except IOError as e: except FileNotFoundError:
if e.errno != errno.ENOENT: pass
raise
return default return default
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
@ -64,11 +62,9 @@ class FileBasedCache(BaseCache):
return return
try: try:
os.remove(fname) os.remove(fname)
except OSError as e: except FileNotFoundError:
# ENOENT can happen if the cache file is removed (by another # The file may have been removed by another process.
# process) after the os.path.exists check. pass
if e.errno != errno.ENOENT:
raise
def has_key(self, key, version=None): def has_key(self, key, version=None):
fname = self._key_to_file(key, version) fname = self._key_to_file(key, version)
@ -99,11 +95,8 @@ class FileBasedCache(BaseCache):
if not os.path.exists(self._dir): if not os.path.exists(self._dir):
try: try:
os.makedirs(self._dir, 0o700) os.makedirs(self._dir, 0o700)
except OSError as e: except FileExistsError:
if e.errno != errno.EEXIST: pass
raise EnvironmentError(
"Cache directory '%s' does not exist "
"and could not be created'" % self._dir)
def _key_to_file(self, key, version=None): def _key_to_file(self, key, version=None):
""" """

View File

@ -71,10 +71,10 @@ def file_move_safe(old_file_name, new_file_name, chunk_size=1024 * 64, allow_ove
try: try:
os.remove(old_file_name) os.remove(old_file_name)
except OSError as e: except PermissionError as e:
# Certain operating systems (Cygwin and Windows) # Certain operating systems (Cygwin and Windows)
# fail when deleting opened files, ignore it. (For the # fail when deleting opened files, ignore it. (For the
# systems where this happens, temporary files will be auto-deleted # systems where this happens, temporary files will be auto-deleted
# on close anyway.) # on close anyway.)
if getattr(e, 'winerror', 0) != 32 and getattr(e, 'errno', 0) != 13: if getattr(e, 'winerror', 0) != 32:
raise raise

View File

@ -1,4 +1,3 @@
import errno
import os import os
from datetime import datetime from datetime import datetime
from urllib.parse import urljoin from urllib.parse import urljoin
@ -224,9 +223,6 @@ class FileSystemStorage(Storage):
full_path = self.path(name) full_path = self.path(name)
# Create any intermediate directories that do not exist. # Create any intermediate directories that do not exist.
# Note that there is a race between os.path.exists and os.makedirs:
# if os.makedirs fails with EEXIST, the directory was created
# concurrently, and we can continue normally. Refs #16082.
directory = os.path.dirname(full_path) directory = os.path.dirname(full_path)
if not os.path.exists(directory): if not os.path.exists(directory):
try: try:
@ -240,9 +236,11 @@ class FileSystemStorage(Storage):
os.umask(old_umask) os.umask(old_umask)
else: else:
os.makedirs(directory) os.makedirs(directory)
except OSError as e: except FileNotFoundError:
if e.errno != errno.EEXIST: # There's a race between os.path.exists() and os.makedirs().
raise # If os.makedirs() fails with FileNotFoundError, the directory
# was created concurrently.
pass
if not os.path.isdir(directory): if not os.path.isdir(directory):
raise IOError("%s exists and is not a directory." % directory) raise IOError("%s exists and is not a directory." % directory)
@ -280,13 +278,10 @@ class FileSystemStorage(Storage):
_file.close() _file.close()
else: else:
os.close(fd) os.close(fd)
except OSError as e: except FileExistsError:
if e.errno == errno.EEXIST: # A new name is needed if the file exists.
# Ooops, the file exists. We need a new file name. name = self.get_available_name(name)
name = self.get_available_name(name) full_path = self.path(name)
full_path = self.path(name)
else:
raise
else: else:
# OK, the file save worked. Break out of the loop. # OK, the file save worked. Break out of the loop.
break break
@ -301,13 +296,12 @@ class FileSystemStorage(Storage):
assert name, "The name argument is not allowed to be empty." assert name, "The name argument is not allowed to be empty."
name = self.path(name) name = self.path(name)
# If the file exists, delete it from the filesystem. # If the file exists, delete it from the filesystem.
# If os.remove() fails with ENOENT, the file may have been removed
# concurrently, and it's safe to continue normally.
try: try:
os.remove(name) os.remove(name)
except OSError as e: except FileNotFoundError:
if e.errno != errno.ENOENT: # If os.remove() fails with FileNotFoundError, the file may have
raise # been removed concurrently.
pass
def exists(self, name): def exists(self, name):
return os.path.exists(self.path(name)) return os.path.exists(self.path(name))

View File

@ -2,7 +2,6 @@
Classes representing uploaded files. Classes representing uploaded files.
""" """
import errno
import os import os
from io import BytesIO from io import BytesIO
@ -71,12 +70,11 @@ class TemporaryUploadedFile(UploadedFile):
def close(self): def close(self):
try: try:
return self.file.close() return self.file.close()
except OSError as e: except FileNotFoundError:
if e.errno != errno.ENOENT: # The file was moved or deleted before the tempfile could unlink
# Means the file was moved or deleted before the tempfile # it. Still sets self.file.close_called and calls
# could unlink it. Still sets self.file.close_called and # self.file.file.close() before the exception.
# calls self.file.file.close() before the exception pass
raise
class InMemoryUploadedFile(UploadedFile): class InMemoryUploadedFile(UploadedFile):

View File

@ -1,5 +1,4 @@
import cgi import cgi
import errno
import mimetypes import mimetypes
import os import os
import posixpath import posixpath
@ -76,12 +75,10 @@ class TemplateCommand(BaseCommand):
top_dir = path.join(os.getcwd(), name) top_dir = path.join(os.getcwd(), name)
try: try:
os.makedirs(top_dir) os.makedirs(top_dir)
except FileExistsError:
raise CommandError("'%s' already exists" % top_dir)
except OSError as e: except OSError as e:
if e.errno == errno.EEXIST: raise CommandError(e)
message = "'%s' already exists" % top_dir
else:
message = e
raise CommandError(message)
else: else:
top_dir = os.path.abspath(path.expanduser(target)) top_dir = os.path.abspath(path.expanduser(target))
if not os.path.exists(top_dir): if not os.path.exists(top_dir):

View File

@ -1,4 +1,3 @@
import errno
import string import string
from django.conf import settings from django.conf import settings
@ -31,14 +30,12 @@ class TemplateStrings(BaseEngine):
try: try:
with open(template_file, encoding=settings.FILE_CHARSET) as fp: with open(template_file, encoding=settings.FILE_CHARSET) as fp:
template_code = fp.read() template_code = fp.read()
except IOError as e: except FileNotFoundError:
if e.errno == errno.ENOENT: tried.append((
tried.append(( Origin(template_file, template_name, self),
Origin(template_file, template_name, self), 'Source does not exist',
'Source does not exist', ))
)) continue
continue
raise
return Template(template_code) return Template(template_code)

View File

@ -2,8 +2,6 @@
Wrapper for loading templates from the filesystem. Wrapper for loading templates from the filesystem.
""" """
import errno
from django.core.exceptions import SuspiciousFileOperation from django.core.exceptions import SuspiciousFileOperation
from django.template import Origin, TemplateDoesNotExist from django.template import Origin, TemplateDoesNotExist
from django.utils._os import safe_join from django.utils._os import safe_join
@ -24,10 +22,8 @@ class Loader(BaseLoader):
try: try:
with open(origin.name, encoding=self.engine.file_charset) as fp: with open(origin.name, encoding=self.engine.file_charset) as fp:
return fp.read() return fp.read()
except IOError as e: except FileNotFoundError:
if e.errno == errno.ENOENT: raise TemplateDoesNotExist(origin)
raise TemplateDoesNotExist(origin)
raise
def get_template_sources(self, template_name): def get_template_sources(self, template_name):
""" """

View File

@ -1360,7 +1360,7 @@ class FileBasedCacheTests(BaseCacheTests, TestCase):
# Returns the default instead of erroring. # Returns the default instead of erroring.
self.assertEqual(cache.get('foo', 'baz'), 'baz') self.assertEqual(cache.get('foo', 'baz'), 'baz')
def test_get_does_not_ignore_non_enoent_errno_values(self): def test_get_does_not_ignore_non_filenotfound_exceptions(self):
with mock.patch('builtins.open', side_effect=IOError): with mock.patch('builtins.open', side_effect=IOError):
with self.assertRaises(IOError): with self.assertRaises(IOError):
cache.get('foo') cache.get('foo')

View File

@ -1,4 +1,3 @@
import errno
import os import os
import shutil import shutil
import sys import sys
@ -416,9 +415,9 @@ class FileStorageTests(SimpleTestCase):
real_makedirs(path) real_makedirs(path)
elif path == os.path.join(self.temp_dir, 'raced'): elif path == os.path.join(self.temp_dir, 'raced'):
real_makedirs(path) real_makedirs(path)
raise OSError(errno.EEXIST, 'simulated EEXIST') raise FileNotFoundError()
elif path == os.path.join(self.temp_dir, 'error'): elif path == os.path.join(self.temp_dir, 'error'):
raise OSError(errno.EACCES, 'simulated EACCES') raise FileExistsError()
else: else:
self.fail('unexpected argument %r' % path) self.fail('unexpected argument %r' % path)
@ -433,8 +432,8 @@ class FileStorageTests(SimpleTestCase):
with self.storage.open('raced/test.file') as f: with self.storage.open('raced/test.file') as f:
self.assertEqual(f.read(), b'saved with race') self.assertEqual(f.read(), b'saved with race')
# OSErrors aside from EEXIST are still raised. # Exceptions aside from FileNotFoundError are raised.
with self.assertRaises(OSError): with self.assertRaises(FileExistsError):
self.storage.save('error/test.file', ContentFile('not saved')) self.storage.save('error/test.file', ContentFile('not saved'))
finally: finally:
os.makedirs = real_makedirs os.makedirs = real_makedirs
@ -452,9 +451,9 @@ class FileStorageTests(SimpleTestCase):
real_remove(path) real_remove(path)
elif path == os.path.join(self.temp_dir, 'raced.file'): elif path == os.path.join(self.temp_dir, 'raced.file'):
real_remove(path) real_remove(path)
raise OSError(errno.ENOENT, 'simulated ENOENT') raise FileNotFoundError()
elif path == os.path.join(self.temp_dir, 'error.file'): elif path == os.path.join(self.temp_dir, 'error.file'):
raise OSError(errno.EACCES, 'simulated EACCES') raise PermissionError()
else: else:
self.fail('unexpected argument %r' % path) self.fail('unexpected argument %r' % path)
@ -469,9 +468,9 @@ class FileStorageTests(SimpleTestCase):
self.storage.delete('raced.file') self.storage.delete('raced.file')
self.assertFalse(self.storage.exists('normal.file')) self.assertFalse(self.storage.exists('normal.file'))
# OSErrors aside from ENOENT are still raised. # Exceptions aside from FileNotFoundError are raised.
self.storage.save('error.file', ContentFile('delete with error')) self.storage.save('error.file', ContentFile('delete with error'))
with self.assertRaises(OSError): with self.assertRaises(PermissionError):
self.storage.delete('error.file') self.storage.delete('error.file')
finally: finally:
os.remove = real_remove os.remove = real_remove

View File

@ -1,5 +1,4 @@
import base64 import base64
import errno
import hashlib import hashlib
import json import json
import os import os
@ -564,9 +563,8 @@ class DirectoryCreationTests(SimpleTestCase):
"""Permission errors are not swallowed""" """Permission errors are not swallowed"""
os.chmod(MEDIA_ROOT, 0o500) os.chmod(MEDIA_ROOT, 0o500)
self.addCleanup(os.chmod, MEDIA_ROOT, 0o700) self.addCleanup(os.chmod, MEDIA_ROOT, 0o700)
with self.assertRaises(OSError) as cm: with self.assertRaises(PermissionError):
self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x'), save=False) self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x'), save=False)
self.assertEqual(cm.exception.errno, errno.EACCES)
def test_not_a_directory(self): def test_not_a_directory(self):
"""The correct IOError is raised when the upload directory name exists but isn't a directory""" """The correct IOError is raised when the upload directory name exists but isn't a directory"""

View File

@ -1,4 +1,3 @@
import errno
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -51,9 +50,8 @@ class PathNotImplementedStorage(storage.Storage):
name = self._path(name) name = self._path(name)
try: try:
os.remove(name) os.remove(name)
except OSError as e: except FileNotFoundError:
if e.errno != errno.ENOENT: pass
raise
def path(self, name): def path(self, name):
raise NotImplementedError raise NotImplementedError