diff --git a/.circleci/config.yml b/.circleci/config.yml index aec1098be52d8..890308fa1cdbc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -164,15 +164,16 @@ jobs: steps: - checkout - restore_cache: - key: python-requirements-{{ checksum "requirements-dev.txt" }} + key: python-requirements-{{ checksum "requirements-typehint.txt" }} - run: name: Setup environment command: | + make install-dev-types make install mkdir -p target/reports mkdir -p target/coverage - save_cache: - key: python-requirements-{{ checksum "requirements-dev.txt" }} + key: python-requirements-{{ checksum "requirements-typehint.txt" }} paths: - "~/.cache/pip" - persist_to_workspace: diff --git a/.github/actions/load-localstack-docker-from-artifacts/action.yml b/.github/actions/load-localstack-docker-from-artifacts/action.yml index 97215dedb1042..cb22c52682734 100644 --- a/.github/actions/load-localstack-docker-from-artifacts/action.yml +++ b/.github/actions/load-localstack-docker-from-artifacts/action.yml @@ -18,7 +18,7 @@ runs: with: python-version-file: '.python-version' cache: 'pip' - cache-dependency-path: 'requirements-dev.txt' + cache-dependency-path: 'requirements-typehint.txt' - name: Install docker helper dependencies shell: bash diff --git a/.github/actions/setup-tests-env/action.yml b/.github/actions/setup-tests-env/action.yml index bb8c467628165..95cd7fe359787 100644 --- a/.github/actions/setup-tests-env/action.yml +++ b/.github/actions/setup-tests-env/action.yml @@ -8,11 +8,11 @@ runs: with: python-version-file: '.python-version' cache: 'pip' - cache-dependency-path: 'requirements-dev.txt' + cache-dependency-path: 'requirements-typehint.txt' - name: Install Community Dependencies shell: bash - run: make install-dev + run: make install-dev-types - name: Setup environment shell: bash diff --git a/.github/workflows/aws-main.yml b/.github/workflows/aws-main.yml index 013ff5b13f0d7..33574bf907ef5 100644 --- a/.github/workflows/aws-main.yml +++ b/.github/workflows/aws-main.yml @@ -184,7 +184,7 @@ jobs: fetch-depth: 0 - name: Load Localstack ${{ env.PLATFORM_NAME_AMD64 }} Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: ${{ env.PLATFORM_NAME_AMD64 }} @@ -213,7 +213,7 @@ jobs: TARGET_IMAGE_NAME="public.ecr.aws/localstack/localstack" ./bin/docker-helper.sh push - name: Load Localstack ${{ env.PLATFORM_NAME_ARM64 }} Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: ${{ env.PLATFORM_NAME_ARM64 }} diff --git a/.github/workflows/aws-tests.yml b/.github/workflows/aws-tests.yml index 8a6b69bc9ced6..94aacdd82be74 100644 --- a/.github/workflows/aws-tests.yml +++ b/.github/workflows/aws-tests.yml @@ -198,7 +198,7 @@ jobs: fetch-depth: 0 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Linting run: make lint @@ -309,7 +309,7 @@ jobs: tests/aws/services/lambda_/functions/common - name: Load Localstack Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: "${{ env.PLATFORM }}" @@ -375,10 +375,10 @@ jobs: fetch-depth: 0 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Load Localstack Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: "${{ env.PLATFORM }}" @@ -449,7 +449,7 @@ jobs: fetch-depth: 0 - name: Load Localstack Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: "${{ env.PLATFORM }}" @@ -496,7 +496,7 @@ jobs: uses: actions/checkout@v4 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Run Cloudwatch v1 Provider Tests timeout-minutes: 30 @@ -539,7 +539,7 @@ jobs: uses: actions/checkout@v4 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Download Test Selection if: ${{ env.TESTSELECTION_PYTEST_ARGS }} @@ -588,7 +588,7 @@ jobs: uses: actions/checkout@v4 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Download Test Selection if: ${{ env.TESTSELECTION_PYTEST_ARGS }} @@ -639,7 +639,7 @@ jobs: uses: actions/checkout@v4 - name: Prepare Local Test Environment - uses: localstack/localstack/.github/actions/setup-tests-env@master + uses: ./.github/actions/setup-tests-env - name: Download Test Selection if: ${{ env.TESTSELECTION_PYTEST_ARGS }} @@ -691,7 +691,7 @@ jobs: fetch-depth: 0 - name: Load Localstack Docker Image - uses: localstack/localstack/.github/actions/load-localstack-docker-from-artifacts@master + uses: ./.github/actions/load-localstack-docker-from-artifacts with: platform: "${{ env.PLATFORM }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a93acc1a504f..88c4037b14b64 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,6 +15,7 @@ repos: hooks: - id: mypy entry: bash -c 'cd localstack-core && mypy --install-types --non-interactive' + additional_dependencies: ['botocore-stubs', 'rolo'] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 diff --git a/localstack-core/localstack/aws/api/core.py b/localstack-core/localstack/aws/api/core.py index 57cb5503a0e6d..dbe32d7973284 100644 --- a/localstack-core/localstack/aws/api/core.py +++ b/localstack-core/localstack/aws/api/core.py @@ -1,5 +1,14 @@ import functools -from typing import Any, NamedTuple, Optional, Protocol, Type, TypedDict, Union +from typing import ( + Any, + Callable, + NamedTuple, + ParamSpec, + Protocol, + Type, + TypedDict, + TypeVar, +) from botocore.model import OperationModel, ServiceModel from rolo.gateway import RequestContext as RoloRequestContext @@ -13,6 +22,10 @@ class ServiceRequest(TypedDict): pass +P = ParamSpec("P") +T = TypeVar("T") + + ServiceResponse = Any @@ -28,7 +41,7 @@ class ServiceException(Exception): sender_fault: bool message: str - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any): super(ServiceException, self).__init__(*args) if len(args) >= 1: @@ -72,38 +85,38 @@ class RequestContext(RoloRequestContext): context, so it can be used for logging or modification before going to the serializer. """ - request: Optional[Request] + request: Request """The underlying incoming HTTP request.""" - service: Optional[ServiceModel] + service: ServiceModel | None """The botocore ServiceModel of the service the request is made to.""" - operation: Optional[OperationModel] + operation: OperationModel | None """The botocore OperationModel of the AWS operation being invoked.""" - region: Optional[str] + region: str """The region the request is made to.""" partition: str """The partition the request is made to.""" - account_id: Optional[str] + account_id: str """The account the request is made from.""" - request_id: Optional[str] + request_id: str | None """The autogenerated AWS request ID identifying the original request""" - service_request: Optional[ServiceRequest] + service_request: ServiceRequest | None """The AWS operation parameters.""" - service_response: Optional[ServiceResponse] + service_response: ServiceResponse | None """The response from the AWS emulator backend.""" - service_exception: Optional[ServiceException] + service_exception: ServiceException | None """The exception the AWS emulator backend may have raised.""" - internal_request_params: Optional[InternalRequestParameters] + internal_request_params: InternalRequestParameters | None """Data sent by client-side LocalStack during internal calls.""" - trace_context: dict + trace_context: dict[str, Any] """Tracing metadata such as X-Ray trace headers""" - def __init__(self, request=None) -> None: + def __init__(self, request: Request): super().__init__(request) self.service = None self.operation = None - self.region = None + self.region = None # type: ignore[assignment] # type=str, because we know it will always be set downstream self.partition = "aws" # Sensible default - will be overwritten by region-handler - self.account_id = None + self.account_id = None # type: ignore[assignment] # type=str, because we know it will always be set downstream self.request_id = long_uid() self.service_request = None self.service_response = None @@ -119,7 +132,7 @@ def is_internal_call(self) -> bool: return self.internal_request_params is not None @property - def service_operation(self) -> Optional[ServiceOperation]: + def service_operation(self) -> ServiceOperation | None: """ If both the service model and the operation model are set, this returns a tuple of the service name and operation name. @@ -130,7 +143,7 @@ def service_operation(self) -> Optional[ServiceOperation]: return None return ServiceOperation(self.service.service_name, self.operation.name) - def __repr__(self): + def __repr__(self) -> str: return f"" @@ -141,7 +154,7 @@ class ServiceRequestHandler(Protocol): def __call__( self, context: RequestContext, request: ServiceRequest - ) -> Optional[Union[ServiceResponse, Response]]: + ) -> ServiceResponse | Response | None: """ Handle the given request. @@ -152,19 +165,21 @@ def __call__( raise NotImplementedError -def handler(operation: str = None, context: bool = True, expand: bool = True): +def handler( + operation: str | None = None, context: bool = True, expand: bool = True +) -> Callable[[Callable[P, T]], Callable[P, T]]: """ Decorator that indicates that the given function is a handler """ - def wrapper(fn): + def wrapper(fn: Callable[P, T]) -> Callable[P, T]: @functools.wraps(fn) - def operation_marker(*args, **kwargs): + def operation_marker(*args: P.args, **kwargs: P.kwargs) -> T: return fn(*args, **kwargs) - operation_marker.operation = operation - operation_marker.expand_parameters = expand - operation_marker.pass_context = context + operation_marker.operation = operation # type: ignore[attr-defined] + operation_marker.expand_parameters = expand # type: ignore[attr-defined] + operation_marker.pass_context = context # type: ignore[attr-defined] return operation_marker diff --git a/localstack-core/localstack/aws/client.py b/localstack-core/localstack/aws/client.py index 331b82603aeef..6d938c086a8cf 100644 --- a/localstack-core/localstack/aws/client.py +++ b/localstack-core/localstack/aws/client.py @@ -395,8 +395,7 @@ def __call__( operation: OperationModel = request.operation_model # create request - context = RequestContext() - context.request = create_http_request(request) + context = RequestContext(request=create_http_request(request)) # TODO: just a hacky thing to unblock the service model being set to `sqs-query` blocking for now # this is using the same services as `localstack.aws.protocol.service_router.resolve_conflicts`, maybe diff --git a/localstack-core/localstack/aws/forwarder.py b/localstack-core/localstack/aws/forwarder.py index 2a6378cdaa217..c25d4b90f6c09 100644 --- a/localstack-core/localstack/aws/forwarder.py +++ b/localstack-core/localstack/aws/forwarder.py @@ -262,11 +262,10 @@ def create_aws_request_context( ) aws_request: AWSPreparedRequest = client._endpoint.create_request(request_dict, operation) - context = RequestContext() + context = RequestContext(request=create_http_request(aws_request)) context.service = service context.operation = operation context.region = region - context.request = create_http_request(aws_request) context.service_request = parameters return context diff --git a/localstack-core/localstack/testing/aws/util.py b/localstack-core/localstack/testing/aws/util.py index d93ef4cfa492a..2fadd02b9b257 100644 --- a/localstack-core/localstack/testing/aws/util.py +++ b/localstack-core/localstack/testing/aws/util.py @@ -108,13 +108,14 @@ def create_client_with_keys( def create_request_context( service_name: str, operation_name: str, region: str, aws_request: AWSPreparedRequest ) -> RequestContext: - context = RequestContext() + if hasattr(aws_request.body, "read"): + aws_request.body = aws_request.body.read() + request = create_http_request(aws_request) + + context = RequestContext(request=request) context.service = load_service(service_name) context.operation = context.service.operation_model(operation_name=operation_name) context.region = region - if hasattr(aws_request.body, "read"): - aws_request.body = aws_request.body.read() - context.request = create_http_request(aws_request) parser = create_parser(context.service) _, instance = parser.parse(context.request) context.service_request = instance diff --git a/localstack-core/mypy.ini b/localstack-core/mypy.ini index d5ec889accc0b..b2844cc18c3a2 100644 --- a/localstack-core/mypy.ini +++ b/localstack-core/mypy.ini @@ -1,7 +1,7 @@ [mypy] explicit_package_bases = true mypy_path=localstack-core -files=localstack/packages,localstack/services/kinesis/packages.py +files=localstack/aws/api/core.py,localstack/packages,localstack/services/kinesis/packages.py ignore_missing_imports = False follow_imports = silent ignore_errors = False diff --git a/tests/aws/test_moto.py b/tests/aws/test_moto.py index 38f80039db67d..e28b4fd71ebc9 100644 --- a/tests/aws/test_moto.py +++ b/tests/aws/test_moto.py @@ -246,11 +246,10 @@ def test_call_with_sns_with_full_uri(): headers={"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"}, ) sns_service = load_service("sns") - context = RequestContext() + context = RequestContext(sns_request) context.account = "test" context.region = "us-west-1" context.service = sns_service - context.request = sns_request context.operation = sns_service.operation_model("CreateTopic") create_topic_response = moto.call_moto(context) diff --git a/tests/integration/test_forwarder.py b/tests/integration/test_forwarder.py index 477f86ea9cf2c..562fe4b6f8915 100644 --- a/tests/integration/test_forwarder.py +++ b/tests/integration/test_forwarder.py @@ -25,7 +25,7 @@ def test_request_forwarder(_, __) -> ServiceResponse: # invoke the function and expect the result from the fallback function dispatcher = ForwardingFallbackDispatcher(test_provider, test_request_forwarder) - assert dispatcher["TestOperation"](RequestContext(), ServiceRequest()) == "fallback-result" + assert dispatcher["TestOperation"](RequestContext(None), ServiceRequest()) == "fallback-result" def test_forwarding_fallback_dispatcher_avoid_fallback(): @@ -44,4 +44,4 @@ def test_request_forwarder(_, __) -> ServiceResponse: # expect a NotImplementedError exception (and not the ServiceException from the fallthrough) dispatcher = ForwardingFallbackDispatcher(test_provider, test_request_forwarder) with pytest.raises(NotImplementedError): - dispatcher["TestOperation"](RequestContext(), ServiceRequest()) + dispatcher["TestOperation"](RequestContext(None), ServiceRequest()) diff --git a/tests/unit/aws/handlers/analytics.py b/tests/unit/aws/handlers/analytics.py index 125ee674db911..26e52c02a26dc 100644 --- a/tests/unit/aws/handlers/analytics.py +++ b/tests/unit/aws/handlers/analytics.py @@ -40,7 +40,7 @@ def test_ignores_requests_without_service(self): counter = ServiceRequestCounter(service_request_aggregator=aggregator) chain = HandlerChain([counter]) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) aggregator.start.assert_not_called() aggregator.add_request.assert_not_called() diff --git a/tests/unit/aws/handlers/service.py b/tests/unit/aws/handlers/service.py index 52cc0063fcac3..c6f039a29e5cd 100644 --- a/tests/unit/aws/handlers/service.py +++ b/tests/unit/aws/handlers/service.py @@ -111,8 +111,7 @@ def test_sets_exception_from_error_response(self, service_response_handler_chain assert context.service_response is None def test_nothing_set_does_nothing(self, service_response_handler_chain): - context = RequestContext() - context.request = Request("GET", "/_localstack/health") + context = RequestContext(request=Request("GET", "/_localstack/health")) service_response_handler_chain.handle(context, Response("ok", 200)) diff --git a/tests/unit/aws/test_chain.py b/tests/unit/aws/test_chain.py index 3e29132cee9a7..c2ddaf91ef1e8 100644 --- a/tests/unit/aws/test_chain.py +++ b/tests/unit/aws/test_chain.py @@ -28,7 +28,7 @@ def inner1(_chain: HandlerChain, request: RequestContext, response: Response): chain.response_handlers.append(response1) chain.finalizers.append(finalizer) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_not_called() @@ -57,7 +57,7 @@ def inner1(_chain: HandlerChain, request: RequestContext, response: Response): chain.response_handlers.append(response1) chain.finalizers.append(finalizer) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_not_called() @@ -86,7 +86,7 @@ def inner1(_chain: HandlerChain, request: RequestContext, response: Response): chain.response_handlers.append(response1) chain.finalizers.append(finalizer) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_called_once() @@ -113,7 +113,7 @@ def test_composite_handler_continues_handler_chain(self): chain.response_handlers.append(response1) chain.finalizers.append(finalizer) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) outer1.assert_called_once() outer2.assert_called_once() inner1.assert_called_once() @@ -145,7 +145,7 @@ def inner1(_chain: HandlerChain, request: RequestContext, response: Response): chain.response_handlers.append(response1) chain.finalizers.append(finalizer) - chain.handle(RequestContext(), Response()) + chain.handle(RequestContext(None), Response()) outer1.assert_called_once() outer2.assert_not_called() inner2.assert_not_called() diff --git a/tests/unit/aws/test_skeleton.py b/tests/unit/aws/test_skeleton.py index 03fd831e04392..846d41340cd18 100644 --- a/tests/unit/aws/test_skeleton.py +++ b/tests/unit/aws/test_skeleton.py @@ -157,11 +157,7 @@ def _get_sqs_request_headers(): def test_skeleton_e2e_sqs_send_message(): sqs_service = load_service("sqs-query") skeleton = Skeleton(sqs_service, TestSqsApi()) - context = RequestContext() - context.account = "test" - context.region = "us-west-1" - context.service = sqs_service - context.request = Request( + request = Request( **{ "method": "POST", "path": "/", @@ -169,6 +165,10 @@ def test_skeleton_e2e_sqs_send_message(): "headers": _get_sqs_request_headers(), } ) + context = RequestContext(request) + context.account = "test" + context.region = "us-west-1" + context.service = sqs_service result = skeleton.invoke(context) # Use the parser from botocore to parse the serialized response @@ -215,11 +215,7 @@ def test_skeleton_e2e_sqs_send_message(): def test_skeleton_e2e_sqs_send_message_not_implemented(api_class, oracle_message): sqs_service = load_service("sqs-query") skeleton = Skeleton(sqs_service, api_class) - context = RequestContext() - context.account = "test" - context.region = "us-west-1" - context.service = sqs_service - context.request = Request( + request = Request( **{ "method": "POST", "path": "/", @@ -227,6 +223,10 @@ def test_skeleton_e2e_sqs_send_message_not_implemented(api_class, oracle_message "headers": _get_sqs_request_headers(), } ) + context = RequestContext(request) + context.account = "test" + context.region = "us-west-1" + context.service = sqs_service result = skeleton.invoke(context) # Use the parser from botocore to parse the serialized response @@ -260,11 +260,7 @@ def delete_queue(_context: RequestContext, _request: ServiceRequest): sqs_service = load_service("sqs-query") skeleton = Skeleton(sqs_service, table) - context = RequestContext() - context.account = "test" - context.region = "us-west-1" - context.service = sqs_service - context.request = Request( + request = Request( **{ "method": "POST", "path": "/", @@ -272,6 +268,10 @@ def delete_queue(_context: RequestContext, _request: ServiceRequest): "headers": _get_sqs_request_headers(), } ) + context = RequestContext(request) + context.account = "test" + context.region = "us-west-1" + context.service = sqs_service result = skeleton.invoke(context) # Use the parser from botocore to parse the serialized response @@ -293,11 +293,7 @@ def test_dispatch_missing_method_returns_internal_failure(): sqs_service = load_service("sqs-query") skeleton = Skeleton(sqs_service, table) - context = RequestContext() - context.account = "test" - context.region = "us-west-1" - context.service = sqs_service - context.request = Request( + request = Request( **{ "method": "POST", "path": "/", @@ -305,6 +301,10 @@ def test_dispatch_missing_method_returns_internal_failure(): "headers": _get_sqs_request_headers(), } ) + context = RequestContext(request) + context.account = "test" + context.region = "us-west-1" + context.service = sqs_service result = skeleton.invoke(context) # Use the parser from botocore to parse the serialized response @@ -335,7 +335,7 @@ def fn(context, arg_one, arg_two): assert arg_two == 69 dispatcher = ServiceRequestDispatcher(fn, "SomeAction") - dispatcher(RequestContext(), SomeAction(ArgOne="foo", ArgTwo=69)) + dispatcher(RequestContext(None), SomeAction(ArgOne="foo", ArgTwo=69)) def test_without_context_without_expand(self): def fn(*args): @@ -345,7 +345,7 @@ def fn(*args): dispatcher = ServiceRequestDispatcher( fn, "SomeAction", pass_context=False, expand_parameters=False ) - dispatcher(RequestContext(), ServiceRequest()) + dispatcher(RequestContext(None), ServiceRequest()) def test_without_expand(self): def fn(*args): @@ -356,11 +356,11 @@ def fn(*args): dispatcher = ServiceRequestDispatcher( fn, "SomeAction", pass_context=True, expand_parameters=False ) - dispatcher(RequestContext(), ServiceRequest()) + dispatcher(RequestContext(None), ServiceRequest()) def test_dispatch_without_args(self): def fn(context): assert type(context) == RequestContext dispatcher = ServiceRequestDispatcher(fn, "SomeAction") - dispatcher(RequestContext(), ServiceRequest()) + dispatcher(RequestContext(None), ServiceRequest()) diff --git a/tests/unit/services/kms/test_kms.py b/tests/unit/services/kms/test_kms.py index 72e4b870eb36c..ffdec68c06b58 100644 --- a/tests/unit/services/kms/test_kms.py +++ b/tests/unit/services/kms/test_kms.py @@ -48,7 +48,7 @@ def test_generate_data_key_pair_invalid_spec_raises_unsupported_exception( provider, invalid_spec, dry_run ): # Arrange - context = RequestContext() + context = RequestContext(None) context.account_id = "000000000000" context.region = "us-east-1" @@ -79,7 +79,7 @@ def test_generate_data_key_pair_invalid_spec_raises_validation_exception( provider, invalid_spec, dry_run ): # Arrange - context = RequestContext() + context = RequestContext(None) context.account_id = "000000000000" context.region = "us-east-1" @@ -101,7 +101,7 @@ def test_generate_data_key_pair_real_key(provider): # Arrange account_id = "000000000000" region_name = "us-east-1" - context = RequestContext() + context = RequestContext(None) context.account_id = account_id context.region = region_name @@ -131,7 +131,7 @@ def test_generate_data_key_pair_dry_run(provider): # Arrange account_id = "000000000000" region_name = "us-east-1" - context = RequestContext() + context = RequestContext(None) context.account_id = account_id context.region = region_name @@ -158,7 +158,7 @@ def test_generate_data_key_pair_without_plaintext(provider): # Arrange account_id = "000000000000" region_name = "us-east-1" - context = RequestContext() + context = RequestContext(None) context.account_id = account_id context.region = region_name @@ -188,7 +188,7 @@ def test_generate_data_key_pair_without_plaintext_dry_run(provider): # Arrange account_id = "000000000000" region_name = "us-east-1" - context = RequestContext() + context = RequestContext(None) context.account_id = account_id context.region = region_name diff --git a/tests/unit/services/s3/test_s3.py b/tests/unit/services/s3/test_s3.py index 1420ff4de5e84..a01fe9d58f8c3 100644 --- a/tests/unit/services/s3/test_s3.py +++ b/tests/unit/services/s3/test_s3.py @@ -377,10 +377,10 @@ class TestS3PresignedUrl: @staticmethod def _create_fake_context_from_path(path: str, method: str = "GET"): - fake_context = RequestContext() - fake_context.request = Request( + request = Request( method=method, path=path, query_string=urlparse(f"http://localhost{path}").query ) + fake_context = RequestContext(request) return fake_context def test_is_presigned_url_request(self):