Issue #17244: Don't mask exceptions raised during the creation of
bytecode files in py_compile.

Thanks to Arfrever Frehtes Taifersar Arahesis for the bug report.
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 03ca79f..77c14bc 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -474,6 +474,18 @@
     return source_path if _path_isfile(source_stats) else bytecode_path
 
 
+def _calc_mode(path):
+    """Calculate the mode permissions for a bytecode file."""
+    try:
+        mode = _os.stat(path).st_mode
+    except OSError:
+        mode = 0o666
+    # We always ensure write access so we can update cached files
+    # later even when the source files are read-only on Windows (#6074)
+    mode |= 0o200
+    return mode
+
+
 def _verbose_message(message, *args, verbosity=1):
     """Print the message to stderr if -v/PYTHONVERBOSE is turned on."""
     if sys.flags.verbose >= verbosity:
@@ -1060,13 +1072,7 @@
 
     def _cache_bytecode(self, source_path, bytecode_path, data):
         # Adapt between the two APIs
-        try:
-            mode = _os.stat(source_path).st_mode
-        except OSError:
-            mode = 0o666
-        # We always ensure write access so we can update cached files
-        # later even when the source files are read-only on Windows (#6074)
-        mode |= 0o200
+        mode = _calc_mode(source_path)
         return self.set_data(bytecode_path, data, _mode=mode)
 
     def set_data(self, path, data, *, _mode=0o666):
diff --git a/Lib/py_compile.py b/Lib/py_compile.py
index d255a2d..701e8ac 100644
--- a/Lib/py_compile.py
+++ b/Lib/py_compile.py
@@ -106,7 +106,7 @@
     source_bytes = loader.get_data(file)
     try:
         code = loader.source_to_code(source_bytes, dfile or file,
-                _optimize=optimize)
+                                     _optimize=optimize)
     except Exception as err:
         py_exc = PyCompileError(err.__class__, err, dfile or file)
         if doraise:
@@ -121,11 +121,13 @@
     except FileExistsError:
         pass
     source_stats = loader.path_stats(file)
-    bytecode = importlib._bootstrap._code_to_bytecode(code,
-        source_stats['mtime'], len(source_bytes))
-    loader._cache_bytecode(file, cfile, bytecode)
+    bytecode = importlib._bootstrap._code_to_bytecode(
+            code, source_stats['mtime'], source_stats['size'])
+    mode = importlib._bootstrap._calc_mode(file)
+    importlib._bootstrap._write_atomic(cfile, bytecode, mode)
     return cfile
 
+
 def main(args=None):
     """Compile several source files.
 
diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py
index f3c1a6a..13947b1 100644
--- a/Lib/test/test_py_compile.py
+++ b/Lib/test/test_py_compile.py
@@ -2,6 +2,7 @@
 import os
 import py_compile
 import shutil
+import stat
 import tempfile
 import unittest
 
@@ -54,8 +55,18 @@
         self.assertTrue(os.path.exists(self.pyc_path))
         self.assertFalse(os.path.exists(self.cache_path))
 
-def test_main():
-    support.run_unittest(PyCompileTests)
+    def test_exceptions_propagate(self):
+        # Make sure that exceptions raised thanks to issues with writing
+        # bytecode.
+        # http://bugs.python.org/issue17244
+        mode = os.stat(self.directory)
+        os.chmod(self.directory, stat.S_IREAD)
+        try:
+            with self.assertRaises(IOError):
+                py_compile.compile(self.source_path, self.pyc_path)
+        finally:
+            os.chmod(self.directory, mode.st_mode)
+
 
 if __name__ == "__main__":
-    test_main()
+    unittest.main()
\ No newline at end of file