diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index bc893c9..0eb02fd 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,5 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:8a5d3f6a2e43ed8293f34e06a2f56931d1e88a2694c3bb11b15df4eb256ad163 -# created: 2022-04-06T10:30:21.687684602Z + digest: sha256:9db98b055a7f8bd82351238ccaacfd3cda58cdf73012ab58b8da146368330021 +# created: 2022-07-25T16:02:49.174178716Z diff --git a/.github/auto-approve.yml b/.github/auto-approve.yml new file mode 100644 index 0000000..311ebbb --- /dev/null +++ b/.github/auto-approve.yml @@ -0,0 +1,3 @@ +# https://github.com/googleapis/repo-automation-bots/tree/main/packages/auto-approve +processes: + - "OwlBotTemplateChanges" diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index e5be6ed..5531b01 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: ['3.6', '3.7', '3.8', '3.9', '3.10'] + python: ['3.7', '3.8', '3.9', '3.10'] steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.kokoro/continuous/prerelease-deps.cfg b/.kokoro/continuous/prerelease-deps.cfg new file mode 100644 index 0000000..3595fb4 --- /dev/null +++ b/.kokoro/continuous/prerelease-deps.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Only run this nox session. +env_vars: { + key: "NOX_SESSION" + value: "prerelease_deps" +} diff --git a/.kokoro/docker/docs/Dockerfile b/.kokoro/docker/docs/Dockerfile index 4e1b1fb..238b87b 100644 --- a/.kokoro/docker/docs/Dockerfile +++ b/.kokoro/docker/docs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from ubuntu:20.04 +from ubuntu:22.04 ENV DEBIAN_FRONTEND noninteractive @@ -60,8 +60,24 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* \ && rm -f /var/cache/apt/archives/*.deb +###################### Install python 3.8.11 + +# Download python 3.8.11 +RUN wget https://www.python.org/ftp/python/3.8.11/Python-3.8.11.tgz + +# Extract files +RUN tar -xvf Python-3.8.11.tgz + +# Install python 3.8.11 +RUN ./Python-3.8.11/configure --enable-optimizations +RUN make altinstall + +###################### Install pip RUN wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \ - && python3.8 /tmp/get-pip.py \ + && python3 /tmp/get-pip.py \ && rm /tmp/get-pip.py +# Test pip +RUN python3 -m pip + CMD ["python3.8"] diff --git a/.kokoro/presubmit/prerelease-deps.cfg b/.kokoro/presubmit/prerelease-deps.cfg new file mode 100644 index 0000000..3595fb4 --- /dev/null +++ b/.kokoro/presubmit/prerelease-deps.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Only run this nox session. +env_vars: { + key: "NOX_SESSION" + value: "prerelease_deps" +} diff --git a/.kokoro/samples/python3.6/common.cfg b/.kokoro/samples/python3.6/common.cfg deleted file mode 100644 index d3407ac..0000000 --- a/.kokoro/samples/python3.6/common.cfg +++ /dev/null @@ -1,40 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Specify which tests to run -env_vars: { - key: "RUN_TESTS_SESSION" - 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-run/.kokoro/test-samples.sh" -} - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" -} - -# Download secrets for samples -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "python-run/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.6/continuous.cfg b/.kokoro/samples/python3.6/continuous.cfg deleted file mode 100644 index 7218af1..0000000 --- a/.kokoro/samples/python3.6/continuous.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} - diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg deleted file mode 100644 index 0768744..0000000 --- a/.kokoro/samples/python3.6/periodic-head.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-run/.kokoro/test-samples-against-head.sh" -} diff --git a/.kokoro/samples/python3.6/periodic.cfg b/.kokoro/samples/python3.6/periodic.cfg deleted file mode 100644 index 71cd1e5..0000000 --- a/.kokoro/samples/python3.6/periodic.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "False" -} diff --git a/.kokoro/samples/python3.6/presubmit.cfg b/.kokoro/samples/python3.6/presubmit.cfg deleted file mode 100644 index a1c8d97..0000000 --- a/.kokoro/samples/python3.6/presubmit.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} \ No newline at end of file diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh index 8a324c9..2c6500c 100755 --- a/.kokoro/test-samples-impl.sh +++ b/.kokoro/test-samples-impl.sh @@ -33,7 +33,7 @@ export PYTHONUNBUFFERED=1 env | grep KOKORO # Install nox -python3.6 -m pip install --upgrade --quiet nox +python3.9 -m pip install --upgrade --quiet nox # Use secrets acessor service account to get secrets if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then @@ -76,7 +76,7 @@ for file in samples/**/requirements.txt; do echo "------------------------------------------------------------" # Use nox to execute the tests for the project. - python3.6 -m nox -s "$RUN_TESTS_SESSION" + python3.9 -m nox -s "$RUN_TESTS_SESSION" EXIT=$? # If this is a periodic build, send the test log to the FlakyBot. diff --git a/.repo-metadata.json b/.repo-metadata.json index 30ce3fc..a44b13d 100644 --- a/.repo-metadata.json +++ b/.repo-metadata.json @@ -12,5 +12,6 @@ "api_id": "run.googleapis.com", "default_version": "v2", "codeowner_team": "@googleapis/aap-dpes", - "api_shortname": "run" -} \ No newline at end of file + "api_shortname": "run", + "api_description": "is a managed compute platform that enables you to run containers that are invocable via requests or events." +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc8035..852fae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.1](https://github.com/googleapis/python-run/compare/v0.2.0...v0.2.1) (2022-07-26) + + +### Bug Fixes + +* require python 3.7+ ([#26](https://github.com/googleapis/python-run/issues/26)) ([854f73d](https://github.com/googleapis/python-run/commit/854f73db0893e080dc6098d134809692e8685f39)) + ## [0.2.0](https://github.com/googleapis/python-run/compare/v0.1.0...v0.2.0) (2022-04-14) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8c49d3d..f7895cd 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -22,7 +22,7 @@ In order to add a feature: documentation. - The feature must work fully on the following CPython versions: - 3.6, 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows. + 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -221,13 +221,11 @@ Supported Python Versions We support: -- `Python 3.6`_ - `Python 3.7`_ - `Python 3.8`_ - `Python 3.9`_ - `Python 3.10`_ -.. _Python 3.6: https://docs.python.org/3.6/ .. _Python 3.7: https://docs.python.org/3.7/ .. _Python 3.8: https://docs.python.org/3.8/ .. _Python 3.9: https://docs.python.org/3.9/ @@ -239,7 +237,7 @@ Supported versions can be found in our ``noxfile.py`` `config`_. .. _config: https://github.com/googleapis/python-run/blob/main/noxfile.py -We also explicitly decided to support Python 3 beginning with version 3.6. +We also explicitly decided to support Python 3 beginning with version 3.7. Reasons for this include: - Encouraging use of newest versions of Python 3 diff --git a/README.rst b/README.rst index 2529902..0b8b573 100644 --- a/README.rst +++ b/README.rst @@ -3,18 +3,18 @@ Python Client for Cloud Run API |preview| |pypi| |versions| -`Cloud Run API`_: +`Cloud Run API`_: is a managed compute platform that enables you to run containers that are invocable via requests or events. - `Client Library Documentation`_ - `Product Documentation`_ .. |preview| image:: https://img.shields.io/badge/support-preview-orange.svg - :target: https://github.com/googleapis/google-cloud-python/blob/main/README.rst#beta-support + :target: https://github.com/googleapis/google-cloud-python/blob/main/README.rst#stability-levels .. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-run.svg :target: https://pypi.org/project/google-cloud-run/ .. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-run.svg :target: https://pypi.org/project/google-cloud-run/ -.. _Cloud Run API: https://cloud.google.com/run +.. _Cloud Run API: https://cloud.google.com/run/docs .. _Client Library Documentation: https://cloud.google.com/python/docs/reference/run/latest .. _Product Documentation: https://cloud.google.com/run/docs @@ -47,10 +47,30 @@ dependencies. .. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ +Code samples and snippets +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Code samples and snippets live in the `samples/` folder. + + Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.6 +Our client libraries are compatible with all current `active`_ and `maintenance`_ versions of +Python. + +Python >= 3.7 + +.. _active: https://devguide.python.org/devcycle/#in-development-main-branch +.. _maintenance: https://devguide.python.org/devcycle/#maintenance-branches + +Unsupported Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Python <= 3.6 + +If you are using an `end-of-life`_ +version of Python, we recommend that you update as soon as possible to an actively supported version. +.. _end-of-life: https://devguide.python.org/devcycle/#end-of-life-branches Mac/Linux ^^^^^^^^^ @@ -77,11 +97,11 @@ Next Steps ~~~~~~~~~~ - Read the `Client Library Documentation`_ for Cloud Run API - API to see other available methods on the client. + to see other available methods on the client. - Read the `Cloud Run API Product documentation`_ to learn more about the product and see How-to Guides. - View this `README`_ to see the full list of Cloud APIs that we cover. .. _Cloud Run API Product documentation: https://cloud.google.com/run/docs -.. _README: https://github.com/googleapis/google-cloud-python/blob/main/README.rst \ No newline at end of file +.. _README: https://github.com/googleapis/google-cloud-python/blob/main/README.rst diff --git a/google/cloud/run_v2/services/revisions/async_client.py b/google/cloud/run_v2/services/revisions/async_client.py index 1f4e6cc..480fcb0 100644 --- a/google/cloud/run_v2/services/revisions/async_client.py +++ b/google/cloud/run_v2/services/revisions/async_client.py @@ -229,9 +229,9 @@ async def get_revision( from google.cloud import run_v2 - def sample_get_revision(): + async def sample_get_revision(): # Create a client - client = run_v2.RevisionsClient() + client = run_v2.RevisionsAsyncClient() # Initialize request argument(s) request = run_v2.GetRevisionRequest( @@ -239,7 +239,7 @@ def sample_get_revision(): ) # Make the request - response = client.get_revision(request=request) + response = await client.get_revision(request=request) # Handle the response print(response) @@ -329,9 +329,9 @@ async def list_revisions( from google.cloud import run_v2 - def sample_list_revisions(): + async def sample_list_revisions(): # Create a client - client = run_v2.RevisionsClient() + client = run_v2.RevisionsAsyncClient() # Initialize request argument(s) request = run_v2.ListRevisionsRequest( @@ -342,7 +342,7 @@ def sample_list_revisions(): page_result = client.list_revisions(request=request) # Handle the response - for response in page_result: + async for response in page_result: print(response) Args: @@ -440,9 +440,9 @@ async def delete_revision( from google.cloud import run_v2 - def sample_delete_revision(): + async def sample_delete_revision(): # Create a client - client = run_v2.RevisionsClient() + client = run_v2.RevisionsAsyncClient() # Initialize request argument(s) request = run_v2.DeleteRevisionRequest( @@ -454,7 +454,7 @@ def sample_delete_revision(): print("Waiting for operation to complete...") - response = operation.result() + response = await operation.result() # Handle the response print(response) diff --git a/google/cloud/run_v2/services/services/async_client.py b/google/cloud/run_v2/services/services/async_client.py index c1d5c92..e2cccd8 100644 --- a/google/cloud/run_v2/services/services/async_client.py +++ b/google/cloud/run_v2/services/services/async_client.py @@ -234,9 +234,9 @@ async def create_service( from google.cloud import run_v2 - def sample_create_service(): + async def sample_create_service(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = run_v2.CreateServiceRequest( @@ -249,7 +249,7 @@ def sample_create_service(): print("Waiting for operation to complete...") - response = operation.result() + response = await operation.result() # Handle the response print(response) @@ -370,9 +370,9 @@ async def get_service( from google.cloud import run_v2 - def sample_get_service(): + async def sample_get_service(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = run_v2.GetServiceRequest( @@ -380,7 +380,7 @@ def sample_get_service(): ) # Make the request - response = client.get_service(request=request) + response = await client.get_service(request=request) # Handle the response print(response) @@ -482,9 +482,9 @@ async def list_services( from google.cloud import run_v2 - def sample_list_services(): + async def sample_list_services(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = run_v2.ListServicesRequest( @@ -495,7 +495,7 @@ def sample_list_services(): page_result = client.list_services(request=request) # Handle the response - for response in page_result: + async for response in page_result: print(response) Args: @@ -603,9 +603,9 @@ async def update_service( from google.cloud import run_v2 - def sample_update_service(): + async def sample_update_service(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = run_v2.UpdateServiceRequest( @@ -616,7 +616,7 @@ def sample_update_service(): print("Waiting for operation to complete...") - response = operation.result() + response = await operation.result() # Handle the response print(response) @@ -725,9 +725,9 @@ async def delete_service( from google.cloud import run_v2 - def sample_delete_service(): + async def sample_delete_service(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = run_v2.DeleteServiceRequest( @@ -739,7 +739,7 @@ def sample_delete_service(): print("Waiting for operation to complete...") - response = operation.result() + response = await operation.result() # Handle the response print(response) @@ -842,9 +842,9 @@ async def get_iam_policy( from google.cloud import run_v2 from google.iam.v1 import iam_policy_pb2 # type: ignore - def sample_get_iam_policy(): + async def sample_get_iam_policy(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = iam_policy_pb2.GetIamPolicyRequest( @@ -852,7 +852,7 @@ def sample_get_iam_policy(): ) # Make the request - response = client.get_iam_policy(request=request) + response = await client.get_iam_policy(request=request) # Handle the response print(response) @@ -979,9 +979,9 @@ async def set_iam_policy( from google.cloud import run_v2 from google.iam.v1 import iam_policy_pb2 # type: ignore - def sample_set_iam_policy(): + async def sample_set_iam_policy(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = iam_policy_pb2.SetIamPolicyRequest( @@ -989,7 +989,7 @@ def sample_set_iam_policy(): ) # Make the request - response = client.set_iam_policy(request=request) + response = await client.set_iam_policy(request=request) # Handle the response print(response) @@ -1118,9 +1118,9 @@ async def test_iam_permissions( from google.cloud import run_v2 from google.iam.v1 import iam_policy_pb2 # type: ignore - def sample_test_iam_permissions(): + async def sample_test_iam_permissions(): # Create a client - client = run_v2.ServicesClient() + client = run_v2.ServicesAsyncClient() # Initialize request argument(s) request = iam_policy_pb2.TestIamPermissionsRequest( @@ -1129,7 +1129,7 @@ def sample_test_iam_permissions(): ) # Make the request - response = client.test_iam_permissions(request=request) + response = await client.test_iam_permissions(request=request) # Handle the response print(response) diff --git a/noxfile.py b/noxfile.py index 6ee5e8a..70739b1 100644 --- a/noxfile.py +++ b/noxfile.py @@ -19,17 +19,19 @@ from __future__ import absolute_import import os import pathlib +import re import shutil import warnings import nox BLACK_VERSION = "black==22.3.0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] +ISORT_VERSION = "isort==5.10.1" +LINT_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] DEFAULT_PYTHON_VERSION = "3.8" -UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] +UNIT_TEST_PYTHON_VERSIONS = ["3.7", "3.8", "3.9", "3.10"] UNIT_TEST_STANDARD_DEPENDENCIES = [ "mock", "asyncmock", @@ -83,7 +85,7 @@ def lint(session): session.run( "black", "--check", - *BLACK_PATHS, + *LINT_PATHS, ) session.run("flake8", "google", "tests") @@ -94,7 +96,27 @@ def blacken(session): session.install(BLACK_VERSION) session.run( "black", - *BLACK_PATHS, + *LINT_PATHS, + ) + + +@nox.session(python=DEFAULT_PYTHON_VERSION) +def format(session): + """ + Run isort to sort imports. Then run black + to format code to uniform standard. + """ + session.install(BLACK_VERSION, ISORT_VERSION) + # Use the --fss option to sort imports using strict alphabetical order. + # See https://pycqa.github.io/isort/docs/configuration/options.html#force-sort-within-sections + session.run( + "isort", + "--fss", + *LINT_PATHS, + ) + session.run( + "black", + *LINT_PATHS, ) @@ -303,3 +325,93 @@ def docfx(session): os.path.join("docs", ""), os.path.join("docs", "_build", "html", ""), ) + + +@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) +def prerelease_deps(session): + """Run all tests with prerelease versions of dependencies installed.""" + + # Install all dependencies + session.install("-e", ".[all, tests, tracing]") + unit_deps_all = UNIT_TEST_STANDARD_DEPENDENCIES + UNIT_TEST_EXTERNAL_DEPENDENCIES + session.install(*unit_deps_all) + system_deps_all = ( + SYSTEM_TEST_STANDARD_DEPENDENCIES + + SYSTEM_TEST_EXTERNAL_DEPENDENCIES + + SYSTEM_TEST_EXTRAS + ) + session.install(*system_deps_all) + + # Because we test minimum dependency versions on the minimum Python + # version, the first version we test with in the unit tests sessions has a + # constraints file containing all dependencies and extras. + with open( + CURRENT_DIRECTORY + / "testing" + / f"constraints-{UNIT_TEST_PYTHON_VERSIONS[0]}.txt", + encoding="utf-8", + ) as constraints_file: + constraints_text = constraints_file.read() + + # Ignore leading whitespace and comment lines. + constraints_deps = [ + match.group(1) + for match in re.finditer( + r"^\s*(\S+)(?===\S+)", constraints_text, flags=re.MULTILINE + ) + ] + + session.install(*constraints_deps) + + prerel_deps = [ + "protobuf", + # dependency of grpc + "six", + "googleapis-common-protos", + "grpcio", + "grpcio-status", + "google-api-core", + "proto-plus", + "google-cloud-testutils", + # dependencies of google-cloud-testutils" + "click", + ] + + for dep in prerel_deps: + session.install("--pre", "--no-deps", "--upgrade", dep) + + # Remaining dependencies + other_deps = [ + "requests", + "google-auth", + ] + session.install(*other_deps) + + # Print out prerelease package versions + session.run( + "python", "-c", "import google.protobuf; print(google.protobuf.__version__)" + ) + session.run("python", "-c", "import grpc; print(grpc.__version__)") + + session.run("py.test", "tests/unit") + + system_test_path = os.path.join("tests", "system.py") + system_test_folder_path = os.path.join("tests", "system") + + # Only run system tests if found. + if os.path.exists(system_test_path): + session.run( + "py.test", + "--verbose", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) + if os.path.exists(system_test_folder_path): + session.run( + "py.test", + "--verbose", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) diff --git a/scripts/readme-gen/readme_gen.py b/scripts/readme-gen/readme_gen.py index d309d6e..91b5967 100644 --- a/scripts/readme-gen/readme_gen.py +++ b/scripts/readme-gen/readme_gen.py @@ -28,7 +28,10 @@ jinja_env = jinja2.Environment( trim_blocks=True, loader=jinja2.FileSystemLoader( - os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates')))) + os.path.abspath(os.path.join(os.path.dirname(__file__), "templates")) + ), + autoescape=True, +) README_TMPL = jinja_env.get_template('README.tmpl.rst') diff --git a/scripts/readme-gen/templates/install_deps.tmpl.rst b/scripts/readme-gen/templates/install_deps.tmpl.rst index 275d649..6f069c6 100644 --- a/scripts/readme-gen/templates/install_deps.tmpl.rst +++ b/scripts/readme-gen/templates/install_deps.tmpl.rst @@ -12,7 +12,7 @@ Install Dependencies .. _Python Development Environment Setup Guide: https://cloud.google.com/python/setup -#. Create a virtualenv. Samples are compatible with Python 3.6+. +#. Create a virtualenv. Samples are compatible with Python 3.7+. .. code-block:: bash diff --git a/setup.py b/setup.py index 78e1636..55c7a23 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ name = "google-cloud-run" description = "Cloud Run API client library" -version = "0.2.0" +version = "0.2.1" release_status = "Development Status :: 4 - Beta" url = "https://github.com/googleapis/python-run" dependencies = [ @@ -30,8 +30,9 @@ # Until this issue is closed # https://github.com/googleapis/google-cloud-python/issues/10566 "google-api-core[grpc] >= 1.31.5, <3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0", - "proto-plus >= 1.15.0", - "googleapis-common-protos >= 1.56.0", + "proto-plus >= 1.15.0, <2.0.0dev", + "protobuf >= 3.19.0, <4.0.0dev", + "googleapis-common-protos >= 1.56.1, <2.0.0dev", "grpc-google-iam-v1 >= 0.12.4, <1.0.0dev", ] @@ -67,7 +68,6 @@ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -77,7 +77,7 @@ ], platforms="Posix; MacOS X; Windows", packages=packages, - python_requires=">=3.6", + python_requires=">=3.7", namespace_packages=namespaces, install_requires=dependencies, include_package_data=True, diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index a0c021a..2631951 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -6,5 +6,6 @@ # Then this file should have google-cloud-foo==1.14.0 google-api-core==1.31.5 proto-plus==1.15.0 -googleapis-common-protos==1.56.0 +googleapis-common-protos==1.56.1 grpc-google-iam-v1==0.12.4 +protobuf==3.19.0 diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt index e69de29..2631951 100644 --- a/testing/constraints-3.7.txt +++ b/testing/constraints-3.7.txt @@ -0,0 +1,11 @@ +# This constraints file is used to check that lower bounds +# are correct in setup.py +# List all library dependencies and extras in this file. +# Pin the version to the lower bound. +# e.g., if setup.py has "google-cloud-foo >= 1.14.0, < 2.0.0dev", +# Then this file should have google-cloud-foo==1.14.0 +google-api-core==1.31.5 +proto-plus==1.15.0 +googleapis-common-protos==1.56.1 +grpc-google-iam-v1==0.12.4 +protobuf==3.19.0 diff --git a/tests/unit/gapic/run_v2/test_revisions.py b/tests/unit/gapic/run_v2/test_revisions.py index 7a67476..659cc58 100644 --- a/tests/unit/gapic/run_v2/test_revisions.py +++ b/tests/unit/gapic/run_v2/test_revisions.py @@ -785,7 +785,7 @@ def test_get_revision_field_headers(): # a field header. Set these to a non-empty value. request = revision.GetRevisionRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_revision), "__call__") as call: @@ -801,7 +801,7 @@ def test_get_revision_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -815,7 +815,7 @@ async def test_get_revision_field_headers_async(): # a field header. Set these to a non-empty value. request = revision.GetRevisionRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_revision), "__call__") as call: @@ -831,7 +831,7 @@ async def test_get_revision_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -1013,7 +1013,7 @@ def test_list_revisions_field_headers(): # a field header. Set these to a non-empty value. request = revision.ListRevisionsRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_revisions), "__call__") as call: @@ -1029,7 +1029,7 @@ def test_list_revisions_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -1043,7 +1043,7 @@ async def test_list_revisions_field_headers_async(): # a field header. Set these to a non-empty value. request = revision.ListRevisionsRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_revisions), "__call__") as call: @@ -1061,7 +1061,7 @@ async def test_list_revisions_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -1192,7 +1192,7 @@ def test_list_revisions_pager(transport_name: str = "grpc"): assert pager._metadata == metadata - results = [i for i in pager] + results = list(pager) assert len(results) == 6 assert all(isinstance(i, revision.Revision) for i in results) @@ -1427,7 +1427,7 @@ def test_delete_revision_field_headers(): # a field header. Set these to a non-empty value. request = revision.DeleteRevisionRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_revision), "__call__") as call: @@ -1443,7 +1443,7 @@ def test_delete_revision_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -1457,7 +1457,7 @@ async def test_delete_revision_field_headers_async(): # a field header. Set these to a non-empty value. request = revision.DeleteRevisionRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_revision), "__call__") as call: @@ -1475,7 +1475,7 @@ async def test_delete_revision_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] diff --git a/tests/unit/gapic/run_v2/test_services.py b/tests/unit/gapic/run_v2/test_services.py index 79098db..80d7445 100644 --- a/tests/unit/gapic/run_v2/test_services.py +++ b/tests/unit/gapic/run_v2/test_services.py @@ -721,7 +721,7 @@ def test_create_service_field_headers(): # a field header. Set these to a non-empty value. request = gcr_service.CreateServiceRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_service), "__call__") as call: @@ -737,7 +737,7 @@ def test_create_service_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -751,7 +751,7 @@ async def test_create_service_field_headers_async(): # a field header. Set these to a non-empty value. request = gcr_service.CreateServiceRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_service), "__call__") as call: @@ -769,7 +769,7 @@ async def test_create_service_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -1033,7 +1033,7 @@ def test_get_service_field_headers(): # a field header. Set these to a non-empty value. request = service.GetServiceRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_service), "__call__") as call: @@ -1049,7 +1049,7 @@ def test_get_service_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -1063,7 +1063,7 @@ async def test_get_service_field_headers_async(): # a field header. Set these to a non-empty value. request = service.GetServiceRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_service), "__call__") as call: @@ -1079,7 +1079,7 @@ async def test_get_service_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -1261,7 +1261,7 @@ def test_list_services_field_headers(): # a field header. Set these to a non-empty value. request = service.ListServicesRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_services), "__call__") as call: @@ -1277,7 +1277,7 @@ def test_list_services_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -1291,7 +1291,7 @@ async def test_list_services_field_headers_async(): # a field header. Set these to a non-empty value. request = service.ListServicesRequest() - request.parent = "parent/value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_services), "__call__") as call: @@ -1309,7 +1309,7 @@ async def test_list_services_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent/value", + "parent=parent_value", ) in kw["metadata"] @@ -1440,7 +1440,7 @@ def test_list_services_pager(transport_name: str = "grpc"): assert pager._metadata == metadata - results = [i for i in pager] + results = list(pager) assert len(results) == 6 assert all(isinstance(i, service.Service) for i in results) @@ -1675,7 +1675,7 @@ def test_update_service_field_headers(): # a field header. Set these to a non-empty value. request = gcr_service.UpdateServiceRequest() - request.service.name = "service.name/value" + request.service.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_service), "__call__") as call: @@ -1691,7 +1691,7 @@ def test_update_service_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "service.name=service.name/value", + "service.name=name_value", ) in kw["metadata"] @@ -1705,7 +1705,7 @@ async def test_update_service_field_headers_async(): # a field header. Set these to a non-empty value. request = gcr_service.UpdateServiceRequest() - request.service.name = "service.name/value" + request.service.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_service), "__call__") as call: @@ -1723,7 +1723,7 @@ async def test_update_service_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "service.name=service.name/value", + "service.name=name_value", ) in kw["metadata"] @@ -1911,7 +1911,7 @@ def test_delete_service_field_headers(): # a field header. Set these to a non-empty value. request = service.DeleteServiceRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_service), "__call__") as call: @@ -1927,7 +1927,7 @@ def test_delete_service_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -1941,7 +1941,7 @@ async def test_delete_service_field_headers_async(): # a field header. Set these to a non-empty value. request = service.DeleteServiceRequest() - request.name = "name/value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_service), "__call__") as call: @@ -1959,7 +1959,7 @@ async def test_delete_service_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name/value", + "name=name_value", ) in kw["metadata"] @@ -2147,7 +2147,7 @@ def test_get_iam_policy_field_headers(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.GetIamPolicyRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: @@ -2163,7 +2163,7 @@ def test_get_iam_policy_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"] @@ -2177,7 +2177,7 @@ async def test_get_iam_policy_field_headers_async(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.GetIamPolicyRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: @@ -2193,7 +2193,7 @@ async def test_get_iam_policy_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"] @@ -2316,7 +2316,7 @@ def test_set_iam_policy_field_headers(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.SetIamPolicyRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: @@ -2332,7 +2332,7 @@ def test_set_iam_policy_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"] @@ -2346,7 +2346,7 @@ async def test_set_iam_policy_field_headers_async(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.SetIamPolicyRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: @@ -2362,7 +2362,7 @@ async def test_set_iam_policy_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"] @@ -2489,7 +2489,7 @@ def test_test_iam_permissions_field_headers(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.TestIamPermissionsRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -2507,7 +2507,7 @@ def test_test_iam_permissions_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"] @@ -2521,7 +2521,7 @@ async def test_test_iam_permissions_field_headers_async(): # a field header. Set these to a non-empty value. request = iam_policy_pb2.TestIamPermissionsRequest() - request.resource = "resource/value" + request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -2541,7 +2541,7 @@ async def test_test_iam_permissions_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource/value", + "resource=resource_value", ) in kw["metadata"]