1717from __future__ import annotations
1818
1919import datetime
20+ import html
2021import random
2122from typing import Any , Optional , Type , TYPE_CHECKING , Union
2223
2627import humanize
2728import IPython
2829import IPython .display as display
29- import ipywidgets as widgets
3030
3131if TYPE_CHECKING :
3232 import bigframes .core .events
@@ -62,39 +62,6 @@ def create_exception_with_feedback_link(
6262 return exception (constants .FEEDBACK_LINK )
6363
6464
65- def repr_query_job_html (query_job : Optional [bigquery .QueryJob ]):
66- """Return query job in html format.
67- Args:
68- query_job (bigquery.QueryJob, Optional):
69- The job representing the execution of the query on the server.
70- Returns:
71- Pywidget html table.
72- """
73- if query_job is None :
74- return display .HTML ("No job information available" )
75- if query_job .dry_run :
76- return display .HTML (
77- f"Computation deferred. Computation will process { get_formatted_bytes (query_job .total_bytes_processed )} "
78- )
79- table_html = "<style> td {text-align: left;}</style>"
80- table_html += "<table>"
81- for key , value in query_job_prop_pairs .items ():
82- job_val = getattr (query_job , value )
83- if job_val is not None :
84- if key == "Job Id" : # add link to job
85- table_html += f"""<tr><td>{ key } </td><td><a target="_blank" href="{ get_job_url (query_job )} ">{ job_val } </a></td></tr>"""
86- elif key == "Slot Time" :
87- table_html += (
88- f"""<tr><td>{ key } </td><td>{ get_formatted_time (job_val )} </td></tr>"""
89- )
90- elif key == "Bytes Processed" :
91- table_html += f"""<tr><td>{ key } </td><td>{ get_formatted_bytes (job_val )} </td></tr>"""
92- else :
93- table_html += f"""<tr><td>{ key } </td><td>{ job_val } </td></tr>"""
94- table_html += "</table>"
95- return widgets .HTML (table_html )
96-
97-
9865def repr_query_job (query_job : Optional [bigquery .QueryJob ]):
9966 """Return query job as a formatted string.
10067 Args:
@@ -113,7 +80,11 @@ def repr_query_job(query_job: Optional[bigquery.QueryJob]):
11380 if job_val is not None :
11481 res += "\n "
11582 if key == "Job Id" : # add link to job
116- res += f"""Job url: { get_job_url (query_job )} """
83+ res += f"""Job url: { get_job_url (
84+ project_id = query_job .project ,
85+ location = query_job .location ,
86+ job_id = query_job .job_id ,
87+ )} """
11788 elif key == "Slot Time" :
11889 res += f"""{ key } : { get_formatted_time (job_val )} """
11990 elif key == "Bytes Processed" :
@@ -125,14 +96,14 @@ def repr_query_job(query_job: Optional[bigquery.QueryJob]):
12596
12697current_display : Optional [display .HTML ] = None
12798current_display_id : Optional [str ] = None
128- previous_message : str = ""
99+ previous_display_html : str = ""
129100
130101
131102def progress_callback (
132103 event : bigframes .core .events .Event ,
133104):
134105 """Displays a progress bar while the query is running"""
135- global current_display , current_display_id
106+ global current_display , current_display_id , previous_display_html
136107
137108 import bigframes ._config
138109 import bigframes .core .events
@@ -148,28 +119,31 @@ def progress_callback(
148119 or current_display is None
149120 or current_display_id is None
150121 ):
122+ previous_display_html = ""
151123 current_display_id = str (random .random ())
152124 current_display = display .HTML ("Starting execution." )
153125 display .display (
154126 current_display ,
155127 display_id = current_display_id ,
156128 )
157129
158- if isinstance (event , bigframes .core .events .ExecutionRunning ):
130+ if isinstance (event , bigframes .core .events .BigQuerySentEvent ):
131+ previous_display_html = render_bqquery_sent_event_html (event )
159132 display .update_display (
160- display .HTML ("Execution happening." ),
133+ display .HTML (previous_display_html ),
161134 display_id = current_display_id ,
162135 )
163136 elif isinstance (event , bigframes .core .events .ExecutionFinished ):
164137 display .update_display (
165- display .HTML (f"{ previous_message } Execution done." ),
138+ display .HTML (f"{ previous_display_html } Execution done." ),
166139 display_id = current_display_id ,
167140 )
168141 elif progress_bar == "terminal" :
169142 if isinstance (event , bigframes .core .events .ExecutionStarted ):
170143 print ("Starting execution." )
171- elif isinstance (event , bigframes .core .events .ExecutionRunning ):
172- print ("Execution happening." )
144+ elif isinstance (event , bigframes .core .events .BigQuerySentEvent ):
145+ message = render_bqquery_sent_event_plaintext (event )
146+ print (message )
173147 elif isinstance (event , bigframes .core .events .ExecutionFinished ):
174148 print ("Execution done." )
175149
@@ -222,43 +196,84 @@ def wait_for_job(job: GenericJob, progress_bar: Optional[str] = None):
222196 raise
223197
224198
225- def get_job_url (query_job : GenericJob ):
199+ def get_job_url (
200+ * ,
201+ project_id : Optional [str ],
202+ location : Optional [str ],
203+ job_id : Optional [str ],
204+ ):
226205 """Return url to the query job in cloud console.
227- Args:
228- query_job (GenericJob):
229- The job representing the execution of the query on the server.
206+
230207 Returns:
231208 String url.
232209 """
233- if (
234- query_job .project is None
235- or query_job .location is None
236- or query_job .job_id is None
237- ):
210+ if project_id is None or location is None or job_id is None :
238211 return None
239- return f"""https://console.cloud.google.com/bigquery?project={ query_job . project } &j=bq:{ query_job . location } :{ query_job . job_id } &page=queryresults"""
212+ return f"""https://console.cloud.google.com/bigquery?project={ project_id } &j=bq:{ location } :{ job_id } &page=queryresults"""
240213
241214
242- def get_query_job_loading_html (query_job : bigquery .QueryJob ):
215+ def render_bqquery_sent_event_html (
216+ event : bigframes .core .events .BigQuerySentEvent ,
217+ ) -> str :
243218 """Return progress bar html string
244219 Args:
245220 query_job (bigquery.QueryJob):
246221 The job representing the execution of the query on the server.
247222 Returns:
248223 Html string.
249224 """
250- return f"""Query job { query_job .job_id } is { query_job .state } . { get_bytes_processed_string (query_job .total_bytes_processed )} <a target="_blank" href="{ get_job_url (query_job )} ">Open Job</a>"""
251225
226+ job_url = get_job_url (
227+ project_id = event .billing_project ,
228+ location = event .location ,
229+ job_id = event .job_id ,
230+ )
231+ if job_url :
232+ job_link = f'<a target="_blank" href="{ job_url } ">Open Job</a>'
233+ else :
234+ job_link = ""
235+
236+ query_id = ""
237+ if event .job_id :
238+ query_id = f" with job ID { event .job_id } :{ event .billing_project } .{ event .job_id } "
239+ elif event .request_id :
240+ query_id = f" with request ID { event .job_id } :{ event .billing_project } .{ event .request_id } "
241+
242+ query_text_details = f"<details><summary>SQL</summary><pre>{ html .escape (event .query )} </pre></details>"
243+
244+ return f"""
245+ Query started{ query_id } .{ job_link } { query_text_details }
246+ """
252247
253- def get_query_job_loading_string (query_job : bigquery .QueryJob ):
254- """Return progress bar string
248+
249+ def render_bqquery_sent_event_plaintext (
250+ event : bigframes .core .events .BigQuerySentEvent ,
251+ ) -> str :
252+ """Return progress bar html string
255253 Args:
256254 query_job (bigquery.QueryJob):
257255 The job representing the execution of the query on the server.
258256 Returns:
259- String
257+ Html string.
260258 """
261- return f"""Query job { query_job .job_id } is { query_job .state } .{ get_bytes_processed_string (query_job .total_bytes_processed )} \n { get_job_url (query_job )} """
259+
260+ job_url = get_job_url (
261+ project_id = event .billing_project ,
262+ location = event .location ,
263+ job_id = event .job_id ,
264+ )
265+ if job_url :
266+ job_link = f" Open job: { job_url } "
267+ else :
268+ job_link = ""
269+
270+ query_id = ""
271+ if event .job_id :
272+ query_id = f" with job ID { event .job_id } :{ event .billing_project } .{ event .job_id } "
273+ elif event .request_id :
274+ query_id = f" with request ID { event .job_id } :{ event .billing_project } .{ event .request_id } "
275+
276+ return f"Query started{ query_id } .{ job_link } "
262277
263278
264279def get_base_job_loading_html (job : GenericJob ):
@@ -269,7 +284,11 @@ def get_base_job_loading_html(job: GenericJob):
269284 Returns:
270285 Html string.
271286 """
272- return f"""{ job .job_type .capitalize ()} job { job .job_id } is { job .state } . <a target="_blank" href="{ get_job_url (job )} ">Open Job</a>"""
287+ return f"""{ job .job_type .capitalize ()} job { job .job_id } is { job .state } . <a target="_blank" href="{ get_job_url (
288+ project_id = job .job_id ,
289+ location = job .location ,
290+ job_id = job .job_id ,
291+ )} ">Open Job</a>"""
273292
274293
275294def get_base_job_loading_string (job : GenericJob ):
@@ -280,7 +299,11 @@ def get_base_job_loading_string(job: GenericJob):
280299 Returns:
281300 String
282301 """
283- return f"""{ job .job_type .capitalize ()} job { job .job_id } is { job .state } . \n { get_job_url (job )} """
302+ return f"""{ job .job_type .capitalize ()} job { job .job_id } is { job .state } . \n { get_job_url (
303+ project_id = job .job_id ,
304+ location = job .location ,
305+ job_id = job .job_id ,
306+ )} """
284307
285308
286309def get_formatted_time (val ):
0 commit comments