diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f6d9f817..508f53e26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,16 @@ at anytime. ### Changed * claim_show API command no longer takes name as argument - * + * Linux default downloads folder changed from `~/Downloads` to `XDG_DOWNLOAD_DIR` + * Linux folders moved from the home directory to `~/.local/share/lbry` + * Windows folders moved from `%AppData%/Roaming` to `%AppData%/Local/lbry` ### Fixed * Fix for https://github.com/lbryio/lbry/issues/750 * Fixed inconsistencies in claim_show output * Fixed daemon process hanging when started without an internet connection * Fixed https://github.com/lbryio/lbry/issues/774 + * Fix XDG compliance on Linux ### Deprecated * diff --git a/lbrynet/conf.py b/lbrynet/conf.py index 2d36f7d99..c63d15012 100644 --- a/lbrynet/conf.py +++ b/lbrynet/conf.py @@ -2,12 +2,18 @@ import base58 import json import logging import os +import re import sys import yaml import envparse -from appdirs import user_data_dir +from appdirs import user_data_dir, user_config_dir from lbrynet.core import utils +try: + from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle +except (ImportError, ValueError): + pass + log = logging.getLogger(__name__) ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -43,6 +49,7 @@ settings_encoders = { '.yml': yaml.safe_dump } + def _win_path_to_bytes(path): """ Encode Windows paths to string. appdirs.user_data_dir() @@ -58,29 +65,77 @@ def _win_path_to_bytes(path): pass return path -if sys.platform.startswith('darwin'): + +def _get_old_directories(platform): + dirs = {} + if platform == WINDOWS: + appdata = get_path(FOLDERID.RoamingAppData, UserHandle.current) + dirs['data'] = os.path.join(appdata, 'lbrynet') + dirs['lbryum'] = os.path.join(appdata, 'lbryum') + dirs['download'] = get_path(FOLDERID.Downloads, UserHandle.current) + elif platform == DARWIN: + dirs['data'] = user_data_dir('LBRY') + dirs['lbryum'] = os.path.expanduser('~/.lbryum') + dirs['download'] = os.path.expanduser('~/Downloads') + elif platform == LINUX: + dirs['data'] = os.path.join(os.path.expanduser('~'), '~/.lbrynet') + dirs['lbryum'] = os.path.join(os.path.expanduser('~'), '~/.lbryum') + dirs['download'] = os.path.join(os.path.expanduser('~'), 'Downloads') + else: + raise ValueError('unknown platform value') + return dirs + + +def _get_new_directories(platform): + dirs = {} + if platform == WINDOWS: + dirs['data'] = user_data_dir('lbrynet', 'lbry') + dirs['lbryum'] = user_data_dir('lbryum', 'lbry') + dirs['download'] = get_path(FOLDERID.Downloads, UserHandle.current) + elif platform == DARWIN: + _get_old_directories(platform) + elif platform == LINUX: + dirs['data'] = user_data_dir('lbry/lbrynet') + dirs['lbryum'] = user_data_dir('lbry/lbryum') + try: + with open(os.path.join(user_config_dir(), 'user-dirs.dirs'), 'r') as xdg: + down_dir = re.search(r'XDG_DOWNLOAD_DIR=(.+)', xdg.read()).group(1) + down_dir = re.sub('\$HOME', os.getenv('HOME'), down_dir) + dirs['download'] = re.sub('\"', '', down_dir) + except EnvironmentError: + dirs['download'] = os.getenv('XDG_DOWNLOAD_DIR') + + if not dirs['download']: + dirs['download'] = os.path.expanduser('~/Downloads') + else: + raise ValueError('unknown platform value') + return dirs + + +if 'darwin' in sys.platform: platform = DARWIN - default_download_directory = os.path.join(os.path.expanduser('~'), 'Downloads') - default_data_dir = user_data_dir('LBRY') - default_lbryum_dir = os.path.join(os.path.expanduser('~'), '.lbryum') -elif sys.platform.startswith('win'): + dirs = _get_old_directories(DARWIN) +elif 'win' in sys.platform: platform = WINDOWS - from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle - - default_download_directory = get_path(FOLDERID.Downloads, UserHandle.current) - default_data_dir = os.path.join( - get_path(FOLDERID.RoamingAppData, UserHandle.current), 'lbrynet') - default_lbryum_dir = os.path.join( - get_path(FOLDERID.RoamingAppData, UserHandle.current), 'lbryum') - - default_download_directory = _win_path_to_bytes(default_download_directory) - default_data_dir = _win_path_to_bytes(default_data_dir) - default_lbryum_dir = _win_path_to_bytes(default_lbryum_dir) + if os.path.isdir(_get_old_directories(WINDOWS)['data']) or \ + os.path.isdir(_get_old_directories(WINDOWS)['lbryum']): + dirs = _get_old_directories(WINDOWS) + else: + dirs = _get_new_directories(WINDOWS) + dirs['data'] = _win_path_to_bytes(dirs['data']) + dirs['lbryum'] = _win_path_to_bytes(dirs['lbryum']) + dirs['download'] = _win_path_to_bytes(dirs['download']) else: platform = LINUX - default_download_directory = os.path.join(os.path.expanduser('~'), 'Downloads') - default_data_dir = os.path.join(os.path.expanduser('~'), '.lbrynet') - default_lbryum_dir = os.path.join(os.path.expanduser('~'), '.lbryum') + if os.path.isdir(_get_old_directories(LINUX)['data']) or \ + os.path.isdir(_get_old_directories(LINUX)['lbryum']): + dirs = _get_old_directories(LINUX) + else: + dirs = _get_new_directories(LINUX) + +default_data_dir = dirs['data'] +default_lbryum_dir = dirs['lbryum'] +default_download_dir = dirs['download'] ICON_PATH = 'icons' if platform is WINDOWS else 'app.icns' @@ -178,7 +233,7 @@ ADJUSTABLE_SETTINGS = { 'data_rate': (float, .0001), # points/megabyte 'delete_blobs_on_remove': (bool, True), 'dht_node_port': (int, 4444), - 'download_directory': (str, default_download_directory), + 'download_directory': (str, default_download_dir), 'download_timeout': (int, 180), 'is_generous_host': (bool, True), 'known_dht_nodes': (list, DEFAULT_DHT_NODES, server_port), diff --git a/lbrynet/daemon/Downloader.py b/lbrynet/daemon/Downloader.py index 14f570ffc..488f02886 100644 --- a/lbrynet/daemon/Downloader.py +++ b/lbrynet/daemon/Downloader.py @@ -56,7 +56,6 @@ class GetStream(object): # fired after the metadata and the first data blob have been downloaded self.data_downloading_deferred = defer.Deferred(None) - @property def download_path(self): return os.path.join(self.download_directory, self.downloader.file_name) @@ -211,4 +210,3 @@ class GetStream(object): raise defer.returnValue((self.downloader, self.finished_deferred)) - diff --git a/lbrynet/daemon/FileStreamer.py b/lbrynet/daemon/FileStreamer.py index 4f8c4db94..bff4926ad 100644 --- a/lbrynet/daemon/FileStreamer.py +++ b/lbrynet/daemon/FileStreamer.py @@ -1,24 +1,14 @@ import logging -import os -import sys import mimetypes -from appdirs import user_data_dir from zope.interface import implements from twisted.internet import defer, error, interfaces, abstract, task, reactor -# TODO: omg, this code is essentially duplicated in Daemon -if sys.platform != "darwin": - data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") -else: - data_dir = user_data_dir("LBRY") -if not os.path.isdir(data_dir): - os.mkdir(data_dir) - log = logging.getLogger(__name__) STATUS_FINISHED = 'finished' + class EncryptedFileStreamer(object): """ Writes LBRY stream to request; will pause to wait for new data if the file @@ -31,7 +21,6 @@ class EncryptedFileStreamer(object): bufferSize = abstract.FileDescriptor.bufferSize - # How long to wait between sending blocks (needed because some # video players freeze up if you try to send data too fast) stream_interval = 0.005 @@ -39,7 +28,6 @@ class EncryptedFileStreamer(object): # How long to wait before checking if new data has been appended to the file new_data_check_interval = 0.25 - def __init__(self, request, path, stream, file_manager): def _set_content_length_header(length): self._request.setHeader('content-length', length) diff --git a/lbrynet/daemon/Resources.py b/lbrynet/daemon/Resources.py index 9abe612b5..c6918b057 100644 --- a/lbrynet/daemon/Resources.py +++ b/lbrynet/daemon/Resources.py @@ -2,26 +2,15 @@ import logging import os import shutil import json -import sys import tempfile -from appdirs import user_data_dir from twisted.web import server, static, resource from twisted.internet import defer, error from lbrynet import conf from lbrynet.daemon.FileStreamer import EncryptedFileStreamer -# TODO: omg, this code is essentially duplicated in Daemon - -if sys.platform != "darwin": - data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") -else: - data_dir = user_data_dir("LBRY") -if not os.path.isdir(data_dir): - os.mkdir(data_dir) - log = logging.getLogger(__name__) diff --git a/lbrynet/daemon/daemon_scripts/Autofetcher.py b/lbrynet/daemon/daemon_scripts/Autofetcher.py index fc73373f2..1cba26d3c 100644 --- a/lbrynet/daemon/daemon_scripts/Autofetcher.py +++ b/lbrynet/daemon/daemon_scripts/Autofetcher.py @@ -1,21 +1,14 @@ import json import logging.handlers -import sys import os -from appdirs import user_data_dir from twisted.internet.task import LoopingCall from twisted.internet import reactor +from lbrynet import conf -if sys.platform != "darwin": - log_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") -else: - log_dir = user_data_dir("LBRY") - -if not os.path.isdir(log_dir): - os.mkdir(log_dir) - +conf.initialize_settings() +log_dir = conf.settings['data_dir'] LOG_FILENAME = os.path.join(log_dir, 'lbrynet-daemon.log') if os.path.isfile(LOG_FILENAME): diff --git a/tests/unit/test_conf.py b/tests/unit/test_conf.py index 17dff30e2..d7adeb174 100644 --- a/tests/unit/test_conf.py +++ b/tests/unit/test_conf.py @@ -58,6 +58,6 @@ class SettingsTest(unittest.TestCase): # check if these directories are returned as string and not unicode # otherwise there will be problems when calling os.path.join on # unicode directory names with string file names - self.assertEqual(str, type(conf.default_download_directory)) + self.assertEqual(str, type(conf.default_download_dir)) self.assertEqual(str, type(conf.default_data_dir)) self.assertEqual(str, type(conf.default_lbryum_dir))