1import builtins 2import os 3import select 4import socket 5import unittest 6import errno 7from errno import EEXIST 8 9 10class SubOSError(OSError): 11 pass 12 13class SubOSErrorWithInit(OSError): 14 def __init__(self, message, bar): 15 self.bar = bar 16 super().__init__(message) 17 18class SubOSErrorWithNew(OSError): 19 def __new__(cls, message, baz): 20 self = super().__new__(cls, message) 21 self.baz = baz 22 return self 23 24class SubOSErrorCombinedInitFirst(SubOSErrorWithInit, SubOSErrorWithNew): 25 pass 26 27class SubOSErrorCombinedNewFirst(SubOSErrorWithNew, SubOSErrorWithInit): 28 pass 29 30class SubOSErrorWithStandaloneInit(OSError): 31 def __init__(self): 32 pass 33 34 35class HierarchyTest(unittest.TestCase): 36 37 def test_builtin_errors(self): 38 self.assertEqual(OSError.__name__, 'OSError') 39 self.assertIs(IOError, OSError) 40 self.assertIs(EnvironmentError, OSError) 41 42 def test_socket_errors(self): 43 self.assertIs(socket.error, IOError) 44 self.assertIs(socket.gaierror.__base__, OSError) 45 self.assertIs(socket.herror.__base__, OSError) 46 self.assertIs(socket.timeout.__base__, OSError) 47 48 def test_select_error(self): 49 self.assertIs(select.error, OSError) 50 51 # mmap.error is tested in test_mmap 52 53 _pep_map = """ 54 +-- BlockingIOError EAGAIN, EALREADY, EWOULDBLOCK, EINPROGRESS 55 +-- ChildProcessError ECHILD 56 +-- ConnectionError 57 +-- BrokenPipeError EPIPE, ESHUTDOWN 58 +-- ConnectionAbortedError ECONNABORTED 59 +-- ConnectionRefusedError ECONNREFUSED 60 +-- ConnectionResetError ECONNRESET 61 +-- FileExistsError EEXIST 62 +-- FileNotFoundError ENOENT 63 +-- InterruptedError EINTR 64 +-- IsADirectoryError EISDIR 65 +-- NotADirectoryError ENOTDIR 66 +-- PermissionError EACCES, EPERM 67 +-- ProcessLookupError ESRCH 68 +-- TimeoutError ETIMEDOUT 69 """ 70 def _make_map(s): 71 _map = {} 72 for line in s.splitlines(): 73 line = line.strip('+- ') 74 if not line: 75 continue 76 excname, _, errnames = line.partition(' ') 77 for errname in filter(None, errnames.strip().split(', ')): 78 _map[getattr(errno, errname)] = getattr(builtins, excname) 79 return _map 80 _map = _make_map(_pep_map) 81 82 def test_errno_mapping(self): 83 # The OSError constructor maps errnos to subclasses 84 # A sample test for the basic functionality 85 e = OSError(EEXIST, "Bad file descriptor") 86 self.assertIs(type(e), FileExistsError) 87 # Exhaustive testing 88 for errcode, exc in self._map.items(): 89 e = OSError(errcode, "Some message") 90 self.assertIs(type(e), exc) 91 othercodes = set(errno.errorcode) - set(self._map) 92 for errcode in othercodes: 93 e = OSError(errcode, "Some message") 94 self.assertIs(type(e), OSError) 95 96 def test_try_except(self): 97 filename = "some_hopefully_non_existing_file" 98 99 # This checks that try .. except checks the concrete exception 100 # (FileNotFoundError) and not the base type specified when 101 # PyErr_SetFromErrnoWithFilenameObject was called. 102 # (it is therefore deliberate that it doesn't use assertRaises) 103 try: 104 open(filename) 105 except FileNotFoundError: 106 pass 107 else: 108 self.fail("should have raised a FileNotFoundError") 109 110 # Another test for PyErr_SetExcFromWindowsErrWithFilenameObject() 111 self.assertFalse(os.path.exists(filename)) 112 try: 113 os.unlink(filename) 114 except FileNotFoundError: 115 pass 116 else: 117 self.fail("should have raised a FileNotFoundError") 118 119 120class AttributesTest(unittest.TestCase): 121 122 def test_windows_error(self): 123 if os.name == "nt": 124 self.assertIn('winerror', dir(OSError)) 125 else: 126 self.assertNotIn('winerror', dir(OSError)) 127 128 def test_posix_error(self): 129 e = OSError(EEXIST, "File already exists", "foo.txt") 130 self.assertEqual(e.errno, EEXIST) 131 self.assertEqual(e.args[0], EEXIST) 132 self.assertEqual(e.strerror, "File already exists") 133 self.assertEqual(e.filename, "foo.txt") 134 if os.name == "nt": 135 self.assertEqual(e.winerror, None) 136 137 @unittest.skipUnless(os.name == "nt", "Windows-specific test") 138 def test_errno_translation(self): 139 # ERROR_ALREADY_EXISTS (183) -> EEXIST 140 e = OSError(0, "File already exists", "foo.txt", 183) 141 self.assertEqual(e.winerror, 183) 142 self.assertEqual(e.errno, EEXIST) 143 self.assertEqual(e.args[0], EEXIST) 144 self.assertEqual(e.strerror, "File already exists") 145 self.assertEqual(e.filename, "foo.txt") 146 147 def test_blockingioerror(self): 148 args = ("a", "b", "c", "d", "e") 149 for n in range(6): 150 e = BlockingIOError(*args[:n]) 151 with self.assertRaises(AttributeError): 152 e.characters_written 153 with self.assertRaises(AttributeError): 154 del e.characters_written 155 e = BlockingIOError("a", "b", 3) 156 self.assertEqual(e.characters_written, 3) 157 e.characters_written = 5 158 self.assertEqual(e.characters_written, 5) 159 del e.characters_written 160 with self.assertRaises(AttributeError): 161 e.characters_written 162 163 164class ExplicitSubclassingTest(unittest.TestCase): 165 166 def test_errno_mapping(self): 167 # When constructing an OSError subclass, errno mapping isn't done 168 e = SubOSError(EEXIST, "Bad file descriptor") 169 self.assertIs(type(e), SubOSError) 170 171 def test_init_overridden(self): 172 e = SubOSErrorWithInit("some message", "baz") 173 self.assertEqual(e.bar, "baz") 174 self.assertEqual(e.args, ("some message",)) 175 176 def test_init_kwdargs(self): 177 e = SubOSErrorWithInit("some message", bar="baz") 178 self.assertEqual(e.bar, "baz") 179 self.assertEqual(e.args, ("some message",)) 180 181 def test_new_overridden(self): 182 e = SubOSErrorWithNew("some message", "baz") 183 self.assertEqual(e.baz, "baz") 184 self.assertEqual(e.args, ("some message",)) 185 186 def test_new_kwdargs(self): 187 e = SubOSErrorWithNew("some message", baz="baz") 188 self.assertEqual(e.baz, "baz") 189 self.assertEqual(e.args, ("some message",)) 190 191 def test_init_new_overridden(self): 192 e = SubOSErrorCombinedInitFirst("some message", "baz") 193 self.assertEqual(e.bar, "baz") 194 self.assertEqual(e.baz, "baz") 195 self.assertEqual(e.args, ("some message",)) 196 e = SubOSErrorCombinedNewFirst("some message", "baz") 197 self.assertEqual(e.bar, "baz") 198 self.assertEqual(e.baz, "baz") 199 self.assertEqual(e.args, ("some message",)) 200 201 def test_init_standalone(self): 202 # __init__ doesn't propagate to OSError.__init__ (see issue #15229) 203 e = SubOSErrorWithStandaloneInit() 204 self.assertEqual(e.args, ()) 205 self.assertEqual(str(e), '') 206 207 208if __name__ == "__main__": 209 unittest.main() 210