Remove Python 3.7 support (#7185)

This commit is contained in:
Bert Blommers 2024-01-06 19:20:57 +00:00
parent 79af51c538
commit 2fd5e800e4
17 changed files with 29 additions and 59 deletions

View File

@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ 3.7, 3.8, 3.9, "3.10", "3.11", "3.12" ]
python-version: [ 3.8, 3.9, "3.10", "3.11", "3.12" ]
steps:
- uses: actions/checkout@v4

View File

@ -46,7 +46,7 @@ jobs:
- name: Start MotoServer
run: |
python -m build
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:3.7-buster /moto/scripts/ci_moto_server.sh &
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:3.9-slim /moto/scripts/ci_moto_server.sh &
python scripts/ci_wait_for_server.py
- name: Test ServerMode/Coverage
env:

View File

@ -35,7 +35,7 @@ jobs:
run: |
pip install PyYAML build
python -m build
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e MOTO_PORT=4566 -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 4566:4566 -v /var/run/docker.sock:/var/run/docker.sock python:3.7-buster /moto/scripts/ci_moto_server.sh &
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e MOTO_PORT=4566 -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 4566:4566 -v /var/run/docker.sock:/var/run/docker.sock python:3.9-slim /moto/scripts/ci_moto_server.sh &
MOTO_PORT=4566 python scripts/ci_wait_for_server.py
- name: Get list of tests for this service
id: get-list

View File

@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12"]
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4

View File

@ -12,7 +12,7 @@ jobs:
- name: Set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: "3.8"
python-version: "3.10"
- name: Start MotoServer
run: |
pip install build

View File

@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12"]
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4

View File

@ -1,7 +1,7 @@
codecov:
notify:
# Leave a GitHub comment after all builds have passed
after_n_builds: 12
after_n_builds: 10
coverage:
status:
project:

View File

@ -1578,10 +1578,6 @@ class APIGatewayBackend(BaseBackend):
validate(api_doc) # type: ignore[arg-type]
except OpenAPIValidationError as e:
raise InvalidOpenAPIDocumentException(e)
except AttributeError:
# Call can fail in Python3.7 due to `typing_extensions 4.6.0` throwing an error
# Easiest to just ignore this for now - Py3.7 is EOL soon anyway
pass
name = api_doc["info"]["title"]
description = api_doc["info"]["description"]
api = self.create_rest_api(name=name, description=description)
@ -1653,10 +1649,6 @@ class APIGatewayBackend(BaseBackend):
validate(api_doc) # type: ignore[arg-type]
except OpenAPIValidationError as e:
raise InvalidOpenAPIDocumentException(e)
except AttributeError:
# Call can fail in Python3.7 due to `typing_extensions 4.6.0` throwing an error
# Easiest to just ignore this for now - Py3.7 is EOL soon anyway
pass
if mode == "overwrite":
api = self.get_rest_api(function_id)

View File

