anki/qt/aqt/package.py
Damien Elmes ba68764fcb Another attempt at fixing missing cacert.pem
A few reports like https://forums.ankiweb.net/t/error-report-check-database-did-not-work/25796
indicate that the previous solution has not helped, and has just made things
worse. My guess is that AppNap on macOS is preventing the timer from even
running before the file gets cleaned up.
2022-12-30 15:30:53 +10:00

92 lines
2.6 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
"""Helpers for the packaged version of Anki."""
from __future__ import annotations
import os
import sys
from pathlib import Path
def _fix_pywin32() -> None:
# extend sys.path with .pth files
import site
site.addsitedir(sys.path[0])
# use updated sys.path to locate dll folder and add it to path
path = sys.path[-1]
path = path.replace("Pythonwin", "pywin32_system32")
os.environ["PATH"] += ";" + path
# import Python modules from .dll files
import importlib.machinery
for name in "pythoncom", "pywintypes":
filename = os.path.join(path, name + "39.dll")
loader = importlib.machinery.ExtensionFileLoader(name, filename)
spec = importlib.machinery.ModuleSpec(name=name, loader=loader, origin=filename)
_mod = importlib._bootstrap._load(spec) # type: ignore
def _patch_pkgutil() -> None:
"""Teach pkgutil.get_data() how to read files from in-memory resources.
This is required for jsonschema."""
import importlib
import pkgutil
def get_data_custom(package: str, resource: str) -> bytes | None:
try:
module = importlib.import_module(package)
reader = module.__loader__.get_resource_reader(package) # type: ignore[attr-defined]
with reader.open_resource(resource) as f:
return f.read()
except:
return None
pkgutil.get_data = get_data_custom
def _patch_certifi() -> None:
"""Tell certifi (and thus requests) to use a file in our package folder.
By default it creates a copy of the data in a temporary folder, which then gets
cleaned up by macOS's temp file cleaner."""
import certifi
def where() -> str:
prefix = Path(sys.prefix)
if sys.platform == "darwin":
path = prefix / "../Resources/certifi/cacert.pem"
else:
path = prefix / "lib" / "certifi" / "cacert.pem"
return str(path)
certifi.where = where
def packaged_build_setup() -> None:
if not getattr(sys, "frozen", False):
return
print("Initial setup...")
if sys.platform == "win32":
_fix_pywin32()
_patch_pkgutil()
_patch_certifi()
# escape hatch for debugging issues with packaged build startup
if os.getenv("ANKI_STARTUP_REPL"):
# mypy incorrectly thinks this does not exist on Windows
is_tty = os.isatty(sys.stdin.fileno()) # type: ignore
if is_tty:
import code
code.InteractiveConsole().interact()
sys.exit(0)