Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: reconfigure tqdm progress bar in %%bigquery magic #1355

Merged
merged 51 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ac10e76
feat: add bigquery job id to tqdm progress bar description
aribray Sep 15, 2022
9db15fc
write to sys.stdout instead of sys.stderr
aribray Sep 20, 2022
6ed2f03
Merge remote-tracking branch 'upstream/main' into aribray--tqdm
aribray Sep 23, 2022
c3ec846
configure progress bar
aribray Sep 23, 2022
f50bf8b
tqdm.notebook
aribray Sep 23, 2022
0c41c9e
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Sep 23, 2022
d679134
reinclude ipywidgets
aribray Sep 23, 2022
87212a5
Merge branch 'aribray--tqdm' of github.com:aribray/python-bigquery in…
aribray Sep 23, 2022
be991b7
reinclude ipywidgets
aribray Sep 23, 2022
c6317a4
change test assertions to tqdm_notebook
aribray Sep 23, 2022
13331b9
change test assertions in test_magics
aribray Sep 23, 2022
d86ae58
remove ipywidgets
aribray Sep 23, 2022
a6c3e88
update assertions in test
aribray Sep 23, 2022
adcef3b
update method args in query.py and table.py
aribray Sep 26, 2022
f50600e
string formatting
aribray Sep 26, 2022
7162f0e
fix typo
aribray Sep 27, 2022
cef0491
fix incorrect import structure for tqdm notebook
aribray Sep 28, 2022
46c3d95
change default decorator back to tqdm
aribray Sep 28, 2022
11966b8
Merge branch 'main' of github.com:aribray/python-bigquery into aribra…
aribray Oct 4, 2022
dfd965f
modify system test
aribray Oct 4, 2022
e785c84
add ipywidgets package for tqdm.notebook feature, set tqdm.notebook a…
aribray Oct 4, 2022
2932a52
change test assertion in test_query_pandas
aribray Oct 5, 2022
54b90e7
revert test changes
aribray Oct 5, 2022
3ea255f
Merge branch 'main' of github.com:aribray/python-bigquery into aribra…
aribray Oct 5, 2022
b94c863
reformat import statement
aribray Oct 6, 2022
4114221
reformat import statement
aribray Oct 6, 2022
09a6608
remove timeouterror side effect
aribray Oct 6, 2022
ef809a0
add tqdm mock patch
aribray Oct 6, 2022
9f174bb
Revert "reformat import statement"
aribray Oct 6, 2022
eabc228
Revert "add tqdm mock patch"
aribray Oct 6, 2022
de9ee35
add timeout side effect
aribray Oct 7, 2022
bd35f96
fix assertion
aribray Oct 7, 2022
f471b8c
fix import
aribray Oct 7, 2022
99e108b
change mock patch to tqdm
aribray Oct 7, 2022
3f53ad5
move assertion
aribray Oct 7, 2022
4e901d4
move assertions
aribray Oct 7, 2022
30a3688
add timeout side effect
aribray Oct 7, 2022
122c5a5
adjust import statement, mock.patch tqdm
aribray Oct 7, 2022
bf4b1c2
create fixture
aribray Oct 7, 2022
84a5073
revert import change
aribray Oct 7, 2022
fd6b101
add import from helper
aribray Oct 7, 2022
9bedca6
fix linting
aribray Oct 7, 2022
a7e361c
Merge branch 'main' of github.com:aribray/python-bigquery into aribra…
aribray Oct 7, 2022
0dfc48d
remove unused imort
aribray Oct 7, 2022
ef3fc98
set ipywidgets version to 7.7.1
aribray Oct 10, 2022
846e66a
Merge branch 'main' of github.com:aribray/python-bigquery into aribra…
aribray Oct 10, 2022
05423ff
set ipywidgets version to 7.7.1
aribray Oct 10, 2022
f06e44d
set ipywidgets version to 7.7.1
aribray Oct 10, 2022
beb9675
Merge branch 'main' of github.com:aribray/python-bigquery into aribra…
aribray Oct 10, 2022
f84f75c
bump sphinx version
aribray Oct 10, 2022
b0c40c5
bump sphinx version
aribray Oct 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions google/cloud/bigquery/_tqdm_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
"""Shared helper functions for tqdm progress bar."""

import concurrent.futures
import sys
import time
import typing
from typing import Optional
import warnings

