Repository: googleapis/google-cloud-python

Issue:
BigQuery: 'Table.location' should be read-only
From https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5678#issuecomment-407830285

Currently, the `Table.location` property is [settable](https://github.com/GoogleCloudPlatform/google-cloud-python/blob/814e75bdff73c8c298eb90f828cc4f8a36f5cc3e/bigquery/google/cloud/bigquery/table.py#L603), but the [API reference](https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#location) marks it as `[Output-only]`.


Discussion:

Resolving patch:
diff --git a/bigquery/google/cloud/bigquery/table.py b/bigquery/google/cloud/bigquery/table.py
--- a/bigquery/google/cloud/bigquery/table.py
+++ b/bigquery/google/cloud/bigquery/table.py
@@ -591,20 +591,12 @@ def friendly_name(self, value):
 
     @property
     def location(self):
-        """Union[str, None]: Location in which the table is hosted (defaults
-        to :data:`None`).
+        """Union[str, None]: Location in which the table is hosted
 
-        Raises:
-            ValueError: For invalid value types.
+        Defaults to :data:`None`.
         """
         return self._properties.get('location')
 
-    @location.setter
-    def location(self, value):
-        if not isinstance(value, six.string_types) and value is not None:
-            raise ValueError("Pass a string, or None")
-        self._properties['location'] = value
-
     @property
     def view_query(self):
         """Union[str, None]: SQL query defining the table as a view (defaults


Test patch:
diff --git a/bigquery/tests/unit/test_client.py b/bigquery/tests/unit/test_client.py
--- a/bigquery/tests/unit/test_client.py
+++ b/bigquery/tests/unit/test_client.py
@@ -1110,7 +1110,10 @@ def test_update_table_w_query(self):
                 'tableId': self.TABLE_ID
             },
             'schema': schema_resource,
-            'view': {'query': query, 'useLegacySql': True},
+            'view': {
+                'query': query,
+                'useLegacySql': True,
+            },
             'location': location,
             'expirationTime': _millis(exp_time)
         }
@@ -1118,31 +1121,34 @@ def test_update_table_w_query(self):
         client = self._make_one(project=self.PROJECT, credentials=creds)
         conn = client._connection = _make_connection(resource)
         table = Table(self.TABLE_REF, schema=schema)
-        table.location = location
         table.expires = exp_time
         table.view_query = query
         table.view_use_legacy_sql = True
-        updated_properties = ['schema', 'view_query', 'location',
-                              'expires', 'view_use_legacy_sql']
+        updated_properties = [
+            'schema', 'view_query', 'expires', 'view_use_legacy_sql']
 
         updated_table = client.update_table(table, updated_properties)
 
+        self.assertEqual(updated_table.schema, table.schema)
+        self.assertEqual(updated_table.view_query, table.view_query)
+        self.assertEqual(updated_table.expires, table.expires)
+        self.assertEqual(
+            updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
+        self.assertEqual(updated_table.location, location)
+
         conn.api_request.assert_called_once_with(
             method='PATCH',
             path='/%s' % path,
             data={
-                'view': {'query': query, 'useLegacySql': True},
-                'location': location,
+                'view': {
+                    'query': query,
+                    'useLegacySql': True,
+                },
                 'expirationTime': str(_millis(exp_time)),
                 'schema': schema_resource,
             },
-            headers=None)
-        self.assertEqual(updated_table.schema, table.schema)
-        self.assertEqual(updated_table.view_query, table.view_query)
-        self.assertEqual(updated_table.location, table.location)
-        self.assertEqual(updated_table.expires, table.expires)
-        self.assertEqual(
-            updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
+            headers=None,
+        )
 
     def test_update_table_w_schema_None(self):
         # Simulate deleting schema:  not sure if back-end will actually
diff --git a/bigquery/tests/unit/test_table.py b/bigquery/tests/unit/test_table.py
--- a/bigquery/tests/unit/test_table.py
+++ b/bigquery/tests/unit/test_table.py
@@ -560,20 +560,6 @@ def test_friendly_name_setter(self):
         table.friendly_name = 'FRIENDLY'
         self.assertEqual(table.friendly_name, 'FRIENDLY')
 
-    def test_location_setter_bad_value(self):
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-        table_ref = dataset.table(self.TABLE_NAME)
-        table = self._make_one(table_ref)
-        with self.assertRaises(ValueError):
-            table.location = 12345
-
-    def test_location_setter(self):
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-        table_ref = dataset.table(self.TABLE_NAME)
-        table = self._make_one(table_ref)
-        table.location = 'LOCATION'
-        self.assertEqual(table.location, 'LOCATION')
-
     def test_view_query_setter_bad_value(self):
         dataset = DatasetReference(self.PROJECT, self.DS_ID)
         table_ref = dataset.table(self.TABLE_NAME)