Skip to content

Commit

Permalink
Merge branch 'jc/work-harder-to-prune-whitespace'
Browse files Browse the repository at this point in the history
* jc/work-harder-to-prune-whitespace:
  test: fix inconsistent leading whitespace
  test: improve teardown cleanup
  api_config: raise errors for mis-configured environment variable
  api_config: avoid whitespace issues in config
  • Loading branch information
couture-ql committed Jan 28, 2022
2 parents 0f2b0c9 + b7cc41f commit b68ff2e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
17 changes: 15 additions & 2 deletions nasdaqdatalink/api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ def raise_empty_file(config_filename):
raise ValueError("File '{:s}' is empty.".format(config_filename))


def raise_empty_environment_variable():
raise ValueError("NASDAQ_DATA_LINK_API_KEY cannot be empty")


def get_first_non_empty(file_handle):
lines = [line.strip() for line in file_handle.readlines()]
return next((line for line in lines if line), None)


def read_key_from_file(filename=None):
if filename is None:
filename = default_config_filename()
Expand All @@ -68,7 +77,7 @@ def read_key_from_file(filename=None):
raise_empty_file(filename)

with open(filename, 'r') as f:
apikey = f.read()
apikey = get_first_non_empty(f)

if not apikey:
raise_empty_file(filename)
Expand All @@ -81,7 +90,11 @@ def api_key_environment_variable_exists():


def read_key_from_environment_variable():
ApiConfig.api_key = os.environ.get(NASDAQ_DATA_LINK_API_KEY)
apikey = os.environ.get(NASDAQ_DATA_LINK_API_KEY)
if not apikey:
raise_empty_environment_variable()

ApiConfig.api_key = apikey


def read_key(filename=None):
Expand Down
70 changes: 64 additions & 6 deletions test/test_api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@
from unittest import TestCase, mock
from nasdaqdatalink.api_config import *

TEST_BASE_PATH = os.path.join(
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config"
)

TEST_KEY_FILE = os.path.join(
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config", "testkeyfile"
TEST_BASE_PATH, "testkeyfile"
)

TEST_DEFAULT_FILE = os.path.join(
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config", "defaultkeyfile"
TEST_BASE_PATH, "defaultkeyfile"
)

TEST_DEFAULT_FILE_CONTENTS = 'keyfordefaultfile'


class ApiConfigTest(TestCase):
def setUp(self):
Expand All @@ -32,6 +38,8 @@ def tearDown(self):
if os.path.exists(TEST_DEFAULT_FILE):
os.remove(TEST_DEFAULT_FILE)

os.removedirs(TEST_BASE_PATH)


def test_read_key_when_environment_variable_set(self):
os.environ['NASDAQ_DATA_LINK_API_KEY'] = 'setinenv'
Expand All @@ -55,11 +63,25 @@ def test_read_key_when_environment_variable_not_set(self):
self.assertEqual(ApiConfig.api_key, 'keyforfile')


def test_read_key_empty_file(self):
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
save_key("")
with self.assertRaises(ValueError):
read_key()


def test_read_key_when_env_key_empty(self):
os.environ['NASDAQ_DATA_LINK_API_KEY'] = ''
with self.assertRaises(ValueError):
read_key()


def test_read_key_when_files_not_set(self):
ApiConfig.api_key = None
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
read_key()
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
read_key()

mock_default_config_filename.assert_called_once
self.assertEqual(ApiConfig.api_key, None)
Expand All @@ -70,7 +92,43 @@ def test_read_key_when_default_file_set(self):
ApiConfig.api_key = None # Set None, we are not testing save_key

with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
read_key()
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
read_key()

self.assertEqual(ApiConfig.api_key, 'keyfordefaultfile')


def _read_key_from_file_helper(self, given, expected):
save_key(given, TEST_DEFAULT_FILE)
ApiConfig.api_key = None # Set None, we are not testing save_key

with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
read_key()

self.assertEqual(ApiConfig.api_key, expected)


def test_read_key_from_file_with_newline(self):
given = f"{TEST_DEFAULT_FILE_CONTENTS}\n"
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)


def test_read_key_from_file_with_leading_newline(self):
given = f"\n{TEST_DEFAULT_FILE_CONTENTS}\n"
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)


def test_read_key_from_file_with_space(self):
given = f" {TEST_DEFAULT_FILE_CONTENTS} "
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)


def test_read_key_from_file_with_tab(self):
given = f"\t{TEST_DEFAULT_FILE_CONTENTS}\t"
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)


def test_read_key_from_file_with_multi_newline(self):
given = "keyfordefaultfile\n\nanotherkey\n"
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)

0 comments on commit b68ff2e

Please sign in to comment.