Skip to content

Commit

Permalink
samples: add type hints to all samples (#476)
Browse files Browse the repository at this point in the history
Closes #264.

And here they are, annotated samples.

We should follow up with a `pytype` CI check, I'll open a separate issue for that.

**PR checklist:**
- [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/python-pubsub/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
- [x] Ensure the tests and linter pass
- [x] Code coverage does not decrease (if any source code was changed)
- [x] Appropriate docs were updated (if necessary)
  • Loading branch information
plamut authored Aug 25, 2021
1 parent 4726a8f commit 1164890
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 176 deletions.
12 changes: 6 additions & 6 deletions samples/snippets/iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import argparse


def get_topic_policy(project_id, topic_id):
def get_topic_policy(project_id: str, topic_id: str) -> None:
"""Prints the IAM policy for the given topic."""
# [START pubsub_get_topic_policy]
from google.cloud import pubsub_v1
Expand All @@ -44,7 +44,7 @@ def get_topic_policy(project_id, topic_id):
# [END pubsub_get_topic_policy]


def get_subscription_policy(project_id, subscription_id):
def get_subscription_policy(project_id: str, subscription_id: str) -> None:
"""Prints the IAM policy for the given subscription."""
# [START pubsub_get_subscription_policy]
from google.cloud import pubsub_v1
Expand All @@ -66,7 +66,7 @@ def get_subscription_policy(project_id, subscription_id):
# [END pubsub_get_subscription_policy]


def set_topic_policy(project_id, topic_id):
def set_topic_policy(project_id: str, topic_id: str) -> None:
"""Sets the IAM policy for a topic."""
# [START pubsub_set_topic_policy]
from google.cloud import pubsub_v1
Expand Down Expand Up @@ -95,7 +95,7 @@ def set_topic_policy(project_id, topic_id):
# [END pubsub_set_topic_policy]


def set_subscription_policy(project_id, subscription_id):
def set_subscription_policy(project_id: str, subscription_id: str) -> None:
"""Sets the IAM policy for a topic."""
# [START pubsub_set_subscription_policy]
from google.cloud import pubsub_v1
Expand Down Expand Up @@ -126,7 +126,7 @@ def set_subscription_policy(project_id, subscription_id):
# [END pubsub_set_subscription_policy]


def check_topic_permissions(project_id, topic_id):
def check_topic_permissions(project_id: str, topic_id: str) -> None:
"""Checks to which permissions are available on the given topic."""
# [START pubsub_test_topic_permissions]
from google.cloud import pubsub_v1
Expand All @@ -150,7 +150,7 @@ def check_topic_permissions(project_id, topic_id):
# [END pubsub_test_topic_permissions]


def check_subscription_permissions(project_id, subscription_id):
def check_subscription_permissions(project_id: str, subscription_id: str) -> None:
"""Checks to which permissions are available on the given subscription."""
# [START pubsub_test_subscription_permissions]
from google.cloud import pubsub_v1
Expand Down
34 changes: 24 additions & 10 deletions samples/snippets/iam_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
# limitations under the License.

import os
from typing import Generator
import uuid

from _pytest.capture import CaptureFixture
from google.api_core.exceptions import NotFound
from google.cloud import pubsub_v1
import pytest
Expand All @@ -28,12 +30,14 @@


@pytest.fixture(scope="module")
def publisher_client():
def publisher_client() -> Generator[pubsub_v1.PublisherClient, None, None]:
yield pubsub_v1.PublisherClient()


@pytest.fixture(scope="module")
def topic_path(publisher_client):
def topic_path(
publisher_client: pubsub_v1.PublisherClient,
) -> Generator[str, None, None]:
topic_path = publisher_client.topic_path(PROJECT_ID, TOPIC_ID)

try:
Expand All @@ -50,14 +54,16 @@ def topic_path(publisher_client):


@pytest.fixture(scope="module")
def subscriber_client():
def subscriber_client() -> Generator[pubsub_v1.SubscriberClient, None, None]:
subscriber_client = pubsub_v1.SubscriberClient()
yield subscriber_client
subscriber_client.close()


@pytest.fixture(scope="module")
def subscription_path(subscriber_client, topic_path):
def subscription_path(
subscriber_client: pubsub_v1.SubscriberClient, topic_path: str,
) -> Generator[str, None, None]:
subscription_path = subscriber_client.subscription_path(PROJECT_ID, SUBSCRIPTION_ID)
subscription = subscriber_client.create_subscription(
request={"name": subscription_path, "topic": topic_path}
Expand All @@ -72,40 +78,48 @@ def subscription_path(subscriber_client, topic_path):
pass


def test_get_topic_policy(topic_path, capsys):
def test_get_topic_policy(topic_path: str, capsys: CaptureFixture) -> None:
iam.get_topic_policy(PROJECT_ID, TOPIC_ID)
out, _ = capsys.readouterr()
assert topic_path in out


def test_get_subscription_policy(subscription_path, capsys):
def test_get_subscription_policy(
subscription_path: str, capsys: CaptureFixture
) -> None:
iam.get_subscription_policy(PROJECT_ID, SUBSCRIPTION_ID)
out, _ = capsys.readouterr()
assert subscription_path in out


def test_set_topic_policy(publisher_client, topic_path):
def test_set_topic_policy(
publisher_client: pubsub_v1.PublisherClient, topic_path: str,
) -> CaptureFixture:
iam.set_topic_policy(PROJECT_ID, TOPIC_ID)
policy = publisher_client.get_iam_policy(request={"resource": topic_path})
assert "roles/pubsub.publisher" in str(policy)
assert "allUsers" in str(policy)


def test_set_subscription_policy(subscriber_client, subscription_path):
def test_set_subscription_policy(
subscriber_client: pubsub_v1.SubscriberClient, subscription_path: str,
) -> None:
iam.set_subscription_policy(PROJECT_ID, SUBSCRIPTION_ID)
policy = subscriber_client.get_iam_policy(request={"resource": subscription_path})
assert "roles/pubsub.viewer" in str(policy)
assert "allUsers" in str(policy)


def test_check_topic_permissions(topic_path, capsys):
def test_check_topic_permissions(topic_path: str, capsys: CaptureFixture) -> None:
iam.check_topic_permissions(PROJECT_ID, TOPIC_ID)
out, _ = capsys.readouterr()
assert topic_path in out
assert "pubsub.topics.publish" in out


def test_check_subscription_permissions(subscription_path, capsys):
def test_check_subscription_permissions(
subscription_path: str, capsys: CaptureFixture,
) -> None:
iam.check_subscription_permissions(PROJECT_ID, SUBSCRIPTION_ID)
out, _ = capsys.readouterr()
assert subscription_path in out
Expand Down
2 changes: 1 addition & 1 deletion samples/snippets/noxfile_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"ignored_versions": ["2.7"],
# Old samples are opted out of enforcing Python type hints
# All new samples should feature them
"enforce_type_hints": False,
"enforce_type_hints": True,
# An envvar key for determining the project id to use. Change it
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
# build specific Cloud project. You can also use your own string
Expand Down
47 changes: 23 additions & 24 deletions samples/snippets/publisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
"""

import argparse
from typing import Callable


def list_topics(project_id):
def list_topics(project_id: str) -> None:
"""Lists all Pub/Sub topics in the given project."""
# [START pubsub_list_topics]
from google.cloud import pubsub_v1
Expand All @@ -40,7 +41,7 @@ def list_topics(project_id):
# [END pubsub_list_topics]


def create_topic(project_id, topic_id):
def create_topic(project_id: str, topic_id: str) -> None:
"""Create a new Pub/Sub topic."""
# [START pubsub_quickstart_create_topic]
# [START pubsub_create_topic]
Expand All @@ -60,7 +61,7 @@ def create_topic(project_id, topic_id):
# [END pubsub_create_topic]


def delete_topic(project_id, topic_id):
def delete_topic(project_id: str, topic_id: str) -> None:
"""Deletes an existing Pub/Sub topic."""
# [START pubsub_delete_topic]
from google.cloud import pubsub_v1
Expand All @@ -78,7 +79,7 @@ def delete_topic(project_id, topic_id):
# [END pubsub_delete_topic]


def publish_messages(project_id, topic_id):
def publish_messages(project_id: str, topic_id: str) -> None:
"""Publishes multiple messages to a Pub/Sub topic."""
# [START pubsub_quickstart_publisher]
# [START pubsub_publish]
Expand Down Expand Up @@ -106,7 +107,7 @@ def publish_messages(project_id, topic_id):
# [END pubsub_publish]


def publish_messages_with_custom_attributes(project_id, topic_id):
def publish_messages_with_custom_attributes(project_id: str, topic_id: str) -> None:
"""Publishes multiple messages with custom attributes
to a Pub/Sub topic."""
# [START pubsub_publish_custom_attributes]
Expand All @@ -133,7 +134,7 @@ def publish_messages_with_custom_attributes(project_id, topic_id):
# [END pubsub_publish_custom_attributes]


def publish_messages_with_error_handler(project_id, topic_id):
def publish_messages_with_error_handler(project_id: str, topic_id: str) -> None:
# [START pubsub_publish_with_error_handler]
"""Publishes multiple messages to a Pub/Sub topic with an error handler."""
from concurrent import futures
Expand All @@ -147,8 +148,10 @@ def publish_messages_with_error_handler(project_id, topic_id):
topic_path = publisher.topic_path(project_id, topic_id)
publish_futures = []

def get_callback(publish_future, data):
def callback(publish_future):
def get_callback(
publish_future: pubsub_v1.publisher.futures.Future, data: str
) -> Callable[[pubsub_v1.publisher.futures.Future], None]:
def callback(publish_future: pubsub_v1.publisher.futures.Future) -> None:
try:
# Wait 60 seconds for the publish call to succeed.
print(publish_future.result(timeout=60))
Expand All @@ -172,7 +175,7 @@ def callback(publish_future):
# [END pubsub_publish_with_error_handler]


def publish_messages_with_batch_settings(project_id, topic_id):
def publish_messages_with_batch_settings(project_id: str, topic_id: str) -> None:
"""Publishes multiple messages to a Pub/Sub topic with batch settings."""
# [START pubsub_publisher_batch_settings]
from concurrent import futures
Expand All @@ -194,7 +197,7 @@ def publish_messages_with_batch_settings(project_id, topic_id):
publish_futures = []

# Resolve the publish future in a separate thread.
def callback(future):
def callback(future: pubsub_v1.publisher.futures.Future) -> None:
message_id = future.result()
print(message_id)

Expand All @@ -213,7 +216,7 @@ def callback(future):
# [END pubsub_publisher_batch_settings]


def publish_messages_with_flow_control_settings(project_id, topic_id):
def publish_messages_with_flow_control_settings(project_id: str, topic_id: str) -> None:
"""Publishes messages to a Pub/Sub topic with flow control settings."""
# [START pubsub_publisher_flow_control]
from concurrent import futures
Expand Down Expand Up @@ -242,7 +245,7 @@ def publish_messages_with_flow_control_settings(project_id, topic_id):
publish_futures = []

# Resolve the publish future in a separate thread.
def callback(publish_future):
def callback(publish_future: pubsub_v1.publisher.futures.Future) -> None:
message_id = publish_future.result()
print(message_id)

Expand All @@ -263,7 +266,7 @@ def callback(publish_future):
# [END pubsub_publisher_flow_control]


def publish_messages_with_retry_settings(project_id, topic_id):
def publish_messages_with_retry_settings(project_id: str, topic_id: str) -> None:
"""Publishes messages with custom retry settings."""
# [START pubsub_publisher_retry_settings]
from google import api_core
Expand Down Expand Up @@ -305,7 +308,7 @@ def publish_messages_with_retry_settings(project_id, topic_id):
# [END pubsub_publisher_retry_settings]


def publish_with_ordering_keys(project_id, topic_id):
def publish_with_ordering_keys(project_id: str, topic_id: str) -> None:
"""Publishes messages with ordering keys."""
# [START pubsub_publish_with_ordering_keys]
from google.cloud import pubsub_v1
Expand Down Expand Up @@ -342,7 +345,7 @@ def publish_with_ordering_keys(project_id, topic_id):
# [END pubsub_publish_with_ordering_keys]


def resume_publish_with_ordering_keys(project_id, topic_id):
def resume_publish_with_ordering_keys(project_id: str, topic_id: str) -> None:
"""Resume publishing messages with ordering keys when unrecoverable errors occur."""
# [START pubsub_resume_publish_with_ordering_keys]
from google.cloud import pubsub_v1
Expand Down Expand Up @@ -383,7 +386,7 @@ def resume_publish_with_ordering_keys(project_id, topic_id):
# [END pubsub_resume_publish_with_ordering_keys]


def detach_subscription(project_id, subscription_id):
def detach_subscription(project_id: str, subscription_id: str) -> None:
"""Detaches a subscription from a topic and drops all messages retained in it."""
# [START pubsub_detach_subscription]
from google.api_core.exceptions import GoogleAPICallError, RetryError
Expand Down Expand Up @@ -416,8 +419,7 @@ def detach_subscription(project_id, subscription_id):

if __name__ == "__main__":
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("project_id", help="Your Google Cloud project ID")

Expand All @@ -440,8 +442,7 @@ def detach_subscription(project_id, subscription_id):
publish_with_custom_attributes_parser.add_argument("topic_id")

publish_with_error_handler_parser = subparsers.add_parser(
"publish-with-error-handler",
help=publish_messages_with_error_handler.__doc__,
"publish-with-error-handler", help=publish_messages_with_error_handler.__doc__,
)
publish_with_error_handler_parser.add_argument("topic_id")

Expand All @@ -464,8 +465,7 @@ def detach_subscription(project_id, subscription_id):
publish_with_retry_settings_parser.add_argument("topic_id")

publish_with_ordering_keys_parser = subparsers.add_parser(
"publish-with-ordering-keys",
help=publish_with_ordering_keys.__doc__,
"publish-with-ordering-keys", help=publish_with_ordering_keys.__doc__,
)
publish_with_ordering_keys_parser.add_argument("topic_id")

Expand All @@ -476,8 +476,7 @@ def detach_subscription(project_id, subscription_id):
resume_publish_with_ordering_keys_parser.add_argument("topic_id")

detach_subscription_parser = subparsers.add_parser(
"detach-subscription",
help=detach_subscription.__doc__,
"detach-subscription", help=detach_subscription.__doc__,
)
detach_subscription_parser.add_argument("subscription_id")

Expand Down
Loading

0 comments on commit 1164890

Please sign in to comment.