Revert "Upgrade python/google-api-python-client to v1.8.1" am: 31456956be am: 24bd0d3e0d am: f67aafdbb0 am: 5f99e4b376

Change-Id: Ie3cbe7a051bb41ea395d46c31db1b3ccd686aeae
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 7d35265..3d44f3e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -11,33 +11,23 @@
 Please run down the following list and make sure you've tried the usual "quick fixes":
 
   - Search the issues already opened: https://github.com/googleapis/google-api-python-client/issues
-  - Search StackOverflow: https://stackoverflow.com/questions/tagged/google-cloud-platform+python
+  - If you have a question, post on Stackoverflow under the `google-api` tag.
+  - If you are reporting an issue or requesting a feature for a G Suite API, please use their [public issue tracker](https://gsuite-developers.googleblog.com/2017/03/a-new-issue-tracker-for-g-suite.html)
 
 If you are still having issues, please be sure to include as much information as possible:
 
 #### Environment details
 
-  - OS type and version:
-  - Python version: `python --version`
-  - pip version: `pip --version`
-  - `google-api-python-client` version: `pip show google-api-python-client`
+  - OS:
+  - Python version:
+  - pip version:
+  - `google-api-python-client` version:
 
 #### Steps to reproduce
 
   1. ?
   2. ?
 
-#### Code example
-
-```python
-# example
-```
-
-#### Stack trace
-```
-# example
-```
-
 Making sure to follow these steps will guarantee the quickest resolution possible.
 
 Thanks!
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index 24c6fa8..0000000
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
-- [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/google-api-python-client/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
-- [ ] Ensure the tests and linter pass
-- [ ] Code coverage does not decrease (if any source code was changed)
-- [ ] Appropriate docs were updated (if necessary)
-
-Fixes #<issue_number_goes_here> 🦕
diff --git a/.github/release-please.yml b/.github/release-please.yml
deleted file mode 100644
index 4507ad0..0000000
--- a/.github/release-please.yml
+++ /dev/null
@@ -1 +0,0 @@
-releaseType: python
diff --git a/.gitignore b/.gitignore
index 1637b1d..cf2c4a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@
 dist/
 
 # Test files
-.nox/
+.tox/
 
 # Coverage files
 .coverage
diff --git a/.kokoro/build.sh b/.kokoro/build.sh
index ab8cebb..e0c966b 100755
--- a/.kokoro/build.sh
+++ b/.kokoro/build.sh
@@ -1,17 +1,4 @@
 #!/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
 
@@ -20,20 +7,7 @@
 # Disable buffering, so that the logs stream through.
 export PYTHONUNBUFFERED=1
 
-# Debug: show build environment
-env | grep KOKORO
+python3 -m pip install --upgrade tox
 
-# Setup service account credentials.
-export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json
-
-# Setup project id.
-export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.json")
-
-# 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
+# Run tests
+tox
diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg
new file mode 100644
index 0000000..c21dc6d
--- /dev/null
+++ b/.kokoro/common.cfg
@@ -0,0 +1,19 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "google-api-python-client/.kokoro/trampoline.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+}
+
+# Tell the trampoline which build file to use.
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/google-api-python-client/.kokoro/build.sh"
+}
diff --git a/.kokoro/continuous/continuous.cfg b/.kokoro/continuous/continuous.cfg
index 8f43917..18a4c35 100644
--- a/.kokoro/continuous/continuous.cfg
+++ b/.kokoro/continuous/continuous.cfg
@@ -1 +1 @@
-# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
+# Format: //devtools/kokoro/config/proto/build.proto
diff --git a/.kokoro/presubmit/presubmit.cfg b/.kokoro/presubmit/presubmit.cfg
index 8f43917..18a4c35 100644
--- a/.kokoro/presubmit/presubmit.cfg
+++ b/.kokoro/presubmit/presubmit.cfg
@@ -1 +1 @@
-# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
+# Format: //devtools/kokoro/config/proto/build.proto
diff --git a/.kokoro/release.sh b/.kokoro/release.sh
deleted file mode 100755
index b4756d0..0000000
--- a/.kokoro/release.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-# Copyright 2020 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.
-
-#!/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-api-python-client
-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
deleted file mode 100644
index 6a8864b..0000000
--- a/.kokoro/release/common.cfg
+++ /dev/null
@@ -1,64 +0,0 @@
-# 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-api-python-client/.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-api-python-client/.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
deleted file mode 100644
index 8f43917..0000000
--- a/.kokoro/release/release.cfg
+++ /dev/null
@@ -1 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
\ No newline at end of file
diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh
index e8c4251..0efc3be 100755
--- a/.kokoro/trampoline.sh
+++ b/.kokoro/trampoline.sh
@@ -12,12 +12,13 @@
 # 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
-
-python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py"  || ret_code=$?
-
-chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
-${KOKORO_GFILE_DIR}/trampoline_cleanup.sh || true
-
-exit ${ret_code}
+# Always run the cleanup script, regardless of the success of bouncing into
+# the container.
+function cleanup() {
+    chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+    ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+    echo "cleanup";
+}
+trap cleanup EXIT
+python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py"
diff --git a/.repo-metadata.json b/.repo-metadata.json
deleted file mode 100644
index 1b810b0..0000000
--- a/.repo-metadata.json
+++ /dev/null
@@ -1,11 +0,0 @@
-  
-{
-    "name": "google-api-python-client",
-    "name_pretty": "Google API Python Client",
-    "client_documentation": "https://github.com/googleapis/google-api-python-client/tree/master/docs#google-api-client-library-for-python-docs",
-    "issue_tracker": "https://github.com/googleapis/google-api-python-client/issues",
-    "release_level": "ga",
-    "language": "python",
-    "repo": "googleapis/google-api-python-client",
-    "distribution_name": "google-api-python-client"
-  }
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG
similarity index 92%
rename from CHANGELOG.md
rename to CHANGELOG
index b0eb4fb..92b744e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG
@@ -1,25 +1,4 @@
-# Changelog
-
-### [1.8.1](https://www.github.com/googleapis/google-api-python-client/compare/v1.8.0...v1.8.1) (2020-04-20)
-
-
-### Bug Fixes
-
-* Adding ConnectionError to retry mechanism ([#822](https://www.github.com/googleapis/google-api-python-client/issues/822)) ([c7516a2](https://www.github.com/googleapis/google-api-python-client/commit/c7516a2ea2c229479633690c109f8763dc0b30ed)), closes [googleapis#558](https://www.github.com/googleapis/googleapis/issues/558)
-* replace '-' in method names with '_' ([#863](https://www.github.com/googleapis/google-api-python-client/issues/863)) ([8ed729f](https://www.github.com/googleapis/google-api-python-client/commit/8ed729f1d868a8713ab442bf0bf59e77ba36afb6))
-
-### v1.8.0
-  Version 1.8.0
-
-  Release to support API endpoint override.
-
-  New Features
-  - Add api endpoint override. ([#829](https://github.com/googleapis/google-api-python-client/pull/829))
-
-  Implementation Changes
-  - Don't set http.redirect_codes if the attr doesn't exist and allow more httplib2 versions. ([#841](https://github.com/googleapis/google-api-python-client/pull/841))
-
-### v1.7.12
+v1.7.12
   Version 1.7.12
   
   Bugfix release
@@ -49,7 +28,7 @@
   - Blacken ([#772](https://github.com/googleapis/google-api-python-client/pull/722))
   - Move kokoro configs ([#832](https://github.com/googleapis/google-api-python-client/pull/832))
   
-### v1.7.11
+v1.7.11
   Version 1.7.11
 
   Bugfix release
@@ -61,7 +40,7 @@
   - Fix typo in filename used in 'docs/auth.md' ([#736](https://github.com/googleapis/google-api-python-client/pull/736))
 
   
-### v1.7.10
+v1.7.10
   Version 1.7.10
 
   Bugfix release
@@ -83,21 +62,21 @@
   - tox.ini: Look for Python syntax errors and undefined names ([#721](https://github.com/googleapis/google-api-python-client/pull/721))
 
 
-### v1.7.9
+v1.7.9
   Version 1.7.9
 
   Bugfix release
   - Remove Django Samples. ([#657](https://github.com/googleapis/google-api-python-client/pull/657))
   - Call request_orig with kwargs ([#658](https://github.com/googleapis/google-api-python-client/pull/658))
 
-### v1.7.8
+v1.7.8
   Version 1.7.8
 
   Bugfix release
   - Convert '$' in method name to '_' ([#616](https://github.com/googleapis/google-api-python-client/pull/616))
   - Alias unitest2 import as unittest in test__auth.py ([#613](https://github.com/googleapis/google-api-python-client/pull/613))
 
-### v1.7.7
+v1.7.7
   Version 1.7.7
 
     Bugfix release
@@ -110,28 +89,28 @@
 
     - Add badges ([#455](https://github.com/google/google-api-python-client/pull/455))
 
-### v1.7.6
+v1.7.6
   Version 1.7.6
 
   Bugfix release
 
   - Add client-side limit for batch requests (#585)
 
-### v1.7.5
+v1.7.5
   Version 1.7.5
 
   Bugfix release
 
   - Fix the client to respect the passed in developerKey and credentials
 
-### v1.7.4
+v1.7.4
   Version 1.7.4
 
   Bugfix release
 
   - Catch ServerNotFoundError to retry the request (#532)
 
-### v1.7.3
+v1.7.3
   Version 1.7.3
 
   Bugfix release
@@ -139,21 +118,21 @@
   - Make apiclient.sample_tools gracefully fail to import (#525).
 
 
-### v1.7.2
+v1.7.2
   Version 1.7.2
 
   Bugfix release
 
   - Remove unnecessary check in apiclient/__ini__.py (#522).
 
-### v1.7.1
+v1.7.1
   Version 1.7.1
 
   Bugfix release
 
   - Remove unnecessary check in setup.py (#518).
 
-### v1.7.0
+v1.7.0
   Version 1.7.0
 
   This release drops the hard requirement on oauth2client and installs
@@ -163,7 +142,7 @@
   - Drop oauth2client dependency (#499)
   - Include tests in source distribution (#514)
 
-### v1.6.7
+v1.6.7
   Version 1.6.7
 
   Bugfix release
@@ -180,7 +159,7 @@
   - discovery.py: remove unused oauth2client import. (#492)
   - Update README to reference GCP API client libraries. (#490)
 
-### v1.6.6
+v1.6.6
   Version 1.6.6
 
   Bugfix release
@@ -189,7 +168,7 @@
   - Increase the default media chunksize to 100MB. (#482)
   - Remove unnecessary parsing of mime headers in HttpRequest.__init__ (#467)
 
-### v1.6.5
+v1.6.5
   Version 1.6.5
 
   Bugfix release
@@ -208,14 +187,14 @@
   - Handle variant error format gracefully. (#459)
   - Avoid testing against Django >= 2.0.0 on Python 2. (#460)
 
-### v1.6.4
+v1.6.4
   Version 1.6.4
 
   Bugfix release
 
   - Warn when google-auth credentials are used but google-auth-httplib2 isn't available. (#443)
 
-### v1.6.3
+v1.6.3
   Version 1.6.3
 
   Bugfix release
@@ -231,7 +210,7 @@
   - Don't treat httplib2.Credentials as oauth credentials. (#425)
   - Various fixes to the Django sample. (#413)
 
-### v1.6.2
+v1.6.2
   Version 1.6.2
 
   Bugfix release
@@ -240,14 +219,14 @@
     when a developerKey was specified. (#347)
   - Official support for Python 3.5 and 3.6. (#341)
  
-### v1.6.1
+v1.6.1
   Version 1.6.1
 
   Bugfix release
 
   - Fixed a bug where using google-auth with scoped credentials would fail. (#328)
 
-### v1.6.0
+v1.6.0
   Version 1.6.0
 
   Release to drop support for Python 2.6 and add support for google-auth.
@@ -268,7 +247,7 @@
   - Fixed resumable upload failure when receiving a 308 response. (#312)
   - Clarified the support versions of Python 3. (#316)
 
-### v1.5.5
+v1.5.5
   Version 1.5.5
 
   Bugfix release
@@ -278,7 +257,7 @@
   - Refresh all discovery docs, not just the preferred ones. (#298)
   - Update minimum httplib2 dependency to >=0.9.2.
 
-### v1.5.4
+v1.5.4
   Version 1.5.4
 
   Bugfix release
@@ -288,14 +267,14 @@
   - Allow oauth2client 4.0.0, with the caveat that file-based discovery
     caching is disabled.
 
-### v1.5.3
+v1.5.3
   Version 1.5.3
 
   Bugfix release
 
   - Fixed import error with oauth2client >= 3.0.0. (#270)
 
-### v1.5.2
+v1.5.2
   Version 1.5.2
 
   Bugfix release
@@ -306,7 +285,7 @@
   - Obtain access token if necessary in BatchHttpRequest.execute(). (#232)
   - Warn when running tests using HttpMock without having a cache. (#261)
 
-### v1.5.1
+v1.5.1
   Version 1.5.1
 
   Bugfix release
@@ -319,7 +298,7 @@
   - Use named loggers instead of the root logger. (#206)
   - New search console example. (#212)
 
-### v1.5.0
+v1.5.0
   Version 1.5.0
 
   Release to support oauth2client >= 2.0.0.
@@ -330,22 +309,22 @@
   - Handle SSL errors with retries (#160)
   - Fix incompatibility with oauth2client v2.0.0 (#182)
 
-### v1.4.2
+v1.4.2
   Version 1.4.2
 
   Add automatic caching for the discovery docs.
 
-### v1.4.1
+v1.4.1
   Version 1.4.1
 
   Add the googleapiclient.discovery.Resource.new_batch_http_request method.
 
-### v1.4.0
+v1.4.0
   Version 1.4.0
 
   Python 3 support.
 
-### v1.3.2
+v1.3.2
   Version 1.3.2
 
   Small bugfix release.
@@ -355,12 +334,12 @@
   - Better handling of `content-length` in media requests.
   - Add support for methodPath entries containing colon.
 
-### v1.3.1
+v1.3.1
   Version 1.3.1
 
   Quick release for a fix around aliasing in v1.3.
 
-### v1.3
+v1.3
   Version 1.3
 
   Add support for the Google Application Default Credentials.
@@ -379,7 +358,7 @@
       setup.py attempts to detect this and prevents it. Simply remove
       the previous version and reinstall to fix this.
 
-### v1.2
+v1.2
   Version 1.2
 
   The use of the gflags library is now deprecated, and is no longer a
@@ -405,7 +384,7 @@
   - Update AdExchange Buyer API examples to version v1.2.
 
 
-### v1.1
+v1.1
   Version 1.1
 
   Add PEM support to SignedJWTAssertionCredentials (used to only support
@@ -433,12 +412,12 @@
   - Ensure that dataWrapper feature is checked before using the 'data' value.
   - HMAC verification does not use a constant time algorithm.
 
-### v1.0
+v1.0
  Version 1.0
 
   - Changes to the code for running tests and building releases.
 
-### v1.0c3
+v1.0c3
  Version 1.0 Release Candidate 3
 
   - In samples and oauth2 decorator, escape untrusted content before displaying it.
@@ -461,7 +440,7 @@
   - oauth2client support for URL-encoded format of exchange token response (e.g.  Facebook)
   - Build cleaner and easier to read docs for dynamic surfaces.
 
-### v1.0c2
+v1.0c2
  Version 1.0 Release Candidate 2
 
   - Parameter values of None should be treated as missing. Fixes issue #144.
@@ -469,7 +448,7 @@
   - Move all remaining samples over to client_secrets.json. Fixes issue #156.
   - Make locked_file.py understand win32file primitives for better awesomeness.
 
-### v1.0c1
+v1.0c1
  Version 1.0 Release Candidate 1
 
  - Documentation for the library has switched to epydoc:
@@ -494,7 +473,7 @@
    * new analytics api samples. Reviewed here: http://codereview.appspot.com/5494058/
  - Convert all inline samples to the Farm API for consistency.
 
-### v1.0beta8
+v1.0beta8
  - Updated meda upload support.
  - Many fixes for batch requests.
  - Better handling for requests that don't require a body.
@@ -509,7 +488,7 @@
       'body' parameter in your call. The solution is to remove the unneeded
       body={} parameter.
 
-### v1.0beta7
+v1.0beta7
  - Support for batch requests.  http://code.google.com/p/google-api-python-client/wiki/Batch
  - Support for media upload.  http://code.google.com/p/google-api-python-client/wiki/MediaUpload
  - Better handling for APIs that return something other than JSON.
diff --git a/METADATA b/METADATA
index cd76b0c..440c5d9 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,10 @@
     type: GIT
     value: "https://github.com/google/google-api-python-client"
   }
-  version: "v1.8.1"
+  version: "v1.7.12"
   last_upgrade_date {
     year: 2020
-    month: 4
-    day: 20
+    month: 3
+    day: 11
   }
 }
diff --git a/README.md b/README.md
index 1ed3078..ee38961 100644
--- a/README.md
+++ b/README.md
@@ -10,14 +10,12 @@
 
 See the [docs folder](docs/README.md) for more detailed instructions and additional documentation.
 
-## Other Google API libraries
+## Google Cloud Platform / Google Ads
 
 For Google Cloud Platform APIs such as Datastore, Cloud Storage or Pub/Sub, we recommend using [Cloud Client Libraries for Python](https://github.com/GoogleCloudPlatform/google-cloud-python).
 
 For Google Ads API, we recommend using [Google Ads API Client Library for Python](https://github.com/googleads/google-ads-python/).
 
-For Google Firebase Admin API, we recommend using [Firebase Admin Python SDK](https://github.com/firebase/firebase-admin-python).
-
 ## Installation
 
 Install this library in a [virtualenv](https://virtualenv.pypa.io/en/latest/) using pip. virtualenv is a tool to
diff --git a/googleapiclient/__init__.py b/googleapiclient/__init__.py
index c9218dd..140b946 100644
--- a/googleapiclient/__init__.py
+++ b/googleapiclient/__init__.py
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+__version__ = "1.7.12"
+
 # Set default logging handler to avoid "No handler found" warnings.
 import logging
 
diff --git a/googleapiclient/discovery.py b/googleapiclient/discovery.py
index 66d4927..87403b9 100644
--- a/googleapiclient/discovery.py
+++ b/googleapiclient/discovery.py
@@ -46,7 +46,6 @@
 # Third-party imports
 import httplib2
 import uritemplate
-import google.api_core.client_options
 
 # Local imports
 from googleapiclient import _auth
@@ -131,10 +130,10 @@
     name: string, method name.
 
   Returns:
-    The name with '_' appended if the name is a reserved word and '$' and '-'
+    The name with '_' appended if the name is a reserved word and '$' 
     replaced with '_'. 
   """
-    name = name.replace("$", "_").replace("-", "_")
+    name = name.replace("$", "_")
     if keyword.iskeyword(name) or name in RESERVED_WORDS:
         return name + "_"
     else:
@@ -177,7 +176,6 @@
     credentials=None,
     cache_discovery=True,
     cache=None,
-    client_options=None,
 ):
     """Construct a Resource for interacting with an API.
 
@@ -204,8 +202,6 @@
     cache_discovery: Boolean, whether or not to cache the discovery doc.
     cache: googleapiclient.discovery_cache.base.CacheBase, an optional
       cache object for the discovery documents.
-    client_options: Dictionary or google.api_core.client_options, Client options to set user
-      options on the client. API endpoint should be set through client_options.
 
   Returns:
     A Resource object with methods for interacting with the service.
@@ -232,7 +228,6 @@
                 model=model,
                 requestBuilder=requestBuilder,
                 credentials=credentials,
-                client_options=client_options
             )
         except HttpError as e:
             if e.resp.status == http_client.NOT_FOUND:
@@ -309,7 +304,6 @@
     model=None,
     requestBuilder=HttpRequest,
     credentials=None,
-    client_options=None
 ):
     """Create a Resource for interacting with an API.
 
@@ -334,8 +328,6 @@
     credentials: oauth2client.Credentials or
       google.auth.credentials.Credentials, credentials to be used for
       authentication.
-    client_options: Dictionary or google.api_core.client_options, Client options to set user
-      options on the client. API endpoint should be set through client_options.
 
   Returns:
     A Resource object with methods for interacting with the service.
@@ -358,16 +350,7 @@
         )
         raise InvalidJsonError()
 
-    # If an API Endpoint is provided on client options, use that as the base URL
-    base = urljoin(service['rootUrl'], service["servicePath"])
-    if client_options:
-        if type(client_options) == dict:
-            client_options = google.api_core.client_options.from_dict(
-                client_options
-            )
-        if client_options.api_endpoint:
-            base = client_options.api_endpoint
-
+    base = urljoin(service["rootUrl"], service["servicePath"])
     schema = Schemas(service)
 
     # If the http client is not specified, then we must construct an http client
diff --git a/googleapiclient/http.py b/googleapiclient/http.py
index 4125666..719664d 100644
--- a/googleapiclient/http.py
+++ b/googleapiclient/http.py
@@ -81,11 +81,6 @@
 
 _LEGACY_BATCH_URI = "https://www.googleapis.com/batch"
 
-if six.PY2:
-    # That's a builtin python3 exception, nonexistent in python2.
-    # Defined to None to avoid NameError while trying to catch it
-    ConnectionError = None
-
 
 def _should_retry_response(resp_status, content):
     """Determines whether a response should be retried.
@@ -182,10 +177,6 @@
             # It's important that this be before socket.error as it's a subclass
             # socket.timeout has no errorcode
             exception = socket_timeout
-        except ConnectionError as connection_error:
-            # Needs to be before socket.error as it's a subclass of
-            # OSError (socket.error)
-            exception = connection_error
         except socket.error as socket_error:
             # errno's contents differ by platform, so we have to match by name.
             if socket.errno.errorcode.get(socket_error.errno) not in {
@@ -1760,18 +1751,16 @@
         connection_type=None,
     ):
         resp, content = self._iterable.pop(0)
-        content = six.ensure_binary(content)
-
-        if content == b"echo_request_headers":
+        if content == "echo_request_headers":
             content = headers
-        elif content == b"echo_request_headers_as_json":
+        elif content == "echo_request_headers_as_json":
             content = json.dumps(headers)
-        elif content == b"echo_request_body":
+        elif content == "echo_request_body":
             if hasattr(body, "read"):
                 content = body.read()
             else:
                 content = body
-        elif content == b"echo_request_uri":
+        elif content == "echo_request_uri":
             content = uri
         if isinstance(content, six.text_type):
             content = content.encode("utf-8")
@@ -1902,13 +1891,6 @@
     # for Resumable Uploads rather than Permanent Redirects.
     # This asks httplib2 to exclude 308s from the status codes
     # it treats as redirects
-    try:
-      http.redirect_codes = http.redirect_codes - {308}
-    except AttributeError:
-      # Apache Beam tests depend on this library and cannot
-      # currently upgrade their httplib2 version
-      # http.redirect_codes does not exist in previous versions
-      # of httplib2, so pass
-      pass
+    http.redirect_codes = http.redirect_codes - {308}
 
     return http
diff --git a/googleapiclient/model.py b/googleapiclient/model.py
index f58549c..554056e 100644
--- a/googleapiclient/model.py
+++ b/googleapiclient/model.py
@@ -27,13 +27,12 @@
 import json
 import logging
 import platform
-import pkg_resources
 
 from six.moves.urllib.parse import urlencode
 
+from googleapiclient import __version__
 from googleapiclient.errors import HttpError
 
-_LIBRARY_VERSION = pkg_resources.get_distribution("google-api-python-client").version
 _PY_VERSION = platform.python_version()
 
 LOGGER = logging.getLogger(__name__)
@@ -153,7 +152,7 @@
         else:
             headers["x-goog-api-client"] = ""
         headers["x-goog-api-client"] += "gdcl/%s gl-python/%s" % (
-            _LIBRARY_VERSION,
+            __version__,
             _PY_VERSION,
         )
 
@@ -219,7 +218,7 @@
                 return self.no_content_response
             return self.deserialize(content)
         else:
-            LOGGER.debug("Content from bad request was: %r" % content)
+            LOGGER.debug("Content from bad request was: %s" % content)
             raise HttpError(resp, content)
 
     def serialize(self, body_value):
diff --git a/noxfile.py b/noxfile.py
deleted file mode 100644
index 438ff41..0000000
--- a/noxfile.py
+++ /dev/null
@@ -1,78 +0,0 @@
-
-# Copyright 2020 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 = [
-    "google-auth",
-    "google-auth-httplib2",
-    "mox",
-    "pyopenssl",
-    "pytest",
-    "pytest-cov",
-    "webtest",
-    "coverage",
-    "unittest2",
-    "mock",
-]
-
-
[email protected](python=["3.7"])
-def lint(session):
-    session.install("flake8")
-    session.run(
-        "flake8",
-        "googleapiclient",
-        "tests",
-        "--count",
-        "--select=E9,F63,F7,F82",
-        "--show-source",
-        "--statistics",
-    )
-
-
[email protected](
-    "oauth2client",
-    [
-        "oauth2client<2dev",
-        "oauth2client>=2,<=3dev",
-        "oauth2client>=3,<=4dev",
-        "oauth2client>=4,<=5dev",
-    ],
-)
[email protected](python=["2.7", "3.5", "3.6", "3.7"])
-def unit(session, oauth2client):
-    session.install(*test_dependencies)
-    session.install(oauth2client)
-    if session.python < "3.0":
-        session.install("django<2.0.0")
-    else:
-        session.install("django>=2.0.0")
-
-    session.install('.')
-
-    # Run py.test against the unit tests.
-    session.run(
-        "py.test",
-        "--quiet",
-        "--cov=googleapiclient",
-        "--cov=tests",
-        "--cov-append",
-        "--cov-config=.coveragerc",
-        "--cov-report=",
-        "--cov-fail-under=85",
-        "tests",
-        *session.posargs,
-    )
\ No newline at end of file
diff --git a/renovate.json b/renovate.json
deleted file mode 100644
index f45d8f1..0000000
--- a/renovate.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "extends": [
-    "config:base"
-  ]
-}
diff --git a/setup.py b/setup.py
index 60974fb..617515b 100644
--- a/setup.py
+++ b/setup.py
@@ -28,40 +28,31 @@
     print("google-api-python-client requires python3 version >= 3.4.", file=sys.stderr)
     sys.exit(1)
 
-import io
-import os
 from setuptools import setup
 
 packages = ["apiclient", "googleapiclient", "googleapiclient/discovery_cache"]
 
 install_requires = [
-    # NOTE: Apache Beam tests depend on this library and cannot
-    # currently upgrade their httplib2 version.
-    # Please see https://github.com/googleapis/google-api-python-client/pull/841
-    "httplib2>=0.9.2,<1dev",
+    "httplib2>=0.17.0,<1dev",
     "google-auth>=1.4.1",
     "google-auth-httplib2>=0.0.3",
-    "google-api-core>=1.13.0,<2dev",
     "six>=1.6.1,<2dev",
     "uritemplate>=3.0.0,<4dev",
 ]
 
-package_root = os.path.abspath(os.path.dirname(__file__))
+long_desc = """The Google API Client for Python is a client library for
+accessing the Plus, Moderator, and many other Google APIs."""
 
-readme_filename = os.path.join(package_root, "README.md")
-with io.open(readme_filename, encoding="utf-8") as readme_file:
-    readme = readme_file.read()
+import googleapiclient
 
-version = "1.8.1"
+version = googleapiclient.__version__
 
 setup(
     name="google-api-python-client",
     version=version,
     description="Google API Client Library for Python",
-    long_description=readme,
-    long_description_content_type='text/markdown',
-    author="Google LLC",
-    author_email="[email protected]",
+    long_description=long_desc,
+    author="Google Inc.",
     url="http://github.com/google/google-api-python-client/",
     install_requires=install_requires,
     python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
@@ -73,6 +64,7 @@
         "Programming Language :: Python :: 2",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.4",
         "Programming Language :: Python :: 3.5",
         "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
diff --git a/synth.metadata b/synth.metadata
deleted file mode 100644
index d06a0f1..0000000
--- a/synth.metadata
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "updateTime": "2020-03-30T20:47:31.469660Z",
-  "sources": [
-    {
-      "git": {
-        "name": "synthtool",
-        "remote": "https://github.com/googleapis/synthtool.git",
-        "sha": "f5e8c88d9870d8aa4eb43fa0b39f07e02bfbe4df"
-      }
-    }
-  ]
-}
\ No newline at end of file
diff --git a/synth.py b/synth.py
deleted file mode 100644
index 017717d..0000000
--- a/synth.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2020 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 synthtool as s
-from synthtool import gcp
-
-common = gcp.CommonTemplates()
-
-# ----------------------------------------------------------------------------
-# Add templated files
-# ----------------------------------------------------------------------------
-templated_files = common.py_library()
-
-# Copy kokoro configs.
-# Docs are excluded as repo docs cannot currently be generated using sphinx.
-s.move(templated_files / '.kokoro', excludes=['**/docs/*', 'publish-docs.sh'])
-
-# Also move issue templates
-s.move(templated_files / '.github')
\ No newline at end of file
diff --git a/tests/test_discovery.py b/tests/test_discovery.py
index 6400f21..f85035e 100644
--- a/tests/test_discovery.py
+++ b/tests/test_discovery.py
@@ -466,7 +466,7 @@
         plus = build_from_document(
             discovery, base=base, credentials=self.MOCK_CREDENTIALS
         )
-        self.assertEqual("https://www.googleapis.com/plus/v1/", plus._baseUrl)
+        self.assertEquals("https://www.googleapis.com/plus/v1/", plus._baseUrl)
 
     def test_building_with_optional_http_with_authorization(self):
         discovery = open(datafile("plus.json")).read()
@@ -503,7 +503,7 @@
         plus = build_from_document(
             discovery, base="https://www.googleapis.com/", http=http
         )
-        self.assertEqual(plus._http, http)
+        self.assertEquals(plus._http, http)
 
     def test_building_with_developer_key_skips_adc(self):
         discovery = open(datafile("plus.json")).read()
@@ -515,25 +515,6 @@
         # application default credentials were used.
         self.assertNotIsInstance(plus._http, google_auth_httplib2.AuthorizedHttp)
 
-    def test_api_endpoint_override_from_client_options(self):
-        discovery = open(datafile("plus.json")).read()
-        api_endpoint = "https://foo.googleapis.com/"
-        options = google.api_core.client_options.ClientOptions(
-            api_endpoint=api_endpoint
-        )
-        plus = build_from_document(discovery, client_options=options)
-
-        self.assertEqual(plus._baseUrl, api_endpoint)
-
-    def test_api_endpoint_override_from_client_options_dict(self):
-        discovery = open(datafile("plus.json")).read()
-        api_endpoint = "https://foo.googleapis.com/"
-        plus = build_from_document(
-            discovery, client_options={"api_endpoint": api_endpoint}
-        )
-
-        self.assertEqual(plus._baseUrl, api_endpoint)
-
 
 class DiscoveryFromHttp(unittest.TestCase):
     def setUp(self):
@@ -607,39 +588,6 @@
         zoo = build("zoo", "v1", http=http, cache_discovery=False)
         self.assertTrue(hasattr(zoo, "animals"))
 
-    def test_api_endpoint_override_from_client_options(self):
-        http = HttpMockSequence(
-            [
-                ({"status": "404"}, "Not found"),
-                ({"status": "200"}, open(datafile("zoo.json"), "rb").read()),
-            ]
-        )
-        api_endpoint = "https://foo.googleapis.com/"
-        options = google.api_core.client_options.ClientOptions(
-            api_endpoint=api_endpoint
-        )
-        zoo = build(
-            "zoo", "v1", http=http, cache_discovery=False, client_options=options
-        )
-        self.assertEqual(zoo._baseUrl, api_endpoint)
-
-    def test_api_endpoint_override_from_client_options_dict(self):
-        http = HttpMockSequence(
-            [
-                ({"status": "404"}, "Not found"),
-                ({"status": "200"}, open(datafile("zoo.json"), "rb").read()),
-            ]
-        )
-        api_endpoint = "https://foo.googleapis.com/"
-        zoo = build(
-            "zoo",
-            "v1",
-            http=http,
-            cache_discovery=False,
-            client_options={"api_endpoint": api_endpoint},
-        )
-        self.assertEqual(zoo._baseUrl, api_endpoint)
-
 
 class DiscoveryFromAppEngineCache(unittest.TestCase):
     def test_appengine_memcache(self):
@@ -980,8 +928,8 @@
         self.http = HttpMock(datafile("zoo.json"), {"status": "200"})
         zoo = build("zoo", "v1", http=self.http)
         request = zoo.animals().crossbreed(media_body=datafile("small.png"))
-        self.assertEqual("image/png", request.headers["content-type"])
-        self.assertEqual(b"PNG", request.body[1:4])
+        self.assertEquals("image/png", request.headers["content-type"])
+        self.assertEquals(b"PNG", request.body[1:4])
 
     def test_simple_media_raise_correct_exceptions(self):
         self.http = HttpMock(datafile("zoo.json"), {"status": "200"})
@@ -1004,8 +952,8 @@
         zoo = build("zoo", "v1", http=self.http)
 
         request = zoo.animals().insert(media_body=datafile("small.png"))
-        self.assertEqual("image/png", request.headers["content-type"])
-        self.assertEqual(b"PNG", request.body[1:4])
+        self.assertEquals("image/png", request.headers["content-type"])
+        self.assertEquals(b"PNG", request.body[1:4])
         assertUrisEqual(
             self,
             "https://www.googleapis.com/upload/zoo/v1/animals?uploadType=media&alt=json",
@@ -1025,8 +973,8 @@
         request = zoo.animals().insert(
             media_body=datafile("small-png"), media_mime_type="image/png"
         )
-        self.assertEqual("image/png", request.headers["content-type"])
-        self.assertEqual(b"PNG", request.body[1:4])
+        self.assertEquals("image/png", request.headers["content-type"])
+        self.assertEquals(b"PNG", request.body[1:4])
         assertUrisEqual(
             self,
             "https://www.googleapis.com/upload/zoo/v1/animals?uploadType=media&alt=json",
@@ -1097,13 +1045,13 @@
         media_upload = MediaFileUpload(datafile("small.png"), resumable=True)
         request = zoo.animals().insert(media_body=media_upload, body={})
         self.assertTrue(request.headers["content-type"].startswith("application/json"))
-        self.assertEqual('{"data": {}}', request.body)
-        self.assertEqual(media_upload, request.resumable)
+        self.assertEquals('{"data": {}}', request.body)
+        self.assertEquals(media_upload, request.resumable)
 
-        self.assertEqual("image/png", request.resumable.mimetype())
+        self.assertEquals("image/png", request.resumable.mimetype())
 
         self.assertNotEquals(request.body, None)
-        self.assertEqual(request.resumable_uri, None)
+        self.assertEquals(request.resumable_uri, None)
 
         http = HttpMockSequence(
             [
@@ -1130,32 +1078,32 @@
         )
 
         status, body = request.next_chunk(http=http)
-        self.assertEqual(None, body)
+        self.assertEquals(None, body)
         self.assertTrue(isinstance(status, MediaUploadProgress))
-        self.assertEqual(0, status.resumable_progress)
+        self.assertEquals(0, status.resumable_progress)
 
         # Two requests should have been made and the resumable_uri should have been
         # updated for each one.
-        self.assertEqual(request.resumable_uri, "http://upload.example.com/2")
-        self.assertEqual(media_upload, request.resumable)
-        self.assertEqual(0, request.resumable_progress)
+        self.assertEquals(request.resumable_uri, "http://upload.example.com/2")
+        self.assertEquals(media_upload, request.resumable)
+        self.assertEquals(0, request.resumable_progress)
 
         # This next chuck call should upload the first chunk
         status, body = request.next_chunk(http=http)
-        self.assertEqual(request.resumable_uri, "http://upload.example.com/3")
-        self.assertEqual(media_upload, request.resumable)
-        self.assertEqual(13, request.resumable_progress)
+        self.assertEquals(request.resumable_uri, "http://upload.example.com/3")
+        self.assertEquals(media_upload, request.resumable)
+        self.assertEquals(13, request.resumable_progress)
 
         # This call will upload the next chunk
         status, body = request.next_chunk(http=http)
-        self.assertEqual(request.resumable_uri, "http://upload.example.com/4")
-        self.assertEqual(media_upload.size() - 1, request.resumable_progress)
-        self.assertEqual('{"data": {}}', request.body)
+        self.assertEquals(request.resumable_uri, "http://upload.example.com/4")
+        self.assertEquals(media_upload.size() - 1, request.resumable_progress)
+        self.assertEquals('{"data": {}}', request.body)
 
         # Final call to next_chunk should complete the upload.
         status, body = request.next_chunk(http=http)
-        self.assertEqual(body, {"foo": "bar"})
-        self.assertEqual(status, None)
+        self.assertEquals(body, {"foo": "bar"})
+        self.assertEquals(status, None)
 
     def test_resumable_media_good_upload(self):
         """Not a multipart upload."""
@@ -1164,12 +1112,12 @@
 
         media_upload = MediaFileUpload(datafile("small.png"), resumable=True)
         request = zoo.animals().insert(media_body=media_upload, body=None)
-        self.assertEqual(media_upload, request.resumable)
+        self.assertEquals(media_upload, request.resumable)
 
-        self.assertEqual("image/png", request.resumable.mimetype())
+        self.assertEquals("image/png", request.resumable.mimetype())
 
-        self.assertEqual(request.body, None)
-        self.assertEqual(request.resumable_uri, None)
+        self.assertEquals(request.body, None)
+        self.assertEquals(request.resumable_uri, None)
 
         http = HttpMockSequence(
             [
@@ -1195,26 +1143,26 @@
         )
 
         status, body = request.next_chunk(http=http)
-        self.assertEqual(None, body)
+        self.assertEquals(None, body)
         self.assertTrue(isinstance(status, MediaUploadProgress))
-        self.assertEqual(13, status.resumable_progress)
+        self.assertEquals(13, status.resumable_progress)
 
         # Two requests should have been made and the resumable_uri should have been
         # updated for each one.
-        self.assertEqual(request.resumable_uri, "http://upload.example.com/2")
+        self.assertEquals(request.resumable_uri, "http://upload.example.com/2")
 
-        self.assertEqual(media_upload, request.resumable)
-        self.assertEqual(13, request.resumable_progress)
+        self.assertEquals(media_upload, request.resumable)
+        self.assertEquals(13, request.resumable_progress)
 
         status, body = request.next_chunk(http=http)
-        self.assertEqual(request.resumable_uri, "http://upload.example.com/3")
-        self.assertEqual(media_upload.size() - 1, request.resumable_progress)
-        self.assertEqual(request.body, None)
+        self.assertEquals(request.resumable_uri, "http://upload.example.com/3")
+        self.assertEquals(media_upload.size() - 1, request.resumable_progress)
+        self.assertEquals(request.body, None)
 
         # Final call to next_chunk should complete the upload.
         status, body = request.next_chunk(http=http)
-        self.assertEqual(body, {"foo": "bar"})
-        self.assertEqual(status, None)
+        self.assertEquals(body, {"foo": "bar"})
+        self.assertEquals(status, None)
 
     def test_resumable_media_good_upload_from_execute(self):
         """Not a multipart upload."""
@@ -1253,7 +1201,7 @@
         )
 
         body = request.execute(http=http)
-        self.assertEqual(body, {"foo": "bar"})
+        self.assertEquals(body, {"foo": "bar"})
 
     def test_resumable_media_fail_unknown_response_code_first_request(self):
         """Not a multipart upload."""
@@ -1299,7 +1247,7 @@
         )
 
         status, body = request.next_chunk(http=http)
-        self.assertEqual(
+        self.assertEquals(
             status.resumable_progress,
             7,
             "Should have first checked length and then tried to PUT more.",
@@ -1623,9 +1571,9 @@
         media_upload = MediaFileUpload(datafile("empty"), resumable=True)
         request = zoo.animals().insert(media_body=media_upload, body=None)
 
-        self.assertEqual(media_upload, request.resumable)
-        self.assertEqual(request.body, None)
-        self.assertEqual(request.resumable_uri, None)
+        self.assertEquals(media_upload, request.resumable)
+        self.assertEquals(request.body, None)
+        self.assertEquals(request.resumable_uri, None)
 
         http = HttpMockSequence(
             [
@@ -1642,9 +1590,9 @@
         )
 
         status, body = request.next_chunk(http=http)
-        self.assertEqual(None, body)
+        self.assertEquals(None, body)
         self.assertTrue(isinstance(status, MediaUploadProgress))
-        self.assertEqual(0, status.progress())
+        self.assertEquals(0, status.progress())
 
 
 class Next(unittest.TestCase):
diff --git a/tests/test_http.py b/tests/test_http.py
index 2c0756e..2bf5060 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -132,31 +132,32 @@
     def request(self, *args, **kwargs):
         if not self.num_errors:
             return httplib2.Response(self.success_json), self.success_data
-        elif self.num_errors == 5 and PY3:
-            ex = ConnectionResetError  # noqa: F821
-        elif self.num_errors == 4:
-            ex = httplib2.ServerNotFoundError()
-        elif self.num_errors == 3:
-            ex = socket.error()
-            ex.errno = socket.errno.EPIPE
-        elif self.num_errors == 2:
-            ex = ssl.SSLError()
         else:
-            # Initialize the timeout error code to the platform's error code.
-            try:
-                # For Windows:
-                ex = socket.error()
-                ex.errno = socket.errno.WSAETIMEDOUT
-            except AttributeError:
-                # For Linux/Mac:
-                if PY3:
-                    ex = socket.timeout()
-                else:
+            self.num_errors -= 1
+            if self.num_errors == 1:  # initial == 2
+                raise ssl.SSLError()
+            if self.num_errors == 3:  # initial == 4
+                raise httplib2.ServerNotFoundError()
+            else:  # initial != 2,4
+                if self.num_errors == 2:
+                    # first try a broken pipe error (#218)
                     ex = socket.error()
-                    ex.errno = socket.errno.ETIMEDOUT
-
-        self.num_errors -= 1
-        raise ex
+                    ex.errno = socket.errno.EPIPE
+                else:
+                    # Initialize the timeout error code to the platform's error code.
+                    try:
+                        # For Windows:
+                        ex = socket.error()
+                        ex.errno = socket.errno.WSAETIMEDOUT
+                    except AttributeError:
+                        # For Linux/Mac:
+                        if PY3:
+                            ex = socket.timeout()
+                        else:
+                            ex = socket.error()
+                            ex.errno = socket.errno.ETIMEDOUT
+                # Now raise the correct error.
+                raise ex
 
 
 class HttpMockWithNonRetriableErrors(object):
@@ -561,14 +562,14 @@
 
     def test_media_io_base_download_retries_connection_errors(self):
         self.request.http = HttpMockWithErrors(
-            5, {"status": "200", "content-range": "0-2/3"}, b"123"
+            4, {"status": "200", "content-range": "0-2/3"}, b"123"
         )
 
         download = MediaIoBaseDownload(fd=self.fd, request=self.request, chunksize=3)
         download._sleep = lambda _x: 0  # do nothing
         download._rand = lambda: 10
 
-        status, done = download.next_chunk(num_retries=5)
+        status, done = download.next_chunk(num_retries=4)
 
         self.assertEqual(self.fd.getvalue(), b"123")
         self.assertEqual(True, done)
@@ -898,13 +899,13 @@
     def test_retry_connection_errors_non_resumable(self):
         model = JsonModel()
         request = HttpRequest(
-            HttpMockWithErrors(5, {"status": "200"}, '{"foo": "bar"}'),
+            HttpMockWithErrors(4, {"status": "200"}, '{"foo": "bar"}'),
             model.response,
             u"https://www.example.com/json_api_endpoint",
         )
         request._sleep = lambda _x: 0  # do nothing
         request._rand = lambda: 10
-        response = request.execute(num_retries=5)
+        response = request.execute(num_retries=4)
         self.assertEqual({u"foo": u"bar"}, response)
 
     def test_retry_connection_errors_resumable(self):
@@ -917,7 +918,7 @@
 
         request = HttpRequest(
             HttpMockWithErrors(
-                5, {"status": "200", "location": "location"}, '{"foo": "bar"}'
+                4, {"status": "200", "location": "location"}, '{"foo": "bar"}'
             ),
             model.response,
             u"https://www.example.com/file_upload",
@@ -926,7 +927,7 @@
         )
         request._sleep = lambda _x: 0  # do nothing
         request._rand = lambda: 10
-        response = request.execute(num_retries=5)
+        response = request.execute(num_retries=4)
         self.assertEqual({u"foo": u"bar"}, response)
 
     def test_retry(self):
@@ -1121,7 +1122,7 @@
 
     def test_id_to_from_content_id_header(self):
         batch = BatchHttpRequest()
-        self.assertEqual("12", batch._header_to_id(batch._id_to_header("12")))
+        self.assertEquals("12", batch._header_to_id(batch._id_to_header("12")))
 
     def test_invalid_content_id_header(self):
         batch = BatchHttpRequest()
@@ -1645,7 +1646,7 @@
     def test_build_http_default_timeout_can_be_set_to_zero(self):
         socket.setdefaulttimeout(0)
         http = build_http()
-        self.assertEqual(http.timeout, 0)
+        self.assertEquals(http.timeout, 0)
     
     def test_build_http_default_308_is_excluded_as_redirect(self):
         http = build_http()
diff --git a/tests/test_json_model.py b/tests/test_json_model.py
index 6857803..0064f3f 100644
--- a/tests/test_json_model.py
+++ b/tests/test_json_model.py
@@ -26,19 +26,17 @@
 import copy
 import json
 import os
-import pkg_resources
 import platform
 import unittest2 as unittest
 import httplib2
 import googleapiclient.model
 
+from googleapiclient import __version__
 from googleapiclient.errors import HttpError
 from googleapiclient.model import JsonModel
 
 from six.moves.urllib.parse import parse_qs
 
-_LIBRARY_VERSION = pkg_resources.get_distribution("google-api-python-client").version
-
 
 class Model(unittest.TestCase):
     def test_json_no_body(self):
@@ -173,7 +171,7 @@
             headers["x-goog-api-client"],
             "gccl/1.23.4"
             + " gdcl/"
-            + _LIBRARY_VERSION
+            + __version__
             + " gl-python/"
             + platform.python_version(),
         )
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..1d9bc13
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,24 @@
+[tox]
+envlist = py{27,34,35,36,37}-oauth2client{1,2,3,4}
+
+[testenv]
+deps =
+       oauth2client1: oauth2client<2dev
+       oauth2client2: oauth2client>=2,<=3dev
+       oauth2client3: oauth2client>=3,<=4dev
+       oauth2client4: oauth2client>=4,<=5dev
+       google-auth
+       google-auth-httplib2
+       mox
+       pyopenssl
+       django<2.0.0; python_version < '3.0.0'
+       django>=2.0.0; python_version > '3.0.0'
+       flake8
+       webtest
+       nose
+       coverage>=3.6,<3.99
+       unittest2
+       mock
+commands =
+       flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+       nosetests --with-coverage --cover-package=googleapiclient --nocapture --cover-erase --cover-tests --cover-branches --cover-min-percentage=85 []