diff --git a/bigquery/google/cloud/bigquery/client.py b/bigquery/google/cloud/bigquery/client.py index 05be0da8123d..9c0bce5eba7e 100644 --- a/bigquery/google/cloud/bigquery/client.py +++ b/bigquery/google/cloud/bigquery/client.py @@ -23,6 +23,7 @@ from google.cloud.bigquery._http import Connection from google.cloud.bigquery.dataset import Dataset from google.cloud.bigquery.dataset import DatasetReference +from google.cloud.bigquery.dataset import Table from google.cloud.bigquery.job import CopyJob from google.cloud.bigquery.job import ExtractJob from google.cloud.bigquery.job import LoadJob @@ -207,6 +208,20 @@ def get_dataset(self, dataset_ref): method='GET', path=dataset_ref.path) return Dataset.from_api_repr(api_response, self) + def get_table(self, table_ref): + """Fetch the table referenced by ``table_ref`` + + :type table_ref: + :class:`google.cloud.bigquery.table.TableReference` + :param table_ref: the table to use. + + :rtype: :class:`google.cloud.bigquery.table.Table` + :returns: a ``Table`` instance + """ + api_response = self._connection.api_request( + method='GET', path=table_ref.path) + return Table.from_api_repr(api_response, self) + def _get_query_results(self, job_id, project=None, timeout_ms=None): """Get the query results object for a query job. diff --git a/bigquery/google/cloud/bigquery/table.py b/bigquery/google/cloud/bigquery/table.py index 4549912305b4..e00f26c434e7 100644 --- a/bigquery/google/cloud/bigquery/table.py +++ b/bigquery/google/cloud/bigquery/table.py @@ -35,7 +35,7 @@ from google.cloud.bigquery._helpers import _SCALAR_VALUE_TO_JSON_ROW -_TABLE_HAS_NO_SCHEMA = "Table has no schema: call 'table.reload()'" +_TABLE_HAS_NO_SCHEMA = "Table has no schema: call 'client.get_table()'" _MARKER = object() _DEFAULT_CHUNKSIZE = 1048576 # 1024 * 1024 B = 1 MB _BASE_UPLOAD_TEMPLATE = ( @@ -85,6 +85,15 @@ def table_id(self): """ return self._table_id + @property + def path(self): + """URL path for the table's APIs. + + :rtype: str + :returns: the path based on project, dataset and table IDs. + """ + return '%s/tables/%s' % (self._dataset_ref.path, self._table_id) + class Table(object): """Tables represent a set of rows whose values correspond to a schema. @@ -616,23 +625,6 @@ def exists(self, client=None): else: return True - def reload(self, client=None): - """API call: refresh table properties via a GET request - - See - https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/get - - :type client: :class:`~google.cloud.bigquery.client.Client` or - ``NoneType`` - :param client: the client to use. If not passed, falls back to the - ``client`` stored on the current dataset. - """ - client = self._require_client(client) - - api_response = client._connection.api_request( - method='GET', path=self.path) - self._set_properties(api_response) - def patch(self, client=None, friendly_name=_MARKER, @@ -750,7 +742,7 @@ def fetch_data(self, max_results=None, page_token=None, client=None): up-to-date with the schema as defined on the back-end: if the two schemas are not identical, the values returned may be incomplete. To ensure that the local copy of the schema is - up-to-date, call :meth:`reload`. + up-to-date, call ``client.get_table``. :type max_results: int :param max_results: (Optional) Maximum number of rows to return. diff --git a/bigquery/tests/system.py b/bigquery/tests/system.py index 5ba2a19cf271..ee66b6aa6af9 100644 --- a/bigquery/tests/system.py +++ b/bigquery/tests/system.py @@ -198,6 +198,21 @@ def test_create_table(self): self.assertTrue(table.exists()) self.assertEqual(table.table_id, TABLE_NAME) + def test_get_table_w_public_dataset(self): + PUBLIC = 'bigquery-public-data' + DATASET_ID = 'samples' + TABLE_ID = 'shakespeare' + table_ref = DatasetReference(PUBLIC, DATASET_ID).table(TABLE_ID) + + table = Config.CLIENT.get_table(table_ref) + + self.assertEqual(table.table_id, TABLE_ID) + self.assertEqual(table.dataset_id, DATASET_ID) + self.assertEqual(table.project, PUBLIC) + schema_names = [field.name for field in table.schema] + self.assertEqual( + schema_names, ['word', 'word_count', 'corpus', 'corpus_date']) + def test_list_tables(self): DATASET_ID = _make_dataset_id('list_tables') dataset = retry_403(Config.CLIENT.create_dataset)(Dataset(DATASET_ID)) @@ -402,8 +417,7 @@ def test_load_table_from_local_avro_file_then_dump_table(self): self.assertEqual(job.output_rows, len(ROWS)) - # Reload table to get the schema before fetching the rows. - table.reload() + table = Config.CLIENT.get_table(table) rows = self._fetch_single_page(table) by_wavelength = operator.itemgetter(1) self.assertEqual(sorted(rows, key=by_wavelength), @@ -532,7 +546,7 @@ def test_load_table_from_storage_w_autodetect_schema(self): retry = RetryInstanceState(_job_done, max_tries=8) retry(job.reload)() - table.reload() + table = Config.CLIENT.get_table(table) field_name = SchemaField( u'Full_Name', u'string', u'NULLABLE', None, ()) field_age = SchemaField(u'Age', u'integer', u'NULLABLE', None, ()) @@ -1163,9 +1177,8 @@ def test_dump_table_w_public_data(self): TABLE_NAME = 'natality' dataset = Dataset(DATASET_ID, Config.CLIENT, project=PUBLIC) - table = dataset.table(TABLE_NAME) - # Reload table to get the schema before fetching the rows. - table.reload() + table_ref = dataset.table(TABLE_NAME) + table = Config.CLIENT.get_table(table_ref) self._fetch_single_page(table) def test_large_query_w_public_data(self): diff --git a/bigquery/tests/unit/test_client.py b/bigquery/tests/unit/test_client.py index d49d8ba4391c..90b06af2d022 100644 --- a/bigquery/tests/unit/test_client.py +++ b/bigquery/tests/unit/test_client.py @@ -383,6 +383,34 @@ def test_create_dataset_w_attrs(self): self.assertEqual(ds.description, DESCRIPTION) self.assertEqual(ds.friendly_name, FRIENDLY_NAME) + def test_get_table(self): + project = 'PROJECT' + dataset_id = 'dataset_id' + table_id = 'table-id' + path = 'projects/%s/datasets/%s/tables/%s' % ( + project, dataset_id, table_id) + creds = _make_credentials() + http = object() + client = self._make_one(project=project, credentials=creds, _http=http) + resource = { + 'id': '%s:%s:%s' % (project, dataset_id, table_id), + 'tableReference': { + 'projectId': project, + 'datasetId': dataset_id, + 'tableId': table_id + }, + } + conn = client._connection = _Connection(resource) + table_ref = client.dataset(dataset_id).table(table_id) + + table = client.get_table(table_ref) + + self.assertEqual(len(conn._requested), 1) + req = conn._requested[0] + self.assertEqual(req['method'], 'GET') + self.assertEqual(req['path'], '/%s' % path) + self.assertEqual(table.table_id, table_id) + def test_job_from_resource_unknown_type(self): PROJECT = 'PROJECT' creds = _make_credentials() diff --git a/bigquery/tests/unit/test_table.py b/bigquery/tests/unit/test_table.py index 7cc7bffe7080..a36a4b216c04 100644 --- a/bigquery/tests/unit/test_table.py +++ b/bigquery/tests/unit/test_table.py @@ -864,45 +864,6 @@ def test_exists_hit_w_alternate_client(self): self.assertEqual(req['path'], '/%s' % PATH) self.assertEqual(req['query_params'], {'fields': 'id'}) - def test_reload_w_bound_client(self): - PATH = 'projects/%s/datasets/%s/tables/%s' % ( - self.PROJECT, self.DS_ID, self.TABLE_NAME) - RESOURCE = self._makeResource() - conn = _Connection(RESOURCE) - client = _Client(project=self.PROJECT, connection=conn) - dataset = DatasetReference(self.PROJECT, self.DS_ID) - table_ref = dataset.table(self.TABLE_NAME) - table = self._make_one(table_ref, client=client) - - table.reload() - - self.assertEqual(len(conn._requested), 1) - req = conn._requested[0] - self.assertEqual(req['method'], 'GET') - self.assertEqual(req['path'], '/%s' % PATH) - self._verifyResourceProperties(table, RESOURCE) - - def test_reload_w_alternate_client(self): - PATH = 'projects/%s/datasets/%s/tables/%s' % ( - self.PROJECT, self.DS_ID, self.TABLE_NAME) - RESOURCE = self._makeResource() - conn1 = _Connection() - client1 = _Client(project=self.PROJECT, connection=conn1) - conn2 = _Connection(RESOURCE) - client2 = _Client(project=self.PROJECT, connection=conn2) - dataset = DatasetReference(self.PROJECT, self.DS_ID) - table_ref = dataset.table(self.TABLE_NAME) - table = self._make_one(table_ref, client=client1) - - table.reload(client=client2) - - self.assertEqual(len(conn1._requested), 0) - self.assertEqual(len(conn2._requested), 1) - req = conn2._requested[0] - self.assertEqual(req['method'], 'GET') - self.assertEqual(req['path'], '/%s' % PATH) - self._verifyResourceProperties(table, RESOURCE) - def test_patch_w_invalid_expiration(self): RESOURCE = self._makeResource() conn = _Connection(RESOURCE)