Files
fn_registry/python/functions/bigquery/client.py
T
egutierrez 5a4f82cf76 chore: auto-commit (26 archivos)
- python/functions/bigquery/bq_auth.md
- python/functions/bigquery/bq_load_from_file.md
- python/functions/bigquery/bq_load_from_gcs.md
- python/functions/bigquery/client.py
- python/functions/bigquery/queries.py
- python/functions/datascience/__init__.py
- python/functions/datascience/decode_qr_image.py
- python/functions/datascience/load_bq_table_to_duckdb.md
- python/functions/datascience/load_bq_table_to_duckdb.py
- python/functions/pipelines/profile_bq_table.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-02 19:00:13 +02:00

86 lines
3.0 KiB
Python

"""Cliente base para Google BigQuery."""
from dataclasses import dataclass, field
import google.auth
from google.cloud import bigquery
from google.oauth2 import service_account
@dataclass
class BQClient:
"""Cliente para Google BigQuery.
Attributes:
project_id: ID del proyecto GCP.
_client: Cliente oficial de BigQuery (interno).
"""
project_id: str
_client: bigquery.Client = field(repr=False)
def close(self) -> None:
"""Cierra el cliente BigQuery."""
self._client.close()
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
def bq_auth(
project_id: str = "",
credentials_path: str = "",
drop_quota_project: bool = False,
) -> BQClient:
"""Autentica contra Google BigQuery.
Tres modos de autenticacion:
1. ADC (Application Default Credentials): sin argumentos, usa gcloud auth
2. Service account JSON: con credentials_path
3. Proyecto explicito: con project_id (usa ADC para credenciales)
Con drop_quota_project=True (y sin credentials_path) resuelve las credenciales
ADC via google.auth.default y elimina el quota project fijado en el ADC del
usuario (creds.with_quota_project(None)). Esto evita el error 403
USER_PROJECT_DENIED cuando el ADC lleva un quota_project_id ajeno al proyecto
contra el que se consulta.
Args:
project_id: ID del proyecto GCP. Vacio = detectar de credenciales.
credentials_path: Ruta a archivo JSON de service account. Vacio = ADC.
drop_quota_project: Si True y sin credentials_path, resuelve ADC con
google.auth.default y descarta el quota project del ADC
(with_quota_project(None)). Default False = comportamiento original.
Returns:
BQClient autenticado listo para usar.
Raises:
google.auth.exceptions.DefaultCredentialsError: Si no hay credenciales configuradas.
FileNotFoundError: Si credentials_path no existe.
Example:
>>> client = bq_auth() # ADC
>>> client = bq_auth("my-project") # ADC con proyecto explicito
>>> client = bq_auth(credentials_path="/path/to/sa.json") # Service account
>>> client = bq_auth("autingo-159109", drop_quota_project=True) # sin quota project
"""
if credentials_path:
creds = service_account.Credentials.from_service_account_file(credentials_path)
proj = project_id or creds.project_id
client = bigquery.Client(credentials=creds, project=proj)
elif drop_quota_project:
creds, adc_project = google.auth.default(
scopes=["https://www.googleapis.com/auth/bigquery"]
)
if hasattr(creds, "with_quota_project"):
creds = creds.with_quota_project(None)
client = bigquery.Client(project=project_id or adc_project, credentials=creds)
elif project_id:
client = bigquery.Client(project=project_id)
else:
client = bigquery.Client()
return BQClient(project_id=client.project, _client=client)