try:
import tqdm # type: ignore
import tqdm.notebook as notebook # type: ignore
aribray marked this conversation as resolved.
Show resolved Hide resolved

except ImportError: # pragma: NO COVER
tqdm = None
Expand All @@ -47,9 +49,22 @@ def get_progress_bar(progress_bar_type, description, total, unit):

try:
if progress_bar_type == "tqdm":
return tqdm.tqdm(desc=description, total=total, unit=unit)
return tqdm.tqdm(
bar_format="{l_bar}{bar}|",
colour="green",
desc=description,
file=sys.stdout,
total=total,
unit=unit,
)
elif progress_bar_type == "tqdm_notebook":
return tqdm.notebook.tqdm(desc=description, total=total, unit=unit)
return notebook.tqdm(
bar_format="{l_bar}{bar}|",
desc=description,
file=sys.stdout,
total=total,
unit=unit,
)
elif progress_bar_type == "tqdm_gui":
return tqdm.tqdm_gui(desc=description, total=total, unit=unit)
except (KeyError, TypeError):
Expand Down Expand Up @@ -80,7 +95,7 @@ def wait_for_query(
"""
default_total = 1
current_stage = None
start_time = time.time()
start_time = time.perf_counter()

progress_bar = get_progress_bar(
progress_bar_type, "Query is running", default_total, "query"
Expand All @@ -95,19 +110,15 @@ def wait_for_query(
current_stage = query_job.query_plan[i]
progress_bar.total = len(query_job.query_plan)
progress_bar.set_description(
"Query executing stage {} and status {} : {:0.2f}s".format(
current_stage.name,
current_stage.status,
time.time() - start_time,
),
f"Query executing stage {current_stage.name} and status {current_stage.status} : {time.perf_counter() - start_time:.2f}s"
)
try:
query_result = query_job.result(
timeout=_PROGRESS_BAR_UPDATE_INTERVAL, max_results=max_results
)
progress_bar.update(default_total)
progress_bar.set_description(
"Query complete after {:0.2f}s".format(time.time() - start_time),
f"Job ID {query_job.job_id} successfully executed",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to include the location in the output too, formatted like the bq cli as location:I'd https://cloud.google.com/python/docs/reference/bigquery/latest/google.cloud.bigquery.job.QueryJob#google_cloud_bigquery_job_QueryJob_location

I believe the location is required to fetch the job metadata for the non-default location.

)
break
except concurrent.futures.TimeoutError:
Expand Down
4 changes: 2 additions & 2 deletions google/cloud/bigquery/job/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -1556,9 +1556,9 @@ def to_arrow(
No progress bar.
``'tqdm'``
Use the :func:`tqdm.tqdm` function to print a progress bar
to :data:`sys.stderr`.
to :data:`sys.stdout`.
``'tqdm_notebook'``
Use the :func:`tqdm.tqdm_notebook` function to display a
Use the :func:`tqdm.notebook.tqdm` function to display a
progress bar as a Jupyter notebook widget.
``'tqdm_gui'``
Use the :func:`tqdm.tqdm_gui` function to display a
Expand Down
21 changes: 12 additions & 9 deletions google/cloud/bigquery/magics/magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def __init__(self):
self._default_query_job_config = bigquery.QueryJobConfig()
self._bigquery_client_options = client_options.ClientOptions()
self._bqstorage_client_options = client_options.ClientOptions()
self._progress_bar_type = "tqdm"
self._progress_bar_type = "tqdm_notebook"

@property
def credentials(self):
Expand Down Expand Up @@ -269,7 +269,7 @@ def progress_bar_type(self):
Manually setting the progress_bar_type:

>>> from google.cloud.bigquery import magics
>>> magics.context.progress_bar_type = "tqdm"
>>> magics.context.progress_bar_type = "tqdm_notebook"
"""
return self._progress_bar_type

Expand All @@ -286,7 +286,7 @@ def _handle_error(error, destination_var=None):

Args:
error (Exception):
An exception that ocurred during the query exectution.
An exception that ocurred during the query execution.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the word ocurred to the correct spelling of occurred

An exception that occurred during the query execution.

destination_var (Optional[str]):
The name of the IPython session variable to store the query job.
"""
Expand Down Expand Up @@ -329,22 +329,25 @@ def _run_query(client, query, job_config=None):
Query complete after 2.07s
'bf633912-af2c-4780-b568-5d868058632b'
"""
start_time = time.time()
start_time = time.perf_counter()
query_job = client.query(query, job_config=job_config)

if job_config and job_config.dry_run:
return query_job

print("Executing query with job ID: {}".format(query_job.job_id))
print(f"Executing query with job ID: {query_job.job_id}")

while True:
print("\rQuery executing: {:0.2f}s".format(time.time() - start_time), end="")
print(
f"\rQuery executing: {time.perf_counter() - start_time:.2f}s".format(),
end="",
)
try:
query_job.result(timeout=0.5)
break
except futures.TimeoutError:
continue
print("\nQuery complete after {:0.2f}s".format(time.time() - start_time))
print(f"\nJob ID {query_job.job_id} successfully executed")
return query_job


Expand All @@ -365,7 +368,7 @@ def _create_dataset_if_necessary(client, dataset_id):
pass
dataset = bigquery.Dataset(dataset_reference)
dataset.location = client.location
print("Creating dataset: {}".format(dataset_id))
print(f"Creating dataset: {dataset_id}")
dataset = client.create_dataset(dataset)


Expand Down Expand Up @@ -500,7 +503,7 @@ def _create_dataset_if_necessary(client, dataset_id):
default=None,
help=(
"Sets progress bar type to display a progress bar while executing the query."
"Defaults to use tqdm. Install the ``tqdm`` package to use this feature."
"Defaults to use tqdm_notebook. Install the ``tqdm`` package to use this feature."
),
)
def _cell_magic(line, query):
Expand Down
12 changes: 6 additions & 6 deletions google/cloud/bigquery/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1728,9 +1728,9 @@ def to_arrow(
No progress bar.
``'tqdm'``
Use the :func:`tqdm.tqdm` function to print a progress bar
to :data:`sys.stderr`.
to :data:`sys.stdout`.
``'tqdm_notebook'``
Use the :func:`tqdm.tqdm_notebook` function to display a
Use the :func:`tqdm.notebook.tqdm` function to display a
progress bar as a Jupyter notebook widget.
``'tqdm_gui'``
Use the :func:`tqdm.tqdm_gui` function to display a
Expand Down Expand Up @@ -1921,9 +1921,9 @@ def to_dataframe(
No progress bar.
``'tqdm'``
Use the :func:`tqdm.tqdm` function to print a progress bar
to :data:`sys.stderr`.
to :data:`sys.stdout`.
``'tqdm_notebook'``
Use the :func:`tqdm.tqdm_notebook` function to display a
Use the :func:`tqdm.notebook.tqdm` function to display a
progress bar as a Jupyter notebook widget.
``'tqdm_gui'``
Use the :func:`tqdm.tqdm_gui` function to display a
Expand Down Expand Up @@ -2075,9 +2075,9 @@ def to_geodataframe(
No progress bar.
``'tqdm'``
Use the :func:`tqdm.tqdm` function to print a progress bar
to :data:`sys.stderr`.
to :data:`sys.stdout`.
``'tqdm_notebook'``
aribray marked this conversation as resolved.
Show resolved Hide resolved
Use the :func:`tqdm.tqdm_notebook` function to display a
Use the :func:`tqdm.notebook.tqdm` function to display a
progress bar as a Jupyter notebook widget.
``'tqdm_gui'``
Use the :func:`tqdm.tqdm_gui` function to display a
Expand Down
10 changes: 5 additions & 5 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def default(session, install_extras=True):
)

if install_extras and session.python == "3.10":
install_target = ".[bqstorage,pandas,tqdm,opentelemetry]"
install_target = ".[bqstorage,ipywidgets,pandas,tqdm,opentelemetry]"
elif install_extras:
install_target = ".[all]"
else:
Expand Down Expand Up @@ -186,7 +186,7 @@ def system(session):
session.install("google-cloud-datacatalog", "-c", constraints_path)

if session.python == "3.10":
extras = "[bqstorage,pandas,tqdm,opentelemetry]"
extras = "[bqstorage,ipywidgets,pandas,tqdm,opentelemetry]"
else:
extras = "[all]"
session.install("-e", f".{extras}", "-c", constraints_path)
Expand Down Expand Up @@ -235,7 +235,7 @@ def snippets(session):
session.install("grpcio", "-c", constraints_path)

if session.python == "3.10":
extras = "[bqstorage,pandas,tqdm,opentelemetry]"
extras = "[bqstorage,ipywidgets,pandas,tqdm,opentelemetry]"
else:
extras = "[all]"
session.install("-e", f".{extras}", "-c", constraints_path)
Expand Down Expand Up @@ -387,7 +387,7 @@ def blacken(session):
def docs(session):
"""Build the docs."""

session.install("recommonmark", "sphinx==4.0.1", "sphinx_rtd_theme")
session.install("recommonmark", "sphinx==4.0.2", "sphinx_rtd_theme")
session.install("google-cloud-storage")
session.install("-e", ".[all]")

Expand All @@ -412,7 +412,7 @@ def docfx(session):

session.install("-e", ".")
session.install(
"sphinx==4.0.1", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml"
"sphinx==4.0.2", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml"
)

shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True)
Expand Down
1 change: 1 addition & 0 deletions samples/magics/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ db-dtypes==1.0.4
google-cloud-bigquery-storage==2.16.1
google-auth-oauthlib==0.5.3
grpcio==1.49.1
ipywidgets==7.7.1
ipython===7.31.1; python_version == '3.7'
ipython===8.0.1; python_version == '3.8'
ipython==8.5.0; python_version >= '3.9'
Expand Down
1 change: 1 addition & 0 deletions samples/snippets/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ google-cloud-bigquery==3.3.3
google-cloud-bigquery-storage==2.16.1
google-auth-oauthlib==0.5.3
grpcio==1.49.1
ipywidgets==7.7.1
ipython===7.31.1; python_version == '3.7'
ipython===8.0.1; python_version == '3.8'
ipython==8.5.0; python_version >= '3.9'
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
# See: https://github.com/googleapis/python-bigquery/issues/757
"bqstorage": [],
"pandas": ["pandas>=1.0.0", "db-dtypes>=0.3.0,<2.0.0dev"],
"ipywidgets": ["ipywidgets==7.7.1"],
"geopandas": ["geopandas>=0.9.0, <1.0dev", "Shapely>=1.6.0, <2.0dev"],
"ipython": ["ipython>=7.0.1,!=8.1.0"],
"tqdm": ["tqdm >= 4.7.4, <5.0.0dev"],
Expand Down
1 change: 1 addition & 0 deletions testing/constraints-3.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ google-cloud-bigquery-storage==2.0.0
google-cloud-core==1.4.1
google-resumable-media==0.6.0
grpcio==1.47.0
ipywidgets==7.7.1
ipython==7.0.1
opentelemetry-api==1.1.0
opentelemetry-instrumentation==0.20b0
Expand Down
3 changes: 1 addition & 2 deletions tests/system/test_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ def test_bigquery_magic(ipython_interactive):
# Removes blanks & terminal code (result of display clearing)
updates = list(filter(lambda x: bool(x) and x != "\x1b[2K", lines))
assert re.match("Executing query with job ID: .*", updates[0])
assert all(re.match("Query executing: .*s", line) for line in updates[1:-1])
assert re.match("Query complete after .*s", updates[-1])
assert (re.match("Query executing: .*s", line) for line in updates[1:-1])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using assert with a tuple will always return True, no matter what is in the tuple unless the tuple is empty.
Are we trying to detect whether any matches are True OR are we trying to detect whether ALL the responses are True (...as implied by the deleted code above)?

In [9]: assert (True, True, True)
<>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
<ipython-input-9-0a5188c9e554>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (True, True, True)

In [10]: assert (False, False, False)
<>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
<ipython-input-10-f31b4c57c272>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (False, False, False)

In [11]: assert (False, False, True)
<>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
<ipython-input-11-59e8f7bc6fa4>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (False, False, True)

In [14]: assert (True,)
<>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
<ipython-input-14-7b46914816ee>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (True,)

In [15]: assert (False,)
<>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
<ipython-input-15-a62a5cb79bea>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (False,)
  
  In [16]: assert ()
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Input In [16], in <cell line: 1>()
----> 1 assert ()

assert isinstance(result, pandas.DataFrame)
assert len(result) == 10 # verify row count
assert list(result) == ["url", "view_count"] # verify column names
Expand Down
Loading