diff --git a/.flake8 b/.flake8 index ed93163..29227d4 100644 --- a/.flake8 +++ b/.flake8 @@ -26,6 +26,7 @@ exclude = *_pb2.py # Standard linting exemptions. + **/.nox/** __pycache__, .git, *.pyc, diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 0975531..cd3a49e 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -87,11 +87,11 @@ for file in samples/**/requirements.txt; do python3.6 -m nox -s "$RUN_TESTS_SESSION" EXIT=$? - # If this is a periodic build, send the test log to the Build Cop Bot. - # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/buildcop. + # If this is a periodic build, send the test log to the FlakyBot. + # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then - chmod +x $KOKORO_GFILE_DIR/linux_amd64/buildcop - $KOKORO_GFILE_DIR/linux_amd64/buildcop + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot fi if [[ $EXIT -ne 0 ]]; then diff --git a/.kokoro/trampoline_v2.sh b/.kokoro/trampoline_v2.sh index 719bcd5..4af6cdc 100755 --- a/.kokoro/trampoline_v2.sh +++ b/.kokoro/trampoline_v2.sh @@ -159,7 +159,7 @@ if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then "KOKORO_GITHUB_COMMIT" "KOKORO_GITHUB_PULL_REQUEST_NUMBER" "KOKORO_GITHUB_PULL_REQUEST_COMMIT" - # For Build Cop Bot + # For FlakyBot "KOKORO_GITHUB_COMMIT_URL" "KOKORO_GITHUB_PULL_REQUEST_URL" ) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a9024b1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml +- repo: https://github.com/psf/black + rev: 19.10b0 + hooks: + - id: black +- repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.4 + hooks: + - id: flake8 diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c392e..ef7b2ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.1.0](https://www.github.com/googleapis/python-os-config/compare/v1.0.0...v1.1.0) (2021-02-12) + + +### Features + +* add `from_service_account_info` ([#31](https://www.github.com/googleapis/python-os-config/issues/31)) ([d8d921f](https://www.github.com/googleapis/python-os-config/commit/d8d921fc28d294039c574e4dc327fbe1caa27337)) + + +### Bug Fixes + +* remove client side receive limits ([#29](https://www.github.com/googleapis/python-os-config/issues/29)) ([628ada4](https://www.github.com/googleapis/python-os-config/commit/628ada4004b1add04f5c2d95b9b1cad48616cf2c)) + ## [1.0.0](https://www.github.com/googleapis/python-os-config/compare/v0.1.2...v1.0.0) (2020-11-18) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 798e1f5..f1e0312 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -21,8 +21,8 @@ In order to add a feature: - The feature must be documented in both the API and narrative documentation. -- The feature must work fully on the following CPython versions: 2.7, - 3.5, 3.6, 3.7 and 3.8 on both UNIX and Windows. +- The feature must work fully on the following CPython versions: + 3.6, 3.7, 3.8 and 3.9 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -111,6 +111,16 @@ Coding Style should point to the official ``googleapis`` checkout and the the branch should be the main branch on that remote (``master``). +- This repository contains configuration for the + `pre-commit `__ tool, which automates checking + our linters during a commit. If you have it installed on your ``$PATH``, + you can enable enforcing those checks via: + +.. code-block:: bash + + $ pre-commit install + pre-commit installed at .git/hooks/pre-commit + Exceptions to PEP8: - Many unit tests use a helper method, ``_call_fut`` ("FUT" is short for @@ -192,25 +202,24 @@ Supported Python Versions We support: -- `Python 3.5`_ - `Python 3.6`_ - `Python 3.7`_ - `Python 3.8`_ +- `Python 3.9`_ -.. _Python 3.5: https://docs.python.org/3.5/ .. _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/ Supported versions can be found in our ``noxfile.py`` `config`_. .. _config: https://github.com/googleapis/python-os-config/blob/master/noxfile.py -Python 2.7 support is deprecated. All code changes should maintain Python 2.7 compatibility until January 1, 2020. We also explicitly decided to support Python 3 beginning with version -3.5. Reasons for this include: +3.6. Reasons for this include: - Encouraging use of newest versions of Python 3 - Taking the lead of `prominent`_ open-source `projects`_ diff --git a/docs/conf.py b/docs/conf.py index 7940715..69b17b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -345,10 +345,10 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), + "python": ("https://python.readthedocs.org/en/latest/", None), + "google-auth": ("https://googleapis.dev/python/google-auth/latest/", None), "google.api_core": ("https://googleapis.dev/python/google-api-core/latest/", None,), - "grpc": ("https://grpc.io/grpc/python/", None), + "grpc": ("https://grpc.github.io/grpc/python/", None), "proto-plus": ("https://proto-plus-python.readthedocs.io/en/latest/", None), } diff --git a/google/cloud/osconfig_v1/services/os_config_service/async_client.py b/google/cloud/osconfig_v1/services/os_config_service/async_client.py index 0c4c1e6..0042cef 100644 --- a/google/cloud/osconfig_v1/services/os_config_service/async_client.py +++ b/google/cloud/osconfig_v1/services/os_config_service/async_client.py @@ -89,6 +89,7 @@ class OsConfigServiceAsyncClient: OsConfigServiceClient.parse_common_location_path ) + from_service_account_info = OsConfigServiceClient.from_service_account_info from_service_account_file = OsConfigServiceClient.from_service_account_file from_service_account_json = from_service_account_file diff --git a/google/cloud/osconfig_v1/services/os_config_service/client.py b/google/cloud/osconfig_v1/services/os_config_service/client.py index d74daa2..f1101be 100644 --- a/google/cloud/osconfig_v1/services/os_config_service/client.py +++ b/google/cloud/osconfig_v1/services/os_config_service/client.py @@ -117,6 +117,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + {@api.name}: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials diff --git a/google/cloud/osconfig_v1/services/os_config_service/transports/grpc.py b/google/cloud/osconfig_v1/services/os_config_service/transports/grpc.py index 6159fb7..45057c7 100644 --- a/google/cloud/osconfig_v1/services/os_config_service/transports/grpc.py +++ b/google/cloud/osconfig_v1/services/os_config_service/transports/grpc.py @@ -151,6 +151,10 @@ def __init__( ssl_credentials=ssl_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) self._ssl_channel_credentials = ssl_credentials else: @@ -169,6 +173,10 @@ def __init__( ssl_credentials=ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) self._stubs = {} # type: Dict[str, Callable] diff --git a/google/cloud/osconfig_v1/services/os_config_service/transports/grpc_asyncio.py b/google/cloud/osconfig_v1/services/os_config_service/transports/grpc_asyncio.py index 3886d69..54903c7 100644 --- a/google/cloud/osconfig_v1/services/os_config_service/transports/grpc_asyncio.py +++ b/google/cloud/osconfig_v1/services/os_config_service/transports/grpc_asyncio.py @@ -196,6 +196,10 @@ def __init__( ssl_credentials=ssl_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) self._ssl_channel_credentials = ssl_credentials else: @@ -214,6 +218,10 @@ def __init__( ssl_credentials=ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) # Run the base constructor. diff --git a/noxfile.py b/noxfile.py index 8e55141..a57e24b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -81,9 +81,8 @@ def default(session): session.run( "py.test", "--quiet", - "--cov=google.cloud.osconfig", - "--cov=google.cloud", - "--cov=tests.unit", + "--cov=google/cloud", + "--cov=tests/unit", "--cov-append", "--cov-config=.coveragerc", "--cov-report=", @@ -143,7 +142,7 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") + session.run("coverage", "report", "--show-missing", "--fail-under=99") session.run("coverage", "erase") diff --git a/setup.py b/setup.py index 1c69152..2f23b61 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ name = "google-cloud-os-config" description = "Google Cloud OS Config API client library" -version = "1.0.0" +version = "1.1.0" # Should be one of: # 'Development Status :: 3 - Alpha' # 'Development Status :: 4 - Beta' diff --git a/synth.metadata b/synth.metadata index 3a49120..16b00f5 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,8 +3,8 @@ { "git": { "name": ".", - "remote": "git@github.com:googleapis/python-os-config", - "sha": "164c39adc34e029c814142c3a8dc43c22654a0b0" + "remote": "https://github.com/googleapis/python-os-config.git", + "sha": "628ada4004b1add04f5c2d95b9b1cad48616cf2c" } }, { @@ -19,14 +19,14 @@ "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" + "sha": "373861061648b5fe5e0ac4f8a38b32d639ee93e4" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" + "sha": "373861061648b5fe5e0ac4f8a38b32d639ee93e4" } } ], @@ -40,5 +40,99 @@ "generator": "gapic-generator-python" } } + ], + "generatedFiles": [ + ".coveragerc", + ".flake8", + ".github/CONTRIBUTING.md", + ".github/ISSUE_TEMPLATE/bug_report.md", + ".github/ISSUE_TEMPLATE/feature_request.md", + ".github/ISSUE_TEMPLATE/support_request.md", + ".github/PULL_REQUEST_TEMPLATE.md", + ".github/release-please.yml", + ".github/snippet-bot.yml", + ".gitignore", + ".kokoro/build.sh", + ".kokoro/continuous/common.cfg", + ".kokoro/continuous/continuous.cfg", + ".kokoro/docker/docs/Dockerfile", + ".kokoro/docker/docs/fetch_gpg_keys.sh", + ".kokoro/docs/common.cfg", + ".kokoro/docs/docs-presubmit.cfg", + ".kokoro/docs/docs.cfg", + ".kokoro/populate-secrets.sh", + ".kokoro/presubmit/common.cfg", + ".kokoro/presubmit/presubmit.cfg", + ".kokoro/publish-docs.sh", + ".kokoro/release.sh", + ".kokoro/release/common.cfg", + ".kokoro/release/release.cfg", + ".kokoro/samples/lint/common.cfg", + ".kokoro/samples/lint/continuous.cfg", + ".kokoro/samples/lint/periodic.cfg", + ".kokoro/samples/lint/presubmit.cfg", + ".kokoro/samples/python3.6/common.cfg", + ".kokoro/samples/python3.6/continuous.cfg", + ".kokoro/samples/python3.6/periodic.cfg", + ".kokoro/samples/python3.6/presubmit.cfg", + ".kokoro/samples/python3.7/common.cfg", + ".kokoro/samples/python3.7/continuous.cfg", + ".kokoro/samples/python3.7/periodic.cfg", + ".kokoro/samples/python3.7/presubmit.cfg", + ".kokoro/samples/python3.8/common.cfg", + ".kokoro/samples/python3.8/continuous.cfg", + ".kokoro/samples/python3.8/periodic.cfg", + ".kokoro/samples/python3.8/presubmit.cfg", + ".kokoro/test-samples.sh", + ".kokoro/trampoline.sh", + ".kokoro/trampoline_v2.sh", + ".pre-commit-config.yaml", + ".trampolinerc", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.rst", + "LICENSE", + "MANIFEST.in", + "docs/_static/custom.css", + "docs/_templates/layout.html", + "docs/conf.py", + "docs/multiprocessing.rst", + "docs/osconfig_v1/services.rst", + "docs/osconfig_v1/types.rst", + "google/cloud/osconfig/__init__.py", + "google/cloud/osconfig/py.typed", + "google/cloud/osconfig_v1/__init__.py", + "google/cloud/osconfig_v1/py.typed", + "google/cloud/osconfig_v1/services/__init__.py", + "google/cloud/osconfig_v1/services/os_config_service/__init__.py", + "google/cloud/osconfig_v1/services/os_config_service/async_client.py", + "google/cloud/osconfig_v1/services/os_config_service/client.py", + "google/cloud/osconfig_v1/services/os_config_service/pagers.py", + "google/cloud/osconfig_v1/services/os_config_service/transports/__init__.py", + "google/cloud/osconfig_v1/services/os_config_service/transports/base.py", + "google/cloud/osconfig_v1/services/os_config_service/transports/grpc.py", + "google/cloud/osconfig_v1/services/os_config_service/transports/grpc_asyncio.py", + "google/cloud/osconfig_v1/types/__init__.py", + "google/cloud/osconfig_v1/types/inventory.py", + "google/cloud/osconfig_v1/types/osconfig_common.py", + "google/cloud/osconfig_v1/types/osconfig_service.py", + "google/cloud/osconfig_v1/types/patch_deployments.py", + "google/cloud/osconfig_v1/types/patch_jobs.py", + "mypy.ini", + "noxfile.py", + "renovate.json", + "samples/AUTHORING_GUIDE.md", + "samples/CONTRIBUTING.md", + "scripts/decrypt-secrets.sh", + "scripts/fixup_osconfig_v1_keywords.py", + "scripts/readme-gen/readme_gen.py", + "scripts/readme-gen/templates/README.tmpl.rst", + "scripts/readme-gen/templates/auth.tmpl.rst", + "scripts/readme-gen/templates/auth_api_key.tmpl.rst", + "scripts/readme-gen/templates/install_deps.tmpl.rst", + "scripts/readme-gen/templates/install_portaudio.tmpl.rst", + "setup.cfg", + "testing/.gitignore", + "tests/unit/gapic/osconfig_v1/__init__.py", + "tests/unit/gapic/osconfig_v1/test_os_config_service.py" ] } \ No newline at end of file diff --git a/synth.py b/synth.py index 9ae99d4..57c869b 100644 --- a/synth.py +++ b/synth.py @@ -19,17 +19,22 @@ import synthtool.gcp as gcp from synthtool.languages import python -gapic = gcp.GAPICMicrogenerator() +gapic = gcp.GAPICBazel() common = gcp.CommonTemplates() # ---------------------------------------------------------------------------- # Generate OS Config GAPIC layer # ---------------------------------------------------------------------------- -library = gapic.py_library( - "osconfig", "v1" -) +versions = ["v1"] + +for version in versions: + library = gapic.py_library( + service="osconfig", + version=version, + bazel_target=f"//google/cloud/osconfig/{version}:osconfig-{version}-py" + ) -s.move(library, excludes=["nox.py", "setup.py", "README.rst", "docs/index.rst"]) + s.move(library, excludes=["nox.py", "setup.py", "README.rst", "docs/index.rst"]) # rename to google-cloud-os-config s.replace(["google/**/*.py", "tests/**/*.py"], "google-cloud-osconfig", "google-cloud-os-config") @@ -46,6 +51,7 @@ templated_files = common.py_library( samples=False, microgenerator=True, + cov_level=99, ) s.move( templated_files, excludes=[".coveragerc"] diff --git a/testing/constraints-3.10.txt b/testing/constraints-3.10.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.11.txt b/testing/constraints-3.11.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt new file mode 100644 index 0000000..08972fd --- /dev/null +++ b/testing/constraints-3.6.txt @@ -0,0 +1,10 @@ +# 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 "foo >= 1.14.0, < 2.0.0dev", +# Then this file should have foo==1.14.0 +google-api-core==1.22.0 +proto-plus==1.10.0 +libcst==0.2.5 \ No newline at end of file diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.8.txt b/testing/constraints-3.8.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.9.txt b/testing/constraints-3.9.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/gapic/osconfig_v1/test_os_config_service.py b/tests/unit/gapic/osconfig_v1/test_os_config_service.py index cbd0460..2affe12 100644 --- a/tests/unit/gapic/osconfig_v1/test_os_config_service.py +++ b/tests/unit/gapic/osconfig_v1/test_os_config_service.py @@ -93,6 +93,19 @@ def test__get_default_mtls_endpoint(): ) +def test_os_config_service_client_from_service_account_info(): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = OsConfigServiceClient.from_service_account_info(info) + assert client.transport._credentials == creds + + assert client.transport._host == "osconfig.googleapis.com:443" + + @pytest.mark.parametrize( "client_class", [OsConfigServiceClient, OsConfigServiceAsyncClient] ) @@ -3027,6 +3040,10 @@ def test_os_config_service_transport_channel_mtls_with_client_cert_source( scopes=("https://www.googleapis.com/auth/cloud-platform",), ssl_credentials=mock_ssl_cred, quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) assert transport.grpc_channel == mock_grpc_channel assert transport._ssl_channel_credentials == mock_ssl_cred @@ -3068,6 +3085,10 @@ def test_os_config_service_transport_channel_mtls_with_adc(transport_class): scopes=("https://www.googleapis.com/auth/cloud-platform",), ssl_credentials=mock_ssl_cred, quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], ) assert transport.grpc_channel == mock_grpc_channel