Skip to content

Commit b68ff2e

Browse files
committed
Merge branch 'jc/work-harder-to-prune-whitespace'
* 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
2 parents 0f2b0c9 + b7cc41f commit b68ff2e

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

nasdaqdatalink/api_config.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ def raise_empty_file(config_filename):
6060
raise ValueError("File '{:s}' is empty.".format(config_filename))
6161

6262

63+
def raise_empty_environment_variable():
64+
raise ValueError("NASDAQ_DATA_LINK_API_KEY cannot be empty")
65+
66+
67+
def get_first_non_empty(file_handle):
68+
lines = [line.strip() for line in file_handle.readlines()]
69+
return next((line for line in lines if line), None)
70+
71+
6372
def read_key_from_file(filename=None):
6473
if filename is None:
6574
filename = default_config_filename()
@@ -68,7 +77,7 @@ def read_key_from_file(filename=None):
6877
raise_empty_file(filename)
6978

7079
with open(filename, 'r') as f:
71-
apikey = f.read()
80+
apikey = get_first_non_empty(f)
7281

7382
if not apikey:
7483
raise_empty_file(filename)
@@ -81,7 +90,11 @@ def api_key_environment_variable_exists():
8190

8291

8392
def read_key_from_environment_variable():
84-
ApiConfig.api_key = os.environ.get(NASDAQ_DATA_LINK_API_KEY)
93+
apikey = os.environ.get(NASDAQ_DATA_LINK_API_KEY)
94+
if not apikey:
95+
raise_empty_environment_variable()
96+
97+
ApiConfig.api_key = apikey
8598

8699

87100
def read_key(filename=None):

test/test_api_config.py

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44
from unittest import TestCase, mock
55
from nasdaqdatalink.api_config import *
66

7+
TEST_BASE_PATH = os.path.join(
8+
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config"
9+
)
10+
711
TEST_KEY_FILE = os.path.join(
8-
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config", "testkeyfile"
12+
TEST_BASE_PATH, "testkeyfile"
913
)
1014

1115
TEST_DEFAULT_FILE = os.path.join(
12-
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config", "defaultkeyfile"
16+
TEST_BASE_PATH, "defaultkeyfile"
1317
)
1418

19+
TEST_DEFAULT_FILE_CONTENTS = 'keyfordefaultfile'
20+
1521

1622
class ApiConfigTest(TestCase):
1723
def setUp(self):
@@ -32,6 +38,8 @@ def tearDown(self):
3238
if os.path.exists(TEST_DEFAULT_FILE):
3339
os.remove(TEST_DEFAULT_FILE)
3440

41+
os.removedirs(TEST_BASE_PATH)
42+
3543

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

5765

66+
def test_read_key_empty_file(self):
67+
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
68+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
69+
save_key("")
70+
with self.assertRaises(ValueError):
71+
read_key()
72+
73+
74+
def test_read_key_when_env_key_empty(self):
75+
os.environ['NASDAQ_DATA_LINK_API_KEY'] = ''
76+
with self.assertRaises(ValueError):
77+
read_key()
78+
79+
5880
def test_read_key_when_files_not_set(self):
5981
ApiConfig.api_key = None
6082
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
61-
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
62-
read_key()
83+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
84+
read_key()
6385

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

7294
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
73-
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
74-
read_key()
95+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
96+
read_key()
7597

7698
self.assertEqual(ApiConfig.api_key, 'keyfordefaultfile')
99+
100+
101+
def _read_key_from_file_helper(self, given, expected):
102+
save_key(given, TEST_DEFAULT_FILE)
103+
ApiConfig.api_key = None # Set None, we are not testing save_key
104+
105+
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
106+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
107+
read_key()
108+
109+
self.assertEqual(ApiConfig.api_key, expected)
110+
111+
112+
def test_read_key_from_file_with_newline(self):
113+
given = f"{TEST_DEFAULT_FILE_CONTENTS}\n"
114+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
115+
116+
117+
def test_read_key_from_file_with_leading_newline(self):
118+
given = f"\n{TEST_DEFAULT_FILE_CONTENTS}\n"
119+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
120+
121+
122+
def test_read_key_from_file_with_space(self):
123+
given = f" {TEST_DEFAULT_FILE_CONTENTS} "
124+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
125+
126+
127+
def test_read_key_from_file_with_tab(self):
128+
given = f"\t{TEST_DEFAULT_FILE_CONTENTS}\t"
129+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
130+
131+
132+
def test_read_key_from_file_with_multi_newline(self):
133+
given = "keyfordefaultfile\n\nanotherkey\n"
134+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy