Skip to content

Commit a27b261

Browse files
committed
Merge branch 'main' into qa
2 parents 0f3152b + 30b18f4 commit a27b261

16 files changed

Lines changed: 732 additions & 43 deletions

.github/workflows/deploy-production.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ on:
44
release:
55
types: [ released ]
66

7+
permissions:
8+
id-token: write
9+
contents: read
10+
711
jobs:
812
check_production_tag:
913
name: Check if the release is tagged as production
@@ -26,10 +30,10 @@ jobs:
2630
runs-on: ubuntu-latest
2731
steps:
2832
- name: Checkout repo
29-
uses: actions/checkout@v3
33+
uses: actions/checkout@v4
3034

3135
- name: Set up Python 3.9
32-
uses: actions/setup-python@v4
36+
uses: actions/setup-python@v5
3337
with:
3438
python-version: '3.9'
3539
cache: 'pip'
@@ -52,6 +56,4 @@ jobs:
5256
.
5357
5458
- name: Publish distribution package to PyPI
55-
uses: pypa/gh-action-pypi-publish@release/v1
56-
with:
57-
password: ${{ secrets.PYPI_API_TOKEN }}
59+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/deploy-qa.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ on:
44
release:
55
types: [ released ]
66

7+
permissions:
8+
id-token: write
9+
contents: read
10+
711
jobs:
812
check_qa_tag:
913
name: Check if the release is tagged as QA
@@ -26,10 +30,10 @@ jobs:
2630
runs-on: ubuntu-latest
2731
steps:
2832
- name: Checkout repo
29-
uses: actions/checkout@v3
33+
uses: actions/checkout@v4
3034

3135
- name: Set up Python 3.9
32-
uses: actions/setup-python@v4
36+
uses: actions/setup-python@v5
3337
with:
3438
python-version: '3.9'
3539
cache: 'pip'
@@ -54,5 +58,4 @@ jobs:
5458
- name: Publish distribution package to Test PyPI
5559
uses: pypa/gh-action-pypi-publish@release/v1
5660
with:
57-
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
58-
repository_url: https://test.pypi.org/legacy/
61+
repository-url: https://test.pypi.org/legacy/

.github/workflows/run-unit-tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
name: Run Python unit tests
22

3-
on:
3+
on:
44
pull_request:
5-
actions: [ opened ]
5+
types: [ labeled, unlabeled, opened, reopened, synchronize ]
66

77
jobs:
88
changelog:
99
name: Updates changelog
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v3
12+
- uses: actions/checkout@v4
1313
- uses: dangoslen/changelog-enforcer@v3
1414
test:
1515
runs-on: ubuntu-latest
1616
steps:
1717
- name: Checkout repo
18-
uses: actions/checkout@v3
18+
uses: actions/checkout@v4
1919

2020
- name: Set up Python 3.9
21-
uses: actions/setup-python@v4
21+
uses: actions/setup-python@v5
2222
with:
2323
python-version: '3.9'
2424
cache: 'pip'

CHANGELOG.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
# Changelog
2+
## v1.5.0 11/19/24
3+
- Added cloudLibrary client
4+
5+
## v1.4.0 9/23/24
6+
- Added SFTP client
7+
8+
## v1.3.2 8/1/24
9+
- Replaced info statements with debug for security purposes
10+
11+
## v1.3.1 7/31/24
12+
- Replaced log statement in Avro client with debug
13+
14+
## v1.3.0 7/30/24
15+
- Added SecretsManager client
16+
17+
## v1.2.1 7/25/24
18+
- Add retry for fetching Avro schemas
19+
220
## v1.2.0 7/17/24
3-
- Generalized Avro functions and separated encoding/decoding behavior.
21+
- Generalized Avro functions and separated encoding/decoding behavior
422

523
## v1.1.6 7/12/24
624
- Add put functionality to Oauth2 Client

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ This package contains common Python utility classes and functions.
77
* Setting and retrieving a resource in S3
88
* Decrypting values with KMS
99
* Encoding and decoding records using a given Avro schema
10+
* Retrieving secrets from AWS Secrets Manager
11+
* Downloading files from a remote SSH SFTP server
1012
* Connecting to and querying a MySQL database
1113
* Connecting to and querying a PostgreSQL database
1214
* Connecting to and querying a PostgreSQL database using a connection pool
1315
* Connecting to and querying Redshift
1416
* Making requests to the Oauth2 authenticated APIs such as NYPL Platform API and Sierra
17+
* Interacting with vendor APIs such as cloudLibrary
1518

1619
## Functions
1720
* 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
@@ -35,7 +38,7 @@ kinesis_client = KinesisClient(...)
3538
# Do not use any version below 1.0.0
3639
# All available optional dependencies can be found in pyproject.toml.
3740
# See the "Managing dependencies" section below for more details.
38-
nypl-py-utils[kinesis-client,config-helper]==1.1.2
41+
nypl-py-utils[kinesis-client,config-helper]==1.5.0
3942
```
4043

4144
## Developing locally
@@ -61,7 +64,7 @@ The optional dependency sets also give the developer the option to manually list
6164
### Using PostgreSQLClient in an AWS Lambda
6265
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:
6366
```bash
64-
pip install --target ./package nypl-py-utils[postgresql-client]==1.1.2
67+
pip install --target ./package nypl-py-utils[postgresql-client]==1.5.0
6568

6669
pip install \
6770
--platform manylinux2014_x86_64 \

pyproject.toml

Lines changed: 12 additions & 2 deletions
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.2.0"
7+
version = "1.5.0"
88
authors = [
99
{ name="Aaron Friedman", email="aaronfriedman@nypl.org" },
1010
]
@@ -27,6 +27,9 @@ avro-client = [
2727
"avro>=1.11.1",
2828
"requests>=2.28.1"
2929
]
30+
cloudlibrary-client = [
31+
"requests>=2.28.1"
32+
]
3033
kinesis-client = [
3134
"boto3>=1.26.5",
3235
"botocore>=1.29.5"
@@ -56,6 +59,13 @@ s3-client = [
5659
"boto3>=1.26.5",
5760
"botocore>=1.29.5"
5861
]
62+
secrets-manager-client = [
63+
"boto3>=1.26.5",
64+
"botocore>=1.29.5"
65+
]
66+
sftp-client = [
67+
"paramiko>=3.4.1"
68+
]
5969
config-helper = [
6070
"nypl_py_utils[kms-client]",
6171
"PyYAML>=6.0"
@@ -67,7 +77,7 @@ research-catalog-identifier-helper = [
6777
"requests>=2.28.1"
6878
]
6979
development = [
70-
"nypl_py_utils[avro-client,kinesis-client,kms-client,mysql-client,oauth2-api-client,postgresql-client,postgresql-pool-client,redshift-client,s3-client,config-helper,obfuscation-helper,research-catalog-identifier-helper]",
80+
"nypl_py_utils[avro-client,kinesis-client,kms-client,mysql-client,oauth2-api-client,postgresql-client,postgresql-pool-client,redshift-client,s3-client,secrets-manager-client,sftp-client,config-helper,obfuscation-helper,research-catalog-identifier-helper]",
7181
"flake8>=6.0.0",
7282
"freezegun>=1.2.2",
7383
"mock>=4.0.3",

src/nypl_py_utils/classes/avro_client.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from avro.io import BinaryDecoder, BinaryEncoder, DatumReader, DatumWriter
66
from io import BytesIO
77
from nypl_py_utils.functions.log_helper import create_log
8-
from requests.exceptions import JSONDecodeError, RequestException
8+
from requests.adapters import HTTPAdapter, Retry
9+
from requests.exceptions import JSONDecodeError
910

1011

1112
class AvroClient:
@@ -15,7 +16,13 @@ class AvroClient:
1516
"""
1617

1718
def __init__(self, platform_schema_url):
18-
self.logger = create_log("avro_encoder")
19+
self.logger = create_log("avro_client")
20+
retry_policy = Retry(total=3, backoff_factor=45,
21+
status_forcelist=[500, 502, 503, 504],
22+
allowed_methods=frozenset(['GET']))
23+
self.session = requests.Session()
24+
self.session.mount("https://",
25+
HTTPAdapter(max_retries=retry_policy))
1926
self.schema = avro.schema.parse(
2027
self.get_json_schema(platform_schema_url))
2128

@@ -27,9 +34,11 @@ def get_json_schema(self, platform_schema_url):
2734
self.logger.info(
2835
"Fetching Avro schema from {}".format(platform_schema_url))
2936
try:
30-
response = requests.get(platform_schema_url)
37+
38+
response = self.session.get(url=platform_schema_url,
39+
timeout=60)
3140
response.raise_for_status()
32-
except RequestException as e:
41+
except Exception as e:
3342
self.logger.error(
3443
"Failed to retrieve schema from {url}: {error}".format(
3544
url=platform_schema_url, error=e
@@ -39,7 +48,7 @@ def get_json_schema(self, platform_schema_url):
3948
"Failed to retrieve schema from {url}: {error}".format(
4049
url=platform_schema_url, error=e
4150
)
42-
) from None
51+
)
4352

4453
try:
4554
json_response = response.json()
@@ -124,7 +133,7 @@ def decode_record(self, record):
124133
125134
Returns a dictionary where each key is a field in the schema.
126135
"""
127-
self.logger.info(
136+
self.logger.debug(
128137
"Decoding {rec} using {schema} schema".format(
129138
rec=record, schema=self.schema.name
130139
)

0 commit comments

Comments
 (0)