Skip to content

Commit fd500a0

Browse files
authored
Merge 6560016 into 0efeee4
2 parents 0efeee4 + 6560016 commit fd500a0

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

source/core.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,14 @@ class App(wx.App):
317317
def OnAssert(self,file,line,cond,msg):
318318
message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg)
319319
log.debugWarning(message,codepath="WX Widgets",stack_info=True)
320+
321+
def InitLocale(self):
322+
# Backport of `InitLocale` from wx Python 4.1.2 as the current version tries to set a Python
323+
# locale to an nonexistent one when creating an instance of `wx.App`.
324+
# This causes a crash when running under a particular version of Universal CRT (#12160)
325+
import locale
326+
locale.setlocale(locale.LC_ALL, "C")
327+
320328
app = App(redirect=False)
321329
# We support queryEndSession events, but in general don't do anything for them.
322330
# However, when running as a Windows Store application, we do want to request to be restarted for updates

source/logHandler.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,20 @@ class Formatter(logging.Formatter):
288288
def formatException(self, ex):
289289
return stripBasePathFromTracebackText(super(Formatter, self).formatException(ex))
290290

291+
def formatTime(self, record, datefmt=None):
292+
"""Custom implementation of `formatTime` which avoids `time.localtime`
293+
since it causes a crash under some versions of Universal CRT ( #12160, Python issue 36792)
294+
"""
295+
import winKernel
296+
timeAsFileTime = winKernel.time_tToFileTime(record.created)
297+
timeAsSystemTime = winKernel.SYSTEMTIME()
298+
winKernel.FileTimeToSystemTime(timeAsFileTime, timeAsSystemTime)
299+
timeAsLocalTime = winKernel.SYSTEMTIME()
300+
winKernel.SystemTimeToTzSpecificLocalTime(None, timeAsSystemTime, timeAsLocalTime)
301+
res = f"{timeAsLocalTime.wHour:02d}:{timeAsLocalTime.wMinute:02d}:{timeAsLocalTime.wSecond:02d}"
302+
return self.default_msec_format % (res, record.msecs)
303+
304+
291305
class StreamRedirector(object):
292306
"""Redirects an output stream to a logger.
293307
"""

source/winKernel.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
#winKernel.py
2-
#A part of NonVisual Desktop Access (NVDA)
3-
#Copyright (C) 2006-2019 NV Access Limited, Rui Batista, Aleksey Sadovoy, Peter Vagner, Mozilla Corporation, Babbage B.V., Joseph Lee
4-
#This file is covered by the GNU General Public License.
5-
#See the file COPYING for more details.
1+
# A part of NonVisual Desktop Access (NVDA)
2+
# Copyright (C) 2006-2021 NV Access Limited, Rui Batista, Aleksey Sadovoy, Peter Vagner,
3+
# Mozilla Corporation, Babbage B.V., Joseph Lee, Łukasz Golonka
4+
# This file is covered by the GNU General Public License.
5+
# See the file COPYING for more details.
66

77
"""Functions that wrap Windows API functions from kernel32.dll and advapi32.dll"""
88

99
import contextlib
1010
import ctypes
1111
import ctypes.wintypes
12-
from ctypes import WinError
12+
from ctypes import byref, Structure, WinError
1313
from ctypes import *
1414
from ctypes.wintypes import *
1515

@@ -160,6 +160,40 @@ class SYSTEMTIME(ctypes.Structure):
160160
("wMilliseconds", WORD)
161161
)
162162

163+
164+
class FILETIME(Structure):
165+
_fields_ = (
166+
("dwLowDateTime", DWORD),
167+
("dwHighDateTime", DWORD)
168+
)
169+
170+
171+
def time_tToFileTime(time_tToConvert: float) -> FILETIME:
172+
"""Converts time_t as returned from `time.time` to a FILETIME structure.
173+
Based on a code snipped from:
174+
https://docs.microsoft.com/en-us/windows/win32/sysinfo/converting-a-time-t-value-to-a-file-time
175+
"""
176+
timeAsFileTime = FILETIME()
177+
res = (int(time_tToConvert) * 10000000) + 116444736000000000
178+
timeAsFileTime.dwLowDateTime = res
179+
timeAsFileTime.dwHighDateTime = res >> 32
180+
return timeAsFileTime
181+
182+
183+
def FileTimeToSystemTime(lpFileTime: FILETIME, lpSystemTime: SYSTEMTIME) -> None:
184+
if kernel32.FileTimeToSystemTime(byref(lpFileTime), byref(lpSystemTime)) == 0:
185+
raise WinError()
186+
187+
188+
def SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation, lpUniversalTime, lpLocalTime):
189+
if lpTimeZoneInformation is not None:
190+
lpTimeZoneInformation = byref(lpTimeZoneInformation)
191+
if kernel32.SystemTimeToTzSpecificLocalTime(
192+
lpTimeZoneInformation, byref(lpUniversalTime), byref(lpLocalTime)
193+
) == 0:
194+
raise WinError()
195+
196+
163197
def GetDateFormatEx(Locale,dwFlags,date,lpFormat):
164198
if date is not None:
165199
date=SYSTEMTIME(date.year,date.month,0,date.day,date.hour,date.minute,date.second,0)

0 commit comments

Comments
 (0)