Skip to content

Commit f00b60b

Browse files
shubha-rajantswast
authored andcommitted
Add --max_results option to Jupyter magics. (#9169)
* added max_results magic option and fixed broken tests * added tests for --max_results magic option * added max_results magic option and fixed broken tests * added tests for --max_results magic option * Removed duplicate `--max_results` magic argument * removed max_results param from run_query, updated tests
1 parent e360baa commit f00b60b

File tree

2 files changed

+77
-4
lines changed

2 files changed

+77
-4
lines changed

bigquery/google/cloud/bigquery/magics.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ def _run_query(client, query, job_config=None):
320320
default=None,
321321
help=("Project to use for executing this query. Defaults to the context project."),
322322
)
323+
@magic_arguments.argument(
324+
"--max_results",
325+
default=None,
326+
help=(
327+
"Maximum number of rows in dataframe returned from executing the query."
328+
"Defaults to returning all rows."
329+
),
330+
)
323331
@magic_arguments.argument(
324332
"--maximum_bytes_billed",
325333
default=None,
@@ -420,6 +428,12 @@ def _cell_magic(line, query):
420428
bqstorage_client = _make_bqstorage_client(
421429
args.use_bqstorage_api or context.use_bqstorage_api, context.credentials
422430
)
431+
432+
if args.max_results:
433+
max_results = int(args.max_results)
434+
else:
435+
max_results = None
436+
423437
job_config = bigquery.job.QueryJobConfig()
424438
job_config.query_parameters = params
425439
job_config.use_legacy_sql = args.use_legacy_sql
@@ -433,7 +447,7 @@ def _cell_magic(line, query):
433447

434448
error = None
435449
try:
436-
query_job = _run_query(client, query, job_config)
450+
query_job = _run_query(client, query, job_config=job_config)
437451
except Exception as ex:
438452
error = str(ex)
439453

@@ -460,7 +474,13 @@ def _cell_magic(line, query):
460474
)
461475
return query_job
462476

463-
result = query_job.to_dataframe(bqstorage_client=bqstorage_client)
477+
if max_results:
478+
result = query_job.result(max_results=max_results).to_dataframe(
479+
bqstorage_client=bqstorage_client
480+
)
481+
else:
482+
result = query_job.to_dataframe(bqstorage_client=bqstorage_client)
483+
464484
if args.destination_var:
465485
IPython.get_ipython().push({args.destination_var: result})
466486
else:

bigquery/tests/unit/test_magics.py

+55-2
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def test_bigquery_magic_with_legacy_sql():
414414
with run_query_patch as run_query_mock:
415415
ip.run_cell_magic("bigquery", "--use_legacy_sql", "SELECT 17 AS num")
416416

417-
job_config_used = run_query_mock.call_args_list[0][0][-1]
417+
job_config_used = run_query_mock.call_args_list[0][1]["job_config"]
418418
assert job_config_used.use_legacy_sql is True
419419

420420

@@ -645,6 +645,57 @@ def test_bigquery_magic_without_bqstorage(monkeypatch):
645645
assert isinstance(return_value, pandas.DataFrame)
646646

647647

648+
@pytest.mark.usefixtures("ipython_interactive")
649+
def test_bigquery_magic_w_max_results_invalid():
650+
ip = IPython.get_ipython()
651+
ip.extension_manager.load_extension("google.cloud.bigquery")
652+
magics.context._project = None
653+
654+
credentials_mock = mock.create_autospec(
655+
google.auth.credentials.Credentials, instance=True
656+
)
657+
default_patch = mock.patch(
658+
"google.auth.default", return_value=(credentials_mock, "general-project")
659+
)
660+
client_query_patch = mock.patch(
661+
"google.cloud.bigquery.client.Client.query", autospec=True
662+
)
663+
664+
sql = "SELECT 17 AS num"
665+
666+
with pytest.raises(ValueError), default_patch, client_query_patch:
667+
ip.run_cell_magic("bigquery", "--max_results=abc", sql)
668+
669+
670+
@pytest.mark.usefixtures("ipython_interactive")
671+
def test_bigquery_magic_w_max_results_valid_calls_queryjob_result():
672+
ip = IPython.get_ipython()
673+
ip.extension_manager.load_extension("google.cloud.bigquery")
674+
magics.context._project = None
675+
676+
credentials_mock = mock.create_autospec(
677+
google.auth.credentials.Credentials, instance=True
678+
)
679+
default_patch = mock.patch(
680+
"google.auth.default", return_value=(credentials_mock, "general-project")
681+
)
682+
client_query_patch = mock.patch(
683+
"google.cloud.bigquery.client.Client.query", autospec=True
684+
)
685+
686+
sql = "SELECT 17 AS num"
687+
688+
query_job_mock = mock.create_autospec(
689+
google.cloud.bigquery.job.QueryJob, instance=True
690+
)
691+
692+
with client_query_patch as client_query_mock, default_patch:
693+
client_query_mock.return_value = query_job_mock
694+
ip.run_cell_magic("bigquery", "--max_results=5", sql)
695+
696+
query_job_mock.result.assert_called_with(max_results=5)
697+
698+
648699
@pytest.mark.usefixtures("ipython_interactive")
649700
def test_bigquery_magic_dryrun_option_sets_job_config():
650701
ip = IPython.get_ipython()
@@ -662,7 +713,7 @@ def test_bigquery_magic_dryrun_option_sets_job_config():
662713
with run_query_patch as run_query_mock:
663714
ip.run_cell_magic("bigquery", "--dry_run", sql)
664715

665-
job_config_used = run_query_mock.call_args_list[0][0][-1]
716+
job_config_used = run_query_mock.call_args_list[0][1]["job_config"]
666717
assert job_config_used.dry_run is True
667718

668719

@@ -924,6 +975,7 @@ def test_bigquery_magic_with_string_params():
924975
run_query_mock.return_value = query_job_mock
925976

926977
ip.run_cell_magic("bigquery", 'params_string_df --params {"num":17}', sql)
978+
927979
run_query_mock.assert_called_once_with(mock.ANY, sql.format(num=17), mock.ANY)
928980

929981
assert "params_string_df" in ip.user_ns # verify that the variable exists
@@ -959,6 +1011,7 @@ def test_bigquery_magic_with_dict_params():
9591011
# Insert dictionary into user namespace so that it can be expanded
9601012
ip.user_ns["params"] = params
9611013
ip.run_cell_magic("bigquery", "params_dict_df --params $params", sql)
1014+
9621015
run_query_mock.assert_called_once_with(mock.ANY, sql.format(num=17), mock.ANY)
9631016

9641017
assert "params_dict_df" in ip.user_ns # verify that the variable exists

0 commit comments

Comments
 (0)