Skip to content

Commit a06085e

Browse files
chalmerlowetswastgcf-owl-bot[bot]
authored
feat: adds ability to provide redirect uri (#595)
* feat: adds ability to provide redirect uri * renames redirect_uri variable * adds js folder to sphinx and auth_redirect_uri * feat: adds javascript functionality related to oauth * feat: adds javascript functionality related to oauth * feat: adds sample authcodescript * feat: adds ability to host oauth page with the documentation * adds clarity to the user interface messaging * updates linting, toctree * updates minimum version of pydata-google-auth * Update docs/_static/js/authcodescripts.js * adds check to avoid override of user given clientid, clientsecret * adds parameters to the func to_gbq * adds docstrings related to three new parameters * Apply suggestions from code review * fix rst formatting * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Tim Swast <[email protected]> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 7907b6b commit a06085e

File tree

7 files changed

+135
-5
lines changed

7 files changed

+135
-5
lines changed

docs/_static/js/authcodescripts.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
3+
// Copyright (c) 2023 pandas-gbq Authors All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
8+
function onloadoauthcode() {
9+
const PARAMS = new Proxy(new URLSearchParams(window.location.search), {
10+
get: (searchParams, prop) => searchParams.get(prop),
11+
});
12+
const AUTH_CODE = PARAMS.code;
13+
14+
document.querySelector('.auth-code').textContent = AUTH_CODE;
15+
16+
setupCopyButton(document.querySelector('.copy'), AUTH_CODE);
17+
}
18+
19+
function setupCopyButton(button, text) {
20+
button.addEventListener('click', () => {
21+
navigator.clipboard.writeText(text);
22+
button.textContent = "Verification Code Copied";
23+
setTimeout(() => {
24+
// Remove the aria-live label so that when the
25+
// button text changes back to "Copy", it is
26+
// not read out.
27+
button.removeAttribute("aria-live");
28+
button.textContent = "Copy";
29+
}, 1000);
30+
31+
// Re-Add the aria-live attribute to enable speech for
32+
// when button text changes next time.
33+
setTimeout(() => {
34+
button.setAttribute("aria-live", "assertive");
35+
}, 2000);
36+
});
37+
}

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Contents:
4141
contributing.rst
4242
changelog.md
4343
privacy.rst
44+
oauth.rst
4445

4546

4647
Indices and tables

docs/oauth.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.. image:: https://lh3.googleusercontent.com/KaU6SyiIpDKe4tyGPgt7yzGVTsfMqBvP9bL24o_4M58puYDO-nY8-BazrNk3RyhRFJA
2+
:alt: gcloud CLI logo
3+
:class: logo
4+
5+
Sign in to BigQuery
6+
===================
7+
8+
You are seeing this page because you are attempting to access BigQuery via one
9+
of several possible methods, including:
10+
11+
* the ``pandas_gbq`` library (https://github.com/googleapis/python-bigquery-pandas)
12+
13+
OR a ``pandas`` library helper function such as:
14+
15+
* ``pandas.DataFrame.to_gbq()``
16+
* ``pandas.read_gbq()``
17+
18+
from this or another machine. If this is not the case, close this tab.
19+
20+
Enter the following verification code in the CommandLine Interface (CLI) on the
21+
machine you want to log into. This is a credential **similar to your password**
22+
and should not be shared with others.
23+
24+
25+
.. raw:: html
26+
27+
<script type="text/javascript">
28+
window.addEventListener( "load", onloadoauthcode )
29+
</script>
30+
31+
<div>
32+
<code class="auth-code"></code>
33+
</div>
34+
<br>
35+
<button class="copy" aria-live="assertive">Copy</button>
36+
37+
.. hint::
38+
39+
You can close this tab when you’re done.

pandas_gbq/auth.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@
2828

2929

3030
def get_credentials(
31-
private_key=None, project_id=None, reauth=False, auth_local_webserver=True
31+
private_key=None,
32+
project_id=None,
33+
reauth=False,
34+
auth_local_webserver=True,
35+
auth_redirect_uri=None,
36+
client_id=None,
37+
client_secret=None,
3238
):
3339
import pydata_google_auth
3440

@@ -41,12 +47,19 @@ def get_credentials(
4147
method from the google-auth package."""
4248
)
4349

50+
if client_id is None:
51+
client_id = CLIENT_ID
52+
53+
if client_secret is None:
54+
client_secret = CLIENT_SECRET
55+
4456
credentials, default_project_id = pydata_google_auth.default(
4557
SCOPES,
46-
client_id=CLIENT_ID,
47-
client_secret=CLIENT_SECRET,
58+
client_id=client_id,
59+
client_secret=client_secret,
4860
credentials_cache=get_credentials_cache(reauth),
4961
auth_local_webserver=auth_local_webserver,
62+
redirect_uri=auth_redirect_uri,
5063
)
5164

5265
project_id = project_id or default_project_id

pandas_gbq/gbq.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,9 @@ def __init__(
280280
location=None,
281281
credentials=None,
282282
use_bqstorage_api=False,
283+
auth_redirect_uri=None,
284+
client_id=None,
285+
client_secret=None,
283286
):
284287
global context
285288
from google.api_core.exceptions import GoogleAPIError
@@ -294,6 +297,10 @@ def __init__(
294297
self.auth_local_webserver = auth_local_webserver
295298
self.dialect = dialect
296299
self.credentials = credentials
300+
self.auth_redirect_uri = auth_redirect_uri
301+
self.client_id = client_id
302+
self.client_secret = client_secret
303+
297304
default_project = None
298305

299306
# Service account credentials have a project associated with them.
@@ -313,6 +320,9 @@ def __init__(
313320
project_id=project_id,
314321
reauth=reauth,
315322
auth_local_webserver=auth_local_webserver,
323+
auth_redirect_uri=auth_redirect_uri,
324+
client_id=client_id,
325+
client_secret=client_secret,
316326
)
317327

318328
if self.project_id is None:
@@ -735,6 +745,9 @@ def read_gbq(
735745
private_key=None,
736746
progress_bar_type="tqdm",
737747
dtypes=None,
748+
auth_redirect_uri=None,
749+
client_id=None,
750+
client_secret=None,
738751
):
739752
r"""Load data from Google BigQuery using google-cloud-python
740753
@@ -864,6 +877,15 @@ def read_gbq(
864877
or
865878
:func:`google.oauth2.service_account.Credentials.from_service_account_file`
866879
instead.
880+
auth_redirect_uri : str
881+
Path to the authentication page for organization-specific authentication
882+
workflows. Used when ``auth_local_webserver=False``.
883+
client_id : str
884+
The Client ID for the Google Cloud Project the user is attempting to
885+
connect to.
886+
client_secret : str
887+
The Client Secret associated with the Client ID for the Google Cloud Project
888+
the user is attempting to connect to.
867889
868890
Returns
869891
-------
@@ -912,6 +934,9 @@ def read_gbq(
912934
credentials=credentials,
913935
private_key=private_key,
914936
use_bqstorage_api=use_bqstorage_api,
937+
auth_redirect_uri=auth_redirect_uri,
938+
client_id=client_id,
939+
client_secret=client_secret,
915940
)
916941

917942
if _is_query(query_or_table):
@@ -969,6 +994,9 @@ def to_gbq(
969994
api_method: str = "default",
970995
verbose=None,
971996
private_key=None,
997+
auth_redirect_uri=None,
998+
client_id=None,
999+
client_secret=None,
9721000
):
9731001
"""Write a DataFrame to a Google BigQuery table.
9741002
@@ -1071,6 +1099,15 @@ def to_gbq(
10711099
or
10721100
:func:`google.oauth2.service_account.Credentials.from_service_account_file`
10731101
instead.
1102+
auth_redirect_uri : str
1103+
Path to the authentication page for organization-specific authentication
1104+
workflows. Used when ``auth_local_webserver=False``.
1105+
client_id : str
1106+
The Client ID for the Google Cloud Project the user is attempting to
1107+
connect to.
1108+
client_secret : str
1109+
The Client Secret associated with the Client ID for the Google Cloud Project
1110+
the user is attempting to connect to.
10741111
"""
10751112

10761113
_test_google_api_imports()
@@ -1131,6 +1168,9 @@ def to_gbq(
11311168
location=location,
11321169
credentials=credentials,
11331170
private_key=private_key,
1171+
auth_redirect_uri=auth_redirect_uri,
1172+
client_id=client_id,
1173+
client_secret=client_secret,
11341174
)
11351175
bqclient = connector.client
11361176

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"numpy >=1.16.6",
2828
"pandas >=1.1.4",
2929
"pyarrow >=3.0.0",
30-
"pydata-google-auth >=1.4.0",
30+
"pydata-google-auth >=1.5.0",
3131
# Note: google-api-core and google-auth are also included via transitive
3232
# dependency on google-cloud-bigquery, but this library also uses them
3333
# directly.

testing/constraints-3.7.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ google-cloud-bigquery-storage==2.16.2
1414
numpy==1.16.6
1515
pandas==1.1.4
1616
pyarrow==3.0.0
17-
pydata-google-auth==1.4.0
17+
pydata-google-auth==1.5.0
1818
tqdm==4.23.0
1919
protobuf==3.19.5

0 commit comments

Comments
 (0)