build: fix system tests, move to Kokoro (#372)
diff --git a/.kokoro/build.sh b/.kokoro/build.sh
new file mode 100755
index 0000000..e803113
--- /dev/null
+++ b/.kokoro/build.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eo pipefail
+
+cd github/google-auth-library-python
+
+# Disable buffering, so that the logs stream through.
+export PYTHONUNBUFFERED=1
+
+# Debug: show build environment
+env | grep KOKORO
+
+# Setup service account credentials.
+
+# add creds to gfile dir
+export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json
+
+# Setup project id.
+export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.txt")
+
+# Activate gcloud with service account credentials
+gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS
+gcloud config set project $PROJECT_ID
+
+# Decrypt system test secrets
+./scripts/decrypt-secrets.sh
+
+# Remove old nox
+python3.6 -m pip uninstall --yes --quiet nox-automation
+
+# Install nox
+python3.6 -m pip install --upgrade --quiet nox
+python3.6 -m nox --version
+
+python3.6 -m nox
+python3.6 -m nox -f system_tests/noxfile.py
\ No newline at end of file
diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg
index 7dbafc2..81f431a 100644
--- a/.kokoro/common.cfg
+++ b/.kokoro/common.cfg
@@ -3,11 +3,14 @@
# Download trampoline resources. These will be in ${KOKORO_GFILE_DIR}
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+# Download resources for tests
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python"
+
# All builds use the trampoline script to run in docker.
build_file: "google-auth-library-python/.kokoro/trampoline.sh"
# Use the Python worker docker iamge.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/silver-python2/python-worker"
+ value: "gcr.io/cloud-devrel-public-resources/python-multi"
}
diff --git a/.kokoro/continuous/common.cfg b/.kokoro/continuous/common.cfg
new file mode 100644
index 0000000..10910e3
--- /dev/null
+++ b/.kokoro/continuous/common.cfg
@@ -0,0 +1,27 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Download resources for system tests (service account key, etc.)
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python"
+
+# Use the trampoline script to run in docker.
+build_file: "google-auth-library-python/.kokoro/trampoline.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+}
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/google-auth-library-python/.kokoro/build.sh"
+}
diff --git a/.kokoro/continuous/continuous.cfg b/.kokoro/continuous/continuous.cfg
new file mode 100644
index 0000000..8f43917
--- /dev/null
+++ b/.kokoro/continuous/continuous.cfg
@@ -0,0 +1 @@
+# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg
new file mode 100644
index 0000000..e49c232
--- /dev/null
+++ b/.kokoro/docs/common.cfg
@@ -0,0 +1,48 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "google-auth-library-python/.kokoro/trampoline.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+}
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/google-auth-library-python/.kokoro/publish-docs.sh"
+}
+
+env_vars: {
+ key: "STAGING_BUCKET"
+ value: "docs-staging"
+}
+
+# Fetch the token needed for reporting release status to GitHub
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "yoshi-automation-github-key"
+ }
+ }
+}
+
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "docuploader_service_account"
+ }
+ }
+}
\ No newline at end of file
diff --git a/.kokoro/docs/docs.cfg b/.kokoro/docs/docs.cfg
new file mode 100644
index 0000000..8f43917
--- /dev/null
+++ b/.kokoro/docs/docs.cfg
@@ -0,0 +1 @@
+# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
diff --git a/.kokoro/presubmit/common.cfg b/.kokoro/presubmit/common.cfg
new file mode 100644
index 0000000..7dbee1c
--- /dev/null
+++ b/.kokoro/presubmit/common.cfg
@@ -0,0 +1,27 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
+
+# Download trampoline resources. These will be in ${KOKORO_GFILE_DIR}
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Download resources for tests
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python"
+
+# Use the trampoline script to run in docker.
+build_file: "google-auth-library-python/.kokoro/trampoline.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+}
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/google-auth-library-python/.kokoro/build.sh"
+}
diff --git a/.kokoro/presubmit/presubmit.cfg b/.kokoro/presubmit/presubmit.cfg
new file mode 100644
index 0000000..8f43917
--- /dev/null
+++ b/.kokoro/presubmit/presubmit.cfg
@@ -0,0 +1 @@
+# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
diff --git a/.kokoro/publish-docs.sh b/.kokoro/publish-docs.sh
new file mode 100755
index 0000000..0d97db8
--- /dev/null
+++ b/.kokoro/publish-docs.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -eo pipefail
+
+# Disable buffering, so that the logs stream through.
+export PYTHONUNBUFFERED=1
+
+cd github/google-auth-library-python
+
+# Remove old nox
+python3.6 -m pip uninstall --yes --quiet nox-automation
+
+# Install nox
+python3.6 -m pip install --upgrade --quiet nox
+python3.6 -m nox --version
+
+# build docs
+nox -s docs
+
+python3 -m pip install gcp-docuploader
+
+# install a json parser
+sudo apt-get update
+sudo apt-get -y install software-properties-common
+sudo add-apt-repository universe
+sudo apt-get update
+sudo apt-get -y install jq
+
+# create metadata
+python3 -m docuploader create-metadata \
+ --name=$(jq --raw-output '.name // empty' .repo-metadata.json) \
+ --version=$(python3 setup.py --version) \
+ --language=$(jq --raw-output '.language // empty' .repo-metadata.json) \
+ --distribution-name=$(python3 setup.py --name) \
+ --product-page=$(jq --raw-output '.product_documentation // empty' .repo-metadata.json) \
+ --github-repository=$(jq --raw-output '.repo // empty' .repo-metadata.json) \
+ --issue-tracker=$(jq --raw-output '.issue_tracker // empty' .repo-metadata.json)
+
+cat docs.metadata
+
+# upload docs
+python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging
diff --git a/.kokoro/release.sh b/.kokoro/release.sh
new file mode 100755
index 0000000..cf85555
--- /dev/null
+++ b/.kokoro/release.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -eo pipefail
+
+# Start the releasetool reporter
+python3 -m pip install gcp-releasetool
+python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script
+
+# Ensure that we have the latest versions of Twine, Wheel, and Setuptools.
+python3 -m pip install --upgrade twine wheel setuptools
+
+# Disable buffering, so that the logs stream through.
+export PYTHONUNBUFFERED=1
+
+# Move into the package, build the distribution and upload.
+TWINE_PASSWORD=$(cat "${KOKORO_KEYSTORE_DIR}/73713_google_cloud_pypi_password")
+cd github/google-auth-library-python
+python3 setup.py sdist bdist_wheel
+twine upload --username gcloudpypi --password "${TWINE_PASSWORD}" dist/*
diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg
new file mode 100644
index 0000000..b2088d0
--- /dev/null
+++ b/.kokoro/release/common.cfg
@@ -0,0 +1,64 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "google-auth-library-python/.kokoro/trampoline.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+}
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/google-auth-library-python/.kokoro/release.sh"
+}
+
+# Fetch the token needed for reporting release status to GitHub
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "yoshi-automation-github-key"
+ }
+ }
+}
+
+# Fetch PyPI password
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "google_cloud_pypi_password"
+ }
+ }
+}
+
+# Fetch magictoken to use with Magic Github Proxy
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "releasetool-magictoken"
+ }
+ }
+}
+
+# Fetch api key to use with Magic Github Proxy
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "magic-github-proxy-api-key"
+ }
+ }
+}
diff --git a/.kokoro/release/release.cfg b/.kokoro/release/release.cfg
new file mode 100644
index 0000000..8f43917
--- /dev/null
+++ b/.kokoro/release/release.cfg
@@ -0,0 +1 @@
+# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
diff --git a/.kokoro/system_tests.cfg b/.kokoro/system_tests.cfg
deleted file mode 100644
index aa3e6c6..0000000
--- a/.kokoro/system_tests.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Download secrets from Cloud Storage.
-gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python"
-
-# Tell the trampoline which build file to use.
-env_vars: {
- key: "TRAMPOLINE_BUILD_FILE"
- value: "github/google-auth-library-python/.kokoro/system_tests.sh"
-}
-
-# Tell the system tests which Google Cloud project to use.
-env_vars: {
- key: "TEST_PROJECT"
- value: "python-docs-samples-tests"
-}
diff --git a/.kokoro/system_tests.sh b/.kokoro/system_tests.sh
deleted file mode 100755
index 29d5097..0000000
--- a/.kokoro/system_tests.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -eo pipefail
-
-export PATH=${PATH}:${HOME}/gcloud/google-cloud-sdk/bin
-
-cd github/google-auth-library-python
-
-# Unencrypt and extract secrets
-SECRETS_PASSWORD=$(cat "${KOKORO_GFILE_DIR}/secrets-password.txt")
-./scripts/decrypt-secrets.sh "${SECRETS_PASSWORD}"
-
-# Setup gcloud, this is needed for the App Engine system test.
-gcloud auth activate-service-account --key-file system_tests/data/service_account.json
-gcloud config set project "${TEST_PROJECT}"
-
-# Run tests
-tox -e py27-system
-tox -e py36-system
diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh
index fef7c24..e8c4251 100755
--- a/.kokoro/trampoline.sh
+++ b/.kokoro/trampoline.sh
@@ -15,14 +15,9 @@
set -eo pipefail
-# Always run the cleanup script, regardless of the success of bouncing into
-# the container.
+python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" || ret_code=$?
-function cleanup() {
- chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
- ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
- echo "cleanup";
-}
-trap cleanup EXIT
+chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+${KOKORO_GFILE_DIR}/trampoline_cleanup.sh || true
-python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py"
+exit ${ret_code}
diff --git a/.repo-metadata.json b/.repo-metadata.json
new file mode 100644
index 0000000..4c8ebe1
--- /dev/null
+++ b/.repo-metadata.json
@@ -0,0 +1,10 @@
+{
+ "name": "google-auth-library-python",
+ "name_pretty": "Google Auth Python Library",
+ "client_documentation": "https://googleapis.dev/python/google-auth-library-python/latest",
+ "issue_tracker": "https://github.com/googleapis/google-auth-library-python/issues",
+ "release_level": "ga",
+ "language": "python",
+ "repo": "googleapis/google-auth-library-python",
+ "distribution_name": "google-auth"
+}
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7335fd7..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-language: python
-sudo: false
-matrix:
- include:
- - python: 3.6
- env: TOXENV=lint
- - python: 3.6
- env: TOXENV=docs
- - python: 2.7
- env: TOXENV=py27
- - python: 3.4
- env: TOXENV=py34
- - python: 3.5
- env: TOXENV=py35
- - python: 3.6
- env: TOXENV=py36
- - python: pypy
- env: TOXENV=pypy
- - python: 3.6
- env: TOXENV=cover
- - python: 3.6
- env: TOXENV=py36-system SYSTEM_TEST=1 SKIP_APP_ENGINE_SYSTEM_TEST=1
- - python: 2.7
- env: TOXENV=py27-system SYSTEM_TEST=1 SKIP_APP_ENGINE_SYSTEM_TEST=1
- - python: 3.6
- env: TOXENV=pytype
-cache:
- directories:
- - ${HOME}/.cache
-install:
-- pip install --upgrade tox
-script:
-- scripts/travis.sh
-deploy:
- provider: pypi
- user: google_opensource
- password:
- secure: bThsMsG/1fg2NlAygLI8GkDc/kGD3TmXUrqmPU9cc6Tym8sMzPYMiDpJk76ttLAV+gfEI++ROvcul4cgW6Jz5d5xJp4sbQAN4eZOyO3Q3hiVPvhuu6wPMM22j8YfT7rmh710moyBujxJccVDCNAJo/3nAbAQVScP8l89YDW5LF9ckgLPLKG0gDEfwLk8ZVlJg8lRsJ7PTWnAp7nfrvXRiBNPEe8yie654wcxV/xzQwAHLSJhAfpBdTHxvUoFazynn+DvGF/zF5R3n3XSPvctGT6tQNr7GDmdp1EqsOL7y2NbunzIDEoN/wUKlmTRcJVownVyLdISNBo3GjbsyOZGwsj86bKpVIgwhFrkZe7BOV9Fqq5wBl7kTvVf5j/FnLrsQaPyGlgHHxNqXSRqjUosT7BGnuTErmhO130Z6q6iXErrCNfBM+sbuLv+LF+vlMuVSdeU/TBGjf5j0ODmsGGF3EuKtudgD64O8L81/ybKo1CxcRoXbK7+pJhvhSAmkFdZ99A22+wiLNe7B1FVmu6ZfO0WO0GPLKsE+1Xn3xxcrX0wO6rE+uXH4CSQEgLza/CltKNL671dZZMJAUsNAVanwKIKCsNu7viOpUVejESyK7I1SA6B5yX74iA/yhunLLnPuPLANbkug7Ob/i5Z1IruWzpEyqm0CC4HfMPvg7FA+Kc=
- on:
- tags: true
- distributions: sdist bdist_wheel
- repo: googleapis/google-auth-library-python
- condition: "$TOXENV = \"cover\""
-env:
- global:
- - secure: s6GdhJklftl8w/9WoETwLtvtKL4ledPA/TuBuqCXQxSuYWaPuTdRVcvoejGkHJpp7i/7v2T/0etYl+5koyskKm5+QZZweaaL7MAyjPGp+hmIaIlWQRz6w481NOf3i9uSmoQycssT0mNmwScNIqo+igbA2y14mr/e9aBuOcxNNzNzFQp2vaRMEju6q7xZMjYdcudUWL48vq9CoNa3X2ZArpqjkApR/TfYlG7glOj43NxuVDN4z9wIyUjaMHBfPgEhjaOaRyEFgEYITRwX1qDoXqcZdTVIq4Cn0uCH+Mvrz6Y+oUJGTJqH1k7N/DhzbSN9lJnVYaQW/yuvGHiGAwbb6Tcxiq2UqqhA9MfbPpmstDECs46v9Z3BT252KvYEQY7Q1v9g2gFhHvFGWISUxs80rnnPhEYfa11JoLvj2t8cowkE4pvj4OH32Eoyvc5H07hW3F5xpuF7Jt7N09TNZkUrpmiRJEhfrVNgjsrWO77/q5h8mXGd+9vYmz++yzKu+63x8x1MpeigGCG73Dpu9Otm5eydOZfpJ39ZfZWUb7G2JahgHaGweM9dmnpJtzHQgijmHjjfAx9jgnQ8IQz9nkFmyMI8H7HouwalnrJtpSSbvMqOQ0kiZhMzdBKH5pD3tjLgSlgA0pKelBwlooY6jGlj4LrtbDAxa6cZyXiFoqWpT1w=
- - CLOUD_SDK_ROOT: ${HOME}/.cache/cloud-sdk
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 8581688..f95b1f1 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -11,36 +11,92 @@
Making changes
--------------
-A few notes on making changes to ``google-auth-libary-python``.
+A few notes on making changes to ``google-auth-library-python``.
- If you've added a new feature or modified an existing feature, be sure to
add or update any applicable documentation in docstrings and in the
documentation (in ``docs/``). You can re-generate the reference documentation
- using ``tox -e docgen``.
+ using ``nox -s docgen``.
- The change must work fully on the following CPython versions: 2.7,
- 3.4, and 3.5 across macOS, Linux, and Windows.
+ 3.5, 3.6, 3.7 across macOS, Linux, and Windows.
- The codebase *must* have 100% test statement coverage after each commit.
- You can test coverage via ``tox -e cover``.
+ You can test coverage via ``nox -e cover``.
Testing changes
---------------
-To test your changes, run unit tests with ``tox``::
+To test your changes, run unit tests with ``nox``::
- $ tox -e py27
- $ tox -e py34
- $ tox -e py35
+ $ nox -s unit
+
+
+Running system tests
+--------------------
+
+You can run the system tests with ``nox``::
+
+ $ nox -f system_tests/noxfile.py
+
+To run a single session, specify it with ``nox -s``::
+
+ $ nox -f system_tests/noxfile.py -s service_account
+
+To run system tests locally, you will need to set up a data directory ::
+
+ $ mkdir system_tests/data
+
+Add a service account file and authorized user file to the data directory.
+Your directory should look like this ::
+
+ system_tests/
+ data/
+ service_account.json
+ authorized_user.json
+
+The files must be named exactly ``service_account.json``
+and ``authorized_user.json``. See `Creating and Managing Service Account Keys`_ for how to
+obtain a service account.
+
+Use the `gcloud CLI`_ to get an authorized user file ::
+
+ $ gcloud auth application-default login --scopes=https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,openid
+
+You will see something like::
+
+ Credentials saved to file: [/usr/local/home/.config/gcloud/application_default_credentials.json]```
+
+Copy the contents of the file to ``authorized_user.json``.
+
+.. _Creating and Managing Service Account Keys: https://cloud.google.com/iam/docs/creating-managing-service-account-keys
+.. _gcloud CLI: https://cloud.google.com/sdk/gcloud/
+
+App Engine System Tests
+^^^^^^^^^^^^^^^^^^^^^^^
+
+To run the App Engine tests, you wil need to deploy a default App Engine service.
+If you already have a default service associated with your project, you can skip this step.
+
+Edit ``app.yaml`` so ``service`` is ``default`` instead of ``google-auth-system-tests``.
+From ``system_tests/app_engine_test_app`` run the following commands ::
+
+ $ pip install --target-lib -r requirements.txt
+ $ gcloud app deploy -q app.yaml
+
+After the app is deployed, change ``service`` in ``app.yaml`` back to ``google-auth-system-tests``.
+You can now run the App Engine tests: ::
+
+ $ nox -f system_tests/noxfile.py -s app_engine
Coding Style
------------
This library is PEP8 & Pylint compliant. Our Pylint config is defined at
``pylintrc`` for package code and ``pylintrc.tests`` for test code. Use
-``tox`` to check for non-compliant code::
+``nox`` to check for non-compliant code::
- $ tox -e lint
+ $ nox -s lint
Documentation Coverage and Building HTML Documentation
------------------------------------------------------
@@ -50,9 +106,9 @@
changed to reflect the bug fix, ideally in the same commit that fixes the bug
or adds the feature.
-To build and review docs use ``tox``::
+To build and review docs use ``nox``::
- $ tox -e docs
+ $ nox -s docs
The HTML version of the docs will be built in ``docs/_build/html``
diff --git a/README.rst b/README.rst
index 3d7ba76..c7dfcea 100644
--- a/README.rst
+++ b/README.rst
@@ -6,16 +6,10 @@
This library simplifies using Google's various server-to-server authentication
mechanisms to access Google APIs.
-.. |build| image:: https://travis-ci.org/GoogleCloudPlatform/google-auth-library-python.svg?branch=master
- :target: https://travis-ci.org/GoogleCloudPlatform/google-auth-library-python
.. |docs| image:: https://readthedocs.org/projects/google-auth/badge/?version=latest
:target: https://google-auth.readthedocs.io/en/latest/
.. |pypi| image:: https://img.shields.io/pypi/v/google-auth.svg
:target: https://pypi.python.org/pypi/google-auth
-.. |compat_check_pypi| image:: https://python-compatibility-tools.appspot.com/one_badge_image?package=google-auth
- :target: https://python-compatibility-tools.appspot.com/one_badge_target?package=google-auth
-.. |compat_check_github| image:: https://python-compatibility-tools.appspot.com/one_badge_image?package=git%2Bgit%3A//github.com/googleapis/google-auth-library-python.git
- :target: https://python-compatibility-tools.appspot.com/one_badge_target?package=git%2Bgit%3A//github.com/googleapis/google-auth-library-python.git
Installing
----------
diff --git a/docs/conf.py b/docs/conf.py
index 831c752..db1872e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -368,7 +368,7 @@
intersphinx_mapping = {
"python": ("https://docs.python.org/3.5", None),
"urllib3": ("https://urllib3.readthedocs.io/en/stable", None),
- "requests": ("http://docs.python-requests.org/en/stable", None),
+ "requests": ("https://requests.kennethreitz.org/en/master/", None),
"requests-oauthlib": ("http://requests-oauthlib.readthedocs.io/en/stable", None),
}
diff --git a/noxfile.py b/noxfile.py
new file mode 100644
index 0000000..aaf1bc5
--- /dev/null
+++ b/noxfile.py
@@ -0,0 +1,118 @@
+# Copyright 2019 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import nox
+
+TEST_DEPENDENCIES = [
+ "flask",
+ "mock",
+ "oauth2client",
+ "pytest",
+ "pytest-cov",
+ "pytest-localserver",
+ "requests",
+ "urllib3",
+ "cryptography",
+ "grpcio",
+]
+BLACK_VERSION = "black==19.3b0"
+BLACK_PATHS = ["google", "tests", "noxfile.py", "setup.py", "docs/conf.py"]
+
+
[email protected](python="3.7")
+def lint(session):
+ session.install("flake8", "flake8-import-order", "docutils", BLACK_VERSION)
+ session.install(".")
+ session.run("black", "--check", *BLACK_PATHS)
+ session.run(
+ "flake8",
+ "--import-order-style=google",
+ "--application-import-names=google,tests,system_tests",
+ "google",
+ "tests",
+ )
+ session.run(
+ "python", "setup.py", "check", "--metadata", "--restructuredtext", "--strict"
+ )
+
+
[email protected](python="3.6")
+def blacken(session):
+ """Run black.
+
+ Format code to uniform standard.
+
+ This currently uses Python 3.6 due to the automated Kokoro run of synthtool.
+ That run uses an image that doesn't have 3.6 installed. Before updating this
+ check the state of the `gcp_ubuntu_config` we use for that Kokoro run.
+ """
+ session.install(BLACK_VERSION)
+ session.run("black", *BLACK_PATHS)
+
+
[email protected](python=["2.7", "3.5", "3.6", "3.7"])
+def unit(session):
+ session.install(*TEST_DEPENDENCIES)
+ session.install(".")
+ session.run(
+ "pytest", "--cov=google.auth", "--cov=google.oauth2", "--cov=tests", "tests"
+ )
+
+
[email protected](python="3.7")
+def cover(session):
+ session.install(*TEST_DEPENDENCIES)
+ session.install(".")
+ session.run(
+ "pytest",
+ "--cov=google.auth",
+ "--cov=google.oauth2",
+ "--cov=tests",
+ "--cov-report=",
+ "tests",
+ )
+ session.run("coverage", "report", "--show-missing", "--fail-under=100")
+
+
[email protected](python="3.7")
+def docgen(session):
+ session.env["SPHINX_APIDOC_OPTIONS"] = "members,inherited-members,show-inheritance"
+ session.install(*TEST_DEPENDENCIES)
+ session.install("sphinx")
+ session.install(".")
+ session.run("rm", "-r", "docs/reference")
+ session.run(
+ "sphinx-apidoc",
+ "--output-dir",
+ "docs/reference",
+ "--separate",
+ "--module-first",
+ "google",
+ )
+
+
[email protected](python="3.7")
+def docs(session):
+ session.install("sphinx", "-r", "docs/requirements-docs.txt")
+ session.install(".")
+ session.run("make", "-C", "docs", "html")
+
+
[email protected](python="pypy")
+def pypy(session):
+ session.install(*TEST_DEPENDENCIES)
+ session.install(".")
+ session.run(
+ "pytest", "--cov=google.auth", "--cov=google.oauth2", "--cov=tests", "tests"
+ )
diff --git a/scripts/decrypt-secrets.sh b/scripts/decrypt-secrets.sh
index e02bfc1..f0ef994 100755
--- a/scripts/decrypt-secrets.sh
+++ b/scripts/decrypt-secrets.sh
@@ -20,8 +20,11 @@
# Work from the project root.
cd $ROOT
-openssl aes-256-cbc -k "$1" \
- -in system_tests/secrets.tar.enc \
- -out system_tests/secrets.tar -d
+gcloud kms decrypt \
+ --location=global \
+ --keyring=ci \
+ --key=kokoro-secrets \
+ --ciphertext-file=system_tests/secrets.tar.enc \
+ --plaintext-file=system_tests/secrets.tar
tar xvf system_tests/secrets.tar
rm system_tests/secrets.tar
diff --git a/scripts/encrypt-secrets.sh b/scripts/encrypt-secrets.sh
index c6291b7..b6521e8 100755
--- a/scripts/encrypt-secrets.sh
+++ b/scripts/encrypt-secrets.sh
@@ -20,13 +20,13 @@
# Work from the project root.
cd $ROOT
-read -s -p "Enter password for encryption: " PASSWORD
-echo
-
tar cvf system_tests/secrets.tar system_tests/data
-openssl aes-256-cbc -k "$PASSWORD" \
- -in system_tests/secrets.tar \
- -out system_tests/secrets.tar.enc
-rm system_tests/secrets.tar
-travis encrypt "SECRETS_PASSWORD=$PASSWORD" --add --override
+gcloud kms encrypt \
+ --location=global \
+ --keyring=ci \
+ --key=kokoro-secrets \
+ --plaintext-file=system_tests/secrets.tar \
+ --ciphertext-file=system_tests/secrets.tar.enc
+
+rm system_tests/secrets.tar
\ No newline at end of file
diff --git a/scripts/obtain_user_auth.py b/scripts/obtain_user_auth.py
deleted file mode 100644
index ae86466..0000000
--- a/scripts/obtain_user_auth.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""This program obtains a set of user credentials.
-
-These credentials are needed to run the system test for OAuth2 credentials.
-It's expected that a developer will run this program manually once to obtain
-a refresh token. It's highly recommended to use a Google account created
-specifically for testing.
-"""
-
-import json
-import os
-
-from oauth2client import client
-from oauth2client import tools
-
-HERE = os.path.dirname(__file__)
-CLIENT_SECRETS_PATH = os.path.abspath(os.path.join(
- HERE, '..', 'system_tests', 'data', 'client_secret.json'))
-AUTHORIZED_USER_PATH = os.path.abspath(os.path.join(
- HERE, '..', 'system_tests', 'data', 'authorized_user.json'))
-SCOPES = ['email', 'profile']
-
-
-class NullStorage(client.Storage):
- """Null storage implementation to prevent oauth2client from failing
- on storage.put."""
- def locked_put(self, credentials):
- pass
-
-
-def main():
- flow = client.flow_from_clientsecrets(CLIENT_SECRETS_PATH, SCOPES)
-
- print('Starting credentials flow...')
- credentials = tools.run_flow(flow, NullStorage())
-
- # Save the credentials in the same format as the Cloud SDK's authorized
- # user file.
- data = {
- 'type': 'authorized_user',
- 'client_id': flow.client_id,
- 'client_secret': flow.client_secret,
- 'refresh_token': credentials.refresh_token
- }
-
- with open(AUTHORIZED_USER_PATH, 'w') as fh:
- json.dump(data, fh, indent=4)
-
- print('Created {}.'.format(AUTHORIZED_USER_PATH))
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/travis.sh b/scripts/travis.sh
index 28bf5fa..2c34091 100755
--- a/scripts/travis.sh
+++ b/scripts/travis.sh
@@ -37,6 +37,6 @@
fi
fi
-# Run tox.
-echo "Running tox..."
-tox
+# Run nox.
+echo "Running nox..."
+nox
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 0f15a38..7c2b287 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,17 +1,2 @@
[bdist_wheel]
-universal = 1
-
-[pytype]
-# Where to start analysis.
-inputs = .
-# Some files aren't worth analyzing, namely tests. Hidden directories (e.g.
-# .tox) are automatically filtered out.
-exclude = tests system_tests
-# All pytype output goes here.
-output = pytype_output
-# Python version (major.minor) of the target code.
-python_version = 3.6
-# Paths to source code directories, separated by ':'.
-pythonpath = .
-# Errors to disable.
-disable = pyi-error
+universal = 1
\ No newline at end of file
diff --git a/synth.metadata b/synth.metadata
new file mode 100644
index 0000000..ebfeb7f
--- /dev/null
+++ b/synth.metadata
@@ -0,0 +1,12 @@
+{
+ "updateTime": "2019-09-12T22:40:28.148018Z",
+ "sources": [
+ {
+ "template": {
+ "name": "python_library",
+ "origin": "synthtool.gcp",
+ "version": "2019.5.2"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/synth.py b/synth.py
new file mode 100644
index 0000000..069b214
--- /dev/null
+++ b/synth.py
@@ -0,0 +1,10 @@
+import synthtool as s
+from synthtool import gcp
+
+common = gcp.CommonTemplates()
+
+# ----------------------------------------------------------------------------
+# Add templated files
+# ----------------------------------------------------------------------------
+templated_files = common.py_library(unit_cov_level=100, cov_level=100)
+s.move(templated_files / '.kokoro') # just move kokoro configs
\ No newline at end of file
diff --git a/system_tests/.gitignore b/system_tests/.gitignore
index f6bf39d..be60550 100644
--- a/system_tests/.gitignore
+++ b/system_tests/.gitignore
@@ -1,2 +1,2 @@
data
-secrets.tar
+secrets.tar
\ No newline at end of file
diff --git a/system_tests/noxfile.py b/system_tests/noxfile.py
index 5f9291a..864a5be 100644
--- a/system_tests/noxfile.py
+++ b/system_tests/noxfile.py
@@ -26,10 +26,12 @@
import subprocess
from nox.command import which
+import nox
import py.path
HERE = os.path.abspath(os.path.dirname(__file__))
+LIBRARY_DIR = os.path.join(HERE, "..")
DATA_DIR = os.path.join(HERE, "data")
SERVICE_ACCOUNT_FILE = os.path.join(DATA_DIR, "service_account.json")
AUTHORIZED_USER_FILE = os.path.join(DATA_DIR, "authorized_user.json")
@@ -167,66 +169,88 @@
# Test sesssions
+TEST_DEPENDENCIES = ["pytest", "requests"]
+PYTHON_VERSIONS=['2.7', '3.7']
-def session_service_account(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def service_account(session):
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_service_account.py")
-def session_oauth2_credentials(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def oauth2_credentials(session):
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_oauth2_credentials.py")
-def session_default_explicit_service_account(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_explicit_service_account(session):
session.env[EXPLICIT_CREDENTIALS_ENV] = SERVICE_ACCOUNT_FILE
session.env[EXPECT_PROJECT_ENV] = "1"
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_default_explicit_authorized_user(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_explicit_authorized_user(session):
session.env[EXPLICIT_CREDENTIALS_ENV] = AUTHORIZED_USER_FILE
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_default_explicit_authorized_user_explicit_project(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_explicit_authorized_user_explicit_project(session):
session.env[EXPLICIT_CREDENTIALS_ENV] = AUTHORIZED_USER_FILE
session.env[EXPLICIT_PROJECT_ENV] = "example-project"
session.env[EXPECT_PROJECT_ENV] = "1"
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_default_cloud_sdk_service_account(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_cloud_sdk_service_account(session):
configure_cloud_sdk(session, SERVICE_ACCOUNT_FILE)
session.env[EXPECT_PROJECT_ENV] = "1"
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_default_cloud_sdk_authorized_user(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_cloud_sdk_authorized_user(session):
configure_cloud_sdk(session, AUTHORIZED_USER_FILE)
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_default_cloud_sdk_authorized_user_configured_project(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def default_cloud_sdk_authorized_user_configured_project(session):
configure_cloud_sdk(session, AUTHORIZED_USER_FILE, project=True)
session.env[EXPECT_PROJECT_ENV] = "1"
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_default.py")
-def session_compute_engine(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def compute_engine(session):
+ session.install(*TEST_DEPENDENCIES)
+ # unset Application Default Credentials so
+ # credentials are detected from environment
+ del session.virtualenv.env["GOOGLE_APPLICATION_CREDENTIALS"]
+ session.install(LIBRARY_DIR)
session.run("pytest", "test_compute_engine.py")
-def session_app_engine(session):
- session.virtualenv = False
-
[email protected](python=["2.7"])
+def app_engine(session):
if SKIP_GAE_TEST_ENV in os.environ:
session.log("Skipping App Engine tests.")
return
@@ -252,6 +276,8 @@
# Vendor in the test application's dependencies
session.chdir(os.path.join(HERE, "app_engine_test_app"))
+ session.install(*TEST_DEPENDENCIES)
+ session.install(LIBRARY_DIR)
session.run(
"pip", "install", "--target", "lib", "-r", "requirements.txt", silent=True
)
@@ -265,7 +291,9 @@
session.run("pytest", "test_app_engine.py")
-def session_grpc(session):
- session.virtualenv = False
[email protected](python=PYTHON_VERSIONS)
+def grpc(session):
+ session.install(LIBRARY_DIR)
+ session.install(*TEST_DEPENDENCIES, "google-cloud-pubsub==1.0.0")
session.env[EXPLICIT_CREDENTIALS_ENV] = SERVICE_ACCOUNT_FILE
session.run("pytest", "test_grpc.py")
diff --git a/system_tests/secrets.tar.enc b/system_tests/secrets.tar.enc
index e61707e..1106f8a 100644
--- a/system_tests/secrets.tar.enc
+++ b/system_tests/secrets.tar.enc
Binary files differ
diff --git a/system_tests/test_compute_engine.py b/system_tests/test_compute_engine.py
index 3fd420c..44f1627 100644
--- a/system_tests/test_compute_engine.py
+++ b/system_tests/test_compute_engine.py
@@ -15,8 +15,8 @@
import pytest
import google.auth
-from google.auth import _helpers
from google.auth import compute_engine
+from google.auth import _helpers
from google.auth import exceptions
from google.auth.compute_engine import _metadata
diff --git a/system_tests/test_grpc.py b/system_tests/test_grpc.py
index ea52830..f025fc0 100644
--- a/system_tests/test_grpc.py
+++ b/system_tests/test_grpc.py
@@ -16,7 +16,9 @@
import google.auth.credentials
import google.auth.jwt
import google.auth.transport.grpc
-from google.cloud.gapic.pubsub.v1 import publisher_client
+from google.cloud import pubsub_v1
+from google.cloud.pubsub_v1.gapic import publisher_client
+from google.cloud.pubsub_v1.gapic.transports import publisher_grpc_transport
def test_grpc_request_with_regular_credentials(http_request):
@@ -25,12 +27,13 @@
credentials, ["https://www.googleapis.com/auth/pubsub"]
)
- channel = google.auth.transport.grpc.secure_authorized_channel(
- credentials, http_request, publisher_client.PublisherClient.SERVICE_ADDRESS
+ transport = publisher_grpc_transport.PublisherGrpcTransport(
+ address=publisher_client.PublisherClient.SERVICE_ADDRESS,
+ credentials=credentials,
)
# Create a pub/sub client.
- client = publisher_client.PublisherClient(channel=channel)
+ client = pubsub_v1.PublisherClient(transport=transport)
# list the topics and drain the iterator to test that an authorized API
# call works.
@@ -40,19 +43,18 @@
def test_grpc_request_with_jwt_credentials():
credentials, project_id = google.auth.default()
- audience = "https://{}/google.pubsub.v1.Publisher".format(
- publisher_client.PublisherClient.SERVICE_ADDRESS
- )
+ audience = "https://pubsub.googleapis.com/google.pubsub.v1.Publisher"
credentials = google.auth.jwt.Credentials.from_signing_credentials(
credentials, audience=audience
)
- channel = google.auth.transport.grpc.secure_authorized_channel(
- credentials, None, publisher_client.PublisherClient.SERVICE_ADDRESS
+ transport = publisher_grpc_transport.PublisherGrpcTransport(
+ address=publisher_client.PublisherClient.SERVICE_ADDRESS,
+ credentials=credentials,
)
# Create a pub/sub client.
- client = publisher_client.PublisherClient(channel=channel)
+ client = pubsub_v1.PublisherClient(transport=transport)
# list the topics and drain the iterator to test that an authorized API
# call works.
@@ -66,12 +68,13 @@
credentials
)
- channel = google.auth.transport.grpc.secure_authorized_channel(
- credentials, None, publisher_client.PublisherClient.SERVICE_ADDRESS
+ transport = publisher_grpc_transport.PublisherGrpcTransport(
+ address=publisher_client.PublisherClient.SERVICE_ADDRESS,
+ credentials=credentials,
)
# Create a pub/sub client.
- client = publisher_client.PublisherClient(channel=channel)
+ client = pubsub_v1.PublisherClient(transport=transport)
# list the topics and drain the iterator to test that an authorized API
# call works.
diff --git a/system_tests/test_oauth2_credentials.py b/system_tests/test_oauth2_credentials.py
index a33b89f..3ecd850 100644
--- a/system_tests/test_oauth2_credentials.py
+++ b/system_tests/test_oauth2_credentials.py
@@ -17,7 +17,7 @@
from google.auth import _helpers
import google.oauth2.credentials
-GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://accounts.google.com/o/oauth2/token"
+GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
def test_refresh(authorized_user_file, http_request, token_info):
@@ -39,9 +39,13 @@
info = token_info(credentials.token)
info_scopes = _helpers.string_to_scopes(info["scope"])
+
+ # Canonical list of scopes at https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login
+ # or do `gcloud auth application-defaut login --help`
assert set(info_scopes) == set(
[
"https://www.googleapis.com/auth/userinfo.email",
- "https://www.googleapis.com/auth/userinfo.profile",
+ "https://www.googleapis.com/auth/cloud-platform",
+ "openid",
]
)
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 59fd6ab..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,92 +0,0 @@
-[tox]
-envlist = lint,py27,py34,py35,py36,pypy,cover,pytype
-
-[testenv]
-deps =
- certifi
- flask
- mock
- oauth2client
- pytest
- pytest-cov
- pytest-localserver
- requests
- requests-oauthlib
- urllib3
- cryptography
- grpcio; platform_python_implementation != 'PyPy'
-commands =
- pytest --cov=google.auth --cov=google.oauth2 --cov=tests {posargs:tests}
-
-[testenv:cover]
-basepython = python3.6
-commands =
- pytest --cov=google.auth --cov=google.oauth2 --cov=tests --cov-report= tests
- coverage report --show-missing --fail-under=100
-deps =
- {[testenv]deps}
-
-[testenv:py36-system]
-basepython = python3.6
-changedir = {toxinidir}/system_tests
-commands =
- nox {posargs}
-deps =
- {[testenv]deps}
- nox-automation
- gapic-google-cloud-pubsub-v1==0.15.0
-passenv =
- SKIP_APP_ENGINE_SYSTEM_TEST
- CLOUD_SDK_ROOT
-
-[testenv:py27-system]
-basepython = python2.7
-changedir = {toxinidir}/system_tests
-commands =
- nox {posargs}
-deps =
- {[testenv]deps}
- nox-automation
- gapic-google-cloud-pubsub-v1==0.15.0
-passenv =
- SKIP_APP_ENGINE_SYSTEM_TEST
- CLOUD_SDK_ROOT
-
-[testenv:docgen]
-basepython = python3.6
-deps =
- {[testenv]deps}
- sphinx
-setenv =
- SPHINX_APIDOC_OPTIONS=members,inherited-members,show-inheritance
-commands =
- rm -r docs/reference
- sphinx-apidoc --output-dir docs/reference --separate --module-first google
-
-[testenv:docs]
-basepython = python3.6
-deps =
- sphinx
- -r{toxinidir}/docs/requirements-docs.txt
-commands = make -C docs html
-
-[testenv:lint]
-basepython = python3.6
-commands =
- flake8 \
- --import-order-style=google \
- --application-import-names="google,tests,system_tests" \
- google tests
- python setup.py check --metadata --restructuredtext --strict
-deps =
- flake8
- flake8-import-order
- docutils
-
-[testenv:pytype]
-basepython = python3.6
-commands =
- pytype
-deps =
- {[testenv]deps}
- pytype