@@ -267,6 +267,8 @@ def __init__(
267267 auth_redirect_uri = None ,
268268 client_id = None ,
269269 client_secret = None ,
270+ user_agent = None ,
271+ rfc9110_delimiter = False ,
270272 ):
271273 global context
272274 from google .api_core .exceptions import ClientError , GoogleAPIError
@@ -284,6 +286,8 @@ def __init__(
284286 self .auth_redirect_uri = auth_redirect_uri
285287 self .client_id = client_id
286288 self .client_secret = client_secret
289+ self .user_agent = user_agent
290+ self .rfc9110_delimiter = rfc9110_delimiter
287291
288292 default_project = None
289293
@@ -337,11 +341,15 @@ def log_elapsed_seconds(self, prefix="Elapsed", postfix="s.", overlong=6):
337341
338342 def get_client (self ):
339343 import google .api_core .client_info
340- import pandas
341344
342345 bigquery = FEATURES .bigquery_try_import ()
346+
347+ user_agent = create_user_agent (
348+ user_agent = self .user_agent , rfc9110_delimiter = self .rfc9110_delimiter
349+ )
350+
343351 client_info = google .api_core .client_info .ClientInfo (
344- user_agent = "pandas-{}" . format ( pandas . __version__ )
352+ user_agent = user_agent ,
345353 )
346354 return bigquery .Client (
347355 project = self .project_id ,
@@ -961,6 +969,8 @@ def to_gbq(
961969 auth_redirect_uri = None ,
962970 client_id = None ,
963971 client_secret = None ,
972+ user_agent = None ,
973+ rfc9110_delimiter = False ,
964974):
965975 """Write a DataFrame to a Google BigQuery table.
966976
@@ -1072,6 +1082,13 @@ def to_gbq(
10721082 client_secret : str
10731083 The Client Secret associated with the Client ID for the Google Cloud Project
10741084 the user is attempting to connect to.
1085+ user_agent : str
1086+ Custom user agent string used as a prefix to the pandas version.
1087+ rfc9110_delimiter : bool
1088+ Sets user agent delimiter to a hyphen or a slash.
1089+ Default is False, meaning a hyphen will be used.
1090+
1091+ .. versionadded:: 0.23.3
10751092 """
10761093
10771094 _test_google_api_imports ()
@@ -1130,6 +1147,8 @@ def to_gbq(
11301147 auth_redirect_uri = auth_redirect_uri ,
11311148 client_id = client_id ,
11321149 client_secret = client_secret ,
1150+ user_agent = user_agent ,
1151+ rfc9110_delimiter = rfc9110_delimiter ,
11331152 )
11341153 bqclient = connector .client
11351154
@@ -1409,3 +1428,59 @@ def create(self, dataset_id):
14091428 self .client .create_dataset (dataset )
14101429 except self .http_error as ex :
14111430 self .process_http_error (ex )
1431+
1432+
1433+ def create_user_agent (
1434+ user_agent : Optional [str ] = None , rfc9110_delimiter : bool = False
1435+ ) -> str :
1436+ """Creates a user agent string.
1437+
1438+ The legacy format of our the user agent string was: `product-x.y.z` (where x,
1439+ y, and z are the major, minor, and micro version numbers).
1440+
1441+ Users are able to prepend this string with their own user agent identifier
1442+ to render something similar to `<my_user_agent> pandas-x.y.z`.
1443+
1444+ The legacy format used a hyphen to separate the product from the product
1445+ version which differs slightly from the format recommended by RFC9110, which is:
1446+ `product/x.y.z`. To produce a user agent more in line with the RFC, set
1447+ rfc9110_delimiter to True. This setting does not depend on whether a
1448+ user_agent is also supplied.
1449+
1450+ Reference:
1451+ https://www.rfc-editor.org/info/rfc9110
1452+
1453+ Args:
1454+ user_agent (Optional[str]): User agent string.
1455+
1456+ rfc9110_delimiter (Optional[bool]): Sets delimiter to a hyphen or a slash.
1457+ Default is False, meaning a hyphen will be used.
1458+
1459+ Returns (str):
1460+ Customized user agent string.
1461+
1462+ Deprecation Warning:
1463+ In a future major release, the default delimiter will be changed to
1464+ a `/` in accordance with RFC9110.
1465+ """
1466+ import pandas as pd
1467+
1468+ if rfc9110_delimiter :
1469+ delimiter = "/"
1470+ else :
1471+ warnings .warn (
1472+ "In a future major release, the default delimiter will be "
1473+ "changed to a `/` in accordance with RFC9110." ,
1474+ PendingDeprecationWarning ,
1475+ stacklevel = 2 ,
1476+ )
1477+ delimiter = "-"
1478+
1479+ identity = f"pandas{ delimiter } { pd .__version__ } "
1480+
1481+ if user_agent is None :
1482+ user_agent = identity
1483+ else :
1484+ user_agent = f"{ user_agent } { identity } "
1485+
1486+ return user_agent
0 commit comments