Skip to content

Commit 5820881

Browse files
authored
Typechecking for manifests (#1224)
* Adding python type checking for src/manifests Signed-off-by: Peter Nied <petern@amazon.com>
1 parent bfd5dad commit 5820881

37 files changed

+561
-491
lines changed

.github/workflows/python-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
pipenv run flake8 .
3232
- name: Run Type Checker
3333
run: |
34-
pipenv run mypy .
34+
pipenv run mypy src/manifests tests/tests_manifests
3535
- name: Run Tests with Coverage
3636
run: |
3737
pipenv run coverage run -m pytest --cov=./src --cov-report=xml

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ repos:
1818
- id: mypy
1919
stages: [commit]
2020
name: mypy
21-
entry: bash -c 'pipenv run mypy .'
21+
entry: bash -c 'pipenv run mypy src/manifests tests/tests_manifests'
2222
language: system
2323
- id: pytest
2424
stages: [commit]

pyproject.toml

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,13 @@ target-version = ['py37']
44

55
[tool.isort]
66
profile = "black"
7-
line_length = 160
7+
line_length = 160
8+
9+
[tool.mypy]
10+
python_version = 3.7
11+
disallow_untyped_defs = true
12+
warn_return_any = true
13+
warn_unused_configs = true
14+
strict_optional = false
15+
show_error_codes = true
16+
ignore_missing_imports = true

src/build_workflow/builders.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88

99
from build_workflow.builder_from_dist import BuilderFromDist
1010
from build_workflow.builder_from_source import BuilderFromSource
11-
from manifests.input_manifest import InputManifest
11+
from manifests.input_manifest import InputComponentFromDist, InputComponentFromSource
1212

1313

1414
class Builders(ABC):
1515
@classmethod
1616
def builder_from(self, component, target):
17-
if type(component) is InputManifest.ComponentFromDist:
17+
if type(component) is InputComponentFromDist:
1818
return BuilderFromDist(component, target)
19-
elif type(component) is InputManifest.ComponentFromSource:
19+
elif type(component) is InputComponentFromSource:
2020
return BuilderFromSource(component, target)
2121
else:
2222
raise ValueError(f"Invalid component type: {type(component)}")

src/ci_workflow/ci_check_lists.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88

99
from ci_workflow.ci_check_list_dist import CiCheckListDist
1010
from ci_workflow.ci_check_list_source import CiCheckListSource
11-
from manifests.input_manifest import InputManifest
11+
from manifests.input_manifest import InputComponentFromDist, InputComponentFromSource
1212

1313

1414
class CiCheckLists(ABC):
1515
@classmethod
1616
def from_component(self, component, target):
17-
if type(component) is InputManifest.ComponentFromDist:
17+
if type(component) is InputComponentFromDist:
1818
return CiCheckListDist(component, target)
19-
elif type(component) is InputManifest.ComponentFromSource:
19+
elif type(component) is InputComponentFromSource:
2020
return CiCheckListSource(component, target)
2121
else:
2222
raise ValueError(f"Invalid component type: {type(component)}")

src/git/git_repository.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88
import os
99
import subprocess
1010
from pathlib import Path
11+
from typing import Any, List
1112

1213
from system.temporary_directory import TemporaryDirectory
1314

1415

1516
class GitRepository:
17+
dir: str
1618
"""
1719
This class checks out a Git repository at a particular ref into an empty named directory (or temporary a directory if no named directory is given).
1820
Temporary directories will be automatically deleted when the GitRepository object goes out of scope; named directories will be left alone.
1921
Clients can obtain the actual commit ID by querying the "sha" attribute, and the temp directory name with "dir".
2022
"""
2123

22-
def __init__(self, url, ref, directory=None, working_subdirectory=None):
24+
def __init__(self, url: str, ref: str, directory: str = None, working_subdirectory: str = None) -> None:
2325
self.url = url
2426
self.ref = ref
2527
if directory is None:
@@ -32,15 +34,14 @@ def __init__(self, url, ref, directory=None, working_subdirectory=None):
3234
self.working_subdirectory = working_subdirectory
3335
self.__checkout__()
3436

35-
def __enter__(self):
37+
def __enter__(self) -> 'GitRepository':
3638
return self
3739

38-
def __exit__(self, exc_type, exc_value, exc_traceback):
40+
def __exit__(self, exc_type: Any, exc_value: Any, exc_traceback: Any) -> None:
3941
if self.temp_dir:
4042
self.temp_dir.__exit__(exc_type, exc_value, exc_traceback)
4143

42-
def __checkout__(self):
43-
# Check out the repository
44+
def __checkout__(self) -> None:
4445
self.execute_silent("git init", self.dir)
4546
self.execute_silent(f"git remote add origin {self.url}", self.dir)
4647
self.execute_silent(f"git fetch --depth 1 origin {self.ref}", self.dir)
@@ -49,18 +50,18 @@ def __checkout__(self):
4950
logging.info(f"Checked out {self.url}@{self.ref} into {self.dir} at {self.sha}")
5051

5152
@property
52-
def working_directory(self):
53+
def working_directory(self) -> str:
5354
if self.working_subdirectory:
5455
return os.path.join(self.dir, self.working_subdirectory)
5556
else:
5657
return self.dir
5758

5859
@classmethod
59-
def stable_ref(self, url, ref):
60+
def stable_ref(self, url: str, ref: str) -> List[str]:
6061
results = subprocess.check_output(f"git ls-remote {url} {ref}", shell=True).decode().strip().split("\t")
6162
return results if len(results) > 1 else [ref, ref]
6263

63-
def execute_silent(self, command, cwd=None):
64+
def execute_silent(self, command: str, cwd: str = None) -> None:
6465
cwd = cwd or self.working_directory
6566
logging.info(f'Executing "{command}" in {cwd}')
6667
subprocess.check_call(
@@ -71,17 +72,17 @@ def execute_silent(self, command, cwd=None):
7172
stderr=subprocess.DEVNULL,
7273
)
7374

74-
def output(self, command, cwd=None):
75+
def output(self, command: str, cwd: str = None) -> str:
7576
cwd = cwd or self.working_directory
7677
logging.info(f'Executing "{command}" in {cwd}')
7778
return subprocess.check_output(command, cwd=cwd, shell=True).decode().strip()
7879

79-
def execute(self, command, cwd=None):
80+
def execute(self, command: str, cwd: str = None) -> None:
8081
cwd = cwd or self.working_directory
8182
logging.info(f'Executing "{command}" in {cwd}')
8283
subprocess.check_call(command, cwd=cwd, shell=True)
8384

84-
def path(self, subdirname=None):
85+
def path(self, subdirname: str = None) -> Path:
8586
dirname = self.dir
8687
if subdirname:
8788
dirname = os.path.join(self.dir, subdirname)

src/manifests/build/build_manifest_1_0.py

+31-27
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# this file be licensed under the Apache-2.0 license or a
55
# compatible open source license.
66

7-
from manifests.component_manifest import ComponentManifest
7+
from typing import Any
8+
from manifests.component_manifest import ComponentManifest, Components, Component
89

910
"""
1011
A BuildManifest is an immutable view of the outputs from a build step
@@ -35,7 +36,7 @@
3536
"""
3637

3738

38-
class BuildManifest_1_0(ComponentManifest):
39+
class BuildManifest_1_0(ComponentManifest['BuildManifest_1_0', 'BuildComponents_1_0']):
3940
SCHEMA = {
4041
"build": {
4142
"required": True,
@@ -73,51 +74,54 @@ class BuildManifest_1_0(ComponentManifest):
7374
},
7475
}
7576

76-
def __init__(self, data):
77+
def __init__(self, data: Any):
7778
super().__init__(data)
7879
self.build = self.Build(data["build"])
7980

80-
def __to_dict__(self):
81+
def __to_dict__(self) -> dict:
8182
return {
8283
"schema-version": "1.0",
8384
"build": self.build.__to_dict__(),
8485
"components": self.components.__to_dict__()
8586
}
8687

87-
class Components(ComponentManifest.Components):
88-
def __create__(self, data):
89-
return BuildManifest_1_0.Component(data)
90-
9188
class Build:
92-
def __init__(self, data):
89+
def __init__(self, data: Any):
9390
self.name = data["name"]
9491
self.version = data["version"]
9592
self.architecture = data["architecture"]
9693
self.id = data["id"]
9794

98-
def __to_dict__(self):
95+
def __to_dict__(self) -> dict:
9996
return {
10097
"name": self.name,
10198
"version": self.version,
10299
"architecture": self.architecture,
103100
"id": self.id
104101
}
105102

106-
class Component(ComponentManifest.Component):
107-
def __init__(self, data):
108-
super().__init__(data)
109-
self.repository = data["repository"]
110-
self.ref = data["ref"]
111-
self.commit_id = data["commit_id"]
112-
self.artifacts = data.get("artifacts", {})
113-
self.version = data["version"]
114103

115-
def __to_dict__(self):
116-
return {
117-
"name": self.name,
118-
"repository": self.repository,
119-
"ref": self.ref,
120-
"commit_id": self.commit_id,
121-
"artifacts": self.artifacts,
122-
"version": self.version,
123-
}
104+
class BuildComponents_1_0(Components['BuildComponent_1_0']):
105+
@classmethod
106+
def __create__(self, data: Any) -> 'BuildComponent_1_0':
107+
return BuildComponent_1_0(data)
108+
109+
110+
class BuildComponent_1_0(Component):
111+
def __init__(self, data: Any):
112+
super().__init__(data)
113+
self.repository = data["repository"]
114+
self.ref = data["ref"]
115+
self.commit_id = data["commit_id"]
116+
self.artifacts = data.get("artifacts", {})
117+
self.version = data["version"]
118+
119+
def __to_dict__(self) -> dict:
120+
return {
121+
"name": self.name,
122+
"repository": self.repository,
123+
"ref": self.ref,
124+
"commit_id": self.commit_id,
125+
"artifacts": self.artifacts,
126+
"version": self.version,
127+
}

src/manifests/build/build_manifest_1_1.py

+30-26
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# this file be licensed under the Apache-2.0 license or a
55
# compatible open source license.
66

7-
from manifests.component_manifest import ComponentManifest
7+
from typing import Any
8+
from manifests.component_manifest import ComponentManifest, Components, Component
89

910
"""
1011
A BuildManifest is an immutable view of the outputs from a build step
@@ -36,7 +37,7 @@
3637
"""
3738

3839

39-
class BuildManifest_1_1(ComponentManifest):
40+
class BuildManifest_1_1(ComponentManifest['BuildManifest_1_1', 'BuildComponents_1_1']):
4041
SCHEMA = {
4142
"build": {
4243
"required": True,
@@ -74,51 +75,54 @@ class BuildManifest_1_1(ComponentManifest):
7475
},
7576
}
7677

77-
def __init__(self, data):
78+
def __init__(self, data: Any):
7879
super().__init__(data)
7980
self.build = self.Build(data["build"])
8081

81-
def __to_dict__(self):
82+
def __to_dict__(self) -> dict:
8283
return {
8384
"schema-version": "1.1",
8485
"build": self.build.__to_dict__(),
8586
"components": self.components.__to_dict__()
8687
}
8788

8889
class Build:
89-
def __init__(self, data):
90+
def __init__(self, data: Any):
9091
self.name = data["name"]
9192
self.version = data["version"]
9293
self.architecture = data["architecture"]
9394
self.id = data["id"]
9495

95-
def __to_dict__(self):
96+
def __to_dict__(self) -> dict:
9697
return {
9798
"name": self.name,
9899
"version": self.version,
99100
"architecture": self.architecture,
100101
"id": self.id
101102
}
102103

103-
class Components(ComponentManifest.Components):
104-
def __create__(self, data):
105-
return BuildManifest_1_1.Component(data)
106104

107-
class Component(ComponentManifest.Component):
108-
def __init__(self, data):
109-
super().__init__(data)
110-
self.repository = data["repository"]
111-
self.ref = data["ref"]
112-
self.commit_id = data["commit_id"]
113-
self.artifacts = data.get("artifacts", {})
114-
self.version = data["version"]
105+
class BuildComponents_1_1(Components['BuildComponent_1_1']):
106+
@classmethod
107+
def __create__(self, data: Any) -> 'BuildComponent_1_1':
108+
return BuildComponent_1_1(data)
115109

116-
def __to_dict__(self):
117-
return {
118-
"name": self.name,
119-
"repository": self.repository,
120-
"ref": self.ref,
121-
"commit_id": self.commit_id,
122-
"artifacts": self.artifacts,
123-
"version": self.version,
124-
}
110+
111+
class BuildComponent_1_1(Component):
112+
def __init__(self, data: Any):
113+
super().__init__(data)
114+
self.repository = data["repository"]
115+
self.ref = data["ref"]
116+
self.commit_id = data["commit_id"]
117+
self.artifacts = data.get("artifacts", {})
118+
self.version = data["version"]
119+
120+
def __to_dict__(self) -> dict:
121+
return {
122+
"name": self.name,
123+
"repository": self.repository,
124+
"ref": self.ref,
125+
"commit_id": self.commit_id,
126+
"artifacts": self.artifacts,
127+
"version": self.version,
128+
}

0 commit comments

Comments
 (0)