◐ Shell
clean mode source ↗

Issue 43961: [Windows] test_logging.test_namer_rotator_inheritance() logs a logging error

vstinner@DESKTOP-DK7VBIL C:\vstinner\python\master>python -m test test_logging -m test_namer_rotator_inheritance
Running Debug|x64 interpreter...
0:00:00 Run tests sequentially
0:00:00 [1/1] test_logging
--- Logging error ---
Traceback (most recent call last):
  File "C:\vstinner\python\master\lib\logging\handlers.py", line 74, in emit
    self.doRollover()
  File "C:\vstinner\python\master\lib\logging\handlers.py", line 179, in doRollover
    self.rotate(self.baseFilename, dfn)
  File "C:\vstinner\python\master\lib\logging\handlers.py", line 117, in rotate
    self.rotator(source, dest)
  File "C:\vstinner\python\master\lib\test\test_logging.py", line 5222, in rotator
    os.rename(source, dest + ".rotated")
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\\Users\\vstinner\\AppData\\Local\\Temp\\test_logging-2-tj71b
t8k.log' -> 'C:\\Users\\vstinner\\AppData\\Local\\Temp\\test_logging-2-tj71bt8k.log.1.test.rotated'
Call stack:
  File "C:\vstinner\python\master\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\vstinner\python\master\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\vstinner\python\master\lib\test\__main__.py", line 2, in <module>
    main()
  File "C:\vstinner\python\master\lib\test\libregrtest\main.py", line 719, in main
    Regrtest().main(tests=tests, **kwargs)
  File "C:\vstinner\python\master\lib\test\libregrtest\main.py", line 641, in main
    self._main(tests, kwargs)
  File "C:\vstinner\python\master\lib\test\libregrtest\main.py", line 694, in _main
    self.run_tests()
  File "C:\vstinner\python\master\lib\test\libregrtest\main.py", line 521, in run_tests
    self.run_tests_sequential()
  File "C:\vstinner\python\master\lib\test\libregrtest\main.py", line 423, in run_tests_sequential
    result = runtest(self.ns, test_name)
  File "C:\vstinner\python\master\lib\test\libregrtest\runtest.py", line 194, in runtest
    return _runtest(ns, test_name)
  File "C:\vstinner\python\master\lib\test\libregrtest\runtest.py", line 154, in _runtest
    result = _runtest_inner(ns, test_name,
  File "C:\vstinner\python\master\lib\test\libregrtest\runtest.py", line 282, in _runtest_inner
    refleak = _runtest_inner2(ns, test_name)
  File "C:\vstinner\python\master\lib\test\libregrtest\runtest.py", line 246, in _runtest_inner2
    test_runner()
  File "C:\vstinner\python\master\lib\test\support\__init__.py", line 682, in inner
    return func(*args, **kwds)
  File "C:\vstinner\python\master\lib\test\test_logging.py", line 5503, in test_main
    support.run_unittest(*tests)
  File "C:\vstinner\python\master\lib\test\support\__init__.py", line 1082, in run_unittest
    _run_suite(suite)
  File "C:\vstinner\python\master\lib\test\support\__init__.py", line 959, in _run_suite
    result = runner.run(suite)
  File "C:\vstinner\python\master\lib\test\support\testresult.py", line 169, in run
    test(self.result)
  File "C:\vstinner\python\master\lib\unittest\suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "C:\vstinner\python\master\lib\unittest\suite.py", line 122, in run
    test(result)
  File "C:\vstinner\python\master\lib\unittest\suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "C:\vstinner\python\master\lib\unittest\suite.py", line 122, in run
    test(result)
  File "C:\vstinner\python\master\lib\unittest\case.py", line 652, in __call__
    return self.run(*args, **kwds)
  File "C:\vstinner\python\master\lib\unittest\case.py", line 592, in run
    self._callTestMethod(testMethod)
  File "C:\vstinner\python\master\lib\unittest\case.py", line 549, in _callTestMethod
    method()
  File "C:\vstinner\python\master\lib\test\test_logging.py", line 5229, in test_namer_rotator_inheritance
    rh.emit(self.next_rec())
Message: '2'
Arguments: None

== Tests result: SUCCESS ==

1 test OK.

Total duration: 1.1 sec
Tests result: SUCCESS
I wrote PR 25684 to fix this issue.

> What does os.rename do on Linux? Does it just overwrite existing files by default?

os.rename() calls rename():
https://man7.org/linux/man-pages/man2/rename.2.html

       rename() renames a file, moving it between directories if
       required.  Any other hard links to the file (as created using
       link(2)) are unaffected.  Open file descriptors for oldpath are
       also unaffected.

       If newpath already exists, it will be atomically replaced, so
       that there is no point at which another process attempting to
       access newpath will find it missing.  However, there will
       probably be a window in which both oldpath and newpath refer to
       the file being renamed.

On Windows, os.rename() is implemented with MoveFileExW(src, dst, 0).

Maybe the test should use os.replace() instead of os.rename()? On Windows, os.replace() is implemented with with MoveFileExW(src, dst, MOVEFILE_REPLACE_EXISTING).

HandlerWithNamerAndRotator.rotator() of test_logging calls os.rename() when the file already exists:

if os.path.exists(source):
    os.rename(source, dest + ".rotated")

And the test fails with "Cannot create a file when that file already exists"... well yes, we just tested that it exists.