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, OSError) 44 self.assertIs(socket.gaierror.__base__, OSError) 45 self.assertIs(socket.herror.__base__, OSError) 46 self.assertIs(socket.timeout, TimeoutError) 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, ENOTCAPABLE 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 if errname == "ENOTCAPABLE" and not hasattr(errno, errname): 79 continue 80 _map[getattr(errno, errname)] = getattr(builtins, excname) 81 return _map 82 _map = _make_map(_pep_map) 83 84 def test_errno_mapping(self): 85 # The OSError constructor maps errnos to subclasses 86 # A sample test for the basic functionality 87 e = OSError(EEXIST, "Bad file descriptor") 88 self.assertIs(type(e), FileExistsError) 89 # Exhaustive testing 90 for errcode, exc in self._map.items(): 91 e = OSError(errcode, "Some message") 92 self.assertIs(type(e), exc) 93 othercodes = set(errno.errorcode) - set(self._map) 94 for errcode in othercodes: 95 e = OSError(errcode, "Some message") 96 self.assertIs(type(e), OSError, repr(e)) 97 98 def test_try_except(self): 99 filename = "some_hopefully_non_existing_file" 100 101 # This checks that try .. except checks the concrete exception 102 # (FileNotFoundError) and not the base type specified when 103 # PyErr_SetFromErrnoWithFilenameObject was called. 104 # (it is therefore deliberate that it doesn't use assertRaises) 105 try: 106 open(filename) 107 except FileNotFoundError: 108 pass 109 else: 110 self.fail("should have raised a FileNotFoundError") 111 112 # Another test for PyErr_SetExcFromWindowsErrWithFilenameObject() 113 self.assertFalse(os.path.exists(filename)) 114 try: 115 os.unlink(filename) 116 except FileNotFoundError: 117 pass 118 else: 119 self.fail("should have raised a FileNotFoundError") 120 121 122class AttributesTest(unittest.TestCase): 123 124 def test_windows_error(self): 125 if os.name == "nt": 126 self.assertIn('winerror', dir(OSError)) 127 else: 128 self.assertNotIn('winerror', dir(OSError)) 129 130 def test_posix_error(self): 131 e = OSError(EEXIST, "File already exists", "foo.txt") 132 self.assertEqual(e.errno, EEXIST) 133 self.assertEqual(e.args[0], EEXIST) 134 self.assertEqual(e.strerror, "File already exists") 135 self.assertEqual(e.filename, "foo.txt") 136 if os.name == "nt": 137 self.assertEqual(e.winerror, None) 138 139 @unittest.skipUnless(os.name == "nt", "Windows-specific test") 140 def test_errno_translation(self): 141 # ERROR_ALREADY_EXISTS (183) -> EEXIST 142 e = OSError(0, "File already exists", "foo.txt", 183) 143 self.assertEqual(e.winerror, 183) 144 self.assertEqual(e.errno, EEXIST) 145 self.assertEqual(e.args[0], EEXIST) 146 self.assertEqual(e.strerror, "File already exists") 147 self.assertEqual(e.filename, "foo.txt") 148 149 def test_blockingioerror(self): 150 args = ("a", "b", "c", "d", "e") 151 for n in range(6): 152 e = BlockingIOError(*args[:n]) 153 with self.assertRaises(AttributeError): 154 e.characters_written 155 with self.assertRaises(AttributeError): 156 del e.characters_written 157 e = BlockingIOError("a", "b", 3) 158 self.assertEqual(e.characters_written, 3) 159 e.characters_written = 5 160 self.assertEqual(e.characters_written, 5) 161 del e.characters_written 162 with self.assertRaises(AttributeError): 163 e.characters_written 164 165 166class ExplicitSubclassingTest(unittest.TestCase): 167 168 def test_errno_mapping(self): 169 # When constructing an OSError subclass, errno mapping isn't done 170 e = SubOSError(EEXIST, "Bad file descriptor") 171 self.assertIs(type(e), SubOSError) 172 173 def test_init_overridden(self): 174 e = SubOSErrorWithInit("some message", "baz") 175 self.assertEqual(e.bar, "baz") 176 self.assertEqual(e.args, ("some message",)) 177 178 def test_init_kwdargs(self): 179 e = SubOSErrorWithInit("some message", bar="baz") 180 self.assertEqual(e.bar, "baz") 181 self.assertEqual(e.args, ("some message",)) 182 183 def test_new_overridden(self): 184 e = SubOSErrorWithNew("some message", "baz") 185 self.assertEqual(e.baz, "baz") 186 self.assertEqual(e.args, ("some message",)) 187 188 def test_new_kwdargs(self): 189 e = SubOSErrorWithNew("some message", baz="baz") 190 self.assertEqual(e.baz, "baz") 191 self.assertEqual(e.args, ("some message",)) 192 193 def test_init_new_overridden(self): 194 e = SubOSErrorCombinedInitFirst("some message", "baz") 195 self.assertEqual(e.bar, "baz") 196 self.assertEqual(e.baz, "baz") 197 self.assertEqual(e.args, ("some message",)) 198 e = SubOSErrorCombinedNewFirst("some message", "baz") 199 self.assertEqual(e.bar, "baz") 200 self.assertEqual(e.baz, "baz") 201 self.assertEqual(e.args, ("some message",)) 202 203 def test_init_standalone(self): 204 # __init__ doesn't propagate to OSError.__init__ (see issue #15229) 205 e = SubOSErrorWithStandaloneInit() 206 self.assertEqual(e.args, ()) 207 self.assertEqual(str(e), '') 208 209 210if __name__ == "__main__": 211 unittest.main() 212