Skip to content

Support configurable settings directory with lazy initialization #1195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 25, 2018
15 changes: 9 additions & 6 deletions plotly/files.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand All @@ -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
11 changes: 8 additions & 3 deletions plotly/io/_orca.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
3 changes: 0 additions & 3 deletions plotly/plotly/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
14 changes: 6 additions & 8 deletions plotly/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 19 additions & 14 deletions plotly/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)',
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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():
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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():
Expand Down