Skip to content

Commit 3ea93fa

Browse files
Merge branch 'main' into qa
2 parents f8952c3 + 3c3fda5 commit 3ea93fa

7 files changed

Lines changed: 62 additions & 20 deletions

File tree

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.9.16

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
2-
## v1.1.0
2+
## v1.1.2
3+
- Update config_helper to accept list environment variables
4+
5+
## v1.1.0/v1.1.1
36
- Add retries for empty responses in oauth2 client. This was added to address a known quirk in the Sierra API where this response is returned:
47
```
58
> GET / HTTP/1.1
@@ -8,6 +11,7 @@
811
> Accept: */*
912
>
1013
```
14+
- Due to an accidental deployment, v1.1.0 and v1.1.1 were both released but are identical
1115

1216
## v1.0.4 - 6/28/23
1317
- Enforce Kinesis stream 1000 records/second write limit

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ This package contains common Python utility classes and functions.
1414
* Making requests to the Oauth2 authenticated APIs such as NYPL Platform API and Sierra
1515

1616
## Functions
17-
* Reading a YAML config file and putting the contents in os.environ
17+
* Reading a YAML config file and putting the contents in os.environ -- see `config/sample.yaml` for an example of how the config file should be formatted
1818
* Creating a logger in the appropriate format
1919
* Obfuscating a value using bcrypt
2020
* Parsing/building Research Catalog identifiers
@@ -35,19 +35,19 @@ kinesis_client = KinesisClient(...)
3535
# Do not use any version below 1.0.0
3636
# All available optional dependencies can be found in pyproject.toml.
3737
# See the "Managing dependencies" section below for more details.
38-
nypl-py-utils[kinesis-client,config-helper]==1.0.4
38+
nypl-py-utils[kinesis-client,config-helper]==1.1.2
3939
```
4040

4141
## Developing locally
4242
In order to use the local version of the package instead of the global version, use a virtual environment. To set up a virtual environment and install all the necessary dependencies, run:
4343

4444
```
45-
python3 -m venv testenv
46-
source testenv/bin/activate
45+
python3 -m venv .venv
46+
source .venv/bin/activate
4747
pip install --upgrade pip
4848
pip install .
4949
pip install '.[development]'
50-
deactivate && source testenv/bin/activate
50+
deactivate && source .venv/bin/activate
5151
```
5252

5353
## Managing dependencies
@@ -57,11 +57,11 @@ When a new client or helper file is created, a new optional dependency set shoul
5757

5858
The optional dependency sets also give the developer the option to manually list out the dependencies of the clients rather than relying upon what the package thinks is required, which can be beneficial in certain circumstances. For instance, AWS lambda functions come with `boto3` and `botocore` pre-installed, so it's not necessary to include these (rather hefty) dependencies in the lambda deployment package.
5959

60-
### Troubleshooting
61-
#### Using PostgreSQLClient in an AWS Lambda
60+
## Troubleshooting
61+
### Using PostgreSQLClient in an AWS Lambda
6262
Because `psycopg` requires a statically linked version of the `libpq` library, the `PostgreSQLClient` cannot be installed as-is in an AWS Lambda function. Instead, it must be packaged as follows:
6363
```bash
64-
pip install --target ./package nypl-py-utils[postgresql-client]==1.0.1
64+
pip install --target ./package nypl-py-utils[postgresql-client]==1.1.2
6565

6666
pip install \
6767
--platform manylinux2014_x86_64 \
@@ -72,7 +72,7 @@ pip install \
7272
'psycopg[binary]'
7373
```
7474

75-
#### Using PostgreSQLClient locally
75+
### Using PostgreSQLClient locally
7676
If using the `PostgreSQLClient` produces the following error locally:
7777
```
7878
ImportError: no pq wrapper available.

config/sample.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
PLAINTEXT_VARIABLES:
3+
STRING_VAR: string-var
4+
INT_VAR: 1
5+
LIST_VAR:
6+
- string-var2
7+
- 2
8+
ENCRYPTED_VARIABLES:
9+
ENCRYPTED_STRING_VAR: AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAGowaAYJKoZIhvcNAQcGoFswWQIBADBUBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDCvE8Pc8PiUEiCGpEAIBEIAnf8fz6YXH959A0ygrM4S95giFnwvp9dYFzp/2ViAIlD5GZ1S04vay
10+
ENCRYPTED_INT_VAR: AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAF8wXQYJKoZIhvcNAQcGoFAwTgIBADBJBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDFQdg7ua7D8XH7UZGgIBEIAcpkIN6+56sbR3Vbk12NX2QDY28dnL8IWgVdnBRA==
11+
ENCRYPTED_LIST_VAR:
12+
- AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAGswaQYJKoZIhvcNAQcGoFwwWgIBADBVBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMTe0jJyHxGaiy0PHQIBEIAo4+qpfJp/gfZqhl1GtN/q9ebn2isiVOn5QLK/fcUtWeG182jiKPdOFA==
13+
- AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAF8wXQYJKoZIhvcNAQcGoFAwTgIBADBJBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDGsG/1m7nes884q8vQIBEIAc9eBDgUgVzVsK3lyebNmc09kGfP7Gzwm6ESJAiA==
14+
...

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "nypl_py_utils"
7-
version = "1.1.1"
7+
version = "1.1.2"
88
authors = [
99
{ name="Aaron Friedman", email="aaronfriedman@nypl.org" },
1010
]

