Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Windows build and runtime on Python 3.11.4 #312

Merged
merged 2 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions DisplayCAL/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2226,7 +2226,5 @@ def writecfg(which="user", worker=None, module=None, options=(), cfg=cfg):
if not cafile:
# Use our bundled CA file
cafile = get_data_path("cacert.pem")
if cafile:
cafile = cafile.encode(fs_enc, "replace")
if cafile:
os.environ["SSL_CERT_FILE"] = cafile
47 changes: 24 additions & 23 deletions DisplayCAL/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
from DisplayCAL.util_os import FileLock, LockingError, UnlockingError

if sys.platform == "win32":
from util_win import win_ver
from DisplayCAL.util_win import win_ver
import ctypes


Expand Down Expand Up @@ -392,8 +392,9 @@ def _main(module, name, app_lock_file_name, probe_ports=True):
handle_error(lang.getstr("app.otherinstance", name))
# Exit
return
lock.unlock()
# Use exclusive lock during app startup
with lock:
with AppLock(app_lock_file_name, "a+", True, True) as lock:
# Create listening socket
appsocket = AppSocket()
if appsocket:
Expand Down Expand Up @@ -513,27 +514,27 @@ def _main(module, name, app_lock_file_name, probe_ports=True):
% ";".join(script).encode(fs_enc),
]
)
# Initialize & run
if module == "3DLUT-maker":
from DisplayCAL.wxLUT3DFrame import main
elif module == "curve-viewer":
from DisplayCAL.wxLUTViewer import main
elif module == "profile-info":
from DisplayCAL.wxProfileInfo import main
elif module == "scripting-client":
from DisplayCAL.wxScriptingClient import main
elif module == "synthprofile":
from DisplayCAL.wxSynthICCFrame import main
elif module == "testchart-editor":
from DisplayCAL.wxTestchartEditor import main
elif module == "VRML-to-X3D-converter":
from DisplayCAL.wxVRML2X3D import main
elif module == "apply-profiles":
from DisplayCAL.profile_loader import main
else:
from DisplayCAL.display_cal import main
# Run main after releasing lock
main()
# Initialize & run
if module == "3DLUT-maker":
from DisplayCAL.wxLUT3DFrame import main
elif module == "curve-viewer":
from DisplayCAL.wxLUTViewer import main
elif module == "profile-info":
from DisplayCAL.wxProfileInfo import main
elif module == "scripting-client":
from DisplayCAL.wxScriptingClient import main
elif module == "synthprofile":
from DisplayCAL.wxSynthICCFrame import main
elif module == "testchart-editor":
from DisplayCAL.wxTestchartEditor import main
elif module == "VRML-to-X3D-converter":
from DisplayCAL.wxVRML2X3D import main
elif module == "apply-profiles":
from DisplayCAL.profile_loader import main
else:
from DisplayCAL.display_cal import main
# Run main after releasing lock
main()


def main(module=None):
Expand Down
2 changes: 1 addition & 1 deletion DisplayCAL/postinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def file_created(path):
installed_files.extend(line.rstrip("\n") for line in recordfile)
recordfile.close()
try:
path.decode("ASCII")
path.encode("ASCII")
except (UnicodeDecodeError, UnicodeEncodeError):
# the contents of the record file used by distutils
# must be ASCII GetShortPathName allows us to avoid
Expand Down
8 changes: 5 additions & 3 deletions DisplayCAL/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ def add_lib_excludes(key, excludebits):
config["excludes"][key].extend([f"{name}.lib{exclude}", f"lib{exclude}"])

