Remove Python 3.7 support (#7185)
This commit is contained in:
parent
79af51c538
commit
2fd5e800e4
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -8,7 +8,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
2
.github/workflows/test_outdated_versions.yml
vendored
2
.github/workflows/test_outdated_versions.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Start MotoServer
|
- name: Start MotoServer
|
||||||
run: |
|
run: |
|
||||||
python -m build
|
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
|
python scripts/ci_wait_for_server.py
|
||||||
- name: Test ServerMode/Coverage
|
- name: Test ServerMode/Coverage
|
||||||
env:
|
env:
|
||||||
|
2
.github/workflows/test_terraform.yml
vendored
2
.github/workflows/test_terraform.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pip install PyYAML build
|
pip install PyYAML build
|
||||||
python -m 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
|
MOTO_PORT=4566 python scripts/ci_wait_for_server.py
|
||||||
- name: Get list of tests for this service
|
- name: Get list of tests for this service
|
||||||
id: get-list
|
id: get-list
|
||||||
|
2
.github/workflows/tests_decoratormode.yml
vendored
2
.github/workflows/tests_decoratormode.yml
vendored
@ -7,7 +7,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
2
.github/workflows/tests_sdk_java.yml
vendored
2
.github/workflows/tests_sdk_java.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.10"
|
||||||
- name: Start MotoServer
|
- name: Start MotoServer
|
||||||
run: |
|
run: |
|
||||||
pip install build
|
pip install build
|
||||||
|
2
.github/workflows/tests_servermode.yml
vendored
2
.github/workflows/tests_servermode.yml
vendored
@ -7,7 +7,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
codecov:
|
codecov:
|
||||||
notify:
|
notify:
|
||||||
# Leave a GitHub comment after all builds have passed
|
# Leave a GitHub comment after all builds have passed
|
||||||
after_n_builds: 12
|
after_n_builds: 10
|
||||||
coverage:
|
coverage:
|
||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
|
@ -1578,10 +1578,6 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
validate(api_doc) # type: ignore[arg-type]
|
validate(api_doc) # type: ignore[arg-type]
|
||||||
except OpenAPIValidationError as e:
|
except OpenAPIValidationError as e:
|
||||||
raise InvalidOpenAPIDocumentException(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"]
|
name = api_doc["info"]["title"]
|
||||||
description = api_doc["info"]["description"]
|
description = api_doc["info"]["description"]
|
||||||
api = self.create_rest_api(name=name, description=description)
|
api = self.create_rest_api(name=name, description=description)
|
||||||
@ -1653,10 +1649,6 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
validate(api_doc) # type: ignore[arg-type]
|
validate(api_doc) # type: ignore[arg-type]
|
||||||
except OpenAPIValidationError as e:
|
except OpenAPIValidationError as e:
|
||||||
raise InvalidOpenAPIDocumentException(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":
|
if mode == "overwrite":
|
||||||
api = self.get_rest_api(function_id)
|
api = self.get_rest_api(function_id)
|
||||||
|
@ -17,7 +17,7 @@ from collections import defaultdict
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from gzip import GzipFile
|
from gzip import GzipFile
|
||||||
from sys import platform
|
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
|
import requests.exceptions
|
||||||
|
|
||||||
@ -64,6 +64,11 @@ from .utils import (
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class LayerDataType(TypedDict):
|
||||||
|
Arn: str
|
||||||
|
CodeSize: int
|
||||||
|
|
||||||
|
|
||||||
def zip2tar(zip_bytes: bytes) -> io.BytesIO:
|
def zip2tar(zip_bytes: bytes) -> io.BytesIO:
|
||||||
tarstream = io.BytesIO()
|
tarstream = io.BytesIO()
|
||||||
timeshift = int((datetime.now() - utcnow()).total_seconds())
|
timeshift = int((datetime.now() - utcnow()).total_seconds())
|
||||||
@ -176,7 +181,7 @@ class _DockerDataVolumeLayerContext:
|
|||||||
|
|
||||||
def __init__(self, lambda_func: "LambdaFunction"):
|
def __init__(self, lambda_func: "LambdaFunction"):
|
||||||
self._lambda_func = lambda_func
|
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
|
self._vol_ref: Optional[_VolumeRefCount] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -623,9 +628,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
|
|||||||
self.package_type = spec.get("PackageType", "Zip")
|
self.package_type = spec.get("PackageType", "Zip")
|
||||||
self.publish = spec.get("Publish", False) # this is ignored currently
|
self.publish = spec.get("Publish", False) # this is ignored currently
|
||||||
self.timeout = spec.get("Timeout", 3)
|
self.timeout = spec.get("Timeout", 3)
|
||||||
self.layers: List[Dict[str, str]] = self._get_layers_data(
|
self.layers: List[LayerDataType] = self._get_layers_data(spec.get("Layers", []))
|
||||||
spec.get("Layers", [])
|
|
||||||
)
|
|
||||||
self.signing_profile_version_arn = spec.get("SigningProfileVersionArn")
|
self.signing_profile_version_arn = spec.get("SigningProfileVersionArn")
|
||||||
self.signing_job_arn = spec.get("SigningJobArn")
|
self.signing_job_arn = spec.get("SigningJobArn")
|
||||||
self.code_signing_config_arn = spec.get("CodeSigningConfigArn")
|
self.code_signing_config_arn = spec.get("CodeSigningConfigArn")
|
||||||
@ -720,7 +723,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return json.dumps(self.get_configuration())
|
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]
|
backend = lambda_backends[self.account_id][self.region]
|
||||||
layer_versions = [
|
layer_versions = [
|
||||||
backend.layers_versions_by_arn(layer_version)
|
backend.layers_versions_by_arn(layer_version)
|
||||||
@ -730,9 +733,9 @@ class LambdaFunction(CloudFormationModel, DockerModel):
|
|||||||
raise UnknownLayerVersionException(layers_versions_arns)
|
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
|
# 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
|
# 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]
|
return [
|
||||||
# We should convert the return-type into a TypedDict the moment we drop Py3.7 support
|
{"Arn": lv.arn, "CodeSize": lv.code_size} for lv in layer_versions if lv
|
||||||
return [{"Arn": lv.arn, "CodeSize": lv.code_size} for lv in layer_versions if lv] # type: ignore
|
]
|
||||||
|
|
||||||
def get_code_signing_config(self) -> Dict[str, Any]:
|
def get_code_signing_config(self) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
@ -122,12 +122,7 @@ class BaseMockAWS(ContextManager["BaseMockAWS"]):
|
|||||||
|
|
||||||
if self.__class__.nested_count == 0:
|
if self.__class__.nested_count == 0:
|
||||||
if self.__class__.mocks_active:
|
if self.__class__.mocks_active:
|
||||||
try:
|
self.default_session_mock.stop()
|
||||||
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.unmock_env_variables()
|
self.unmock_env_variables()
|
||||||
self.__class__.mocks_active = False
|
self.__class__.mocks_active = False
|
||||||
if remove_data:
|
if remove_data:
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
from moto.utilities.distutils_version import LooseVersion
|
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_VERSION_INFO = sys.version_info
|
||||||
PYTHON_311 = sys.version_info >= (3, 11)
|
PYTHON_311 = sys.version_info >= (3, 11)
|
||||||
RESPONSES_VERSION = version("responses")
|
RESPONSES_VERSION = version("responses")
|
||||||
|
@ -133,8 +133,6 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
|
|||||||
and v in vl
|
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:
|
def tag_filter(tag_list: List[Dict[str, Any]]) -> bool:
|
||||||
result = []
|
result = []
|
||||||
if tag_filters:
|
if tag_filters:
|
||||||
|
@ -6,8 +6,7 @@ click
|
|||||||
inflection
|
inflection
|
||||||
lxml
|
lxml
|
||||||
mypy
|
mypy
|
||||||
typing-extensions<=4.5.0; python_version < '3.8'
|
typing-extensions
|
||||||
typing-extensions; python_version >= '3.8'
|
|
||||||
packaging
|
packaging
|
||||||
build
|
build
|
||||||
prompt_toolkit
|
prompt_toolkit
|
||||||
|
@ -10,7 +10,6 @@ license = Apache License 2.0
|
|||||||
test_suite = tests
|
test_suite = tests
|
||||||
classifiers =
|
classifiers =
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3.7
|
|
||||||
Programming Language :: Python :: 3.8
|
Programming Language :: Python :: 3.8
|
||||||
Programming Language :: Python :: 3.9
|
Programming Language :: Python :: 3.9
|
||||||
Programming Language :: Python :: 3.10
|
Programming Language :: Python :: 3.10
|
||||||
@ -25,7 +24,7 @@ project_urls =
|
|||||||
Changelog = https://github.com/getmoto/moto/blob/master/CHANGELOG.md
|
Changelog = https://github.com/getmoto/moto/blob/master/CHANGELOG.md
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
python_requires = >=3.7
|
python_requires = >=3.8
|
||||||
install_requires =
|
install_requires =
|
||||||
boto3>=1.9.201
|
boto3>=1.9.201
|
||||||
botocore>=1.12.201
|
botocore>=1.12.201
|
||||||
@ -36,7 +35,6 @@ install_requires =
|
|||||||
python-dateutil<3.0.0,>=2.1
|
python-dateutil<3.0.0,>=2.1
|
||||||
responses>=0.13.0
|
responses>=0.13.0
|
||||||
Jinja2>=2.10.1
|
Jinja2>=2.10.1
|
||||||
importlib_metadata ; python_version < '3.8'
|
|
||||||
package_dir =
|
package_dir =
|
||||||
moto = moto
|
moto = moto
|
||||||
include_package_data = True
|
include_package_data = True
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from unittest import SkipTest
|
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import pytest
|
import pytest
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto import mock_apigateway, settings
|
from moto import mock_apigateway
|
||||||
|
|
||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
@ -47,9 +45,6 @@ def test_import_rest_api__nested_api():
|
|||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_import_rest_api__invalid_api_creates_nothing():
|
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")
|
client = boto3.client("apigateway", region_name="us-west-2")
|
||||||
|
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from unittest import SkipTest
|
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import pytest
|
import pytest
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto import mock_apigateway, settings
|
from moto import mock_apigateway
|
||||||
|
|
||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
@ -145,9 +143,6 @@ def test_put_rest_api__existing_methods_still_exist():
|
|||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_put_rest_api__fail_on_invalid_spec():
|
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")
|
client = boto3.client("apigateway", region_name="us-east-2")
|
||||||
|
|
||||||
response = client.create_rest_api(name="my_api", description="this is my api")
|
response = client.create_rest_api(name="my_api", description="this is my api")
|
||||||
|
@ -85,7 +85,7 @@ def test_lambda_can_be_updated_by_cloudformation():
|
|||||||
# Verify function has been created
|
# Verify function has been created
|
||||||
created_fn = lmbda.get_function(FunctionName=created_fn_name)
|
created_fn = lmbda.get_function(FunctionName=created_fn_name)
|
||||||
assert created_fn["Configuration"]["Handler"] == "lambda_function.lambda_handler1"
|
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"]
|
assert "/test1.zip" in created_fn["Code"]["Location"]
|
||||||
# Update CF stack
|
# Update CF stack
|
||||||
cf.update_stack(StackName=stack_name, TemplateBody=body2)
|
cf.update_stack(StackName=stack_name, TemplateBody=body2)
|
||||||
@ -97,7 +97,7 @@ def test_lambda_can_be_updated_by_cloudformation():
|
|||||||
== created_fn["Configuration"]["FunctionArn"]
|
== created_fn["Configuration"]["FunctionArn"]
|
||||||
)
|
)
|
||||||
assert updated_fn["Configuration"]["Handler"] == "lambda_function.lambda_handler2"
|
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"]
|
assert "/test2.zip" in updated_fn["Code"]["Location"]
|
||||||
|
|
||||||
|
|
||||||
@ -310,8 +310,8 @@ def create_stack(cf, s3):
|
|||||||
s3.create_bucket(Bucket=bucket_name)
|
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="test1.zip", Body=get_zip_file())
|
||||||
s3.put_object(Bucket=bucket_name, Key="test2.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")
|
body1 = get_template(bucket_name, "1", "python3.9")
|
||||||
body2 = get_template(bucket_name, "2", "python3.8")
|
body2 = get_template(bucket_name, "2", "python3.10")
|
||||||
stack = cf.create_stack(StackName=stack_name, TemplateBody=body1)
|
stack = cf.create_stack(StackName=stack_name, TemplateBody=body1)
|
||||||
return body2, stack
|
return body2, stack
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user