Improv paths (#936)

* Refactored main

Improved the main script.
Added configurable directories that default to sane places outside of the install directory.
This should resolve the write permission errors.

* Modified paths to use environment variables

Replaced relative paths with better and configurable ones.

* Reformatted

* Added default paths to init

The tests do not run the main script
This commit is contained in:
gentlegiantJGC 2023-07-03 17:02:37 +01:00 committed by GitHub
parent d36f241ac9
commit e0379a878f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 49 deletions

View File

@ -1,4 +1,5 @@
import logging import os
import platformdirs
experimental_bedrock_resources = False experimental_bedrock_resources = False
@ -6,6 +7,22 @@ from ._version import get_versions
__version__ = get_versions()["version"] __version__ = get_versions()["version"]
del get_versions del get_versions
# Initialise default paths. These should be initialised in main before this is imported
# but the tests don't run main so a default is required for that case.
data_dir = platformdirs.user_data_dir("AmuletMapEditor", "AmuletTeam")
os.environ.setdefault("DATA_DIR", data_dir)
config_dir = platformdirs.user_config_dir("AmuletMapEditor", "AmuletTeam")
if config_dir == data_dir:
config_dir = os.path.join(data_dir, "Config")
os.environ.setdefault("CONFIG_DIR", config_dir)
os.environ.setdefault(
"CACHE_DIR", platformdirs.user_cache_dir("AmuletMapEditor", "AmuletTeam")
)
os.environ.setdefault(
"LOG_DIR", platformdirs.user_log_dir("AmuletMapEditor", "AmuletTeam")
)
from amulet_map_editor.api import config as CONFIG, lang from amulet_map_editor.api import config as CONFIG, lang
from amulet_map_editor.api.framework.app import open_level, close_level from amulet_map_editor.api.framework.app import open_level, close_level

View File

@ -3,24 +3,31 @@
def _on_error(e): def _on_error(e):
"""Code to handle errors""" """Code to handle errors"""
err_list = []
try: try:
import traceback import traceback
import sys
import os
err_list.append(traceback.format_exc()) except ImportError as e:
except: # Something has gone seriously wrong
pass print(e)
if isinstance(e, ImportError): print("Failed to import requirements. Check that you extracted correctly.")
err_list.append( input("Press ENTER to continue.")
f"Failed to import requirements. Check that you extracted correctly." else:
err = "\n".join(
[traceback.format_exc()]
+ ["Failed to import requirements. Check that you extracted correctly."]
* isinstance(e, ImportError)
+ [str(e)]
) )
err_list.append(str(e)) print(err)
err = "\n".join(err_list) try:
print(err) with open("crash.log", "w") as f:
with open("./logs/crash.log", "w") as f: f.write(err)
f.write(err) except OSError:
input("Press ENTER to continue.") pass
sys.exit(1) input("Press ENTER to continue.")
sys.exit(1)
try: try:
@ -34,16 +41,17 @@ try:
import glob import glob
import time import time
import wx import wx
import platformdirs
if sys.platform == "linux" and wx.VERSION >= (4, 1, 1): if sys.platform == "linux" and wx.VERSION >= (4, 1, 1):
# bug 247 # bug 247
os.environ["PYOPENGL_PLATFORM"] = "egl" os.environ["PYOPENGL_PLATFORM"] = "egl"
except Exception as e: except Exception as e_:
_on_error(e) _on_error(e_)
def _init_log(): def _init_log():
logs_path = os.path.join(".", "logs") logs_path = os.environ["LOG_DIR"]
# set up handlers # set up handlers
os.makedirs(logs_path, exist_ok=True) os.makedirs(logs_path, exist_ok=True)
# remove all log files older than a week # remove all log files older than a week
@ -72,22 +80,36 @@ def _init_log():
def main(): def main():
try: try:
# Initialise default paths.
data_dir = platformdirs.user_data_dir("AmuletMapEditor", "AmuletTeam")
os.environ.setdefault("DATA_DIR", data_dir)
config_dir = platformdirs.user_config_dir("AmuletMapEditor", "AmuletTeam")
if config_dir == data_dir:
config_dir = os.path.join(data_dir, "Config")
os.environ.setdefault("CONFIG_DIR", config_dir)
os.environ.setdefault(
"CACHE_DIR", platformdirs.user_cache_dir("AmuletMapEditor", "AmuletTeam")
)
os.environ.setdefault(
"LOG_DIR", platformdirs.user_log_dir("AmuletMapEditor", "AmuletTeam")
)
_init_log() _init_log()
from amulet_map_editor.api.framework import AmuletApp from amulet_map_editor.api.framework import AmuletApp
except Exception as e: except Exception as e:
_on_error(e) _on_error(e)
AmuletApp = None else:
try:
app = AmuletApp(0)
app.MainLoop()
except Exception as e:
log = logging.getLogger(__name__)
log.critical(
f"Amulet Crashed. Sorry about that. Please report it to a developer if you think this is an issue. \n{traceback.format_exc()}"
)
input("Press ENTER to continue.")
try:
app = AmuletApp(0)
app.MainLoop()
except Exception as e:
log = logging.getLogger(__name__)
log.critical(
f"Amulet Crashed. Sorry about that. Please report it to a developer if you think this is an issue. \n{traceback.format_exc()}"
)
input("Press ENTER to continue.")
sys.exit(0) sys.exit(0)

View File

@ -3,7 +3,7 @@ import pickle
import gzip import gzip
from typing import Any from typing import Any
_path = os.path.abspath(os.path.join(".", "config")) _path = os.path.abspath(os.path.join(os.environ["CONFIG_DIR"]))
def get(identifier: str, default: Any = None) -> Any: def get(identifier: str, default: Any = None) -> Any:

View File

@ -113,7 +113,7 @@ class OpenGLResourcePack:
default=0, default=0,
) )
cache_dir = os.path.join(".", "cache", "resource_pack") cache_dir = os.path.join(os.environ["CACHE_DIR"], "resource_packs", "atlas")
img_path = os.path.join(cache_dir, f"{cache_id}.png") img_path = os.path.join(cache_dir, f"{cache_id}.png")
bounds_path = os.path.join(cache_dir, f"{cache_id}.json") bounds_path = os.path.join(cache_dir, f"{cache_id}.json")
try: try:

