diff options
author | Jon Wayne Parrott <jonwayne@google.com> | 2017-03-22 12:59:41 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-22 12:59:41 -0700 |
commit | 06a27e853b05b58102dfc3d8a459c213b5c15a63 (patch) | |
tree | 9ac276e7a9d835823e89d46d53b7816332eaf5f4 | |
parent | 0190660f79c4310987f405b3d8e5db4c5927665b (diff) | |
download | google-auth-library-python-06a27e853b05b58102dfc3d8a459c213b5c15a63.tar.gz |
Separate oauthlib integration into its own package (#137)
* Centralize the run_pylint script.
* Use io.open instead of open in setup.py for httplib2_transport
* Move httplib2_transport -> additional_packages/google_auth_httplib2
* Remove unneeded dependencies in google_auth_httplib2
* Update classifiers to note 3.6 support.
* Don't install the HEAD version of google-auth when testing google-auth-httplib2.
* Add google-auth-oauthlib package.
* Remove google.oauth2.oauthlib and google.oauth2.flow and associated tests.
* Make travis run google-auth-oauthlib's tox.
* Specify tox workdir.
33 files changed, 413 insertions, 309 deletions
diff --git a/additional_packages/README.md b/additional_packages/README.md new file mode 100644 index 0000000..827c548 --- /dev/null +++ b/additional_packages/README.md @@ -0,0 +1,4 @@ +# Additional packages for Google Auth Library Python + +This folder contains seperately distributed auxilliary packages for use +with google-auth. diff --git a/httplib2_transport/.coveragerc b/additional_packages/google_auth_httplib2/.coveragerc index c44dd8e..c44dd8e 100644 --- a/httplib2_transport/.coveragerc +++ b/additional_packages/google_auth_httplib2/.coveragerc diff --git a/httplib2_transport/LICENSE b/additional_packages/google_auth_httplib2/LICENSE index 261eeb9..261eeb9 100644 --- a/httplib2_transport/LICENSE +++ b/additional_packages/google_auth_httplib2/LICENSE diff --git a/httplib2_transport/MANIFEST.in b/additional_packages/google_auth_httplib2/MANIFEST.in index aac7fe1..aac7fe1 100644 --- a/httplib2_transport/MANIFEST.in +++ b/additional_packages/google_auth_httplib2/MANIFEST.in diff --git a/httplib2_transport/README.rst b/additional_packages/google_auth_httplib2/README.rst index 15477d0..15477d0 100644 --- a/httplib2_transport/README.rst +++ b/additional_packages/google_auth_httplib2/README.rst diff --git a/httplib2_transport/google_auth_httplib2.py b/additional_packages/google_auth_httplib2/google_auth_httplib2.py index 866841b..866841b 100644 --- a/httplib2_transport/google_auth_httplib2.py +++ b/additional_packages/google_auth_httplib2/google_auth_httplib2.py diff --git a/httplib2_transport/setup.cfg b/additional_packages/google_auth_httplib2/setup.cfg index 2a9acf1..2a9acf1 100644 --- a/httplib2_transport/setup.cfg +++ b/additional_packages/google_auth_httplib2/setup.cfg diff --git a/httplib2_transport/setup.py b/additional_packages/google_auth_httplib2/setup.py index e85c309..ec04881 100644 --- a/httplib2_transport/setup.py +++ b/additional_packages/google_auth_httplib2/setup.py @@ -12,19 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +import io + from setuptools import setup DEPENDENCIES = ( - 'pyasn1>=0.1.7', - 'pyasn1-modules>=0.0.5', - 'rsa>=3.1.4', - 'six>=1.9.0', 'google-auth' ) -with open('README.rst', 'r') as fh: +with io.open('README.rst', 'r') as fh: long_description = fh.read() @@ -46,6 +44,7 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', diff --git a/httplib2_transport/tests/__init__.py b/additional_packages/google_auth_httplib2/tests/__init__.py index e69de29..e69de29 100644 --- a/httplib2_transport/tests/__init__.py +++ b/additional_packages/google_auth_httplib2/tests/__init__.py diff --git a/httplib2_transport/tests/compliance.py b/additional_packages/google_auth_httplib2/tests/compliance.py index a97a11b..a97a11b 100644 --- a/httplib2_transport/tests/compliance.py +++ b/additional_packages/google_auth_httplib2/tests/compliance.py diff --git a/httplib2_transport/tests/test_google_auth_httplib2.py b/additional_packages/google_auth_httplib2/tests/test_google_auth_httplib2.py index 635965f..635965f 100644 --- a/httplib2_transport/tests/test_google_auth_httplib2.py +++ b/additional_packages/google_auth_httplib2/tests/test_google_auth_httplib2.py diff --git a/httplib2_transport/tox.ini b/additional_packages/google_auth_httplib2/tox.ini index 84635e8..95f3454 100644 --- a/httplib2_transport/tox.ini +++ b/additional_packages/google_auth_httplib2/tox.ini @@ -9,9 +9,6 @@ deps = pytest-cov pytest-localserver httplib2 - {toxinidir}/.. -# Always recreate because of the relative path in deps above. -recreate = True commands = py.test --cov=google_auth_httplib2 --cov=tests {posargs:tests} @@ -31,7 +28,9 @@ commands = --import-order-style=google \ --application-import-names="google_auth_httplib2,tests" \ google_auth_httplib2.py tests - python {toxinidir}/scripts/run_pylint.py + python {toxinidir}/../../scripts/run_pylint.py \ + --library-filesets google_auth_httplib2.py \ + --test-filesets tests deps = flake8 flake8-import-order diff --git a/additional_packages/google_auth_oauthlib/.coveragerc b/additional_packages/google_auth_oauthlib/.coveragerc new file mode 100644 index 0000000..c44dd8e --- /dev/null +++ b/additional_packages/google_auth_oauthlib/.coveragerc @@ -0,0 +1,13 @@ +[run] +branch = True + +[report] +omit = + */conftest.py +exclude_lines = + # Re-enable the standard pragma + pragma: NO COVER + # Ignore debug-only repr + def __repr__ + # Don't complain if tests don't hit defensive assertion code: + raise NotImplementedError diff --git a/additional_packages/google_auth_oauthlib/CHANGELOG.rst b/additional_packages/google_auth_oauthlib/CHANGELOG.rst new file mode 100644 index 0000000..dbb95df --- /dev/null +++ b/additional_packages/google_auth_oauthlib/CHANGELOG.rst @@ -0,0 +1,4 @@ +v0.0.1 +------ + +Initial release. This package contains the functionality previously located in `google.oauth2.oauthlib` and `google.oauth2.flows`. diff --git a/additional_packages/google_auth_oauthlib/LICENSE b/additional_packages/google_auth_oauthlib/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/additional_packages/google_auth_oauthlib/MANIFEST.in b/additional_packages/google_auth_oauthlib/MANIFEST.in new file mode 100644 index 0000000..aac7fe1 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/MANIFEST.in @@ -0,0 +1,2 @@ +include README.rst LICENSE +recursive-include tests * diff --git a/additional_packages/google_auth_oauthlib/README.rst b/additional_packages/google_auth_oauthlib/README.rst new file mode 100644 index 0000000..44c478b --- /dev/null +++ b/additional_packages/google_auth_oauthlib/README.rst @@ -0,0 +1,28 @@ +oauthlib integration for Google Auth +==================================== + +|pypi| + +This library provides `oauthlib`_ integration with `google-auth`_. + +.. |pypi| image:: https://img.shields.io/pypi/v/google-auth-oauthlib.svg + :target: https://pypi.python.org/pypi/google-auth-oauthlib + +.. _oauthlib: https://github.com/idan/oauthlib +.. _google-auth: https://github.com/GoogleCloudPlatform/google-auth + +Installing +---------- + +You can install using `pip`_:: + + $ pip install google-auth-oauthlib + +.. _pip: https://pip.pypa.io/en/stable/ + +License +------- + +Apache 2.0 - See `the LICENSE`_ for more information. + +.. _the LICENSE: https://github.com/GoogleCloudPlatform/google-auth-library-python/blob/master/LICENSE diff --git a/additional_packages/google_auth_oauthlib/google_auth_oauthlib/__init__.py b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/__init__.py diff --git a/google/oauth2/flow.py b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/flow.py index e70ee3d..a040659 100644 --- a/google/oauth2/flow.py +++ b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/flow.py @@ -14,21 +14,17 @@ """OAuth 2.0 Authorization Flow -.. warning:: - This module is experimental and is subject to change signficantly - within major version releases. - This module provides integration with `requests-oauthlib`_ for running the `OAuth 2.0 Authorization Flow`_ and acquiring user credentials. Here's an example of using the flow with the installed application authorization flow:: - import google.oauth2.flow + from google_auth_oauthlib.flow import Flow # Create the flow using the client secrets file from the Google API # Console. - flow = google.oauth2.flow.Flow.from_client_secrets_file( + flow = Flow.from_client_secrets_file( 'path/to/client_secrets.json', scopes=['profile', 'email'], redirect_uri='urn:ietf:wg:oauth:2.0:oob') @@ -57,7 +53,8 @@ import json import google.auth.transport.requests import google.oauth2.credentials -import google.oauth2.oauthlib + +import google_auth_oauthlib.helpers class Flow(object): @@ -133,7 +130,7 @@ class Flow(object): 'Client secrets must be for a web or installed app.') session, client_config = ( - google.oauth2.oauthlib.session_from_client_config( + google_auth_oauthlib.helpers.session_from_client_config( client_config, scopes, **kwargs)) return cls(session, client_type, client_config) @@ -240,7 +237,7 @@ class Flow(object): Raises: ValueError: If there is no access token in the session. """ - return google.oauth2.oauthlib.credentials_from_session( + return google_auth_oauthlib.helpers.credentials_from_session( self.oauth2session, self.client_config) def authorized_session(self): diff --git a/google/oauth2/oauthlib.py b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/helpers.py index e1c6089..901423b 100644 --- a/google/oauth2/oauthlib.py +++ b/additional_packages/google_auth_oauthlib/google_auth_oauthlib/helpers.py @@ -12,15 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Integration with oauthlib - -.. warning:: - This module is experimental and is subject to change signficantly - within major version releases. +"""Integration helpers. This module provides helpers for integrating with `requests-oauthlib`_. Typically, you'll want to use the higher-level helpers in -:mod:`google.oauth2.flow`. +:mod:`google_auth_oauthlib.flow`. .. _requests-oauthlib: http://requests-oauthlib.readthedocs.io/en/stable/ """ diff --git a/additional_packages/google_auth_oauthlib/setup.cfg b/additional_packages/google_auth_oauthlib/setup.cfg new file mode 100644 index 0000000..2a9acf1 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal = 1 diff --git a/additional_packages/google_auth_oauthlib/setup.py b/additional_packages/google_auth_oauthlib/setup.py new file mode 100644 index 0000000..3652470 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/setup.py @@ -0,0 +1,59 @@ +# Copyright 2014 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. + +import io + +from setuptools import find_packages +from setuptools import setup + + +DEPENDENCIES = ( + 'google-auth', + 'requests-oauthlib>=0.7.0', +) + + +with io.open('README.rst', 'r') as fh: + long_description = fh.read() + + +setup( + name='google-auth-oauthlib', + version='0.0.1', + author='Google Cloud Platform', + author_email='jonwayne+google-auth@google.com', + description='Google Authentication Library', + long_description=long_description, + url='https://github.com/GoogleCloudPlatform/google-auth-library-python', + packages=find_packages(exclude=('tests*',)), + install_requires=DEPENDENCIES, + license='Apache 2.0', + keywords='google auth oauth client oauthlib', + classifiers=( + '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', + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: POSIX', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: OS Independent', + 'Topic :: Internet :: WWW/HTTP', + ), +) diff --git a/additional_packages/google_auth_oauthlib/tests/__init__.py b/additional_packages/google_auth_oauthlib/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/tests/__init__.py diff --git a/additional_packages/google_auth_oauthlib/tests/data/client_secrets.json b/additional_packages/google_auth_oauthlib/tests/data/client_secrets.json new file mode 100644 index 0000000..1baa499 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/tests/data/client_secrets.json @@ -0,0 +1,14 @@ +{ + "web": { + "client_id": "example.apps.googleusercontent.com", + "project_id": "example", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_secret": "itsasecrettoeveryone", + "redirect_uris": [ + "urn:ietf:wg:oauth:2.0:oob", + "http://localhost" + ] + } +} diff --git a/tests/oauth2/test_flow.py b/additional_packages/google_auth_oauthlib/tests/test_flow.py index e5d108f..663a02f 100644 --- a/tests/oauth2/test_flow.py +++ b/additional_packages/google_auth_oauthlib/tests/test_flow.py @@ -18,9 +18,9 @@ import os import mock import pytest -from google.oauth2 import flow +from google_auth_oauthlib import flow -DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data') +DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') CLIENT_SECRETS_FILE = os.path.join(DATA_DIR, 'client_secrets.json') with open(CLIENT_SECRETS_FILE, 'r') as fh: diff --git a/tests/oauth2/test_oauthlib.py b/additional_packages/google_auth_oauthlib/tests/test_helpers.py index a16c904..faae76b 100644 --- a/tests/oauth2/test_oauthlib.py +++ b/additional_packages/google_auth_oauthlib/tests/test_helpers.py @@ -18,9 +18,9 @@ import os import mock import pytest -from google.oauth2 import oauthlib +from google_auth_oauthlib import helpers -DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data') +DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') CLIENT_SECRETS_FILE = os.path.join(DATA_DIR, 'client_secrets.json') with open(CLIENT_SECRETS_FILE, 'r') as fh: @@ -28,7 +28,7 @@ with open(CLIENT_SECRETS_FILE, 'r') as fh: def test_session_from_client_config_web(): - session, config = oauthlib.session_from_client_config( + session, config = helpers.session_from_client_config( CLIENT_SECRETS_INFO, scopes=mock.sentinel.scopes) assert config == CLIENT_SECRETS_INFO @@ -38,7 +38,7 @@ def test_session_from_client_config_web(): def test_session_from_client_config_installed(): info = {'installed': CLIENT_SECRETS_INFO['web']} - session, config = oauthlib.session_from_client_config( + session, config = helpers.session_from_client_config( info, scopes=mock.sentinel.scopes) assert config == info assert session.client_id == info['installed']['client_id'] @@ -47,16 +47,16 @@ def test_session_from_client_config_installed(): def test_session_from_client_config_bad_format(): with pytest.raises(ValueError): - oauthlib.session_from_client_config({}, scopes=[]) + helpers.session_from_client_config({}, scopes=[]) def test_session_from_client_config_missing_keys(): with pytest.raises(ValueError): - oauthlib.session_from_client_config({'web': {}}, scopes=[]) + helpers.session_from_client_config({'web': {}}, scopes=[]) def test_session_from_client_secrets_file(): - session, config = oauthlib.session_from_client_secrets_file( + session, config = helpers.session_from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=mock.sentinel.scopes) assert config == CLIENT_SECRETS_INFO assert session.client_id == CLIENT_SECRETS_INFO['web']['client_id'] @@ -65,7 +65,7 @@ def test_session_from_client_secrets_file(): @pytest.fixture def session(): - session, _ = oauthlib.session_from_client_config( + session, _ = helpers.session_from_client_config( CLIENT_SECRETS_INFO, scopes=mock.sentinel.scopes) yield session @@ -76,7 +76,7 @@ def test_credentials_from_session(session): 'refresh_token': mock.sentinel.refresh_token } - credentials = oauthlib.credentials_from_session( + credentials = helpers.credentials_from_session( session, CLIENT_SECRETS_INFO['web']) assert credentials.token == mock.sentinel.access_token @@ -89,4 +89,4 @@ def test_credentials_from_session(session): def test_bad_credentials(session): with pytest.raises(ValueError): - oauthlib.credentials_from_session(session) + helpers.credentials_from_session(session) diff --git a/additional_packages/google_auth_oauthlib/tox.ini b/additional_packages/google_auth_oauthlib/tox.ini new file mode 100644 index 0000000..3cac089 --- /dev/null +++ b/additional_packages/google_auth_oauthlib/tox.ini @@ -0,0 +1,35 @@ +[tox] +envlist = lint,py27,py34,py35,py36,pypy,cover + +[testenv] +deps = + mock + pytest + pytest-cov +commands = + py.test --cov=google_auth_oauthlib --cov=tests {posargs:tests} + +[testenv:cover] +basepython = python3.6 +commands = + py.test --cov=google_auth_oauthlib --cov=tests --cov-report= tests + coverage report --show-missing --fail-under=100 +deps = + {[testenv]deps} + +[testenv:lint] +basepython = python3.5 +commands = + python setup.py check --metadata --restructuredtext --strict + flake8 \ + --import-order-style=google \ + --application-import-names="google_auth_oauthlib,tests" \ + google_auth_oauthlib tests + python {toxinidir}/../../scripts/run_pylint.py \ + --library-filesets google_auth_oauthlib \ + --test-filesets tests +deps = + flake8 + flake8-import-order + pylint + docutils diff --git a/httplib2_transport/scripts/.gitignore b/httplib2_transport/scripts/.gitignore deleted file mode 100644 index 3596d32..0000000 --- a/httplib2_transport/scripts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Generated files -pylintrc -pylintrc.test diff --git a/httplib2_transport/scripts/run_pylint.py b/httplib2_transport/scripts/run_pylint.py deleted file mode 100644 index 643957a..0000000 --- a/httplib2_transport/scripts/run_pylint.py +++ /dev/null @@ -1,256 +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 script runs Pylint on the specified source. - -Before running Pylint, it generates a Pylint configuration on -the fly based on programmatic defaults. - -.. note:: - - This file **really** breaks DRY, but is provided here as - **mostly** a copy of the true source file: - ``httplib2_transport/../scripts/run_pylint.py``. - This is done so that the ``httplib2_transport`` sub-package - can be self-contained. -""" - -from __future__ import print_function - -import collections -import copy -import io -import os -import subprocess -import sys - -import six - - -_SCRIPTS_DIR = os.path.abspath(os.path.dirname(__file__)) -PRODUCTION_RC = os.path.join(_SCRIPTS_DIR, 'pylintrc') -TEST_RC = os.path.join(_SCRIPTS_DIR, 'pylintrc.test') - -_PRODUCTION_RC_ADDITIONS = { - 'MESSAGES CONTROL': { - 'disable': [ - 'I', - 'import-error', - ], - }, -} -_PRODUCTION_RC_REPLACEMENTS = { - 'MASTER': { - 'ignore': ['CVS', '.git', '.cache', '.tox', '.nox'], - 'load-plugins': 'pylint.extensions.check_docs', - }, - 'REPORTS': { - 'reports': 'no', - }, - 'BASIC': { - 'method-rgx': '[a-z_][a-z0-9_]{2,40}$', - 'function-rgx': '[a-z_][a-z0-9_]{2,40}$', - }, - 'TYPECHECK': { - 'ignored-modules': ['six', 'google.protobuf'], - }, - 'DESIGN': { - 'min-public-methods': '0', - 'max-args': '10', - 'max-attributes': '15', - }, -} -_TEST_RC_ADDITIONS = copy.deepcopy(_PRODUCTION_RC_ADDITIONS) -_TEST_RC_ADDITIONS['MESSAGES CONTROL']['disable'].extend([ - 'missing-docstring', - 'no-member', - 'no-self-use', - 'protected-access', - 'unused-argument', -]) -_TEST_RC_REPLACEMENTS = copy.deepcopy(_PRODUCTION_RC_REPLACEMENTS) -_TEST_RC_REPLACEMENTS.setdefault('BASIC', {}) -_TEST_RC_REPLACEMENTS['BASIC'].update({ - 'good-names': ['i', 'j', 'k', 'ex', 'Run', '_', 'fh'], - 'method-rgx': '[a-z_][a-z0-9_]{2,80}$', - 'function-rgx': '[a-z_][a-z0-9_]{2,80}$', -}) -IGNORED_FILES = () - -_ERROR_TEMPLATE = 'Pylint failed on {} with status {:d}.' -_LINT_FILESET_MSG = ( - 'Keyword arguments rc_filename and description are both ' - 'required. No other keyword arguments are allowed.') - - -def get_default_config(): - """Get the default Pylint configuration. - - .. note:: - - The output of this function varies based on the current version of - Pylint installed. - - Returns: - str: The default Pylint configuration. - """ - # Swallow STDERR if it says - # "No config file found, using default configuration" - result = subprocess.check_output(['pylint', '--generate-rcfile'], - stderr=subprocess.PIPE) - # On Python 3, this returns bytes (from STDOUT), so we - # convert to a string. - return result.decode('utf-8') - - -def read_config(contents): - """Reads pylintrc config into native ConfigParser object. - - Args: - contents (str): The contents of the file containing the INI config. - - Returns - ConfigParser.ConfigParser: The parsed configuration. - """ - file_obj = io.StringIO(contents) - config = six.moves.configparser.ConfigParser() - config.readfp(file_obj) - return config - - -def _transform_opt(opt_val): - """Transform a config option value to a string. - - If already a string, do nothing. If an iterable, then - combine into a string by joining on ",". - - Args: - opt_val (Union[str, list]): A config option's value. - - Returns: - str: The option value converted to a string. - """ - if isinstance(opt_val, (list, tuple)): - return ','.join(opt_val) - else: - return opt_val - - -def lint_fileset(*paths, **kwargs): - """Lints a group of files using a given rcfile. - - Keyword arguments are - - * ``rc_filename`` (``str``): The name of the Pylint config RC file. - * ``description`` (``str``): A description of the files and configuration - currently being run. - - Args: - paths (tuple): Directories or filenames to run Pylint in/on. - kwargs: The keyword arguments. The only keyword arguments - are ``rc_filename`` and ``description`` and both - are required. - - Raises: - KeyError: If the wrong keyword arguments are used. - """ - try: - rc_filename = kwargs['rc_filename'] - description = kwargs['description'] - if len(kwargs) != 2: - raise KeyError - except KeyError: - raise KeyError(_LINT_FILESET_MSG) - - pylint_shell_command = ['pylint', '--rcfile', rc_filename] - pylint_shell_command.extend(paths) - status_code = subprocess.call(pylint_shell_command) - if status_code != 0: - error_message = _ERROR_TEMPLATE.format(description, status_code) - print(error_message, file=sys.stderr) - sys.exit(status_code) - - -def make_rc(base_cfg, target_filename, - additions=None, replacements=None): - """Combines a base rc and additions into single file. - - Args: - base_cfg (ConfigParser.ConfigParser): The configuration we are - merging into. - target_filename (str): The filename where the new configuration - will be saved. - additions (dict): (Optional) The values added to the configuration. - replacements (dict): (Optional) The wholesale replacements for - the new configuration. - - Raises: - KeyError: if one of the additions or replacements does not - already exist in the current config. - """ - # Set-up the mutable default values. - if additions is None: - additions = {} - if replacements is None: - replacements = {} - - # Create fresh config, which must extend the base one. - new_cfg = six.moves.configparser.ConfigParser() - # pylint: disable=protected-access - new_cfg._sections = copy.deepcopy(base_cfg._sections) - new_sections = new_cfg._sections - # pylint: enable=protected-access - - for section, opts in additions.items(): - curr_section = new_sections.setdefault( - section, collections.OrderedDict()) - for opt, opt_val in opts.items(): - curr_val = curr_section.get(opt) - if curr_val is None: - raise KeyError('Expected to be adding to existing option.') - curr_val = curr_val.rstrip(',') - opt_val = _transform_opt(opt_val) - curr_section[opt] = '%s, %s' % (curr_val, opt_val) - - for section, opts in replacements.items(): - curr_section = new_sections.setdefault( - section, collections.OrderedDict()) - for opt, opt_val in opts.items(): - curr_val = curr_section.get(opt) - if curr_val is None: - raise KeyError('Expected to be replacing existing option.') - opt_val = _transform_opt(opt_val) - curr_section[opt] = '%s' % (opt_val,) - - with open(target_filename, 'w') as file_obj: - new_cfg.write(file_obj) - - -def main(): - """Script entry point. Lints both sets of files.""" - default_config = read_config(get_default_config()) - make_rc(default_config, PRODUCTION_RC, - additions=_PRODUCTION_RC_ADDITIONS, - replacements=_PRODUCTION_RC_REPLACEMENTS) - make_rc(default_config, TEST_RC, - additions=_TEST_RC_ADDITIONS, - replacements=_TEST_RC_REPLACEMENTS) - lint_fileset('google_auth_httplib2.py', rc_filename=PRODUCTION_RC, - description='Library') - lint_fileset('tests', rc_filename=TEST_RC, - description='Test') - - -if __name__ == '__main__': - main() diff --git a/scripts/run_pylint.py b/scripts/run_pylint.py index e9ac7ec..c33a53e 100644 --- a/scripts/run_pylint.py +++ b/scripts/run_pylint.py @@ -20,6 +20,7 @@ the fly based on programmatic defaults. from __future__ import print_function +import argparse import collections import copy import io @@ -236,6 +237,12 @@ def make_rc(base_cfg, target_filename, def main(): """Script entry point. Lints both sets of files.""" + parser = argparse.ArgumentParser() + parser.add_argument('--library-filesets', nargs='+', default=[]) + parser.add_argument('--test-filesets', nargs='+', default=[]) + + args = parser.parse_args() + default_config = read_config(get_default_config()) make_rc(default_config, PRODUCTION_RC, additions=_PRODUCTION_RC_ADDITIONS, @@ -243,11 +250,11 @@ def main(): make_rc(default_config, TEST_RC, additions=_TEST_RC_ADDITIONS, replacements=_TEST_RC_REPLACEMENTS) - lint_fileset('google', rc_filename=PRODUCTION_RC, + + lint_fileset(*args.library_filesets, rc_filename=PRODUCTION_RC, description='Library') - lint_fileset('tests', 'system_tests', rc_filename=TEST_RC, + lint_fileset(*args.test_filesets, rc_filename=TEST_RC, description='Test') - if __name__ == '__main__': main() diff --git a/scripts/travis.sh b/scripts/travis.sh index 9e11de8..5acb4c2 100755 --- a/scripts/travis.sh +++ b/scripts/travis.sh @@ -43,7 +43,14 @@ tox # Run tox for sub-packages. if [[ $TOXENV != "docs" && -z $SYSTEM_TEST ]]; then - echo "Running tox for httplib2_transport..." - cd httplib2_transport - tox + echo "Running tox for google_auth_httplib2..." + cd additional_packages/google_auth_httplib2 + # --workdir is specified to avoid path names being too long, which + # causes subprocess calls to hit the execve character limit. + # See https://github.com/pypa/virtualenv/issues/596 + tox --workdir ~/.tox-httplib2 + cd $ROOT + echo "Running tox for google_auth_oauthlib..." + cd additional_packages/google_auth_oauthlib + tox --workdir ~/.tox-oauthlib fi @@ -25,10 +25,6 @@ DEPENDENCIES = ( 'six>=1.9.0', ) -EXTRA_OAUTHLIB_DEPENDENCIES = ( - 'requests-oauthlib>=0.7.0', -) - with io.open('README.rst', 'r') as fh: long_description = fh.read() @@ -44,9 +40,6 @@ setup( packages=find_packages(exclude=('tests*', 'system_tests*')), namespace_packages=('google',), install_requires=DEPENDENCIES, - extras_require={ - 'oauthlib': EXTRA_OAUTHLIB_DEPENDENCIES, - }, license='Apache 2.0', keywords='google auth oauth client', classifiers=( @@ -55,6 +48,7 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', @@ -77,7 +77,9 @@ commands = --import-order-style=google \ --application-import-names="google,tests,system_tests" \ google tests - python {toxinidir}/scripts/run_pylint.py + python {toxinidir}/scripts/run_pylint.py \ + --library-filesets google \ + --test-filesets tests system_tests deps = flake8 flake8-import-order |