for exclude in ("32", "64"):
for pycompat in ("38", "39", "310"):
for pycompat in ("38", "39", "310", "311"):
if key == "win32" and (
pycompat == sys.version[0] + sys.version[2] or exclude == excludebits[0]
pycompat == str(sys.version_info[0]) + str(sys.version_info[1]) or exclude == excludebits[0]
):
continue
config["excludes"][key].extend(
Expand Down Expand Up @@ -955,7 +955,7 @@ def findall(
packages = [name, f"{name}.lib", f"{name}.lib.agw"]
if sdist:
# For source distributions we want all libraries
for pycompat in ("38", "39", "310"):
for pycompat in ("38", "39", "310", "311"):
packages.extend(
[
f"{name}.lib{bits}",
Expand Down Expand Up @@ -1265,6 +1265,8 @@ def copy_package_data(self, package, target_dir):
"mswsock.dll",
"urlmon.dll",
"w9xpopen.exe",
"gdiplus.dll",
"mfc90.dll",
],
"excludes": config["excludes"]["all"] + config["excludes"]["win32"],
"bundle_files": 3 if wx.VERSION >= (2, 8, 10, 1) else 1,
Expand Down
60 changes: 30 additions & 30 deletions DisplayCAL/util_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,95 +104,95 @@ def open(path, *args, **kwargs):

_access = os.access

def access(path, mode):
return _access(make_win32_compatible_long_path(path), mode)
def access(path, mode, *args, **kwargs):
return _access(make_win32_compatible_long_path(path), mode, *args, **kwargs)

os.access = access

_exists = os.path.exists

def exists(path):
return _exists(make_win32_compatible_long_path(path))
def exists(path, *args, **kwargs):
return _exists(make_win32_compatible_long_path(path), *args, **kwargs)

os.path.exists = exists

_isdir = os.path.isdir

def isdir(path):
return _isdir(make_win32_compatible_long_path(path))
def isdir(path, *args, **kwargs):
return _isdir(make_win32_compatible_long_path(path), *args, **kwargs)

os.path.isdir = isdir

_isfile = os.path.isfile

def isfile(path):
return _isfile(make_win32_compatible_long_path(path))
def isfile(path, *args, **kwargs):
return _isfile(make_win32_compatible_long_path(path), *args, **kwargs)

os.path.isfile = isfile

def listdir(path):
return _listdir(make_win32_compatible_long_path(path))
def listdir(path, *args, **kwargs):
return _listdir(make_win32_compatible_long_path(path), *args, **kwargs)

_lstat = os.lstat

def lstat(path):
return _lstat(make_win32_compatible_long_path(path))
def lstat(path, *args, **kwargs):
return _lstat(make_win32_compatible_long_path(path), *args, **kwargs)

os.lstat = lstat

_mkdir = os.mkdir

def mkdir(path, mode=0o777):
return _mkdir(make_win32_compatible_long_path(path, 247), mode)
def mkdir(path, mode=0o777, *args, **kwargs):
return _mkdir(make_win32_compatible_long_path(path, 247), mode, *args, **kwargs)

os.mkdir = mkdir

_makedirs = os.makedirs

def makedirs(path, mode=0o777):
return _makedirs(make_win32_compatible_long_path(path, 247), mode)
def makedirs(path, mode=0o777, *args, **kwargs):
return _makedirs(make_win32_compatible_long_path(path, 247), mode, *args, **kwargs)

os.makedirs = makedirs

_remove = os.remove

def remove(path):
return _remove(make_win32_compatible_long_path(path))
def remove(path, *args, **kwargs):
return _remove(make_win32_compatible_long_path(path), *args, **kwargs)

os.remove = retry_sharing_violation_factory(remove)

_rename = os.rename

def rename(src, dst):
def rename(src, dst, *args, **kwargs):
src, dst = [make_win32_compatible_long_path(path) for path in (src, dst)]
return _rename(src, dst)
return _rename(src, dst, *args, **kwargs)

os.rename = retry_sharing_violation_factory(rename)

_stat = os.stat

def stat(path):
return _stat(make_win32_compatible_long_path(path))
def stat(path, *args, **kwargs):
return _stat(make_win32_compatible_long_path(path), *args, **kwargs)

os.stat = stat

_unlink = os.unlink

def unlink(path):
return _unlink(make_win32_compatible_long_path(path))
def unlink(path, *args, **kwargs):
return _unlink(make_win32_compatible_long_path(path), *args, **kwargs)

os.unlink = retry_sharing_violation_factory(unlink)

_GetShortPathName = win32api.GetShortPathName

def GetShortPathName(path):
return _GetShortPathName(make_win32_compatible_long_path(path))
def GetShortPathName(path, *args, **kwargs):
return _GetShortPathName(make_win32_compatible_long_path(path), *args, **kwargs)

win32api.GetShortPathName = GetShortPathName
else:

def listdir(path):
paths = _listdir(path)
def listdir(path, *args, **kwargs):
paths = _listdir(path, *args, **kwargs)
if isinstance(path, str):
# Undecodable filenames will still be string objects. Ignore them.
paths = [path for path in paths if isinstance(path, str)]
Expand Down Expand Up @@ -465,9 +465,9 @@ def listdir_re(path, rex=None):
def make_win32_compatible_long_path(path, maxpath=259):
if (
sys.platform == "win32"
and len(path) > maxpath
and len(str(path)) > maxpath
and os.path.isabs(path)
and not path.startswith("\\\\?\\")
and not str(path).startswith("\\\\?\\")
):
path = "\\\\?\\" + path
return path
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[build-system]
requires = ["setuptools"]
requires = ["setuptools",
'pywin32; platform_system=="Windows"']
build-backend = "setuptools.build_meta"
6 changes: 3 additions & 3 deletions util/winmanifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,9 +990,9 @@ def toprettyxml(self, indent=" ", newl=os.linesep, encoding="UTF-8"):
xmlstr = domtree.toprettyxml(indent, newl, encoding)
else:
xmlstr = domtree.toprettyxml(indent, newl)
xmlstr = xmlstr.strip(os.linesep).replace(
'<?xml version="1.0" encoding="%s"?>' % encoding,
'<?xml version="1.0" encoding="%s" standalone="yes"?>' % encoding,
xmlstr = xmlstr.strip(os.linesep.encode('utf-8')).replace(
('<?xml version="1.0" encoding="%s"?>' % encoding).encode('utf-8'),
('<?xml version="1.0" encoding="%s" standalone="yes"?>' % encoding).encode('utf-8'),
)
domtree.unlink()
return xmlstr
Expand Down