diff --git a/bigquery/google/cloud/bigquery/dataset.py b/bigquery/google/cloud/bigquery/dataset.py index fc641c3a4d58..e464fcfb93bd 100644 --- a/bigquery/google/cloud/bigquery/dataset.py +++ b/bigquery/google/cloud/bigquery/dataset.py @@ -151,6 +151,45 @@ def table(self, table_id): """ return TableReference(self, table_id) + @classmethod + def from_api_repr(cls, resource): + project = resource['projectId'] + dataset_id = resource['datasetId'] + return cls(project, dataset_id) + + def to_api_repr(self): + return { + 'projectId': self._project, + 'datasetId': self._dataset_id, + } + + def _key(self): + """A tuple key that uniquely describes this field. + + Used to compute this instance's hashcode and evaluate equality. + + Returns: + tuple: The contents of this :class:`DatasetReference`. + """ + return ( + self._project, + self._dataset_id, + ) + + def __eq__(self, other): + if not isinstance(other, DatasetReference): + return NotImplemented + return self._key() == other._key() + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self._key()) + + def __repr__(self): + return 'DatasetReference{}'.format(self._key()) + class Dataset(object): """Datasets are containers for tables. diff --git a/bigquery/google/cloud/bigquery/schema.py b/bigquery/google/cloud/bigquery/schema.py index 4aea34ac22e0..535c445a3726 100644 --- a/bigquery/google/cloud/bigquery/schema.py +++ b/bigquery/google/cloud/bigquery/schema.py @@ -126,7 +126,7 @@ def to_api_repr(self): return answer def _key(self): - """A tuple key that unique-ly describes this field. + """A tuple key that uniquely describes this field. Used to compute this instance's hashcode and evaluate equality. diff --git a/bigquery/google/cloud/bigquery/table.py b/bigquery/google/cloud/bigquery/table.py index 87112ada3ea1..542e87db0bb8 100644 --- a/bigquery/google/cloud/bigquery/table.py +++ b/bigquery/google/cloud/bigquery/table.py @@ -105,6 +105,63 @@ def path(self): return '/projects/%s/datasets/%s/tables/%s' % ( self._project, self._dataset_id, self._table_id) + @classmethod + def from_api_repr(cls, resource): + """Factory: construct a table reference given its API representation + + :type resource: dict + :param resource: table reference representation returned from the API + + :rtype: :class:`google.cloud.bigquery.table.TableReference` + :returns: Table reference parsed from ``resource``. + """ + from google.cloud.bigquery.dataset import DatasetReference + + project = resource['projectId'] + dataset_id = resource['datasetId'] + table_id = resource['tableId'] + return cls(DatasetReference(project, dataset_id), table_id) + + def to_api_repr(self): + """Construct the API resource representation of this table reference. + + :rtype: dict + :returns: Table reference as represented as an API resource + """ + return { + 'projectId': self._project, + 'datasetId': self._dataset_id, + 'tableId': self._table_id, + } + + def _key(self): + """A tuple key that uniquely describes this field. + + Used to compute this instance's hashcode and evaluate equality. + + Returns: + tuple: The contents of this :class:`DatasetReference`. + """ + return ( + self._project, + self._dataset_id, + self._table_id, + ) + + def __eq__(self, other): + if not isinstance(other, TableReference): + return NotImplemented + return self._key() == other._key() + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self._key()) + + def __repr__(self): + return 'TableReference{}'.format(self._key()) + class Table(object): """Tables represent a set of rows whose values correspond to a schema. diff --git a/bigquery/tests/unit/test_dataset.py b/bigquery/tests/unit/test_dataset.py index ced77990a65d..c04d154b52da 100644 --- a/bigquery/tests/unit/test_dataset.py +++ b/bigquery/tests/unit/test_dataset.py @@ -114,6 +114,70 @@ def test_table(self): self.assertEqual(table_ref.project, 'some-project-1') self.assertEqual(table_ref.table_id, 'table_1') + def test_to_api_repr(self): + dataset = self._make_one('project_1', 'dataset_1') + + resource = dataset.to_api_repr() + + self.assertEqual( + resource, + { + 'projectId': 'project_1', + 'datasetId': 'dataset_1', + }) + + def test_from_api_repr(self): + from google.cloud.bigquery.dataset import DatasetReference + expected = self._make_one('project_1', 'dataset_1') + + got = DatasetReference.from_api_repr( + { + 'projectId': 'project_1', + 'datasetId': 'dataset_1', + }) + + self.assertEqual(expected, got) + + def test___eq___wrong_type(self): + dataset = self._make_one('project_1', 'dataset_1') + other = object() + self.assertNotEqual(dataset, other) + self.assertEqual(dataset, mock.ANY) + + def test___eq___project_mismatch(self): + dataset = self._make_one('project_1', 'dataset_1') + other = self._make_one('project_2', 'dataset_1') + self.assertNotEqual(dataset, other) + + def test___eq___dataset_mismatch(self): + dataset = self._make_one('project_1', 'dataset_1') + other = self._make_one('project_1', 'dataset_2') + self.assertNotEqual(dataset, other) + + def test___eq___equality(self): + dataset = self._make_one('project_1', 'dataset_1') + other = self._make_one('project_1', 'dataset_1') + self.assertEqual(dataset, other) + + def test___hash__set_equality(self): + dataset1 = self._make_one('project_1', 'dataset_1') + dataset2 = self._make_one('project_1', 'dataset_2') + set_one = {dataset1, dataset2} + set_two = {dataset1, dataset2} + self.assertEqual(set_one, set_two) + + def test___hash__not_equals(self): + dataset1 = self._make_one('project_1', 'dataset_1') + dataset2 = self._make_one('project_1', 'dataset_2') + set_one = {dataset1} + set_two = {dataset2} + self.assertNotEqual(set_one, set_two) + + def test___repr__(self): + dataset = self._make_one('project1', 'dataset1') + expected = "DatasetReference('project1', 'dataset1')" + self.assertEqual(repr(dataset), expected) + class TestDataset(unittest.TestCase): from google.cloud.bigquery.dataset import DatasetReference diff --git a/bigquery/tests/unit/test_table.py b/bigquery/tests/unit/test_table.py index 2327d11b1ed3..f2c2297d244b 100644 --- a/bigquery/tests/unit/test_table.py +++ b/bigquery/tests/unit/test_table.py @@ -58,6 +58,98 @@ def test_ctor_defaults(self): self.assertEqual(table_ref.dataset_id, dataset_ref.dataset_id) self.assertEqual(table_ref.table_id, 'table_1') + def test_to_api_repr(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset_ref = DatasetReference('project_1', 'dataset_1') + table_ref = self._make_one(dataset_ref, 'table_1') + + resource = table_ref.to_api_repr() + + self.assertEqual( + resource, + { + 'projectId': 'project_1', + 'datasetId': 'dataset_1', + 'tableId': 'table_1', + }) + + def test_from_api_repr(self): + from google.cloud.bigquery.dataset import DatasetReference + from google.cloud.bigquery.table import TableReference + dataset_ref = DatasetReference('project_1', 'dataset_1') + expected = self._make_one(dataset_ref, 'table_1') + + got = TableReference.from_api_repr( + { + 'projectId': 'project_1', + 'datasetId': 'dataset_1', + 'tableId': 'table_1', + }) + + self.assertEqual(expected, got) + + def test___eq___wrong_type(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset_ref = DatasetReference('project_1', 'dataset_1') + table = self._make_one(dataset_ref, 'table_1') + other = object() + self.assertNotEqual(table, other) + self.assertEqual(table, mock.ANY) + + def test___eq___project_mismatch(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + other_dataset = DatasetReference('project_2', 'dataset_1') + table = self._make_one(dataset, 'table_1') + other = self._make_one(other_dataset, 'table_1') + self.assertNotEqual(table, other) + + def test___eq___dataset_mismatch(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + other_dataset = DatasetReference('project_1', 'dataset_2') + table = self._make_one(dataset, 'table_1') + other = self._make_one(other_dataset, 'table_1') + self.assertNotEqual(table, other) + + def test___eq___table_mismatch(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + table = self._make_one(dataset, 'table_1') + other = self._make_one(dataset, 'table_2') + self.assertNotEqual(table, other) + + def test___eq___equality(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + table = self._make_one(dataset, 'table_1') + other = self._make_one(dataset, 'table_1') + self.assertEqual(table, other) + + def test___hash__set_equality(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + table1 = self._make_one(dataset, 'table1') + table2 = self._make_one(dataset, 'table2') + set_one = {table1, table2} + set_two = {table1, table2} + self.assertEqual(set_one, set_two) + + def test___hash__not_equals(self): + from google.cloud.bigquery.dataset import DatasetReference + dataset = DatasetReference('project_1', 'dataset_1') + table1 = self._make_one(dataset, 'table1') + table2 = self._make_one(dataset, 'table2') + set_one = {table1} + set_two = {table2} + self.assertNotEqual(set_one, set_two) + + def test___repr__(self): + dataset = DatasetReference('project1', 'dataset1') + table1 = self._make_one(dataset, 'table1') + expected = "TableReference('project1', 'dataset1', 'table1')" + self.assertEqual(repr(table1), expected) + class TestTable(unittest.TestCase, _SchemaBase):