Skip to content

Commit 22325ad

Browse files
committed
api_config: avoid whitespace issues in config
When users create add their API Key to a config file it is possible that whitespace accidentally added into the file will cause issues when constructing the URI. Fix API call failures by trying harder to remove whitespace in the file. Ensure read_key() will strip whitespace and only use the first line. Signed-off-by: Jamie Couture <jamie.couture@nasdaq.com>
1 parent 1920b0d commit 22325ad

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

nasdaqdatalink/api_config.py

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

6262

63+
def get_first_non_empty(file_handle):
64+
lines = [line.strip() for line in file_handle.readlines()]
65+
return next((line for line in lines if line), None)
66+
67+
6368
def read_key_from_file(filename=None):
6469
if filename is None:
6570
filename = default_config_filename()
@@ -68,7 +73,7 @@ def read_key_from_file(filename=None):
6873
raise_empty_file(filename)
6974

7075
with open(filename, 'r') as f:
71-
apikey = f.read()
76+
apikey = get_first_non_empty(f)
7277

7378
if not apikey:
7479
raise_empty_file(filename)

test/test_api_config.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
os.path.dirname(os.path.realpath(__file__)), ".nasdaq-config", "defaultkeyfile"
1313
)
1414

15+
TEST_DEFAULT_FILE_CONTENTS = 'keyfordefaultfile'
16+
1517

1618
class ApiConfigTest(TestCase):
1719
def setUp(self):
@@ -55,6 +57,14 @@ def test_read_key_when_environment_variable_not_set(self):
5557
self.assertEqual(ApiConfig.api_key, 'keyforfile')
5658

5759

60+
def test_read_key_empty_file(self):
61+
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
62+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
63+
save_key("")
64+
with self.assertRaises(ValueError):
65+
read_key()
66+
67+
5868
def test_read_key_when_files_not_set(self):
5969
ApiConfig.api_key = None
6070
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
@@ -74,3 +84,38 @@ def test_read_key_when_default_file_set(self):
7484
read_key()
7585

7686
self.assertEqual(ApiConfig.api_key, 'keyfordefaultfile')
87+
88+
def _read_key_from_file_helper(self, given, expected):
89+
save_key(given, TEST_DEFAULT_FILE)
90+
ApiConfig.api_key = None # Set None, we are not testing save_key
91+
92+
with mock.patch("nasdaqdatalink.api_config.default_config_filename") as mock_default_config_filename:
93+
mock_default_config_filename.return_value = TEST_DEFAULT_FILE
94+
read_key()
95+
96+
self.assertEqual(ApiConfig.api_key, expected)
97+
98+
99+
def test_read_key_from_file_with_newline(self):
100+
given = f"{TEST_DEFAULT_FILE_CONTENTS}\n"
101+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
102+
103+
104+
def test_read_key_from_file_with_leading_newline(self):
105+
given = f"\n{TEST_DEFAULT_FILE_CONTENTS}\n"
106+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
107+
108+
109+
def test_read_key_from_file_with_space(self):
110+
given = f" {TEST_DEFAULT_FILE_CONTENTS} "
111+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
112+
113+
114+
def test_read_key_from_file_with_tab(self):
115+
given = f"\t{TEST_DEFAULT_FILE_CONTENTS}\t"
116+
self._read_key_from_file_helper(given, TEST_DEFAULT_FILE_CONTENTS)
117+
118+
119+
def test_read_key_from_file_with_multi_newline(self):
120+
given = "keyfordefaultfile\n\nanotherkey\n"
121+
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