diff --git a/src/ca_certs_locater.py b/src/ca_certs_locater.py index 979fc5c..15366ba 100644 --- a/src/ca_certs_locater.py +++ b/src/ca_certs_locater.py @@ -3,7 +3,7 @@ import sys if sys.version[0] == "3": raise ImportError() import os -from platform_utils import paths +import paths def get(): return os.path.join(paths.app_path(), "cacerts.txt") \ No newline at end of file diff --git a/src/fixes/fix_requests.py b/src/fixes/fix_requests.py index ed8da72..150d893 100644 --- a/src/fixes/fix_requests.py +++ b/src/fixes/fix_requests.py @@ -2,7 +2,7 @@ import requests import os import logging -from platform_utils import paths +import paths log = logging.getLogger("fixes.fix_requests") diff --git a/src/i18n.py b/src/i18n.py index 6fff11a..f639dd2 100644 --- a/src/i18n.py +++ b/src/i18n.py @@ -4,7 +4,7 @@ import gettext import locale import sys import logging -from platform_utils import paths +import paths log = logging.getLogger("i18n") diff --git a/src/main.py b/src/main.py index 1e02f3c..b14288c 100644 --- a/src/main.py +++ b/src/main.py @@ -24,7 +24,7 @@ import i18n i18n.setup() import application import widgetUtils -from platform_utils import paths +import paths def setup(): log.debug("Starting music-dl %s" % (application.version,)) diff --git a/src/paths.py b/src/paths.py new file mode 100644 index 0000000..37d6cb4 --- /dev/null +++ b/src/paths.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- + +import inspect +import platform +import os +import subprocess +import sys +import string +import unicodedata + + +def app_data_path(app_name=None): + """Cross-platform method for determining where to put application data.""" + """Requires the name of the application""" + plat = platform.system() + if plat == 'Windows': + import winpaths + path = winpaths.get_appdata() + elif plat == 'Darwin': + path = os.path.join(os.path.expanduser('~'), 'Library', 'Application Support') + elif plat == 'Linux': + path = os.path.expanduser('~') + app_name = '.%s' % app_name.replace(' ', '_') + return os.path.join(path, app_name) + +def prepare_app_data_path(app_name): + """Creates the application's data directory, given its name.""" + dir = app_data_path(app_name) + return ensure_path(dir) + +def embedded_data_path(): + if platform.system() == 'Darwin' and is_frozen(): + return os.path.abspath(os.path.join(executable_directory(), '..', 'Resources')) + return app_path() + +def is_frozen(): + """Return a bool indicating if application is compressed""" + import imp + return hasattr(sys, 'frozen') or imp.is_frozen("__main__") + +def get_executable(): + """Returns the full executable path/name if frozen, or the full path/name of the main module if not.""" + if is_frozen(): + if platform.system() != 'Darwin': + return sys.executable +#On darwin, sys.executable points to python. We want the full path to the exe we ran. + exedir = os.path.abspath(os.path.dirname(sys.executable)) + items = os.listdir(exedir) + items.remove('python') + return os.path.join(exedir, items[0]) + #Not frozen + try: + import __main__ + return os.path.abspath(__main__.__file__) + except AttributeError: + return sys.argv[0] + +def get_module(level=2): + """Hacky method for deriving the caller of this function's module.""" + return inspect.getmodule(inspect.stack()[level][0]).__file__ + +def executable_directory(): + """Always determine the directory of the executable, even when run with py2exe or otherwise frozen""" + executable = get_executable() + path = os.path.abspath(os.path.dirname(executable)) + return path + +def app_path(): + """Return the root of the application's directory""" + path = executable_directory() + if is_frozen() and platform.system() == 'Darwin': + path = os.path.abspath(os.path.join(path, '..', '..')) + return path + +def module_path(level=2): + return os.path.abspath(os.path.dirname(get_module(level))) + +def documents_path(): + """On windows, returns the path to My Documents. On OSX, returns the user's Documents folder. For anything else, returns the user's home directory.""" + plat = platform.system() + if plat == 'Windows': + import winpaths + path = winpaths.get_my_documents() + elif plat == 'Darwin': + path = os.path.join(os.path.expanduser('~'), 'Documents') + else: + path = os.path.expanduser('~') + return path + +def safe_filename(filename): + """Given a filename, returns a safe version with no characters that would not work on different platforms.""" + SAFE_FILE_CHARS = "'-_.()[]{}!@#$%^&+=`~ " + filename = unicode(filename) + new_filename = ''.join(c for c in filename if c in SAFE_FILE_CHARS or c.isalnum()) + #Windows doesn't like directory names ending in space, macs consider filenames beginning with a dot as hidden, and windows removes dots at the ends of filenames. + return new_filename.strip(' .') + +def ensure_path(path): + if not os.path.exists(path): + os.makedirs(path) + return path + +def start_file(path): + if platform.system() == 'Windows': + os.startfile(path) + else: + subprocess.Popen(['open', path]) + +def get_applications_path(): + """Return the directory where applications are commonly installed on the system.""" + plat = platform.system() + if plat == 'Windows': + import winpaths + return winpaths.get_program_files() + elif plat == 'Darwin': + return '/Applications' diff --git a/src/storage.py b/src/storage.py index 40f8387..5d205ea 100644 --- a/src/storage.py +++ b/src/storage.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals # at top of module -from platform_utils import paths +import paths import os import glob diff --git a/src/update/update.py b/src/update/update.py index 84299dc..65cf5bd 100644 --- a/src/update/update.py +++ b/src/update/update.py @@ -12,7 +12,7 @@ try: except ImportError: import zipfile -from platform_utils import paths +import paths def perform_update(endpoint, current_version, app_name='', password=None, update_available_callback=None, progress_callback=None, update_complete_callback=None): requests_session = create_requests_session(app_name=app_name, version=current_version)