Skip to content

Commit 3c0d725

Browse files
Improve debugging (#1261)
* Update pyinstaller * Improve type hinting in pyinstaller spec * Improve logging setup * Add a main script with debug logging * Disable debug logging of some modules * Add a debug executable
1 parent cb562c0 commit 3c0d725

File tree

5 files changed

+170
-10
lines changed

5 files changed

+170
-10
lines changed

.github/workflows/python-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
- name: Install dependencies
3232
run: |
3333
python -m pip install --upgrade pip
34-
pip install setuptools wheel twine pyinstaller~=5.6 build
34+
pip install setuptools wheel twine pyinstaller~=6.18 build
3535
3636
- name: Setup
3737
run: |

Amulet.spec

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from PyInstaller.utils.hooks import collect_submodules
66

7-
from typing import Dict, Tuple, Set
7+
from typing import Dict, Tuple, Set, TYPE_CHECKING
88
import sys
99
import os
1010
import glob
@@ -21,6 +21,13 @@ import PyMCTranslate
2121
import minecraft_model_reader
2222
import amulet_map_editor
2323

24+
if TYPE_CHECKING:
25+
from PyInstaller.building.build_main import Analysis
26+
from PyInstaller.building.datastruct import Tree
27+
from PyInstaller.building.api import PYZ, EXE, COLLECT
28+
import PyInstaller.building.osx
29+
from PyInstaller.building.osx import BUNDLE
30+
2431
sys.modules["FixTk"] = None
2532

2633
AMULET_NBT_PATH = amulet_nbt.__path__[0]
@@ -40,7 +47,10 @@ hidden.extend(collect_submodules("OpenGL.GL.shaders"))
4047

4148

4249
a = Analysis(
43-
[os.path.join(AMULET_MAP_EDITOR, "__main__.py")],
50+
[
51+
os.path.join(AMULET_MAP_EDITOR, "__main__.py"),
52+
os.path.join(AMULET_MAP_EDITOR, "__main_debug__.py"),
53+
],
4454
binaries=[],
4555
datas=[],
4656
hiddenimports=hidden,
@@ -97,6 +107,7 @@ sys.stdout.flush() # fix the log being out of order
97107
pyz = PYZ(a.pure, a.zipped_data)
98108
exe = EXE(
99109
pyz,
110+
a.scripts[:-1],
100111
a.scripts,
101112
[],
102113
exclude_binaries=True,
@@ -108,8 +119,22 @@ exe = EXE(
108119
console=os.name == "nt", # Only show the console on windows
109120
icon="icon.ico",
110121
)
122+
exe_debug = EXE(
123+
pyz,
124+
a.scripts[:-2] + a.scripts[-1:],
125+
[],
126+
exclude_binaries=True,
127+
name="amulet_app_debug",
128+
debug=False,
129+
bootloader_ignore_signals=False,
130+
strip=False,
131+
upx=True,
132+
console=os.name == "nt", # Only show the console on windows
133+
icon="icon.ico",
134+
)
111135
coll = COLLECT(
112136
exe,
137+
exe_debug,
113138
a.binaries,
114139
a.zipfiles,
115140
a.datas,

amulet_map_editor/__main__.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,31 @@ def _init_log():
6262
):
6363
os.remove(path)
6464

65-
log = logging.getLogger()
66-
log.setLevel(logging.DEBUG if "amulet-debug" in sys.argv else logging.INFO)
65+
debug = "--amulet-debug" in sys.argv
6766

6867
file_handler = logging.FileHandler(
69-
os.path.join(logs_path, f"amulet_{os.getpid()}.log"), "w", encoding="utf-8"
68+
os.path.join(logs_path, f"amulet_{os.getpid()}.log"),
69+
"w",
70+
encoding="utf-8",
7071
)
7172
file_handler.setFormatter(
72-
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
73+
logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
7374
)
74-
log.addHandler(file_handler)
7575

7676
console_handler = logging.StreamHandler()
77-
console_handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
78-
log.addHandler(console_handler)
77+
console_handler.setFormatter(
78+
logging.Formatter(
79+
"%(levelname)s - %(name)s - %(message)s"
80+
if debug
81+
else "%(levelname)s - %(message)s"
82+
)
83+
)
84+
85+
logging.basicConfig(
86+
level=logging.DEBUG if debug else logging.INFO,
87+
handlers=[file_handler, console_handler],
88+
force=True,
89+
)
7990

8091

8192
def main():
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env python3
2+
3+
4+
def _on_error(e):
5+
"""Code to handle errors"""
6+
try:
7+
import traceback
8+
import sys
9+
import os
10+
11+
except ImportError as e:
12+
# Something has gone seriously wrong
13+
print(e)
14+
print("Failed to import requirements. Check that you extracted correctly.")
15+
input("Press ENTER to continue.")
16+
else:
17+
err = "\n".join(
18+
[traceback.format_exc()]
19+
+ ["Failed to import requirements. Check that you extracted correctly."]
20+
* isinstance(e, ImportError)
21+
+ [str(e)]
22+
)
23+
print(err)
24+
try:
25+
with open("crash.log", "w") as f:
26+
f.write(err)
27+
except OSError:
28+
pass
29+
input("Press ENTER to continue.")
30+
sys.exit(1)
31+
32+
33+
try:
34+
import sys
35+
36+
if sys.version_info[:2] < (3, 7):
37+
raise Exception("Must be using Python 3.7+")
38+
import logging
39+
import os
40+
import traceback
41+
import glob
42+
import time
43+
import wx
44+
import platformdirs
45+
46+
if sys.platform == "linux" and wx.VERSION >= (4, 1, 1):
47+
# bug 247
48+
os.environ["PYOPENGL_PLATFORM"] = "egl"
49+
except Exception as e_:
50+
_on_error(e_)
51+
52+
53+
def _init_log():
54+
logs_path = os.environ["LOG_DIR"]
55+
# set up handlers
56+
os.makedirs(logs_path, exist_ok=True)
57+
# remove all log files older than a week
58+
for path in glob.glob(os.path.join(glob.escape(logs_path), "*.log")):
59+
if (
60+
os.path.isfile(path)
61+
and os.path.getmtime(path) < time.time() - 3600 * 24 * 7
62+
):
63+
os.remove(path)
64+
65+
file_handler = logging.FileHandler(
66+
os.path.join(logs_path, f"amulet_{os.getpid()}.log"),
67+
"w",
68+
encoding="utf-8",
69+
)
70+
file_handler.setFormatter(
71+
logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
72+
)
73+
74+
console_handler = logging.StreamHandler()
75+
console_handler.setFormatter(
76+
logging.Formatter("%(levelname)s - %(name)s - %(message)s")
77+
)
78+
79+
logging.basicConfig(
80+
level=logging.DEBUG,
81+
handlers=[file_handler, console_handler],
82+
force=True,
83+
)
84+
85+
86+
def main():
87+
try:
88+
# Initialise default paths.
89+
data_dir = platformdirs.user_data_dir("AmuletMapEditor", "AmuletTeam")
90+
os.environ.setdefault("DATA_DIR", data_dir)
91+
config_dir = platformdirs.user_config_dir("AmuletMapEditor", "AmuletTeam")
92+
if config_dir == data_dir:
93+
config_dir = os.path.join(data_dir, "Config")
94+
os.environ.setdefault("CONFIG_DIR", config_dir)
95+
os.environ.setdefault(
96+
"CACHE_DIR", platformdirs.user_cache_dir("AmuletMapEditor", "AmuletTeam")
97+
)
98+
os.environ.setdefault(
99+
"LOG_DIR", platformdirs.user_log_dir("AmuletMapEditor", "AmuletTeam")
100+
)
101+
102+
_init_log()
103+
from amulet_map_editor.api.framework import AmuletApp
104+
105+
except Exception as e:
106+
_on_error(e)
107+
else:
108+
try:
109+
app = AmuletApp(0)
110+
app.MainLoop()
111+
except Exception as e:
112+
log = logging.getLogger(__name__)
113+
log.critical(
114+
f"Amulet Crashed. Sorry about that. Please report it to a developer if you think this is an issue. \n{traceback.format_exc()}"
115+
)
116+
input("Press ENTER to continue.")
117+
118+
sys.exit(0)
119+
120+
121+
if __name__ == "__main__":
122+
main()

amulet_map_editor/api/framework/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
# Disable OpenGL_accelerate logging
1414
logging.getLogger("OpenGL.acceleratesupport").setLevel(logging.CRITICAL)
15+
logging.getLogger("OpenGL.GL.shaders").setLevel(logging.INFO)
16+
logging.getLogger("PIL.PngImagePlugin").setLevel(logging.INFO)
1517

1618
log = logging.getLogger(__name__)
1719

0 commit comments

Comments
 (0)