diff --git a/plotly/files.py b/plotly/files.py index 9668f144b13..0973a01450c 100644 --- a/plotly/files.py +++ b/plotly/files.py @@ -1,10 +1,11 @@ import os # file structure -PLOTLY_DIR = os.path.join(os.path.expanduser("~"), ".plotly") +PLOTLY_DIR = os.environ.get("PLOTLY_DIR", + os.path.join(os.path.expanduser("~"), ".plotly")) + CREDENTIALS_FILE = os.path.join(PLOTLY_DIR, ".credentials") CONFIG_FILE = os.path.join(PLOTLY_DIR, ".config") -TEST_DIR = os.path.join(os.path.expanduser("~"), ".test") TEST_FILE = os.path.join(PLOTLY_DIR, ".permission_test") # this sets both the DEFAULTS and the TYPES for these files @@ -25,8 +26,6 @@ def _permissions(): try: - os.mkdir(TEST_DIR) - os.rmdir(TEST_DIR) if not os.path.exists(PLOTLY_DIR): os.mkdir(PLOTLY_DIR) with open(TEST_FILE, 'w') as f: @@ -37,8 +36,12 @@ def _permissions(): return False -_file_permissions = _permissions() +_file_permissions = None -def check_file_permissions(): +def ensure_writable_plotly_dir(): + # Cache permissions status + global _file_permissions + if _file_permissions is None: + _file_permissions = _permissions() return _file_permissions diff --git a/plotly/io/_orca.py b/plotly/io/_orca.py index 7b3acceb18b..045e2407d6a 100644 --- a/plotly/io/_orca.py +++ b/plotly/io/_orca.py @@ -13,7 +13,7 @@ from six import string_types import plotly -from plotly.files import PLOTLY_DIR +from plotly.files import PLOTLY_DIR, ensure_writable_plotly_dir from plotly.io._utils import validate_coerce_fig_to_dict from plotly.optional_imports import get_module @@ -354,8 +354,13 @@ def save(self): ------- None """ - with open(self.config_file, 'w') as f: - json.dump(self._props, f, indent=4) + if ensure_writable_plotly_dir(): + with open(self.config_file, 'w') as f: + json.dump(self._props, f, indent=4) + else: + warnings.warn("""\ +Failed to write orca configuration file at '{path}'""".format( + path=self.config_file)) @property def port(self): diff --git a/plotly/plotly/plotly.py b/plotly/plotly/plotly.py index 127cb0cb180..9844c8cca2e 100644 --- a/plotly/plotly/plotly.py +++ b/plotly/plotly/plotly.py @@ -57,9 +57,6 @@ "'secret'." ) -# test file permissions and make sure nothing is corrupted -tools.ensure_local_plotly_files() - # don't break backwards compatibility def sign_in(username, api_key, **kwargs): diff --git a/plotly/tests/test_plot_ly/test_get_figure/test_get_figure.py b/plotly/tests/test_plot_ly/test_get_figure/test_get_figure.py index d4ce5efd921..368835a80c9 100644 --- a/plotly/tests/test_plot_ly/test_get_figure/test_get_figure.py +++ b/plotly/tests/test_plot_ly/test_get_figure/test_get_figure.py @@ -98,7 +98,7 @@ def test_get_figure_raw(self): py.get_figure('PlotlyImageTest', str(file_id), raw=True) -class TestBytesVStrings(TestCase): +class TestBytesVStrings(PlotlyTestCase): @skipIf(not six.PY3, 'Decoding and missing escapes only seen in PY3') def test_proper_escaping(self): diff --git a/plotly/tests/utils.py b/plotly/tests/utils.py index 43d2dbb04aa..8ca85cc75aa 100644 --- a/plotly/tests/utils.py +++ b/plotly/tests/utils.py @@ -36,16 +36,14 @@ def tearDown(self): self.restore_session() def stash_files(self): - if files.check_file_permissions(): - self._credentials = utils.load_json_dict(files.CREDENTIALS_FILE) - self._config = utils.load_json_dict(files.CONFIG_FILE) + self._credentials = utils.load_json_dict(files.CREDENTIALS_FILE) + self._config = utils.load_json_dict(files.CONFIG_FILE) def restore_files(self): - if files.check_file_permissions(): - if self._credentials is not None: - utils.save_json_dict(files.CREDENTIALS_FILE, self._credentials) - if self._config is not None: - utils.save_json_dict(files.CONFIG_FILE, self._config) + if self._credentials and files.ensure_writable_plotly_dir(): + utils.save_json_dict(files.CREDENTIALS_FILE, self._credentials) + if self._config and files.ensure_writable_plotly_dir(): + utils.save_json_dict(files.CONFIG_FILE, self._config) def stash_session(self): self._session = copy.deepcopy(session._session) diff --git a/plotly/tools.py b/plotly/tools.py index 80ec787eaba..87b789309b3 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -12,10 +12,11 @@ import warnings import six +import copy from plotly import exceptions, optional_imports, session, utils from plotly.files import (CONFIG_FILE, CREDENTIALS_FILE, FILE_CONTENT, - check_file_permissions) + ensure_writable_plotly_dir) DEFAULT_PLOTLY_COLORS = ['rgb(31, 119, 180)', 'rgb(255, 127, 14)', 'rgb(44, 160, 44)', 'rgb(214, 39, 40)', @@ -78,7 +79,7 @@ def ensure_local_plotly_files(): If the config or credential files aren't filled out, then write them to the disk. """ - if check_file_permissions(): + if ensure_writable_plotly_dir(): for fn in [CREDENTIALS_FILE, CONFIG_FILE]: utils.ensure_file_exists(fn) contents = utils.load_json_dict(fn) @@ -124,7 +125,7 @@ def set_credentials_file(username=None, :param (str) proxy_password: The pw associated with your Proxy un """ - if not check_file_permissions(): + if not ensure_writable_plotly_dir(): raise exceptions.PlotlyError("You don't have proper file permissions " "to run this function.") ensure_local_plotly_files() # make sure what's there is OK @@ -152,11 +153,13 @@ def get_credentials_file(*args): get_credentials_file('username') """ - if check_file_permissions(): - ensure_local_plotly_files() # make sure what's there is OK - return utils.load_json_dict(CREDENTIALS_FILE, *args) - else: - return FILE_CONTENT[CREDENTIALS_FILE] + # Read credentials from file if possible + credentials = utils.load_json_dict(CREDENTIALS_FILE, *args) + if not credentials: + # Credentials could not be read, use defaults + credentials = copy.copy(FILE_CONTENT[CREDENTIALS_FILE]) + + return credentials def reset_credentials_file(): @@ -185,7 +188,7 @@ def set_config_file(plotly_domain=None, :param (bool) world_readable: True = public, False = private """ - if not check_file_permissions(): + if not ensure_writable_plotly_dir(): raise exceptions.PlotlyError("You don't have proper file permissions " "to run this function.") ensure_local_plotly_files() # make sure what's there is OK @@ -247,11 +250,13 @@ def get_config_file(*args): get_config_file('plotly_domain') """ - if check_file_permissions(): - ensure_local_plotly_files() # make sure what's there is OK - return utils.load_json_dict(CONFIG_FILE, *args) - else: - return FILE_CONTENT[CONFIG_FILE] + # Read config from file if possible + config = utils.load_json_dict(CONFIG_FILE, *args) + if not config: + # Config could not be read, use defaults + config = copy.copy(FILE_CONTENT[CONFIG_FILE]) + + return config def reset_config_file():