View File

@ -77,16 +77,13 @@ class BaseEditCanvas(EventCanvas):
self._mouse: MouseMovement = MouseMovement(self) self._mouse: MouseMovement = MouseMovement(self)
self._mouse.set_middle() self._mouse.set_middle()
resource_packs_dir = os.path.join(os.environ["DATA_DIR"], "resource_packs")
readme_path = os.path.join(resource_packs_dir, "readme.txt")
# create the resource packs location # create the resource packs location
try: os.makedirs(resource_packs_dir, exist_ok=True)
os.makedirs("resource_packs", exist_ok=True) if not os.path.isfile(readme_path):
if not os.path.isfile("resource_packs/readme.txt"): with open(readme_path, "w") as f:
with open("resource_packs/readme.txt", "w") as f: f.write("Put the Java resource pack you want loaded in here.")
f.write("Put the Java resource pack you want loaded in here.")
except PermissionError as e:
raise PermissionError(
"Amulet is not able to write to the install directory. Try moving Amulet to somewhere else on your computer."
) from e
self._renderer: Optional[Renderer] = None self._renderer: Optional[Renderer] = None
self._opengl_resource_pack = None self._opengl_resource_pack = None
@ -97,10 +94,11 @@ class BaseEditCanvas(EventCanvas):
All code in here must be thread safe and not touch the OpenGL state. All code in here must be thread safe and not touch the OpenGL state.
""" """
packs = [] packs = []
resource_packs_dir = os.path.join(os.environ["DATA_DIR"], "resource_packs")
user_packs = [ user_packs = [
load_resource_pack(os.path.join("resource_packs", rp)) load_resource_pack(os.path.join(resource_packs_dir, rp))
for rp in os.listdir("resource_packs") for rp in os.listdir(resource_packs_dir)
if os.path.isdir(os.path.join("resource_packs", rp)) if os.path.isdir(os.path.join(resource_packs_dir, rp))
] ]
if ( if (
self.world.level_wrapper.platform == "bedrock" self.world.level_wrapper.platform == "bedrock"

View File

@ -36,7 +36,8 @@ class UIOperationLoader(BaseOperationLoader):
"""Parse the export dictionary and setup as required.""" """Parse the export dictionary and setup as required."""
options_path = os.path.abspath( options_path = os.path.abspath(
os.path.join( os.path.join(
"config", os.environ["CONFIG_DIR"],
"plugins",
"edit_plugins", "edit_plugins",
f"""{''.join(c for c in self._name if c in ValidChrs)}_{ f"""{''.join(c for c in self._name if c in ValidChrs)}_{
struct.unpack( struct.unpack(

View File

@ -1,13 +1,8 @@
import os import os
import pkgutil
import sys
from typing import Optional
from types import ModuleType
import importlib.util
from amulet_map_editor.programs.edit.plugins.operations import stock_plugins from amulet_map_editor.programs.edit.plugins.operations import stock_plugins
STOCK_PLUGINS_DIR: str = stock_plugins.__path__[0] STOCK_PLUGINS_DIR: str = stock_plugins.__path__[0]
STOCK_PLUGINS_NAME: str = stock_plugins.__name__ STOCK_PLUGINS_NAME: str = stock_plugins.__name__
CUSTOM_PLUGINS_DIR = os.path.abspath("plugins") CUSTOM_PLUGINS_DIR = os.path.join(os.environ["DATA_DIR"], "plugins")

View File

@ -25,6 +25,7 @@ install_requires =
amulet-nbt~=2.0 amulet-nbt~=2.0
pymctranslate~=1.2 pymctranslate~=1.2
minecraft-resource-pack~=1.3 minecraft-resource-pack~=1.3
platformdirs~=3.1
packages = find: packages = find: