From 510a37ac6d42119449b8c0d92f1eb9fc030fc6ee Mon Sep 17 00:00:00 2001 From: arithmetic1728 Date: Wed, 21 Oct 2020 11:42:11 -0700 Subject: [PATCH] chore: update kokoro --- .kokoro/docs/common.cfg | 2 +- .kokoro/samples/python3.6/common.cfg | 6 + .kokoro/samples/python3.7/common.cfg | 6 + .kokoro/samples/python3.8/common.cfg | 6 + .kokoro/test-samples.sh | 8 +- CONTRIBUTING.rst | 19 -- docs/conf.py | 1 + samples/snippets/noxfile.py | 31 +-- scripts/fixup_pubsub_v1_keywords.py | 278 +++++++-------------------- synth.metadata | 8 +- 10 files changed, 117 insertions(+), 248 deletions(-) diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg index 7815c2d6a..b81c7b901 100644 --- a/.kokoro/docs/common.cfg +++ b/.kokoro/docs/common.cfg @@ -30,7 +30,7 @@ env_vars: { env_vars: { key: "V2_STAGING_BUCKET" - value: "docs-staging-v2-staging" + value: "docs-staging-v2" } # It will upload the docker image after successful builds. diff --git a/.kokoro/samples/python3.6/common.cfg b/.kokoro/samples/python3.6/common.cfg index 354ad19ef..6b9890422 100644 --- a/.kokoro/samples/python3.6/common.cfg +++ b/.kokoro/samples/python3.6/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.6" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py36" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-pubsub/.kokoro/test-samples.sh" diff --git a/.kokoro/samples/python3.7/common.cfg b/.kokoro/samples/python3.7/common.cfg index becd0399d..e2cb0f168 100644 --- a/.kokoro/samples/python3.7/common.cfg +++ b/.kokoro/samples/python3.7/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.7" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py37" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-pubsub/.kokoro/test-samples.sh" diff --git a/.kokoro/samples/python3.8/common.cfg b/.kokoro/samples/python3.8/common.cfg index 685dfdc59..cb7a71d5c 100644 --- a/.kokoro/samples/python3.8/common.cfg +++ b/.kokoro/samples/python3.8/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.8" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py38" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-pubsub/.kokoro/test-samples.sh" diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 98851b56b..6064e7ad6 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -28,6 +28,12 @@ if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then git checkout $LATEST_RELEASE fi +# Exit early if samples directory doesn't exist +if [ ! -d "./samples" ]; then + echo "No tests run. `./samples` not found" + exit 0 +fi + # Disable buffering, so that the logs stream through. export PYTHONUNBUFFERED=1 @@ -101,4 +107,4 @@ cd "$ROOT" # Workaround for Kokoro permissions issue: delete secrets rm testing/{test-env.sh,client-secrets.json,service-account.json} -exit "$RTN" \ No newline at end of file +exit "$RTN" diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 7eb8028d5..d0bb3c5a5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -80,25 +80,6 @@ We use `nox `__ to instrument our tests. .. nox: https://pypi.org/project/nox/ -Note on Editable Installs / Develop Mode -======================================== - -- As mentioned previously, using ``setuptools`` in `develop mode`_ - or a ``pip`` `editable install`_ is not possible with this - library. This is because this library uses `namespace packages`_. - For context see `Issue #2316`_ and the relevant `PyPA issue`_. - - Since ``editable`` / ``develop`` mode can't be used, packages - need to be installed directly. Hence your changes to the source - tree don't get incorporated into the **already installed** - package. - -.. _namespace packages: https://www.python.org/dev/peps/pep-0420/ -.. _Issue #2316: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2316 -.. _PyPA issue: https://github.com/pypa/packaging-problems/issues/12 -.. _develop mode: https://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode -.. _editable install: https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs - ***************************************** I'm getting weird errors... Can you help? ***************************************** diff --git a/docs/conf.py b/docs/conf.py index a785da8a8..48cf73642 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -39,6 +39,7 @@ "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.coverage", + "sphinx.ext.doctest", "sphinx.ext.napoleon", "sphinx.ext.todo", "sphinx.ext.viewcode", diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 5660f08be..01686e4a0 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -37,22 +37,24 @@ TEST_CONFIG = { # You can opt out from the test for specific Python versions. - "ignored_versions": ["2.7"], + 'ignored_versions': ["2.7"], + # 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 # to use your own Cloud project. - "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + 'gcloud_project_env': 'GOOGLE_CLOUD_PROJECT', # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # A dictionary you want to inject into your test. Don't put any # secrets here. These values will override predefined values. - "envs": {}, + 'envs': {}, } try: # Ensure we can import noxfile_config in the project's directory. - sys.path.append(".") + sys.path.append('.') from noxfile_config import TEST_CONFIG_OVERRIDE except ImportError as e: print("No user noxfile_config found: detail: {}".format(e)) @@ -67,12 +69,12 @@ def get_pytest_env_vars(): ret = {} # Override the GCLOUD_PROJECT and the alias. - env_key = TEST_CONFIG["gcloud_project_env"] + env_key = TEST_CONFIG['gcloud_project_env'] # This should error out if not set. - ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] + ret['GOOGLE_CLOUD_PROJECT'] = os.environ[env_key] # Apply user supplied envs. - ret.update(TEST_CONFIG["envs"]) + ret.update(TEST_CONFIG['envs']) return ret @@ -81,7 +83,7 @@ def get_pytest_env_vars(): ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] # Any default versions that should be ignored. -IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] +IGNORED_VERSIONS = TEST_CONFIG['ignored_versions'] TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) @@ -136,7 +138,7 @@ def lint(session): args = FLAKE8_COMMON_ARGS + [ "--application-import-names", ",".join(local_names), - ".", + "." ] session.run("flake8", *args) @@ -180,9 +182,9 @@ def py(session): if session.python in TESTED_VERSIONS: _session_tests(session) else: - session.skip( - "SKIPPED: {} tests are disabled for this sample.".format(session.python) - ) + session.skip("SKIPPED: {} tests are disabled for this sample.".format( + session.python + )) # @@ -199,6 +201,11 @@ def _get_repo_root(): break if Path(p / ".git").exists(): return str(p) + # .git is not available in repos cloned via Cloud Build + # setup.py is always in the library's root, so use that instead + # https://github.com/googleapis/synthtool/issues/792 + if Path(p / "setup.py").exists(): + return str(p) p = p.parent raise Exception("Unable to detect repository root.") diff --git a/scripts/fixup_pubsub_v1_keywords.py b/scripts/fixup_pubsub_v1_keywords.py index 1c9ec6f8c..b54a7ad37 100644 --- a/scripts/fixup_pubsub_v1_keywords.py +++ b/scripts/fixup_pubsub_v1_keywords.py @@ -20,11 +20,12 @@ import libcst as cst import pathlib import sys -from typing import Any, Callable, Dict, List, Sequence, Tuple +from typing import (Any, Callable, Dict, List, Sequence, Tuple) def partition( - predicate: Callable[[Any], bool], iterator: Sequence[Any] + predicate: Callable[[Any], bool], + iterator: Sequence[Any] ) -> Tuple[List[Any], List[Any]]: """A stable, out-of-place partition.""" results = ([], []) @@ -37,127 +38,39 @@ def partition( class pubsubCallTransformer(cst.CSTTransformer): - CTRL_PARAMS: Tuple[str] = ("retry", "timeout", "metadata") + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - "acknowledge": ( - "subscription", - "ack_ids", - ), - "create_snapshot": ( - "name", - "subscription", - "labels", - ), - "create_subscription": ( - "name", - "topic", - "push_config", - "ack_deadline_seconds", - "retain_acked_messages", - "message_retention_duration", - "labels", - "enable_message_ordering", - "expiration_policy", - "filter", - "dead_letter_policy", - "retry_policy", - "detached", - ), - "create_topic": ( - "name", - "labels", - "message_storage_policy", - "kms_key_name", - ), - "delete_snapshot": ("snapshot",), - "delete_subscription": ("subscription",), - "delete_topic": ("topic",), - "detach_subscription": ("subscription",), - "get_snapshot": ("snapshot",), - "get_subscription": ("subscription",), - "get_topic": ("topic",), - "list_snapshots": ( - "project", - "page_size", - "page_token", - ), - "list_subscriptions": ( - "project", - "page_size", - "page_token", - ), - "list_topics": ( - "project", - "page_size", - "page_token", - ), - "list_topic_snapshots": ( - "topic", - "page_size", - "page_token", - ), - "list_topic_subscriptions": ( - "topic", - "page_size", - "page_token", - ), - "modify_ack_deadline": ( - "subscription", - "ack_ids", - "ack_deadline_seconds", - ), - "modify_push_config": ( - "subscription", - "push_config", - ), - "pull": ( - "subscription", - "max_messages", - "return_immediately", - ), - "seek": ( - "subscription", - "time", - "snapshot", - ), - "streaming_pull": ( - "subscription", - "stream_ack_deadline_seconds", - "ack_ids", - "modify_deadline_seconds", - "modify_deadline_ack_ids", - "client_id", - "max_outstanding_messages", - "max_outstanding_bytes", - ), - "update_snapshot": ( - "snapshot", - "update_mask", - ), - "update_subscription": ( - "subscription", - "update_mask", - ), - "update_topic": ( - "topic", - "update_mask", - ), - "get_iam_policy": ( - "resource", - "options", - ), - "set_iam_policy": ( - "resource", - "policy", - ), - "test_iam_permissions": ( - "resource", - "permissions", - ), - } + 'acknowledge': ('subscription', 'ack_ids', ), + 'create_snapshot': ('name', 'subscription', 'labels', ), + 'create_subscription': ('name', 'topic', 'push_config', 'ack_deadline_seconds', 'retain_acked_messages', 'message_retention_duration', 'labels', 'enable_message_ordering', 'expiration_policy', 'filter', 'dead_letter_policy', 'retry_policy', 'detached', ), + 'create_topic': ('name', 'labels', 'message_storage_policy', 'kms_key_name', ), + 'delete_snapshot': ('snapshot', ), + 'delete_subscription': ('subscription', ), + 'delete_topic': ('topic', ), + 'detach_subscription': ('subscription', ), + 'get_snapshot': ('snapshot', ), + 'get_subscription': ('subscription', ), + 'get_topic': ('topic', ), + 'list_snapshots': ('project', 'page_size', 'page_token', ), + 'list_subscriptions': ('project', 'page_size', 'page_token', ), + 'list_topics': ('project', 'page_size', 'page_token', ), + 'list_topic_snapshots': ('topic', 'page_size', 'page_token', ), + 'list_topic_subscriptions': ('topic', 'page_size', 'page_token', ), + 'modify_ack_deadline': ('subscription', 'ack_ids', 'ack_deadline_seconds', ), + 'modify_push_config': ('subscription', 'push_config', ), + 'publish': ('topic', 'messages', ), + 'pull': ('subscription', 'max_messages', 'return_immediately', ), + 'seek': ('subscription', 'time', 'snapshot', ), + 'streaming_pull': ('subscription', 'stream_ack_deadline_seconds', 'ack_ids', 'modify_deadline_seconds', 'modify_deadline_ack_ids', 'client_id', 'max_outstanding_messages', 'max_outstanding_bytes', ), + 'update_snapshot': ('snapshot', 'update_mask', ), + 'update_subscription': ('subscription', 'update_mask', ), + 'update_topic': ('topic', 'update_mask', ), + + 'get_iam_policy': ('resource', 'options', ), + 'set_iam_policy': ('resource', 'policy', ), + 'test_iam_permissions': ('resource', 'permissions', ), - def __init__(self, use_keywords=False): - self._use_keywords = use_keywords + } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: try: @@ -175,80 +88,35 @@ def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: return updated kwargs, ctrl_kwargs = partition( - lambda a: not a.keyword.value in self.CTRL_PARAMS, kwargs + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs ) - args, ctrl_args = args[: len(kword_params)], args[len(kword_params) :] - ctrl_kwargs.extend( - cst.Arg( - value=a.value, - keyword=cst.Name(value=ctrl), - equal=cst.AssignEqual( - whitespace_before=cst.SimpleWhitespace(""), - whitespace_after=cst.SimpleWhitespace(""), - ), - ) - for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS) - ) + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) - if self._use_keywords: - new_kwargs = [ - cst.Arg( - value=arg.value, - keyword=cst.Name(value=name), - equal=cst.AssignEqual( - whitespace_before=cst.SimpleWhitespace(""), - whitespace_after=cst.SimpleWhitespace(""), - ), + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), + cst.Element(value=arg.value) ) - for name, arg in zip(kword_params, args + kwargs) - ] - new_kwargs.extend( - [ - cst.Arg( - value=arg.value, - keyword=cst.Name(value=arg.keyword.value), - equal=cst.AssignEqual( - whitespace_before=cst.SimpleWhitespace(""), - whitespace_after=cst.SimpleWhitespace(""), - ), - ) - for arg in ctrl_kwargs - ] - ) - return updated.with_changes(args=new_kwargs) - else: - request_arg = cst.Arg( - value=cst.Dict( - [ - cst.DictElement( - cst.SimpleString('"{}"'.format(name)), - cst.Element(value=arg.value), - ) - for name, arg in zip(kword_params, args + kwargs) - ] - + [ - cst.DictElement( - cst.SimpleString('"{}"'.format(arg.keyword.value)), - cst.Element(value=arg.value), - ) - for arg in ctrl_kwargs - ] - ), - keyword=cst.Name("request"), - equal=cst.AssignEqual( - whitespace_before=cst.SimpleWhitespace(""), - whitespace_after=cst.SimpleWhitespace(""), - ), - ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) - return updated.with_changes(args=[request_arg]) + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) def fix_files( in_dir: pathlib.Path, out_dir: pathlib.Path, - use_keywords: bool = False, *, transformer=pubsubCallTransformer(), ): @@ -261,12 +129,11 @@ def fix_files( pyfile_gen = ( pathlib.Path(os.path.join(root, f)) for root, _, files in os.walk(in_dir) - for f in files - if os.path.splitext(f)[1] == ".py" + for f in files if os.path.splitext(f)[1] == ".py" ) for fpath in pyfile_gen: - with open(fpath, "r") as f: + with open(fpath, 'r') as f: src = f.read() # Parse the code and insert method call fixes. @@ -278,11 +145,11 @@ def fix_files( updated_path.parent.mkdir(parents=True, exist_ok=True) # Generate the updated source file at the corresponding path. - with open(updated_path, "w") as f: + with open(updated_path, 'w') as f: f.write(updated.code) -if __name__ == "__main__": +if __name__ == '__main__': parser = argparse.ArgumentParser( description="""Fix up source that uses the pubsub client library. @@ -297,34 +164,24 @@ def fix_files( These all constitute false negatives. The tool will also detect false positives when an API method shares a name with another method. -""" - ) +""") parser.add_argument( - "-d", - "--input-directory", + '-d', + '--input-directory', required=True, - dest="input_dir", - help="the input directory to walk for python files to fix up", + dest='input_dir', + help='the input directory to walk for python files to fix up', ) parser.add_argument( - "-o", - "--output-directory", + '-o', + '--output-directory', required=True, - dest="output_dir", - help="the directory to output files fixed via un-flattening", - ) - parser.add_argument( - "-k", - "--use-keywords", - required=False, - action="store_true", - dest="use_keywords", - help="Use keyword arguments instead of constructing a request", + dest='output_dir', + help='the directory to output files fixed via un-flattening', ) args = parser.parse_args() input_dir = pathlib.Path(args.input_dir) output_dir = pathlib.Path(args.output_dir) - use_keywords = args.use_keywords if not input_dir.is_dir(): print( f"input directory '{input_dir}' does not exist or is not a directory", @@ -346,5 +203,4 @@ def fix_files( ) sys.exit(-1) - transformer = pubsubCallTransformer(use_keywords=use_keywords) - fix_files(input_dir, output_dir, use_keywords, transformer=transformer) + fix_files(input_dir, output_dir) diff --git a/synth.metadata b/synth.metadata index 148d44682..4f96e4800 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,28 +4,28 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-pubsub.git", - "sha": "c957047c84c5586e4a782e9ae297094be6cdba2e" + "sha": "d45bfbf169339501ac16261f62ea97f294bfae60" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + "sha": "901ddd44e9ef7887ee681b9183bbdea99437fdcc" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + "sha": "901ddd44e9ef7887ee681b9183bbdea99437fdcc" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + "sha": "901ddd44e9ef7887ee681b9183bbdea99437fdcc" } } ],