-
Notifications
You must be signed in to change notification settings - Fork 50
feat: use default session connection #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4d17229
b0e9215
dd05552
6739428
4ee895e
dcf93fa
c79c86e
62ac080
cd6c86a
71ec5b0
aa42ff7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,8 @@ | |
) | ||
logger = logging.getLogger(__name__) | ||
|
||
_BIGFRAMES_DEFAULT_CONNECTION_ID = "bigframes-default-connection" | ||
|
||
|
||
class BqConnectionManager: | ||
"""Manager to handle operations with BQ connections.""" | ||
|
@@ -162,3 +164,25 @@ def _get_service_account_if_connection_exists( | |
pass | ||
|
||
return service_account | ||
|
||
|
||
def get_connection_name_full( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] since it takes a connection and returns a connection after resolving the format, would prefer naming it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will address in another PR. |
||
connection_name: Optional[str], default_project: str, default_location: str | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. awkward to have optional argument followed by mandatory arguments, would be nice to have it in the end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional only means it can be value None. It is OK to put it at the front, as it is the most important param of the function. Not really "optional", which means it has a default value. Then it has to be at the end. |
||
) -> str: | ||
"""Retrieve the full connection name of the form <PROJECT_NUMBER/PROJECT_ID>.<LOCATION>.<CONNECTION_ID>. | ||
Use default project, location or connection_id when any of them are missing.""" | ||
if connection_name is None: | ||
return ( | ||
f"{default_project}.{default_location}.{_BIGFRAMES_DEFAULT_CONNECTION_ID}" | ||
) | ||
|
||
if connection_name.count(".") == 2: | ||
return connection_name | ||
|
||
if connection_name.count(".") == 1: | ||
return f"{default_project}.{connection_name}" | ||
|
||
if connection_name.count(".") == 0: | ||
return f"{default_project}.{default_location}.{connection_name}" | ||
|
||
raise ValueError(f"Invalid connection name format: {connection_name}.") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,8 +38,9 @@ class PaLM2TextGenerator(base.Predictor): | |
session (bigframes.Session or None): | ||
BQ session to create the model. If None, use the global default session. | ||
connection_name (str or None): | ||
connection to connect with remote service. str of the format <PROJECT_NUMBER/PROJECT_ID>.<REGION>.<CONNECTION_NAME>. | ||
if None, use default connection in session context. | ||
connection to connect with remote service. str of the format <PROJECT_NUMBER/PROJECT_ID>.<LOCATION>.<CONNECTION_ID>. | ||
if None, use default connection in session context. BigQuery DataFrame will try to create the connection and attach | ||
permission if the connection isn't fully setup. | ||
""" | ||
|
||
def __init__( | ||
|
@@ -48,7 +49,14 @@ def __init__( | |
connection_name: Optional[str] = None, | ||
): | ||
self.session = session or bpd.get_global_session() | ||
self.connection_name = connection_name or self.session._bq_connection | ||
|
||
connection_name = connection_name or self.session._bq_connection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about this a bit, we are resolving between 3 potential sources of connection:
How about we set the default in self._bq_connection = context.bq_connection or "bigframes-default-connection" We are assuming other session defaults there, such as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh yea, I did this way at first place, but then I found remote_function doesn't always have a session object. So I had to put the default away from session. Then we added default session... We can move it to session. |
||
self.connection_name = clients.get_connection_name_full( | ||
connection_name, | ||
default_project=self.session._project, | ||
default_location=self.session._location, | ||
) | ||
|
||
self._bq_connection_manager = clients.BqConnectionManager( | ||
self.session.bqconnectionclient, self.session.resourcemanagerclient | ||
) | ||
|
@@ -180,7 +188,14 @@ def __init__( | |
connection_name: Optional[str] = None, | ||
): | ||
self.session = session or bpd.get_global_session() | ||
self.connection_name = connection_name or self.session._bq_connection | ||
|
||
connection_name = connection_name or self.session._bq_connection | ||
self.connection_name = clients.get_connection_name_full( | ||
connection_name, | ||
default_project=self.session._project, | ||
default_location=self.session._location, | ||
) | ||
|
||
self._bq_connection_manager = clients.BqConnectionManager( | ||
self.session.bqconnectionclient, self.session.resourcemanagerclient | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Copyright 2023 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 pytest | ||
|
||
from bigframes import clients | ||
|
||
|
||
def test_get_connection_name_full_none(): | ||
connection_name = clients.get_connection_name_full( | ||
None, default_project="default-project", default_location="us" | ||
) | ||
assert connection_name == "default-project.us.bigframes-default-connection" | ||
|
||
|
||
def test_get_connection_name_full_connection_id(): | ||
connection_name = clients.get_connection_name_full( | ||
"connection-id", default_project="default-project", default_location="us" | ||
) | ||
assert connection_name == "default-project.us.connection-id" | ||
|
||
|
||
def test_get_connection_name_full_location_connection_id(): | ||
connection_name = clients.get_connection_name_full( | ||
"eu.connection-id", default_project="default-project", default_location="us" | ||
) | ||
assert connection_name == "default-project.eu.connection-id" | ||
|
||
|
||
def test_get_connection_name_full_all(): | ||
connection_name = clients.get_connection_name_full( | ||
"my-project.eu.connection-id", | ||
default_project="default-project", | ||
default_location="us", | ||
) | ||
assert connection_name == "my-project.eu.connection-id" | ||
|
||
|
||
def test_get_connection_name_full_raise_value_error(): | ||
|
||
with pytest.raises(ValueError): | ||
clients.get_connection_name_full( | ||
"my-project.eu.connection-id.extra_field", | ||
default_project="default-project", | ||
default_location="us", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be tidier to make it a class method in
BqConnectionManager
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the function is only a helper that does string manipulation. Instead of the BqConnectionManager which contains the states of the clients. So separate them.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO it would still make sense. A
@classmethod
would mean that it does not depend on the instance level state. But conceptually it would fit in nicely - BqConnectionManager sounds like the entity which is supposed to know the low level details of a connection and can provide helper functions about the same.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That could work. Will address in another PR.