Skip to content

Commit f39e919

Browse files
authored
fix: Add type hints for iam api-client samples (#9977)
## Description Fixes b/280879750 Note: Before submitting a pull request, please open an issue for discussion if you are not associated with Google. ## Checklist - [ ] I have followed [Sample Guidelines from AUTHORING_GUIDE.MD](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/AUTHORING_GUIDE.md) - [ ] README is updated to include [all relevant information](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/AUTHORING_GUIDE.md#readme-file) - [ ] **Tests** pass: `nox -s py-3.9` (see [Test Environment Setup](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/AUTHORING_GUIDE.md#test-environment-setup)) - [ ] **Lint** pass: `nox -s lint` (see [Test Environment Setup](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/AUTHORING_GUIDE.md#test-environment-setup)) - [ ] These samples need a new **API enabled** in testing projects to pass (let us know which ones) - [ ] These samples need a new/updated **env vars** in testing projects set to pass (let us know which ones) - [ ] This sample adds a new sample directory, and I updated the [CODEOWNERS file](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/.github/CODEOWNERS) with the codeowners for this sample - [ ] This sample adds a new **Product API**, and I updated the [Blunderbuss issue/PR auto-assigner](https://togithub.com/GoogleCloudPlatform/python-docs-samples/blob/main/.github/blunderbuss.yml) with the codeowners for this sample - [x] Please **merge** this PR for me once it is approved
1 parent e50e0c4 commit f39e919

12 files changed

+105
-86
lines changed

iam/api-client/access.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
import argparse
2222
import os
2323

24-
from google.oauth2 import service_account
25-
import googleapiclient.discovery
24+
from google.oauth2 import service_account # type: ignore
25+
import googleapiclient.discovery # type: ignore
2626

2727

2828
# [START iam_get_policy]
29-
def get_policy(project_id, version=1):
29+
def get_policy(project_id: str, version: int = 1) -> dict:
3030
"""Gets IAM policy for a project."""
3131

3232
credentials = service_account.Credentials.from_service_account_file(
@@ -52,7 +52,7 @@ def get_policy(project_id, version=1):
5252

5353

5454
# [START iam_modify_policy_add_member]
55-
def modify_policy_add_member(policy, role, member):
55+
def modify_policy_add_member(policy: dict, role: str, member: str) -> dict:
5656
"""Adds a new member to a role binding."""
5757

5858
binding = next(b for b in policy["bindings"] if b["role"] == role)
@@ -65,7 +65,7 @@ def modify_policy_add_member(policy, role, member):
6565

6666

6767
# [START iam_modify_policy_add_role]
68-
def modify_policy_add_role(policy, role, member):
68+
def modify_policy_add_role(policy: dict, role: str, member: str) -> dict:
6969
"""Adds a new role binding to a policy."""
7070

7171
binding = {"role": role, "members": [member]}
@@ -78,7 +78,7 @@ def modify_policy_add_role(policy, role, member):
7878

7979

8080
# [START iam_modify_policy_remove_member]
81-
def modify_policy_remove_member(policy, role, member):
81+
def modify_policy_remove_member(policy: dict, role: str, member: str) -> dict:
8282
"""Removes a member from a role binding."""
8383
binding = next(b for b in policy["bindings"] if b["role"] == role)
8484
if "members" in binding and member in binding["members"]:
@@ -91,7 +91,7 @@ def modify_policy_remove_member(policy, role, member):
9191

9292

9393
# [START iam_set_policy]
94-
def set_policy(project_id, policy):
94+
def set_policy(project_id: str, policy: dict) -> dict:
9595
"""Sets IAM policy for a project."""
9696

9797
credentials = service_account.Credentials.from_service_account_file(
@@ -115,7 +115,7 @@ def set_policy(project_id, policy):
115115

116116

117117
# [START iam_test_permissions]
118-
def test_permissions(project_id):
118+
def test_permissions(project_id: str) -> dict:
119119
"""Tests IAM permissions of the caller"""
120120

121121
credentials = service_account.Credentials.from_service_account_file(
@@ -144,7 +144,7 @@ def test_permissions(project_id):
144144
# [END iam_test_permissions]
145145

146146

147-
def main():
147+
def main() -> None:
148148
parser = argparse.ArgumentParser(
149149
description=__doc__,
150150
formatter_class=argparse.RawDescriptionHelpFormatter,

iam/api-client/access_test.py

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,85 +13,101 @@
1313
# limitations under the License.
1414

1515
import os
16+
from typing import Iterator
1617
import uuid
1718

18-
from googleapiclient import errors
19+
from googleapiclient import errors # type: ignore
1920
import pytest
20-
from retrying import retry
21+
from retrying import retry # type: ignore
2122

2223
import access
2324
import service_accounts
2425

25-
2626
# Setting up variables for testing
2727
GCLOUD_PROJECT = os.environ["GOOGLE_CLOUD_PROJECT"]
2828

2929
# specifying a sample role to be assigned
3030
GCP_ROLE = "roles/owner"
3131

3232

33-
def retry_if_conflict(exception):
34-
return (isinstance(exception, errors.HttpError)
35-
and 'There were concurrent policy changes' in str(exception))
33+
def retry_if_conflict(exception: Exception) -> bool:
34+
return isinstance(
35+
exception, errors.HttpError
36+
) and "There were concurrent policy changes" in str(exception)
3637

3738

3839
@pytest.fixture(scope="module")
39-
def test_member():
40+
def test_member() -> Iterator[str]:
4041
# section to create service account to test policy updates.
4142
# we use the first portion of uuid4 because full version is too long.
42-
name = "python-test-" + str(uuid.uuid4()).split('-')[0]
43+
name = "python-test-" + str(uuid.uuid4()).split("-")[0]
4344
email = name + "@" + GCLOUD_PROJECT + ".iam.gserviceaccount.com"
4445
member = "serviceAccount:" + email
45-
service_accounts.create_service_account(
46-
GCLOUD_PROJECT, name, "Py Test Account"
47-
)
46+
service_accounts.create_service_account(GCLOUD_PROJECT, name, "Py Test Account")
4847

4948
yield member
5049

5150
# deleting the service account created above
5251
service_accounts.delete_service_account(email)
5352

5453

55-
def test_get_policy(capsys):
54+
def test_get_policy(capsys: pytest.LogCaptureFixture) -> None:
5655
access.get_policy(GCLOUD_PROJECT, version=3)
5756
out, _ = capsys.readouterr()
5857
assert "etag" in out
5958

6059

61-
def test_modify_policy_add_role(test_member, capsys):
62-
@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000,
63-
stop_max_attempt_number=5, retry_on_exception=retry_if_conflict)
64-
def test_call():
60+
def test_modify_policy_add_role(
61+
test_member: str, capsys: pytest.LogCaptureFixture
62+
) -> None:
63+
@retry(
64+
wait_exponential_multiplier=1000,
65+
wait_exponential_max=10000,
66+
stop_max_attempt_number=5,
67+
retry_on_exception=retry_if_conflict,
68+
)
69+
def test_call() -> None:
6570
policy = access.get_policy(GCLOUD_PROJECT, version=3)
6671
access.modify_policy_add_role(policy, GCLOUD_PROJECT, test_member)
6772
out, _ = capsys.readouterr()
6873
assert "etag" in out
74+
6975
test_call()
7076

7177

72-
def test_modify_policy_remove_member(test_member, capsys):
73-
@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000,
74-
stop_max_attempt_number=5, retry_on_exception=retry_if_conflict)
75-
def test_call():
78+
def test_modify_policy_remove_member(test_member: str, capsys: pytest.LogCaptureFixture) -> None:
79+
@retry(
80+
wait_exponential_multiplier=1000,
81+
wait_exponential_max=10000,
82+
stop_max_attempt_number=5,
83+
retry_on_exception=retry_if_conflict,
84+
)
85+
def test_call() -> None:
7686
policy = access.get_policy(GCLOUD_PROJECT, version=3)
7787
access.modify_policy_remove_member(policy, GCP_ROLE, test_member)
7888
out, _ = capsys.readouterr()
7989
assert "iam.gserviceaccount.com" in out
90+
8091
test_call()
8192

8293

83-
def test_set_policy(capsys):
84-
@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000,
85-
stop_max_attempt_number=5, retry_on_exception=retry_if_conflict)
86-
def test_call():
94+
def test_set_policy(capsys: pytest.LogCaptureFixture) -> None:
95+
@retry(
96+
wait_exponential_multiplier=1000,
97+
wait_exponential_max=10000,
98+
stop_max_attempt_number=5,
99+
retry_on_exception=retry_if_conflict,
100+
)
101+
def test_call() -> None:
87102
policy = access.get_policy(GCLOUD_PROJECT, version=3)
88103
access.set_policy(GCLOUD_PROJECT, policy)
89104
out, _ = capsys.readouterr()
90105
assert "etag" in out
106+
91107
test_call()
92108

93109

94-
def test_permissions(capsys):
110+
def test_permissions(capsys: pytest.LogCaptureFixture) -> None:
95111
access.test_permissions(GCLOUD_PROJECT)
96112
out, _ = capsys.readouterr()
97113
assert "permissions" in out

iam/api-client/custom_roles.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@
2424
import argparse
2525
import os
2626

27-
from google.oauth2 import service_account
28-
import googleapiclient.discovery
29-
27+
from google.oauth2 import service_account # type: ignore
28+
import googleapiclient.discovery # type: ignore
3029

3130
credentials = service_account.Credentials.from_service_account_file(
3231
filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
@@ -36,7 +35,7 @@
3635

3736

3837
# [START iam_query_testable_permissions]
39-
def query_testable_permissions(resource):
38+
def query_testable_permissions(resource: str) -> None:
4039
"""Lists valid permissions for a resource."""
4140

4241
# pylint: disable=no-member
@@ -49,7 +48,7 @@ def query_testable_permissions(resource):
4948

5049

5150
# [START iam_get_role]
52-
def get_role(name):
51+
def get_role(name: str) -> None:
5352
"""Gets a role."""
5453

5554
# pylint: disable=no-member
@@ -61,7 +60,7 @@ def get_role(name):
6160

6261

6362
# [START iam_create_role]
64-
def create_role(name, project, title, description, permissions, stage):
63+
def create_role(name: str, project: str, title: str, description: str, permissions: str, stage: str) -> dict:
6564
"""Creates a role."""
6665

6766
# pylint: disable=no-member
@@ -83,7 +82,7 @@ def create_role(name, project, title, description, permissions, stage):
8382

8483

8584
# [START iam_edit_role]
86-
def edit_role(name, project, title, description, permissions, stage):
85+
def edit_role(name: str, project: str, title: str, description: str, permissions: str, stage: str) -> dict:
8786
"""Creates a role."""
8887

8988
# pylint: disable=no-member
@@ -102,7 +101,7 @@ def edit_role(name, project, title, description, permissions, stage):
102101

103102

104103
# [START iam_list_roles]
105-
def list_roles(project_id):
104+
def list_roles(project_id: str) -> None:
106105
"""Lists roles."""
107106

108107
# pylint: disable=no-member
@@ -114,7 +113,7 @@ def list_roles(project_id):
114113

115114

116115
# [START iam_disable_role]
117-
def disable_role(name, project):
116+
def disable_role(name: str, project: str) -> dict:
118117
"""Disables a role."""
119118

120119
# pylint: disable=no-member
@@ -130,7 +129,7 @@ def disable_role(name, project):
130129

131130

132131
# [START iam_delete_role]
133-
def delete_role(name, project):
132+
def delete_role(name: str, project: str) -> dict:
134133
"""Deletes a role."""
135134

136135
# pylint: disable=no-member
@@ -143,7 +142,7 @@ def delete_role(name, project):
143142

144143

145144
# [START iam_undelete_role]
146-
def undelete_role(name, project):
145+
def undelete_role(name: str, project: str) -> dict:
147146
"""Undeletes a role."""
148147

149148
# pylint: disable=no-member
@@ -158,7 +157,7 @@ def undelete_role(name, project):
158157
# [END iam_undelete_role]
159158

160159

161-
def main():
160+
def main() -> None:
162161
parser = argparse.ArgumentParser(
163162
description=__doc__,
164163
formatter_class=argparse.RawDescriptionHelpFormatter)

iam/api-client/custom_roles_test.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
# limitations under the License.
1414

1515
import os
16+
from typing import Iterator
1617
import uuid
1718

1819
import pytest
1920

2021
import custom_roles
2122

22-
2323
GCLOUD_PROJECT = os.environ["GOOGLE_CLOUD_PROJECT"]
2424

2525

@@ -31,7 +31,7 @@
3131
# Since this fixture will throw an exception upon failing to create or delete
3232
# a custom role, there are no separatetests for those activities needed.
3333
@pytest.fixture(scope="module")
34-
def custom_role():
34+
def custom_role() -> Iterator[str]:
3535
role_name = "pythonTestCustomRole" + str(uuid.uuid4().hex)
3636
custom_roles.create_role(
3737
role_name,
@@ -47,7 +47,7 @@ def custom_role():
4747
custom_roles.delete_role(role_name, GCLOUD_PROJECT)
4848

4949

50-
def test_query_testable_permissions(capsys):
50+
def test_query_testable_permissions(capsys: pytest.CaptureFixture) -> None:
5151
custom_roles.query_testable_permissions(
5252
"//cloudresourcemanager.googleapis.com/projects/" + GCLOUD_PROJECT
5353
)
@@ -56,19 +56,19 @@ def test_query_testable_permissions(capsys):
5656
assert "\n" in out
5757

5858

59-
def test_list_roles(capsys):
59+
def test_list_roles(capsys: pytest.CaptureFixture) -> None:
6060
custom_roles.list_roles(GCLOUD_PROJECT)
6161
out, _ = capsys.readouterr()
6262
assert "roles/" in out
6363

6464

65-
def test_get_role(capsys):
65+
def test_get_role(capsys: pytest.CaptureFixture) -> None:
6666
custom_roles.get_role("roles/appengine.appViewer")
6767
out, _ = capsys.readouterr()
6868
assert "roles/" in out
6969

7070

71-
def test_edit_role(custom_role, capsys):
71+
def test_edit_role(custom_role: dict, capsys: pytest.CaptureFixture) -> None:
7272
custom_roles.edit_role(
7373
custom_role,
7474
GCLOUD_PROJECT,
@@ -81,7 +81,7 @@ def test_edit_role(custom_role, capsys):
8181
assert "Updated role:" in out
8282

8383

84-
def test_disable_role(custom_role, capsys):
84+
def test_disable_role(custom_role: dict, capsys: pytest.CaptureFixture) -> None:
8585
custom_roles.disable_role(custom_role, GCLOUD_PROJECT)
8686
out, _ = capsys.readouterr()
8787
assert "Disabled role:" in out

iam/api-client/grantable_roles.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import argparse
1818
import os
1919

20-
from google.oauth2 import service_account
21-
import googleapiclient.discovery
20+
from google.oauth2 import service_account # type: ignore
21+
import googleapiclient.discovery # type: ignore
2222

2323
credentials = service_account.Credentials.from_service_account_file(
2424
filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
@@ -28,7 +28,7 @@
2828

2929

3030
# [START iam_view_grantable_roles]
31-
def view_grantable_roles(full_resource_name):
31+
def view_grantable_roles(full_resource_name: str) -> None:
3232
roles = service.roles().queryGrantableRoles(body={
3333
'fullResourceName': full_resource_name
3434
}).execute()

iam/api-client/grantable_roles_test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
import os
1616

17+
import pytest
18+
1719
import grantable_roles
1820

1921

20-
def test_grantable_roles(capsys):
22+
def test_grantable_roles(capsys: pytest.CaptureFixture) -> None:
2123
project = os.environ['GOOGLE_CLOUD_PROJECT']
2224
resource = '//cloudresourcemanager.googleapis.com/projects/' + project
2325
grantable_roles.view_grantable_roles(resource)

0 commit comments

Comments
 (0)