diff -r c793d62cdecc Lib/test/test_import.py --- a/Lib/test/test_import.py Sun Aug 19 17:57:29 2012 -0400 +++ b/Lib/test/test_import.py Mon Aug 20 16:39:35 2012 +1000 @@ -10,9 +10,8 @@ import textwrap import shutil -from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree, - is_jython, check_warnings, EnvironmentVarGuard) -from test import symlink_support +from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree, is_jython, check_warnings, EnvironmentVarGuard) +import symlink_support from test import script_helper def remove_files(name): @@ -119,7 +118,7 @@ remove_files(TESTFN) unload(TESTFN) del sys.path[0] - + def test_imp_module(self): # Verify that the imp module can correctly load and find .py files @@ -305,7 +304,73 @@ del sys.path[0] remove_files(TESTFN) +class FilePermissionTests(unittest.TestCase): + def setUp(self): + self.filename = 'readonlyPermission' + self.pyfilename = self.filename + os.extsep + 'py' + self.pycfilename = self.filename + os.extsep + 'pyc' + self.pyofilename = self.filename + os.extsep + 'pyo' + def tearDown(self): + self.clean_up_file(self.pyfilename) + self.clean_up_file(self.pycfilename) + self.clean_up_file(self.pyofilename) + + def clean_up_file(self,filename): + if os.path.exists(filename): + os.chmod(filename, (stat.S_IWUSR | stat.S_IRUSR)) + os.remove(filename) + def check_py_file_permission(self, permission): + # Check that the created .pyc and .pyo have exactly the same + # read/write permission as the .py file + print '-' * 50 + print 'test_imp_file_permission' + + self.create_file_and_check( permission ) + + self.clean_up_file(self.pyfilename) + + self.create_file_and_check( permission ) + + def create_file_and_check(self,permission): + p = permission + f = open(self.pyfilename, 'w').close() + # os.chmod(self.pyfilename, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)) + os.chmod(self.pyfilename, p) + s_py = os.stat(self.pyfilename) + print s_py + print 'stat.S_IMODE(s_py.st_mode): o%o' % stat.S_IMODE(s_py.st_mode) + + # assert .py file has read-only permission + # 0444 on windows and 0400 on other systems + if os.name == 'nt': + self.assertEqual( stat.S_IMODE(s_py.st_mode), + p | p >> 3 | p >> 6 ) + else: + self.assertEqual( stat.S_IMODE(s_py.st_mode), + p ) + + import imp + imp.load_module(self.filename, *imp.find_module(self.filename)) + # __import__( filename ) + s_pyc = os.stat(self.pycfilename) + print 'stat.S_IMODE(s_pyc.st_mode): o%o' % stat.S_IMODE(s_pyc.st_mode) + + # assert .pyc file also has read-only permission + # 0444 on windows and 0400 on other systems + if os.name == 'nt': + self.assertEqual( stat.S_IMODE(s_py.st_mode), + p | p >> 3 | p >> 6 ) + else: + self.assertEqual( stat.S_IMODE(s_py.st_mode), + p ) + + def test_readonly_permission(self): + self.check_py_file_permission( permission=stat.S_IRUSR ) + + def test_write_permission(self): + self.check_py_file_permission( permission=(stat.S_IWUSR | stat.S_IRUSR) ) + class PycRewritingTests(unittest.TestCase): # Test that the `co_filename` attribute on code objects always points # to the right file, even when various things happen (e.g. both the .py @@ -548,8 +613,10 @@ sys.path[:] = self.orig_sys_path def test_main(verbose=None): - run_unittest(ImportTests, PycRewritingTests, PathsTests, - RelativeImportTests, TestSymbolicallyLinkedPackage) + # run_unittest(ImportTests, PycRewritingTests, PathsTests, + # RelativeImportTests, TestSymbolicallyLinkedPackage, + # FilePermissionTests) + run_unittest(FilePermissionTests) if __name__ == '__main__': # Test needs to be a package, so we can do relative imports. diff -r c793d62cdecc Python/import.c --- a/Python/import.c Sun Aug 19 17:57:29 2012 -0400 +++ b/Python/import.c Mon Aug 20 16:39:35 2012 +1000 @@ -875,8 +875,24 @@ which is just fine (since it's only a cache). XXX If the file exists and is writable but the directory is not writable, the file will never be written. Oh well. + If the os is Windows then unlink() will fail on read-only files, + so chmod() is used to ensure the file has write access setting + before unlink is called. */ int fd; +#if defined(MS_WINDOWS) + int cd; + cd = chmod(filename, _S_IWRITE | _S_IREAD); + if ( cd < 0 ) + { + if ( errno != ENOENT ) + { + printf("Problem modifying permission on .pyc or .pyo file\n"); + printf("This means thie file might not have been deleted\n"); + } + // otherwise the file doesn't exist so it's okay + } +#endif (void) unlink(filename); fd = open(filename, O_EXCL|O_CREAT|O_WRONLY|O_TRUNC #ifdef O_BINARY @@ -886,7 +902,7 @@ , mode, "ctxt=bin", "shr=nil" #else , mode -#endif +#endif ); if (fd < 0) return NULL;