From d36214056e9fd6edd0305fcbc3df6a19cabec1f1 Mon Sep 17 00:00:00 2001 From: itsb Date: Thu, 12 Jan 2017 17:25:02 -0800 Subject: [PATCH 1/7] user-controllable plotly config directory --- plotly/files.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plotly/files.py b/plotly/files.py index a97e79fe255..bfbee85bd71 100644 --- a/plotly/files.py +++ b/plotly/files.py @@ -1,10 +1,9 @@ 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 @@ -23,8 +22,6 @@ 'auto_open': True}} try: - os.mkdir(TEST_DIR) - os.rmdir(TEST_DIR) if not os.path.exists(PLOTLY_DIR): os.mkdir(PLOTLY_DIR) f = open(TEST_FILE, 'w') From 981882f9a37be7ff110acdfe2689fc1d2ed67f62 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 16:10:19 -0400 Subject: [PATCH 2/7] Don't create .plotly directory or test permissions until settings need to be written When settings are accessed and directory or files don't exist, return the defaults --- plotly/files.py | 6 +++++- plotly/io/_orca.py | 11 ++++++++--- plotly/plotly/plotly.py | 3 --- plotly/tools.py | 24 ++++++++++++++---------- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/plotly/files.py b/plotly/files.py index a8aef7bb506..fb18b0bbfda 100644 --- a/plotly/files.py +++ b/plotly/files.py @@ -33,8 +33,12 @@ def _permissions(): return False -_file_permissions = _permissions() +_file_permissions = None def check_file_permissions(): + # 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..005cf797437 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, check_file_permissions 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 check_file_permissions(): + 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/tools.py b/plotly/tools.py index 80ec787eaba..e7883789945 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -152,11 +152,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 = FILE_CONTENT[CREDENTIALS_FILE] + + return credentials def reset_credentials_file(): @@ -247,11 +249,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 = FILE_CONTENT[CONFIG_FILE] + + return config def reset_config_file(): From e5add62c33f3b4a9b0afc13ee0c0bad0b7d3f7c2 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 16:14:30 -0400 Subject: [PATCH 3/7] Rename check_file_permissions -> ensure_writeable_plotly_dir --- plotly/files.py | 2 +- plotly/io/_orca.py | 4 ++-- plotly/tests/utils.py | 4 ++-- plotly/tools.py | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plotly/files.py b/plotly/files.py index fb18b0bbfda..0888bb6c499 100644 --- a/plotly/files.py +++ b/plotly/files.py @@ -36,7 +36,7 @@ def _permissions(): _file_permissions = None -def check_file_permissions(): +def ensure_writable_plotly_dir(): # Cache permissions status global _file_permissions if _file_permissions is None: diff --git a/plotly/io/_orca.py b/plotly/io/_orca.py index 005cf797437..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, check_file_permissions +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,7 +354,7 @@ def save(self): ------- None """ - if check_file_permissions(): + if ensure_writable_plotly_dir(): with open(self.config_file, 'w') as f: json.dump(self._props, f, indent=4) else: diff --git a/plotly/tests/utils.py b/plotly/tests/utils.py index 43d2dbb04aa..0d46696614b 100644 --- a/plotly/tests/utils.py +++ b/plotly/tests/utils.py @@ -36,12 +36,12 @@ def tearDown(self): self.restore_session() def stash_files(self): - if files.check_file_permissions(): + if files.ensure_writable_plotly_dir(): 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 files.ensure_writable_plotly_dir(): if self._credentials is not None: utils.save_json_dict(files.CREDENTIALS_FILE, self._credentials) if self._config is not None: diff --git a/plotly/tools.py b/plotly/tools.py index e7883789945..f375dbd5d0d 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -15,7 +15,7 @@ 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 +78,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 +124,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 @@ -187,7 +187,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 From dd7048ded4599745f34c03d7a7d5f0d0710633f8 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 16:14:39 -0400 Subject: [PATCH 4/7] PEP8 --- plotly/files.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plotly/files.py b/plotly/files.py index 0888bb6c499..0973a01450c 100644 --- a/plotly/files.py +++ b/plotly/files.py @@ -1,7 +1,9 @@ import os # file structure -PLOTLY_DIR = os.environ.get("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_FILE = os.path.join(PLOTLY_DIR, ".permission_test") @@ -21,6 +23,7 @@ 'sharing': 'public', 'auto_open': True}} + def _permissions(): try: if not os.path.exists(PLOTLY_DIR): From 0e2c7d8a9af065868f762d7d228be97b670eea5c Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 18:26:19 -0400 Subject: [PATCH 5/7] Don't create .plotly directory for tests that don't need it --- plotly/tests/utils.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plotly/tests/utils.py b/plotly/tests/utils.py index 0d46696614b..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.ensure_writable_plotly_dir(): - 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.ensure_writable_plotly_dir(): - 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) From 985b0350fd49e88c4f72a2ff03be3ed34afd05ea Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 19:14:08 -0400 Subject: [PATCH 6/7] Fix parent class of TestByteVStrings test case It needs to be PlotlyTestCase in order to trigger the saving/restoration of config and credentials. --- plotly/tests/test_plot_ly/test_get_figure/test_get_figure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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): From 434ce28683e2ee3e60090a97edd86c02e158b2b5 Mon Sep 17 00:00:00 2001 From: Jon Mease Date: Mon, 24 Sep 2018 19:15:23 -0400 Subject: [PATCH 7/7] copy default credentials/config dict before returning Otherwise defaults themselves are mutated! --- plotly/tools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plotly/tools.py b/plotly/tools.py index f375dbd5d0d..87b789309b3 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -12,6 +12,7 @@ import warnings import six +import copy from plotly import exceptions, optional_imports, session, utils from plotly.files import (CONFIG_FILE, CREDENTIALS_FILE, FILE_CONTENT, @@ -156,7 +157,7 @@ def get_credentials_file(*args): credentials = utils.load_json_dict(CREDENTIALS_FILE, *args) if not credentials: # Credentials could not be read, use defaults - credentials = FILE_CONTENT[CREDENTIALS_FILE] + credentials = copy.copy(FILE_CONTENT[CREDENTIALS_FILE]) return credentials @@ -253,7 +254,7 @@ def get_config_file(*args): config = utils.load_json_dict(CONFIG_FILE, *args) if not config: # Config could not be read, use defaults - config = FILE_CONTENT[CONFIG_FILE] + config = copy.copy(FILE_CONTENT[CONFIG_FILE]) return config