Content-Length: 559976 | pFad | https://github.com/googleapis/python-bigquery/commit/cb646ceea172bf199f366ae0592546dff2d3bcb2

BB feat: support job reservation (#2186) · googleapis/python-bigquery@cb646ce · GitHub
Skip to content

Commit cb646ce

Browse files
Linchinchalmerlowe
andauthored
feat: support job reservation (#2186)
* feat: support job reservation * Update google/cloud/bigquery/job/base.py Co-authored-by: Chalmer Lowe <chalmerlowe@google.com> --------- Co-authored-by: Chalmer Lowe <chalmerlowe@google.com>
1 parent 7ec2848 commit cb646ce

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

google/cloud/bigquery/job/base.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,26 @@ def job_timeout_ms(self, value):
224224
else:
225225
self._properties.pop("jobTimeoutMs", None)
226226

227+
@property
228+
def reservation(self):
229+
"""str: Optional. The reservation that job would use.
230+
231+
User can specify a reservation to execute the job. If reservation is
232+
not set, reservation is determined based on the rules defined by the
233+
reservation assignments. The expected format is
234+
projects/{project}/locations/{location}/reservations/{reservation}.
235+
236+
Raises:
237+
ValueError: If ``value`` type is not None or of string type.
238+
"""
239+
return self._properties.setdefault("reservation", None)
240+
241+
@reservation.setter
242+
def reservation(self, value):
243+
if value and not isinstance(value, str):
244+
raise ValueError("Reservation must be None or a string.")
245+
self._properties["reservation"] = value
246+
227247
@property
228248
def labels(self):
229249
"""Dict[str, str]: Labels for the job.
@@ -488,6 +508,18 @@ def location(self):
488508
"""str: Location where the job runs."""
489509
return _helpers._get_sub_prop(self._properties, ["jobReference", "location"])
490510

511+
@property
512+
def reservation_id(self):
513+
"""str: Name of the primary reservation assigned to this job.
514+
515+
Note that this could be different than reservations reported in
516+
the reservation field if parent reservations were used to execute
517+
this job.
518+
"""
519+
return _helpers._get_sub_prop(
520+
self._properties, ["statistics", "reservation_id"]
521+
)
522+
491523
def _require_client(self, client):
492524
"""Check client or verify over-ride.
493525

tests/unit/job/test_base.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,16 @@ def test_state(self):
443443
status["state"] = state
444444
self.assertEqual(job.state, state)
445445

446+
def test_reservation_id(self):
447+
reservation_id = "RESERVATION-ID"
448+
client = _make_client(project=self.PROJECT)
449+
job = self._make_one(self.JOB_ID, client)
450+
self.assertIsNone(job.reservation_id)
451+
stats = job._properties["statistics"] = {}
452+
self.assertIsNone(job.reservation_id)
453+
stats["reservation_id"] = reservation_id
454+
self.assertEqual(job.reservation_id, reservation_id)
455+
446456
def _set_properties_job(self):
447457
client = _make_client(project=self.PROJECT)
448458
job = self._make_one(self.JOB_ID, client)
@@ -1188,31 +1198,37 @@ def test_fill_query_job_config_from_default(self):
11881198
job_config = QueryJobConfig()
11891199
job_config.dry_run = True
11901200
job_config.maximum_bytes_billed = 1000
1201+
job_config.reservation = "reservation_1"
11911202

11921203
default_job_config = QueryJobConfig()
11931204
default_job_config.use_query_cache = True
11941205
default_job_config.maximum_bytes_billed = 2000
1206+
default_job_config.reservation = "reservation_2"
11951207

11961208
final_job_config = job_config._fill_from_default(default_job_config)
11971209
self.assertTrue(final_job_config.dry_run)
11981210
self.assertTrue(final_job_config.use_query_cache)
11991211
self.assertEqual(final_job_config.maximum_bytes_billed, 1000)
1212+
self.assertEqual(final_job_config.reservation, "reservation_1")
12001213

12011214
def test_fill_load_job_from_default(self):
12021215
from google.cloud.bigquery import LoadJobConfig
12031216

12041217
job_config = LoadJobConfig()
12051218
job_config.create_session = True
12061219
job_config.encoding = "UTF-8"
1220+
job_config.reservation = "reservation_1"
12071221

12081222
default_job_config = LoadJobConfig()
12091223
default_job_config.ignore_unknown_values = True
12101224
default_job_config.encoding = "ISO-8859-1"
1225+
default_job_config.reservation = "reservation_2"
12111226

12121227
final_job_config = job_config._fill_from_default(default_job_config)
12131228
self.assertTrue(final_job_config.create_session)
12141229
self.assertTrue(final_job_config.ignore_unknown_values)
12151230
self.assertEqual(final_job_config.encoding, "UTF-8")
1231+
self.assertEqual(final_job_config.reservation, "reservation_1")
12161232

12171233
def test_fill_from_default_conflict(self):
12181234
from google.cloud.bigquery import QueryJobConfig
@@ -1232,10 +1248,12 @@ def test_fill_from_empty_default_conflict(self):
12321248
job_config = QueryJobConfig()
12331249
job_config.dry_run = True
12341250
job_config.maximum_bytes_billed = 1000
1251+
job_config.reservation = "reservation_1"
12351252

12361253
final_job_config = job_config._fill_from_default(default_job_config=None)
12371254
self.assertTrue(final_job_config.dry_run)
12381255
self.assertEqual(final_job_config.maximum_bytes_billed, 1000)
1256+
self.assertEqual(final_job_config.reservation, "reservation_1")
12391257

12401258
@mock.patch("google.cloud.bigquery._helpers._get_sub_prop")
12411259
def test__get_sub_prop_wo_default(self, _get_sub_prop):
@@ -1338,3 +1356,27 @@ def test_job_timeout_properties(self):
13381356
job_config.job_timeout_ms = None
13391357
assert job_config.job_timeout_ms is None
13401358
assert "jobTimeoutMs" not in job_config._properties
1359+
1360+
def test_reservation_miss(self):
1361+
job_config = self._make_one()
1362+
self.assertEqual(job_config.reservation, None)
1363+
1364+
def test_reservation_hit(self):
1365+
job_config = self._make_one()
1366+
job_config._properties["reservation"] = "foo"
1367+
self.assertEqual(job_config.reservation, "foo")
1368+
1369+
def test_reservation_update_in_place(self):
1370+
job_config = self._make_one()
1371+
job_config.reservation = "bar" # update in place
1372+
self.assertEqual(job_config.reservation, "bar")
1373+
1374+
def test_reservation_setter_invalid(self):
1375+
job_config = self._make_one()
1376+
with self.assertRaises(ValueError):
1377+
job_config.reservation = object()
1378+
1379+
def test_reservation_setter(self):
1380+
job_config = self._make_one()
1381+
job_config.reservation = "foo"
1382+
self.assertEqual(job_config._properties["reservation"], "foo")

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://github.com/googleapis/python-bigquery/commit/cb646ceea172bf199f366ae0592546dff2d3bcb2

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy