TechDebt: MyPy CodeCommit & CodePipeline (#5624)

This commit is contained in:
Bert Blommers 2022-10-31 17:34:03 -01:00 committed by GitHub
parent 15891efcef
commit ba1919cc6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 69 additions and 56 deletions

View File

@ -4,7 +4,7 @@ from moto.core.exceptions import JsonRESTError
class RepositoryNameExistsException(JsonRESTError): class RepositoryNameExistsException(JsonRESTError):
code = 400 code = 400
def __init__(self, repository_name): def __init__(self, repository_name: str):
super().__init__( super().__init__(
"RepositoryNameExistsException", "RepositoryNameExistsException",
"Repository named {0} already exists".format(repository_name), "Repository named {0} already exists".format(repository_name),
@ -14,7 +14,7 @@ class RepositoryNameExistsException(JsonRESTError):
class RepositoryDoesNotExistException(JsonRESTError): class RepositoryDoesNotExistException(JsonRESTError):
code = 400 code = 400
def __init__(self, repository_name): def __init__(self, repository_name: str):
super().__init__( super().__init__(
"RepositoryDoesNotExistException", "RepositoryDoesNotExistException",
"{0} does not exist".format(repository_name), "{0} does not exist".format(repository_name),
@ -24,7 +24,7 @@ class RepositoryDoesNotExistException(JsonRESTError):
class InvalidRepositoryNameException(JsonRESTError): class InvalidRepositoryNameException(JsonRESTError):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"InvalidRepositoryNameException", "InvalidRepositoryNameException",
"The repository name is not valid. Repository names can be any valid " "The repository name is not valid. Repository names can be any valid "

View File

@ -2,11 +2,18 @@ from moto.core import BaseBackend, BaseModel
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
from moto.moto_api._internal import mock_random from moto.moto_api._internal import mock_random
from datetime import datetime from datetime import datetime
from typing import Dict, List, Optional
from .exceptions import RepositoryDoesNotExistException, RepositoryNameExistsException from .exceptions import RepositoryDoesNotExistException, RepositoryNameExistsException
class CodeCommit(BaseModel): class CodeCommit(BaseModel):
def __init__(self, account_id, region, repository_description, repository_name): def __init__(
self,
account_id: str,
region: str,
repository_description: str,
repository_name: str,
):
current_date = iso_8601_datetime_with_milliseconds(datetime.utcnow()) current_date = iso_8601_datetime_with_milliseconds(datetime.utcnow())
self.repository_metadata = dict() self.repository_metadata = dict()
self.repository_metadata["repositoryName"] = repository_name self.repository_metadata["repositoryName"] = repository_name
@ -31,18 +38,22 @@ class CodeCommit(BaseModel):
class CodeCommitBackend(BaseBackend): class CodeCommitBackend(BaseBackend):
def __init__(self, region_name, account_id): def __init__(self, region_name: str, account_id: str):
super().__init__(region_name, account_id) super().__init__(region_name, account_id)
self.repositories = {} self.repositories: Dict[str, CodeCommit] = {}
@staticmethod @staticmethod
def default_vpc_endpoint_service(service_region, zones): def default_vpc_endpoint_service(
service_region: str, zones: List[str]
) -> List[Dict[str, str]]:
"""Default VPC endpoint service.""" """Default VPC endpoint service."""
return BaseBackend.default_vpc_endpoint_service_factory( return BaseBackend.default_vpc_endpoint_service_factory(
service_region, zones, "codecommit" service_region, zones, "codecommit"
) )
def create_repository(self, repository_name, repository_description): def create_repository(
self, repository_name: str, repository_description: str
) -> Dict[str, str]:
repository = self.repositories.get(repository_name) repository = self.repositories.get(repository_name)
if repository: if repository:
raise RepositoryNameExistsException(repository_name) raise RepositoryNameExistsException(repository_name)
@ -53,14 +64,14 @@ class CodeCommitBackend(BaseBackend):
return self.repositories[repository_name].repository_metadata return self.repositories[repository_name].repository_metadata
def get_repository(self, repository_name): def get_repository(self, repository_name: str) -> Dict[str, str]:
repository = self.repositories.get(repository_name) repository = self.repositories.get(repository_name)
if not repository: if not repository:
raise RepositoryDoesNotExistException(repository_name) raise RepositoryDoesNotExistException(repository_name)
return repository.repository_metadata return repository.repository_metadata
def delete_repository(self, repository_name): def delete_repository(self, repository_name: str) -> Optional[str]:
repository = self.repositories.get(repository_name) repository = self.repositories.get(repository_name)
if repository: if repository:

View File

@ -2,11 +2,11 @@ import json
import re import re
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import codecommit_backends from .models import codecommit_backends, CodeCommitBackend
from .exceptions import InvalidRepositoryNameException from .exceptions import InvalidRepositoryNameException
def _is_repository_name_valid(repository_name): def _is_repository_name_valid(repository_name: str) -> bool:
name_regex = re.compile(r"[\w\.-]+") name_regex = re.compile(r"[\w\.-]+")
result = name_regex.split(repository_name) result = name_regex.split(repository_name)
if len(result) > 0: if len(result) > 0:
@ -17,14 +17,14 @@ def _is_repository_name_valid(repository_name):
class CodeCommitResponse(BaseResponse): class CodeCommitResponse(BaseResponse):
def __init__(self): def __init__(self) -> None:
super().__init__(service_name="codecommit") super().__init__(service_name="codecommit")
@property @property
def codecommit_backend(self): def codecommit_backend(self) -> CodeCommitBackend:
return codecommit_backends[self.current_account][self.region] return codecommit_backends[self.current_account][self.region]
def create_repository(self): def create_repository(self) -> str:
if not _is_repository_name_valid(self._get_param("repositoryName")): if not _is_repository_name_valid(self._get_param("repositoryName")):
raise InvalidRepositoryNameException() raise InvalidRepositoryNameException()
@ -35,7 +35,7 @@ class CodeCommitResponse(BaseResponse):
return json.dumps({"repositoryMetadata": repository_metadata}) return json.dumps({"repositoryMetadata": repository_metadata})
def get_repository(self): def get_repository(self) -> str:
if not _is_repository_name_valid(self._get_param("repositoryName")): if not _is_repository_name_valid(self._get_param("repositoryName")):
raise InvalidRepositoryNameException() raise InvalidRepositoryNameException()
@ -45,7 +45,7 @@ class CodeCommitResponse(BaseResponse):
return json.dumps({"repositoryMetadata": repository_metadata}) return json.dumps({"repositoryMetadata": repository_metadata})
def delete_repository(self): def delete_repository(self) -> str:
if not _is_repository_name_valid(self._get_param("repositoryName")): if not _is_repository_name_valid(self._get_param("repositoryName")):
raise InvalidRepositoryNameException() raise InvalidRepositoryNameException()

View File

@ -4,35 +4,35 @@ from moto.core.exceptions import JsonRESTError
class InvalidStructureException(JsonRESTError): class InvalidStructureException(JsonRESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("InvalidStructureException", message) super().__init__("InvalidStructureException", message)
class PipelineNotFoundException(JsonRESTError): class PipelineNotFoundException(JsonRESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("PipelineNotFoundException", message) super().__init__("PipelineNotFoundException", message)
class ResourceNotFoundException(JsonRESTError): class ResourceNotFoundException(JsonRESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("ResourceNotFoundException", message) super().__init__("ResourceNotFoundException", message)
class InvalidTagsException(JsonRESTError): class InvalidTagsException(JsonRESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("InvalidTagsException", message) super().__init__("InvalidTagsException", message)
class TooManyTagsException(JsonRESTError): class TooManyTagsException(JsonRESTError):
code = 400 code = 400
def __init__(self, arn): def __init__(self, arn: str):
super().__init__( super().__init__(
"TooManyTagsException", "Tag limit exceeded for resource [{}].".format(arn) "TooManyTagsException", "Tag limit exceeded for resource [{}].".format(arn)
) )

View File

@ -1,11 +1,9 @@
import json import json
from datetime import datetime from datetime import datetime
from typing import Any, Dict, List, Tuple
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
from moto.iam.exceptions import IAMNotFoundException from moto.iam.exceptions import IAMNotFoundException
from moto.iam.models import iam_backends, IAMBackend
from moto.iam import iam_backends
from moto.codepipeline.exceptions import ( from moto.codepipeline.exceptions import (
InvalidStructureException, InvalidStructureException,
@ -18,26 +16,26 @@ from moto.core import BaseBackend, BaseModel
class CodePipeline(BaseModel): class CodePipeline(BaseModel):
def __init__(self, account_id, region, pipeline): def __init__(self, account_id: str, region: str, pipeline: Dict[str, Any]):
# the version number for a new pipeline is always 1 # the version number for a new pipeline is always 1
pipeline["version"] = 1 pipeline["version"] = 1
self.pipeline = self.add_default_values(pipeline) self.pipeline = self.add_default_values(pipeline)
self.tags = {} self.tags: Dict[str, str] = {}
self._arn = f"arn:aws:codepipeline:{region}:{account_id}:{pipeline['name']}" self._arn = f"arn:aws:codepipeline:{region}:{account_id}:{pipeline['name']}"
self._created = datetime.utcnow() self._created = datetime.utcnow()
self._updated = datetime.utcnow() self._updated = datetime.utcnow()
@property @property
def metadata(self): def metadata(self) -> Dict[str, str]:
return { return {
"pipelineArn": self._arn, "pipelineArn": self._arn,
"created": iso_8601_datetime_with_milliseconds(self._created), "created": iso_8601_datetime_with_milliseconds(self._created),
"updated": iso_8601_datetime_with_milliseconds(self._updated), "updated": iso_8601_datetime_with_milliseconds(self._updated),
} }
def add_default_values(self, pipeline): def add_default_values(self, pipeline: Dict[str, Any]) -> Dict[str, Any]:
for stage in pipeline["stages"]: for stage in pipeline["stages"]:
for action in stage["actions"]: for action in stage["actions"]:
if "runOrder" not in action: if "runOrder" not in action:
@ -51,7 +49,7 @@ class CodePipeline(BaseModel):
return pipeline return pipeline
def validate_tags(self, tags): def validate_tags(self, tags: List[Dict[str, str]]) -> None:
for tag in tags: for tag in tags:
if tag["key"].startswith("aws:"): if tag["key"].startswith("aws:"):
raise InvalidTagsException( raise InvalidTagsException(
@ -65,22 +63,26 @@ class CodePipeline(BaseModel):
class CodePipelineBackend(BaseBackend): class CodePipelineBackend(BaseBackend):
def __init__(self, region_name, account_id): def __init__(self, region_name: str, account_id: str):
super().__init__(region_name, account_id) super().__init__(region_name, account_id)
self.pipelines = {} self.pipelines: Dict[str, CodePipeline] = {}
@staticmethod @staticmethod
def default_vpc_endpoint_service(service_region, zones): def default_vpc_endpoint_service(
service_region: str, zones: List[str]
) -> List[Dict[str, str]]:
"""Default VPC endpoint service.""" """Default VPC endpoint service."""
return BaseBackend.default_vpc_endpoint_service_factory( return BaseBackend.default_vpc_endpoint_service_factory(
service_region, zones, "codepipeline", policy_supported=False service_region, zones, "codepipeline", policy_supported=False
) )
@property @property
def iam_backend(self): def iam_backend(self) -> IAMBackend:
return iam_backends[self.account_id]["global"] return iam_backends[self.account_id]["global"]
def create_pipeline(self, pipeline, tags): def create_pipeline(
self, pipeline: Dict[str, Any], tags: List[Dict[str, str]]
) -> Tuple[Dict[str, Any], List[Dict[str, str]]]:
name = pipeline["name"] name = pipeline["name"]
if name in self.pipelines: if name in self.pipelines:
raise InvalidStructureException( raise InvalidStructureException(
@ -123,7 +125,7 @@ class CodePipelineBackend(BaseBackend):
return pipeline, sorted(tags, key=lambda i: i["key"]) return pipeline, sorted(tags, key=lambda i: i["key"])
def get_pipeline(self, name): def get_pipeline(self, name: str) -> Tuple[Dict[str, Any], Dict[str, str]]:
codepipeline = self.pipelines.get(name) codepipeline = self.pipelines.get(name)
if not codepipeline: if not codepipeline:
@ -133,7 +135,7 @@ class CodePipelineBackend(BaseBackend):
return codepipeline.pipeline, codepipeline.metadata return codepipeline.pipeline, codepipeline.metadata
def update_pipeline(self, pipeline): def update_pipeline(self, pipeline: Dict[str, Any]) -> Dict[str, Any]:
codepipeline = self.pipelines.get(pipeline["name"]) codepipeline = self.pipelines.get(pipeline["name"])
if not codepipeline: if not codepipeline:
@ -148,7 +150,7 @@ class CodePipelineBackend(BaseBackend):
return codepipeline.pipeline return codepipeline.pipeline
def list_pipelines(self): def list_pipelines(self) -> List[Dict[str, str]]:
pipelines = [] pipelines = []
for name, codepipeline in self.pipelines.items(): for name, codepipeline in self.pipelines.items():
@ -163,10 +165,10 @@ class CodePipelineBackend(BaseBackend):
return sorted(pipelines, key=lambda i: i["name"]) return sorted(pipelines, key=lambda i: i["name"])
def delete_pipeline(self, name): def delete_pipeline(self, name: str) -> None:
self.pipelines.pop(name, None) self.pipelines.pop(name, None)
def list_tags_for_resource(self, arn): def list_tags_for_resource(self, arn: str) -> List[Dict[str, str]]:
name = arn.split(":")[-1] name = arn.split(":")[-1]
pipeline = self.pipelines.get(name) pipeline = self.pipelines.get(name)
@ -179,7 +181,7 @@ class CodePipelineBackend(BaseBackend):
return sorted(tags, key=lambda i: i["key"]) return sorted(tags, key=lambda i: i["key"])
def tag_resource(self, arn, tags): def tag_resource(self, arn: str, tags: List[Dict[str, str]]) -> None:
name = arn.split(":")[-1] name = arn.split(":")[-1]
pipeline = self.pipelines.get(name) pipeline = self.pipelines.get(name)
@ -193,7 +195,7 @@ class CodePipelineBackend(BaseBackend):
for tag in tags: for tag in tags:
pipeline.tags.update({tag["key"]: tag["value"]}) pipeline.tags.update({tag["key"]: tag["value"]})
def untag_resource(self, arn, tag_keys): def untag_resource(self, arn: str, tag_keys: List[str]) -> None:
name = arn.split(":")[-1] name = arn.split(":")[-1]
pipeline = self.pipelines.get(name) pipeline = self.pipelines.get(name)

View File

@ -1,63 +1,63 @@
import json import json
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import codepipeline_backends from .models import codepipeline_backends, CodePipelineBackend
class CodePipelineResponse(BaseResponse): class CodePipelineResponse(BaseResponse):
def __init__(self): def __init__(self) -> None:
super().__init__(service_name="codepipeline") super().__init__(service_name="codepipeline")
@property @property
def codepipeline_backend(self): def codepipeline_backend(self) -> CodePipelineBackend:
return codepipeline_backends[self.current_account][self.region] return codepipeline_backends[self.current_account][self.region]
def create_pipeline(self): def create_pipeline(self) -> str:
pipeline, tags = self.codepipeline_backend.create_pipeline( pipeline, tags = self.codepipeline_backend.create_pipeline(
self._get_param("pipeline"), self._get_param("tags") self._get_param("pipeline"), self._get_param("tags")
) )
return json.dumps({"pipeline": pipeline, "tags": tags}) return json.dumps({"pipeline": pipeline, "tags": tags})
def get_pipeline(self): def get_pipeline(self) -> str:
pipeline, metadata = self.codepipeline_backend.get_pipeline( pipeline, metadata = self.codepipeline_backend.get_pipeline(
self._get_param("name") self._get_param("name")
) )
return json.dumps({"pipeline": pipeline, "metadata": metadata}) return json.dumps({"pipeline": pipeline, "metadata": metadata})
def update_pipeline(self): def update_pipeline(self) -> str:
pipeline = self.codepipeline_backend.update_pipeline( pipeline = self.codepipeline_backend.update_pipeline(
self._get_param("pipeline") self._get_param("pipeline")
) )
return json.dumps({"pipeline": pipeline}) return json.dumps({"pipeline": pipeline})
def list_pipelines(self): def list_pipelines(self) -> str:
pipelines = self.codepipeline_backend.list_pipelines() pipelines = self.codepipeline_backend.list_pipelines()
return json.dumps({"pipelines": pipelines}) return json.dumps({"pipelines": pipelines})
def delete_pipeline(self): def delete_pipeline(self) -> str:
self.codepipeline_backend.delete_pipeline(self._get_param("name")) self.codepipeline_backend.delete_pipeline(self._get_param("name"))
return "" return ""
def list_tags_for_resource(self): def list_tags_for_resource(self) -> str:
tags = self.codepipeline_backend.list_tags_for_resource( tags = self.codepipeline_backend.list_tags_for_resource(
self._get_param("resourceArn") self._get_param("resourceArn")
) )
return json.dumps({"tags": tags}) return json.dumps({"tags": tags})
def tag_resource(self): def tag_resource(self) -> str:
self.codepipeline_backend.tag_resource( self.codepipeline_backend.tag_resource(
self._get_param("resourceArn"), self._get_param("tags") self._get_param("resourceArn"), self._get_param("tags")
) )
return "" return ""
def untag_resource(self): def untag_resource(self) -> str:
self.codepipeline_backend.untag_resource( self.codepipeline_backend.untag_resource(
self._get_param("resourceArn"), self._get_param("tagKeys") self._get_param("resourceArn"), self._get_param("tagKeys")
) )

View File

@ -6,7 +6,7 @@ XMLNS_IAM = "https://iam.amazonaws.com/doc/2010-05-08/"
class IAMNotFoundException(RESTError): class IAMNotFoundException(RESTError):
code = 404 code = 404
def __init__(self, message): def __init__(self, message: str):
super().__init__( super().__init__(
"NoSuchEntity", message, xmlns=XMLNS_IAM, template="wrapped_single_error" "NoSuchEntity", message, xmlns=XMLNS_IAM, template="wrapped_single_error"
) )

View File

@ -18,7 +18,7 @@ disable = W,C,R,E
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
[mypy] [mypy]
files= moto/a*,moto/b*,moto/ce,moto/cloudformation,moto/cloudfront,moto/cloudtrail,moto/codebuild,moto/cloudwatch files= moto/a*,moto/b*,moto/ce,moto/cloudformation,moto/cloudfront,moto/cloudtrail,moto/codebuild,moto/cloudwatch,moto/codepipeline,moto/codecommit
show_column_numbers=True show_column_numbers=True
show_error_codes = True show_error_codes = True
disable_error_code=abstract disable_error_code=abstract