From dc8dba8afeb527f8118d9aca11ad27a5493f1966 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Tue, 25 Jun 2019 13:19:02 -0700 Subject: [PATCH] Add docstrings --- examples/python/cancellation/client.py | 2 - examples/python/cancellation/server.py | 61 +++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/examples/python/cancellation/client.py b/examples/python/cancellation/client.py index 288f93d057e..c3bc226be2c 100644 --- a/examples/python/cancellation/client.py +++ b/examples/python/cancellation/client.py @@ -42,8 +42,6 @@ _LOGGER = logging.getLogger(__name__) _TIMEOUT_SECONDS = 0.05 -# TODO(rbellevi): Actually use the logger. - def run_unary_client(server_target, name, ideal_distance): with grpc.insecure_channel(server_target) as channel: diff --git a/examples/python/cancellation/server.py b/examples/python/cancellation/server.py index 1af07e4a1e4..44b8ee26139 100644 --- a/examples/python/cancellation/server.py +++ b/examples/python/cancellation/server.py @@ -21,6 +21,7 @@ from concurrent import futures from collections import deque import argparse import base64 +import contextlib import logging import hashlib import struct @@ -82,7 +83,6 @@ class ResourceLimitExceededError(Exception): """Signifies the request has exceeded configured limits.""" -# TODO(rbellevi): Docstring all the things. # TODO(rbellevi): File issue about indefinite blocking for server-side # streaming. @@ -93,6 +93,28 @@ def _find_secret_of_length(target, stop_event, maximum_hashes, interesting_hamming_distance=None): + """Find a candidate with the given length. + + Args: + target: The search string. + ideal_distance: The desired Hamming distance. + length: The length of secret string to search for. + stop_event: An event indicating whether the RPC should terminate. + maximum_hashes: The maximum number of hashes to check before stopping. + interesting_hamming_distance: If specified, strings with a Hamming + distance from the target below this value will be yielded. + + Yields: + A stream of tuples of type Tuple[Optional[HashNameResponse], int]. The + element of the tuple, if specified, signifies an ideal or interesting + candidate. If this element is None, it signifies that the stream has + ended because an ideal candidate has been found. The second element is + the number of hashes computed up this point. + + Raises: + ResourceLimitExceededError: If the computation exceeds `maximum_hashes` + iterations. + """ digits = [0] * length hashes_computed = 0 while True: @@ -140,6 +162,29 @@ def _find_secret(target, stop_event, maximum_hashes, interesting_hamming_distance=None): + """Find candidate strings. + + Search through the space of all bytestrings, in order of increasing length, + indefinitely, until a hash with a Hamming distance of `maximum_distance` or + less has been found. + + Args: + target: The search string. + maximum_distance: The desired Hamming distance. + stop_event: An event indicating whether the RPC should terminate. + maximum_hashes: The maximum number of hashes to check before stopping. + interesting_hamming_distance: If specified, strings with a Hamming + distance from the target below this value will be yielded. + + Yields: + Instances of HashNameResponse. The final entry in the stream will be of + `maximum_distance` Hamming distance or less from the target string, + while all others will be of less than `interesting_hamming_distance`. + + Raises: + ResourceLimitExceededError: If the computation exceeds `maximum_hashes` + iterations. + """ length = 1 total_hashes = 0 while True: @@ -213,19 +258,21 @@ class HashFinder(hash_name_pb2_grpc.HashFinderServicer): _LOGGER.debug("Regained servicer thread.") -def _run_server(port, maximum_hashes): +@contextlib.contextmanager +def _running_server(port, maximum_hashes): server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=1) hash_name_pb2_grpc.add_HashFinderServicer_to_server( HashFinder(maximum_hashes), server) address = '{}:{}'.format(_SERVER_HOST, port) - server.add_insecure_port(address) + actual_port = server.add_insecure_port(address) server.start() print("Server listening at '{}'".format(address)) try: - while True: - time.sleep(_ONE_DAY_IN_SECONDS) + yield actual_port except KeyboardInterrupt: + pass + finally: server.stop(None) @@ -244,7 +291,9 @@ def main(): nargs='?', help='The maximum number of hashes to search before cancelling.') args = parser.parse_args() - _run_server(args.port, args.maximum_hashes) + with _running_server(args.port, args.maximum_hashes): + while True: + time.sleep(_ONE_DAY_IN_SECONDS) if __name__ == "__main__":