-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Select expressions no-longer force use of labels (#129)
* Fixed a dependency problem that caysed test failures in Python 3.6. The source of the dependency bug is in old versions of google-cloud-core that depend on too-old versions of google-api-core. * Provide a bigquery mock based on sqlite So we don't have t mock at the api level. * Don't force labels in select. #78
- Loading branch information
Showing
6 changed files
with
128 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import mock | ||
import pytest | ||
import sqlalchemy | ||
|
||
import fauxdbi | ||
|
||
|
||
@pytest.fixture() | ||
def faux_conn(): | ||
with mock.patch( | ||
"google.cloud.bigquery.dbapi.connection.Connection", fauxdbi.Connection | ||
): | ||
engine = sqlalchemy.create_engine("bigquery://myproject/mydataset") | ||
conn = engine.connect() | ||
yield conn | ||
conn.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import google.api_core.exceptions | ||
import google.cloud.bigquery.schema | ||
import google.cloud.bigquery.table | ||
import contextlib | ||
import sqlite3 | ||
|
||
|
||
class Connection: | ||
|
||
connection = None | ||
|
||
def __init__(self, client=None, bqstorage_client=None): | ||
# share a single connection: | ||
if self.connection is None: | ||
self.__class__.connection = sqlite3.connect(":memory:") | ||
self._client = FauxClient(client, self.connection) | ||
|
||
def cursor(self): | ||
return Cursor(self.connection) | ||
|
||
def commit(self): | ||
pass | ||
|
||
def rollback(self): | ||
pass | ||
|
||
def close(self): | ||
self.connection.close() | ||
|
||
|
||
class Cursor: | ||
|
||
arraysize = 1 | ||
|
||
def __init__(self, connection): | ||
self.connection = connection | ||
self.cursor = connection.cursor() | ||
|
||
def execute(self, operation, parameters=None): | ||
if parameters: | ||
parameters = { | ||
name: "null" if value is None else repr(value) | ||
for name, value in parameters.items() | ||
} | ||
operation %= parameters | ||
self.cursor.execute(operation, parameters) | ||
self.description = self.cursor.description | ||
self.rowcount = self.cursor.rowcount | ||
|
||
def executemany(self, operation, parameters_list): | ||
for parameters in parameters_list: | ||
self.execute(operation, parameters) | ||
|
||
def close(self): | ||
self.cursor.close() | ||
|
||
def fetchone(self): | ||
return self.cursor.fetchone() | ||
|
||
def fetchmany(self, size=None): | ||
self.cursor.fetchmany(size or self.arraysize) | ||
|
||
def fetchall(self): | ||
return self.cursor.fetchall() | ||
|
||
def setinputsizes(self, sizes): | ||
pass | ||
|
||
def setoutputsize(self, size, column=None): | ||
pass | ||
|
||
|
||
class FauxClient: | ||
def __init__(self, client, connection): | ||
self._client = client | ||
self.project = client.project | ||
self.connection = connection | ||
|
||
def get_table(self, table_ref): | ||
table_name = table_ref.table_id | ||
with contextlib.closing(self.connection.cursor()) as cursor: | ||
cursor.execute( | ||
f"select name from sqlite_master" | ||
f" where type='table' and name='{table_name}'" | ||
) | ||
if list(cursor): | ||
cursor.execute("PRAGMA table_info('{table_name}')") | ||
schema = [ | ||
google.cloud.bigquery.schema.SchemaField( | ||
name=name, | ||
field_type=type_, | ||
mode="REQUIRED" if notnull else "NULLABLE", | ||
) | ||
for cid, name, type_, notnull, dflt_value, pk in cursor | ||
] | ||
return google.cloud.bigquery.table.Table(table_ref, schema) | ||
else: | ||
raise google.api_core.exceptions.NotFound(table_ref) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import sqlalchemy | ||
|
||
|
||
def test_labels_not_forced(faux_conn): | ||
metadata = sqlalchemy.MetaData() | ||
table = sqlalchemy.Table( | ||
"some_table", metadata, sqlalchemy.Column("id", sqlalchemy.Integer) | ||
) | ||
metadata.create_all(faux_conn.engine) | ||
result = faux_conn.execute(sqlalchemy.select([table.c.id])) | ||
assert result.keys() == ["id"] # Look! Just the column name! |