Skip to content

Commit 634c588

Browse files
committed
feat(identifiers): Check Python Runtime
Issues a WARNING if the Python Version will become unsupported. Prints an ERROR to STDERR if Python Version is unsupported. Will start issuing WARNING for Python Version less than 3.6. Will start printing ERROR for Python Version less than 3.5 AFTER Jan 1st, 2022.
1 parent f1edc18 commit 634c588

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

src/aws_encryption_sdk/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
# language governing permissions and limitations under the License.
1313
"""High level AWS Encryption SDK client functions."""
1414
# Below are imported for ease of use by implementors
15-
1615
import warnings
1716

1817
import attr
1918

2019
from aws_encryption_sdk.caches.local import LocalCryptoMaterialsCache # noqa
2120
from aws_encryption_sdk.caches.null import NullCryptoMaterialsCache # noqa
2221
from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError # noqa
23-
from aws_encryption_sdk.identifiers import Algorithm, CommitmentPolicy, __version__ # noqa
22+
from aws_encryption_sdk.identifiers import Algorithm, CommitmentPolicy, __version__, check_python_version # noqa
2423
from aws_encryption_sdk.internal.utils.signature import SignaturePolicy # noqa
2524
from aws_encryption_sdk.key_providers.kms import ( # noqa
2625
DiscoveryAwsKmsMasterKeyProvider,
@@ -36,6 +35,8 @@
3635
StreamEncryptor,
3736
)
3837

38+
check_python_version()
39+
3940

4041
@attr.s(hash=True)
4142
class EncryptionSDKClientConfig(object):

src/aws_encryption_sdk/identifiers.py

+44
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
# ANY KIND, either express or implied. See the License for the specific
1212
# language governing permissions and limitations under the License.
1313
"""AWS Encryption SDK native data structures for defining implementation-specific characteristics."""
14+
import datetime
1415
import struct
16+
import sys
17+
import warnings
1518
from enum import Enum
1619

1720
from cryptography.hazmat.primitives import hashes
@@ -378,3 +381,44 @@ class CommitmentPolicy(Enum):
378381
FORBID_ENCRYPT_ALLOW_DECRYPT = 0
379382
REQUIRE_ENCRYPT_ALLOW_DECRYPT = 1
380383
REQUIRE_ENCRYPT_REQUIRE_DECRYPT = 2
384+
385+
386+
class PythonVersionSupport:
387+
"""Configures Python Version warnings/error messaging"""
388+
389+
WARN_BELOW_MAJOR = 3
390+
WARN_BELOW_MINOR = 6
391+
ERROR_BELOW_MAJOR = 3
392+
ERROR_BELOW_MINOR = 5
393+
ERROR_DATE = datetime.datetime(year=2022, month=1, day=1)
394+
395+
396+
def check_python_version(
397+
warn_below_major=PythonVersionSupport.WARN_BELOW_MAJOR,
398+
warn_below_minor=PythonVersionSupport.WARN_BELOW_MINOR,
399+
error_below_major=PythonVersionSupport.ERROR_BELOW_MAJOR,
400+
error_below_minor=PythonVersionSupport.ERROR_BELOW_MINOR,
401+
error_date=PythonVersionSupport.ERROR_DATE,
402+
):
403+
"""Checks that we are on a supported version of Python.
404+
Prints an error message to stderr if the Python Version is unsupported and therefore untested.
405+
Emits a warning if the Python version will be unsupported.
406+
"""
407+
if datetime.datetime.now() > error_date and (
408+
sys.version_info.major < error_below_major or sys.version_info.minor < error_below_minor
409+
):
410+
sys.stderr.write(
411+
"ERROR: Python {} is not supported by the aws-encryption-sdk! ".format(
412+
".".join(map(str, [sys.version_info.major, sys.version_info.minor]))
413+
)
414+
+ "Please upgrade to Python {} or higher.".format(".".join(map(str, [warn_below_major, warn_below_minor])))
415+
)
416+
return
417+
if sys.version_info.major < warn_below_major or sys.version_info.minor < warn_below_minor:
418+
warnings.warn(
419+
"Python {} support will be removed in a future release. ".format(
420+
".".join(map(str, [sys.version_info.major, sys.version_info.minor]))
421+
)
422+
+ "Please upgrade to Python {} or higher.".format(".".join(map(str, [warn_below_major, warn_below_minor]))),
423+
DeprecationWarning,
424+
)
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Unit test suite for ensuring the Python Runtime is supported."""
14+
import datetime
15+
import sys
16+
17+
import mock
18+
import pytest
19+
20+
from aws_encryption_sdk import check_python_version
21+
from aws_encryption_sdk.identifiers import PythonVersionSupport
22+
23+
pytestmark = [pytest.mark.unit, pytest.mark.local]
24+
25+
26+
class TestBeforeErrorDate:
27+
def test_happy_version(self):
28+
with mock.patch.object(sys, "version_info") as v_info:
29+
v_info.major = PythonVersionSupport.WARN_BELOW_MAJOR
30+
v_info.minor = PythonVersionSupport.WARN_BELOW_MINOR
31+
with pytest.warns(None) as record:
32+
check_python_version(error_date=datetime.datetime.now() + datetime.timedelta(days=1))
33+
assert len(record) == 0
34+
35+
def test_below_warn(self):
36+
with mock.patch.object(sys, "version_info") as v_info:
37+
v_info.major = PythonVersionSupport.WARN_BELOW_MAJOR - 1
38+
v_info.minor = PythonVersionSupport.WARN_BELOW_MINOR
39+
with pytest.warns(DeprecationWarning):
40+
check_python_version(error_date=datetime.datetime.now() + datetime.timedelta(days=1))
41+
42+
43+
class TestAfterErrorDate:
44+
def test_happy_version(self, capsys):
45+
with mock.patch.object(sys, "version_info") as v_info:
46+
v_info.major = PythonVersionSupport.WARN_BELOW_MAJOR
47+
v_info.minor = PythonVersionSupport.WARN_BELOW_MINOR
48+
with pytest.warns(None) as record:
49+
check_python_version(error_date=datetime.datetime.now() - datetime.timedelta(days=1))
50+
assert len(record) == 0
51+
captured = capsys.readouterr().err
52+
assert "ERROR" not in captured
53+
54+
def test_below_error(self, capsys):
55+
with mock.patch.object(sys, "version_info") as v_info:
56+
v_info.major = PythonVersionSupport.ERROR_BELOW_MAJOR
57+
v_info.minor = PythonVersionSupport.ERROR_BELOW_MINOR - 1
58+
with pytest.warns(None) as record:
59+
check_python_version(error_date=datetime.datetime.now() - datetime.timedelta(days=1))
60+
assert len(record) == 0
61+
captured = capsys.readouterr().err
62+
assert "ERROR" in captured

0 commit comments

Comments
 (0)