src/nypl_py_utils/functions/config_helper.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import os
23
import yaml
34

@@ -11,15 +12,17 @@ def load_env_file(run_type, file_string):
1112
"""
1213
This method loads a YAML config file containing environment variables,
1314
decrypts whichever are encrypted, and puts them all into os.environ as
14-
strings.
15+
strings. For a YAML variable containing a list of values, the list is
16+
exported into os.environ as a json string and should be loaded as such.
1517
1618
It requires the YAML file to be split into a 'PLAINTEXT_VARIABLES' section
17-
and an 'ENCRYPTED_VARIABLES' section.
19+
and an 'ENCRYPTED_VARIABLES' section. See config/sample.yaml for an example
20+
config file.
1821
1922
Parameters
2023
----------
2124
run_type: str
22-
The name of the config file to use, e.g. 'devel'
25+
The name of the config file to use, e.g. 'sample'
2326
file_string: str
2427
The path to the config files with the filename as a variable to be
2528
interpolated, e.g. 'config/{}.yaml'
@@ -43,11 +46,18 @@ def load_env_file(run_type, file_string):
4346

4447
if env_dict:
4548
for key, value in env_dict.get('PLAINTEXT_VARIABLES', {}).items():
46-
os.environ[key] = str(value)
49+
if type(value) is list:
50+
os.environ[key] = json.dumps(value)
51+
else:
52+
os.environ[key] = str(value)
4753

4854
kms_client = KmsClient()
4955
for key, value in env_dict.get('ENCRYPTED_VARIABLES', {}).items():
50-
os.environ[key] = kms_client.decrypt(value)
56+
if type(value) is list:
57+
decrypted_list = [kms_client.decrypt(v) for v in value]
58+
os.environ[key] = json.dumps(decrypted_list)
59+
else:
60+
os.environ[key] = kms_client.decrypt(value)
5161
kms_client.close()
5262

5363

tests/test_config_helper.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@
44
from nypl_py_utils.functions.config_helper import (
55
load_env_file, ConfigHelperError)
66

7-
_TEST_VARIABLE_NAMES = ['TEST_STRING', 'TEST_INT', 'TEST_ENCRYPTED_VARIABLE_1',
8-
'TEST_ENCRYPTED_VARIABLE_2']
7+
_TEST_VARIABLE_NAMES = [
8+
'TEST_STRING', 'TEST_INT', 'TEST_LIST', 'TEST_ENCRYPTED_VARIABLE_1',
9+
'TEST_ENCRYPTED_VARIABLE_2', 'TEST_ENCRYPTED_LIST']
10+
911
_TEST_CONFIG_CONTENTS = \
1012
'''---
1113
PLAINTEXT_VARIABLES:
1214
TEST_STRING: string-variable
1315
TEST_INT: 1
16+
TEST_LIST:
17+
- string-var
18+
- 2
1419
ENCRYPTED_VARIABLES:
1520
TEST_ENCRYPTED_VARIABLE_1: test-encryption-1
1621
TEST_ENCRYPTED_VARIABLE_2: test-encryption-2
22+
TEST_ENCRYPTED_LIST:
23+
- test-encryption-3
24+
- test-encryption-4
1725
...'''
1826

1927

@@ -22,7 +30,8 @@ class TestConfigHelper:
2230
def test_load_env_file(self, mocker):
2331
mock_kms_client = mocker.MagicMock()
2432
mock_kms_client.decrypt.side_effect = [
25-
'test-decryption-1', 'test-decryption-2']
33+
'test-decryption-1', 'test-decryption-2', 'test-decryption-3',
34+
'test-decryption-4']
2635
mocker.patch('nypl_py_utils.functions.config_helper.KmsClient',
2736
return_value=mock_kms_client)
2837
mock_file_open = mocker.patch(
@@ -34,13 +43,17 @@ def test_load_env_file(self, mocker):
3443

3544
mock_file_open.assert_called_once_with('test-path/test-env.yaml', 'r')
3645
mock_kms_client.decrypt.assert_has_calls([
37-
mocker.call('test-encryption-1'), mocker.call('test-encryption-2')]
46+
mocker.call('test-encryption-1'), mocker.call('test-encryption-2'),
47+
mocker.call('test-encryption-3'), mocker.call('test-encryption-4')]
3848
)
3949
mock_kms_client.close.assert_called_once()
4050
assert os.environ['TEST_STRING'] == 'string-variable'
4151
assert os.environ['TEST_INT'] == '1'
52+
assert os.environ['TEST_LIST'] == '["string-var", 2]'
4253
assert os.environ['TEST_ENCRYPTED_VARIABLE_1'] == 'test-decryption-1'
4354
assert os.environ['TEST_ENCRYPTED_VARIABLE_2'] == 'test-decryption-2'
55+
assert os.environ['TEST_ENCRYPTED_LIST'] == \
56+
'["test-decryption-3", "test-decryption-4"]'
4457

4558
for key in _TEST_VARIABLE_NAMES:
4659
if key in os.environ:

0 commit comments

Comments
 (0)