Platform specific directories now have one module for each platform.
Added some notes about install mode and build scripts sys.executable is no longer used. Added getSrcFolder for finding the src/ folder of a source checkout.
This commit is contained in:
parent
1e4ae2e688
commit
d1eda07ac1
@ -1,41 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def getUserFilesDirectory():
|
||||
if sys.platform == "win32":
|
||||
import win32api
|
||||
# On Windows, sys.executable is codepage-encoded.
|
||||
# It cannot represent all possible filenames, so get the exe filename
|
||||
# using this wide-character API, which returns a `unicode`
|
||||
exe = win32api.GetModuleFileNameW(None)
|
||||
else:
|
||||
# On OS X, the FS encoding is always UTF-8
|
||||
# OS X filenames are defined to be UTF-8 encoded.
|
||||
# On Linux, the FS encoding is given by the current locale
|
||||
# Linux filenames are defined to be bytestrings.
|
||||
exe = sys.executable.decode(sys.getfilesystemencoding())
|
||||
|
||||
assert os.path.exists(exe), "%r does not exist" % exe
|
||||
if hasattr(sys, 'frozen'):
|
||||
folder = os.path.dirname(exe)
|
||||
else:
|
||||
if exe.endswith("python") or exe.endswith("python.exe"):
|
||||
script = sys.argv[0]
|
||||
# assert the source checkout is not in a non-representable path...
|
||||
assert os.path.exists(script), "Source checkout path cannot be represented with 'mbcs' encoding. Put the source checkout somewhere else."
|
||||
folder = os.path.dirname(os.path.dirname(os.path.dirname(script))) # from src/mcedit, ../../
|
||||
else:
|
||||
folder = os.path.dirname(exe)
|
||||
|
||||
dataDir = os.path.join(folder, "MCEdit User Data")
|
||||
|
||||
if not os.path.exists(dataDir):
|
||||
os.makedirs(dataDir)
|
||||
return dataDir
|
||||
|
||||
def getUserSchematicsDirectory():
|
||||
return os.path.join(getUserFilesDirectory(), "schematics")
|
||||
|
||||
def getUserPluginsDirectory():
|
||||
return os.path.join(getUserFilesDirectory(), "plugins")
|
24
src/mcedit2/util/directories/__init__.py
Normal file
24
src/mcedit2/util/directories/__init__.py
Normal file
@ -0,0 +1,24 @@
|
||||
"""
|
||||
directories
|
||||
|
||||
Get platform specific user data folders.
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
if sys.platform == "win32":
|
||||
from .win32 import getUserFilesDirectory
|
||||
elif sys.platform == "darwin":
|
||||
from .mac import getUserFilesDirectory
|
||||
else:
|
||||
from .posix import getUserFilesDirectory
|
||||
|
||||
|
||||
def getUserSchematicsDirectory():
|
||||
return os.path.join(getUserFilesDirectory(), "schematics")
|
||||
|
||||
def getUserPluginsDirectory():
|
||||
return os.path.join(getUserFilesDirectory(), "plugins")
|
28
src/mcedit2/util/directories/mac.py
Normal file
28
src/mcedit2/util/directories/mac.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
mac
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# no build scripts for OS X yet. assuming py2app or py2installer will be used.
|
||||
#
|
||||
# store user files in source checkout folder
|
||||
|
||||
def getUserFilesDirectory():
|
||||
|
||||
# TODO if sys.getattr('frozen', False):
|
||||
# TODO os.getenv('RESOURCEPATH') or sys.getattr('_MEIPASS'), etc etc...
|
||||
|
||||
# On OS X, the FS encoding is always UTF-8
|
||||
# OS X filenames are defined to be UTF-8 encoded.
|
||||
# We internally handle filenames as unicode.
|
||||
|
||||
script = sys.argv[0].decode(sys.getfilesystemencoding())
|
||||
|
||||
folder = os.path.dirname(os.path.dirname(os.path.dirname(script))) # main script is src/mcedit/main.py, so, ../../
|
||||
dataDir = os.path.join(folder, "MCEdit User Data")
|
||||
return dataDir
|
35
src/mcedit2/util/directories/posix.py
Normal file
35
src/mcedit2/util/directories/posix.py
Normal file
@ -0,0 +1,35 @@
|
||||
"""
|
||||
posix
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# no build scripts for linux yet. no idea if frozen apps will be built for linux.
|
||||
# assume always running from source checkout and put user files in source checkout.
|
||||
|
||||
# xxx for .whl or distro-specific distrib, put user files in ~/.mcedit2
|
||||
|
||||
def getUserFilesDirectory():
|
||||
# On Linux, the FS encoding is given by the current locale
|
||||
# Linux filenames are defined to be bytestrings.
|
||||
|
||||
# TODO: if not os.path.exists(os.path.join(mumble_mumble, ".git")):
|
||||
|
||||
# We handle filenames internally as 'unicode', so decode 'sys.argv[0]'
|
||||
# If a linux filename cannot be decoded with the current locale, ignore it.
|
||||
# If this filename is the script filename, you lose.
|
||||
try:
|
||||
# assert the source checkout is not in a non-representable path...
|
||||
script = sys.argv[0].decode(sys.getfilesystemencoding())
|
||||
except UnicodeDecodeError:
|
||||
print("Script filename %r cannot be decoded with the current locale %s! Please use sensible filenames." % (
|
||||
sys.argv[0], sys.getfilesystemencoding()))
|
||||
raise
|
||||
|
||||
folder = os.path.dirname(os.path.dirname(os.path.dirname(script))) # main script is src/mcedit/main.py, so, ../../
|
||||
dataDir = os.path.join(folder, "MCEdit User Data")
|
||||
return dataDir
|
57
src/mcedit2/util/directories/win32.py
Normal file
57
src/mcedit2/util/directories/win32.py
Normal file
@ -0,0 +1,57 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# when running from source, put the user files in the source checkout
|
||||
# when running from a built app ("frozen"), decide from install mode
|
||||
|
||||
# TODO how to do install mode?
|
||||
# 1. two different downloads
|
||||
# - .exe installer for system-wide/per-user install
|
||||
# - .zip for self-contained/portable install
|
||||
# 2. one download. prompt on first app startup for install mode. create INSTALL_MODE file in
|
||||
# exe folder. check contents of file for install mode and prompt if file is missing.
|
||||
# 3. like MCEdit1. option in app to change install mode and move user folder into app or docs folder
|
||||
# check for presence of user folder in app folder on startup to decide install mode.
|
||||
# 4. ALWAYS self-contained/portable install. same as MultiMC.
|
||||
#
|
||||
# ... also, get auto updater working. manually updating a self-contained install may be weird.
|
||||
|
||||
# I think 4 is the best.
|
||||
from mcedit2.util import resources
|
||||
|
||||
PORTABLE_INSTALL = True
|
||||
|
||||
_userFilesDirectory = None
|
||||
def getUserFilesDirectory():
|
||||
global _userFilesDirectory
|
||||
if _userFilesDirectory is not None:
|
||||
return _userFilesDirectory
|
||||
|
||||
if hasattr(sys, 'frozen'):
|
||||
# On Windows, filenames are UTF-16 encoded.
|
||||
# Filenames are defined as UTF-16.
|
||||
# However, sys.executable is codepage-encoded. Codepages cannot represent all possible
|
||||
# filenames, so we must get the exe filename using this wide-character API.
|
||||
# Wide-character APIs in pywin32 always return a `unicode`.
|
||||
#
|
||||
# Filenames must be passed to Python's filesystem functions as `unicode` to call the
|
||||
# wide-character forms of the underlying Win32 APIs.
|
||||
#
|
||||
# We take care not to store filenames as `bytes`, as this causes the filesystem functions
|
||||
# to use the legacy codepage APIs.
|
||||
|
||||
import win32api
|
||||
exe = win32api.GetModuleFileNameW(None)
|
||||
assert os.path.exists(exe), "MCEdit executable %r does not exist! Something is very wrong." % exe
|
||||
folder = os.path.dirname(exe)
|
||||
|
||||
else:
|
||||
folder = os.path.dirname(resources.getSrcFolder())
|
||||
|
||||
dataDir = os.path.join(folder, "MCEdit User Data")
|
||||
|
||||
if not os.path.exists(dataDir):
|
||||
os.makedirs(dataDir)
|
||||
|
||||
_userFilesDirectory = dataDir
|
||||
return dataDir
|
@ -8,15 +8,50 @@ import sys
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def getSrcFolder():
|
||||
"""
|
||||
Find the 'src/' folder of a source checkout.
|
||||
|
||||
...should maybe assert that '.git' exists?
|
||||
:return: unicode
|
||||
"""
|
||||
import mcedit2
|
||||
mod = os.path.realpath(mcedit2.__file__) # src/mcedit2/__init__.py
|
||||
|
||||
# On Windows, sys.argv[0] is always codepage-encoded, as is the __file__ attribute of any module.
|
||||
# in fact, the entire module import subsystem of python2.7 is either restricted to codepages
|
||||
# or to ASCII (haven't found out which) as `import` seems to break with non-ascii paths.
|
||||
|
||||
# On OS X, it is always UTF-8 encoded and filenames are *always* UTF-8 encoded.
|
||||
|
||||
# On Linux, it is locale-encoded and filenames are defined as bytestrings, so it is possible
|
||||
# to have a filename that cannot be interpreted as unicode. If the user writes a filename
|
||||
# that is not locale-encoded, he loses.
|
||||
|
||||
mod = mod.decode(sys.getfilesystemencoding())
|
||||
|
||||
# Assert the source checkout is not in a non-representable path...
|
||||
assert os.path.exists(mod), ("Source checkout path cannot be represented as unicode. "
|
||||
"Put the source checkout somewhere else.")
|
||||
return os.path.dirname((os.path.dirname(mod)))
|
||||
|
||||
def resourcePath(filename):
|
||||
"""
|
||||
Return the absolute path of a filename included as a resource.
|
||||
|
||||
"Resource" is not well-defined. When packaged with PyInstaller, the filename is found
|
||||
relative to the app's folder (_MEIPASS). When running from source, it is relative to the
|
||||
'src' folder. I'd imagine that when installed as a .whl (on linux) we need to use
|
||||
pkg_resources to get filenames.
|
||||
|
||||
:param filename:
|
||||
:return:
|
||||
"""
|
||||
filename = filename.replace('/', os.path.sep)
|
||||
basedir = getattr(sys, "_MEIPASS", None) # if pyinstaller'd
|
||||
if basedir is None:
|
||||
import mcedit2
|
||||
mod = mcedit2.__file__
|
||||
basedir = os.path.dirname(mod) + "/.."
|
||||
basedir = os.path.normpath(basedir)
|
||||
# should work across platforms
|
||||
basedir = getSrcFolder()
|
||||
path = os.path.join(basedir, filename)
|
||||
if not os.path.exists(path):
|
||||
raise RuntimeError("Could not get resource path for %s\n(Tried %s which does not exist)" % (filename, path))
|
||||
|
Reference in New Issue
Block a user