@ -17,7 +17,7 @@ from collections import defaultdict
from datetime import datetime
from gzip import GzipFile
from sys import platform
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from typing import Any, Dict, Iterable, List, Optional, Tuple, TypedDict, Union
import requests.exceptions
@ -64,6 +64,11 @@ from .utils import (
logger = logging.getLogger(__name__)
class LayerDataType(TypedDict):
Arn: str
CodeSize: int
def zip2tar(zip_bytes: bytes) -> io.BytesIO:
tarstream = io.BytesIO()
timeshift = int((datetime.now() - utcnow()).total_seconds())
@ -176,7 +181,7 @@ class _DockerDataVolumeLayerContext:
def __init__(self, lambda_func: "LambdaFunction"):
self._lambda_func = lambda_func
self._layers: List[Dict[str, str]] = self._lambda_func.layers
self._layers: List[LayerDataType] = self._lambda_func.layers
self._vol_ref: Optional[_VolumeRefCount] = None
@property
@ -623,9 +628,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
self.package_type = spec.get("PackageType", "Zip")
self.publish = spec.get("Publish", False) # this is ignored currently
self.timeout = spec.get("Timeout", 3)
self.layers: List[Dict[str, str]] = self._get_layers_data(
spec.get("Layers", [])
)
self.layers: List[LayerDataType] = self._get_layers_data(spec.get("Layers", []))
self.signing_profile_version_arn = spec.get("SigningProfileVersionArn")
self.signing_job_arn = spec.get("SigningJobArn")
self.code_signing_config_arn = spec.get("CodeSigningConfigArn")
@ -720,7 +723,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
def __repr__(self) -> str:
return json.dumps(self.get_configuration())
def _get_layers_data(self, layers_versions_arns: List[str]) -> List[Dict[str, str]]:
def _get_layers_data(self, layers_versions_arns: List[str]) -> List[LayerDataType]:
backend = lambda_backends[self.account_id][self.region]
layer_versions = [
backend.layers_versions_by_arn(layer_version)
@ -730,9 +733,9 @@ class LambdaFunction(CloudFormationModel, DockerModel):
raise UnknownLayerVersionException(layers_versions_arns)
# The `if lv` part is not necessary - we know there are no None's, because of the `all()`-check earlier
# But MyPy does not seem to understand this
# The `type: ignore` is because `code_size` is an int, and we're returning Dict[str, str]
# We should convert the return-type into a TypedDict the moment we drop Py3.7 support
return [{"Arn": lv.arn, "CodeSize": lv.code_size} for lv in layer_versions if lv] # type: ignore
return [
{"Arn": lv.arn, "CodeSize": lv.code_size} for lv in layer_versions if lv
]
def get_code_signing_config(self) -> Dict[str, Any]:
return {

View File

@ -122,12 +122,7 @@ class BaseMockAWS(ContextManager["BaseMockAWS"]):
if self.__class__.nested_count == 0:
if self.__class__.mocks_active:
try:
self.default_session_mock.stop()
except RuntimeError:
# We only need to check for this exception in Python 3.7
# https://bugs.python.org/issue36366
pass
self.default_session_mock.stop()
self.unmock_env_variables()
self.__class__.mocks_active = False
if remove_data:

View File

@ -1,13 +1,8 @@
import sys
from importlib.metadata import version
from moto.utilities.distutils_version import LooseVersion
try:
from importlib.metadata import version
except ImportError:
from importlib_metadata import version # type: ignore[no-redef]
PYTHON_VERSION_INFO = sys.version_info
PYTHON_311 = sys.version_info >= (3, 11)
RESPONSES_VERSION = version("responses")

View File

@ -133,8 +133,6 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
and v in vl
)
# Any in this case means: str | Optional[str]
# When we drop Python 3.7 we should look into replacing this with a TypedDict
def tag_filter(tag_list: List[Dict[str, Any]]) -> bool:
result = []
if tag_filters:

View File

@ -6,8 +6,7 @@ click
inflection
lxml
mypy
typing-extensions<=4.5.0; python_version < '3.8'
typing-extensions; python_version >= '3.8'
typing-extensions
packaging
build
prompt_toolkit

View File

@ -10,7 +10,6 @@ license = Apache License 2.0
test_suite = tests
classifiers =
Programming Language :: Python :: 3
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
@ -25,7 +24,7 @@ project_urls =
Changelog = https://github.com/getmoto/moto/blob/master/CHANGELOG.md
[options]
python_requires = >=3.7
python_requires = >=3.8
install_requires =
boto3>=1.9.201
botocore>=1.12.201
@ -36,7 +35,6 @@ install_requires =
python-dateutil<3.0.0,>=2.1
responses>=0.13.0
Jinja2>=2.10.1
importlib_metadata ; python_version < '3.8'
package_dir =
moto = moto
include_package_data = True

View File

@ -1,12 +1,10 @@
import os
import sys
from unittest import SkipTest
import boto3
import pytest
from botocore.exceptions import ClientError
from moto import mock_apigateway, settings
from moto import mock_apigateway
@mock_apigateway
@ -47,9 +45,6 @@ def test_import_rest_api__nested_api():
@mock_apigateway
def test_import_rest_api__invalid_api_creates_nothing():
if sys.version_info < (3, 8) or settings.TEST_SERVER_MODE:
raise SkipTest("openapi-module throws an error in Py3.7")
client = boto3.client("apigateway", region_name="us-west-2")
path = os.path.dirname(os.path.abspath(__file__))

View File

@ -1,12 +1,10 @@
import os
import sys
from unittest import SkipTest
import boto3
import pytest
from botocore.exceptions import ClientError
from moto import mock_apigateway, settings
from moto import mock_apigateway
@mock_apigateway
@ -145,9 +143,6 @@ def test_put_rest_api__existing_methods_still_exist():
@mock_apigateway
def test_put_rest_api__fail_on_invalid_spec():
if sys.version_info < (3, 8) or settings.TEST_SERVER_MODE:
raise SkipTest("openapi-module throws an error in Py3.7")
client = boto3.client("apigateway", region_name="us-east-2")
response = client.create_rest_api(name="my_api", description="this is my api")

View File

@ -85,7 +85,7 @@ def test_lambda_can_be_updated_by_cloudformation():
# Verify function has been created
created_fn = lmbda.get_function(FunctionName=created_fn_name)
assert created_fn["Configuration"]["Handler"] == "lambda_function.lambda_handler1"
assert created_fn["Configuration"]["Runtime"] == "python3.7"
assert created_fn["Configuration"]["Runtime"] == "python3.9"
assert "/test1.zip" in created_fn["Code"]["Location"]
# Update CF stack
cf.update_stack(StackName=stack_name, TemplateBody=body2)
@ -97,7 +97,7 @@ def test_lambda_can_be_updated_by_cloudformation():
== created_fn["Configuration"]["FunctionArn"]
)
assert updated_fn["Configuration"]["Handler"] == "lambda_function.lambda_handler2"
assert updated_fn["Configuration"]["Runtime"] == "python3.8"
assert updated_fn["Configuration"]["Runtime"] == "python3.10"
assert "/test2.zip" in updated_fn["Code"]["Location"]
@ -310,8 +310,8 @@ def create_stack(cf, s3):
s3.create_bucket(Bucket=bucket_name)
s3.put_object(Bucket=bucket_name, Key="test1.zip", Body=get_zip_file())
s3.put_object(Bucket=bucket_name, Key="test2.zip", Body=get_zip_file())
body1 = get_template(bucket_name, "1", "python3.7")
body2 = get_template(bucket_name, "2", "python3.8")
body1 = get_template(bucket_name, "1", "python3.9")
body2 = get_template(bucket_name, "2", "python3.10")
stack = cf.create_stack(StackName=stack_name, TemplateBody=body1)
return body2, stack