remove console logs

This commit is contained in:
Ali Abid 2020-08-05 13:15:32 -07:00
parent 53ae797631
commit 2943492564
11 changed files with 232 additions and 180 deletions

View File

@ -11,11 +11,12 @@ import time
import warnings
from abc import ABC, abstractmethod
import base64
import numpy as np
import PIL.Image
import PIL.ImageOps
import scipy.io.wavfile
from gradio import preprocessing_utils, validation_data
from gradio import preprocessing_utils
# Where to find the static resources associated with each template.
# BASE_INPUT_INTERFACE_TEMPLATE_PATH = 'static/js/interfaces/input/{}.js'
@ -31,13 +32,6 @@ class AbstractInput(ABC):
def __init__(self, label):
self.label = label
def get_validation_inputs(self):
"""
An interface can optionally implement a method that returns a list of examples inputs that it should be able to
accept and preprocess for validation purposes.
"""
return []
def get_template_context(self):
"""
:return: a dictionary with context variables for the javascript file associated with the context
@ -63,6 +57,11 @@ class AbstractInput(ABC):
"""
return {}
def rebuild(self, dir, data):
"""
All interfaces should define a method that rebuilds the flagged input when it's passed back (i.e. rebuilds image from base64)
"""
return data
class Textbox(AbstractInput):
"""
@ -253,9 +252,6 @@ class Image(AbstractInput):
self.image_mode = image_mode
super().__init__(label)
def get_validation_inputs(self):
return validation_data.BASE64_COLOR_IMAGES
@classmethod
def get_shortcut_implementations(cls):
return {
@ -290,6 +286,16 @@ class Image(AbstractInput):
else:
return example
def rebuild(self, dir, data):
"""
Default rebuild method to decode a base64 image
"""
im = preprocessing_utils.decode_base64_to_image(data)
timestamp = datetime.datetime.now()
filename = f'input_{timestamp.strftime("%Y-%m-%d-%H-%M-%S")}.png'
im.save(f'{dir}/{filename}', 'PNG')
return filename
class Sketchpad(AbstractInput):
"""
@ -341,6 +347,16 @@ class Sketchpad(AbstractInput):
def process_example(self, example):
return preprocessing_utils.convert_file_to_base64(example)
def rebuild(self, dir, data):
"""
Default rebuild method to decode a base64 image
"""
im = preprocessing_utils.decode_base64_to_image(data)
timestamp = datetime.datetime.now()
filename = f'input_{timestamp.strftime("%Y-%m-%d-%H-%M-%S")}.png'
im.save(f'{dir}/{filename}', 'PNG')
return filename
class Webcam(AbstractInput):
"""
@ -359,9 +375,6 @@ class Webcam(AbstractInput):
self.num_channels = 3
super().__init__(label)
def get_validation_inputs(self):
return validation_data.BASE64_COLOR_IMAGES
@classmethod
def get_shortcut_implementations(cls):
return {
@ -378,6 +391,16 @@ class Webcam(AbstractInput):
im, (self.image_width, self.image_height))
return np.array(im)
def rebuild(self, dir, data):
"""
Default rebuild method to decode a base64 image
"""
im = preprocessing_utils.decode_base64_to_image(data)
timestamp = datetime.datetime.now()
filename = f'input_{timestamp.strftime("%Y-%m-%d-%H-%M-%S")}.png'
im.save('{}/{}'.format(dir, filename), 'PNG')
return filename
class Microphone(AbstractInput):
"""
@ -414,6 +437,15 @@ class Microphone(AbstractInput):
_, signal = scipy.io.wavfile.read(file_obj.name)
return signal
def rebuild(self, dir, data):
inp = data.split(';')[1].split(',')[1]
wav_obj = base64.b64decode(inp)
timestamp = datetime.datetime.now()
filename = f'input_{timestamp.strftime("%Y-%m-%d-%H-%M-%S")}.wav'
with open("{}/{}".format(dir, filename), "wb+") as f:
f.write(wav_obj)
return filename
# Automatically adds all shortcut implementations in AbstractInput into a dictionary.
shortcuts = {}

View File

@ -4,12 +4,11 @@ interface using the input and output types.
"""
import tempfile
import traceback
import webbrowser
import gradio.inputs
import gradio.outputs
from gradio import networking, strings
from gradio import networking, strings, utils
from distutils.version import StrictVersion
import pkg_resources
import requests
@ -20,6 +19,7 @@ from IPython import get_ipython
import sys
import weakref
import analytics
import os
PKG_VERSION_URL = "https://gradio.app/api/pkg-version"
@ -37,21 +37,42 @@ class Interface:
"""
instances = weakref.WeakSet()
def __init__(self, fn, inputs, outputs, saliency=None, verbose=False, examples=None,
@classmethod
def get_instances(cls):
"""
:return: list of all current instances.
"""
return list(
Interface.instances)
def __init__(self, fn, inputs, outputs, verbose=False, examples=None,
live=False, show_input=True, show_output=True,
capture_session=False, title=None, description=None,
thumbnail=None, server_port=None, server_name=networking.LOCALHOST_NAME,
allow_screenshot=True):
allow_screenshot=True, allow_flagging=True,
flagging_dir="flagged"):
"""
Parameters:
fn (Callable): the function to wrap an interface around.
inputs (Union[str, List[Union[str, AbstractInput]]]): a single Gradio input component, or list of Gradio input components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of input components should match the number of parameters in fn.
outputs (Union[str, List[Union[str, AbstractOutput]]]): a single Gradio output component, or list of Gradio output components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of output components should match the number of values returned by fn.
verbose (bool): whether to print detailed information during launch.
examples (List[List[Any]]): sample inputs for the function; if provided, appears below the UI components and can be used to populate the interface. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component.
live (bool): whether the interface should automatically reload on change.
show_input (bool): if False, removes the input from the interface
and underlays it in the output.
show_output (bool): if False, removes the output from the interface
and overlays it in the input.
capture_session (bool): if True, captures the default graph and session (needed for Tensorflow 1.x)
title (str): a title for the interface; if provided, appears above the input and output components.
description (str): a description for the interface; if provided, appears above the input and output components.
examples (List[List[Any]]): sample inputs for the function; if provided, appears below the UI components and can be used to populate the interface. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component.
thumbnail (str): path to image or src to use as display picture for
models listed in gradio.app/hub
allow_screenshot (bool): if False, users will not see a button to
take a screenshot of the interface.
allow_flagging (bool): if False, users will not see a button to flag an
input and output.
flagging_dir (str): what to name the dir where flagged data is stored.
"""
def get_input_instance(iface):
if isinstance(iface, str):
@ -82,11 +103,11 @@ class Interface:
self.output_interfaces = [get_output_instance(outputs)]
if not isinstance(fn, list):
fn = [fn]
self.output_interfaces *= len(fn)
self.predict = fn
self.verbose = verbose
self.status = "OFF"
self.saliency = saliency
self.live = live
self.show_input = show_input
self.show_output = show_output
@ -101,12 +122,13 @@ class Interface:
self.server_port = server_port
self.simple_server = None
self.allow_screenshot = allow_screenshot
self.allow_flagging = allow_flagging
self.flagging_dir = flagging_dir
Interface.instances.add(self)
data = {'fn': fn,
'inputs': inputs,
'outputs': outputs,
'saliency': saliency,
'live': live,
'capture_session': capture_session,
'ip_address': ip_address
@ -117,9 +139,23 @@ class Interface:
import tensorflow as tf
self.session = tf.get_default_graph(), \
tf.keras.backend.get_session()
except (ImportError, AttributeError): # If they are using TF >= 2.0 or don't have TF, just ignore this.
except (ImportError, AttributeError):
# If they are using TF >= 2.0 or don't have TF,
# just ignore this.
pass
if self.allow_flagging:
if self.title is not None:
dir_name = "_".join(self.title.split(" "))
else:
dir_name = "_".join([fn.__name__ for fn in self.predict])
index = 1
while os.path.exists(self.flagging_dir + "/" + dir_name +
"_{}".format(index)):
index += 1
self.flagging_dir = self.flagging_dir + "/" + dir_name + \
"_{}".format(index)
try:
requests.post(analytics_url + 'gradio-initiated-analytics/',
data=data)
@ -141,7 +177,8 @@ class Interface:
"title": self.title,
"description": self.description,
"thumbnail": self.thumbnail,
"allow_screenshot": self.allow_screenshot
"allow_screenshot": self.allow_screenshot,
"allow_flagging": self.allow_flagging
}
try:
param_names = inspect.getfullargspec(self.predict[0])[0]
@ -158,6 +195,15 @@ class Interface:
return config
def process(self, raw_input):
"""
:param raw_input: a list of raw inputs to process and apply the
prediction(s) on.
:return:
processed output: a list of processed outputs to return as the
prediction(s).
duration: a list of time deltas measuring inference time for each
prediction fn.
"""
processed_input = [input_interface.preprocess(
raw_input[i]) for i, input_interface in
enumerate(self.input_interfaces)]
@ -194,82 +240,27 @@ class Interface:
predictions[i]) for i, output_interface in enumerate(self.output_interfaces)]
return processed_output, durations
def validate(self):
if self.validate_flag:
if self.verbose:
print("Interface already validated")
return
validation_inputs = self.input_interface.get_validation_inputs()
n = len(validation_inputs)
if n == 0:
self.validate_flag = True
if self.verbose:
print(
"No validation samples for this interface... skipping validation."
)
return
for m, msg in enumerate(validation_inputs):
if self.verbose:
print(
"Validating samples: {}/{} [".format(m+1, n)
+ "=" * (m + 1)
+ "." * (n - m - 1)
+ "]",
end="\r",
)
try:
processed_input = self.input_interface.preprocess(msg)
prediction = self.predict(processed_input)
except Exception as e:
data = {'error': e}
try:
requests.post(analytics_url + 'gradio-error-analytics/',
data=data)
except requests.ConnectionError:
pass # do not push analytics if no network
if self.verbose:
print("\n----------")
print(
"Validation failed, likely due to incompatible pre-processing and model input. See below:\n"
)
print(traceback.format_exc())
break
try:
_ = self.output_interface.postprocess(prediction)
except Exception as e:
data = {'error': e}
try:
requests.post(analytics_url + 'gradio-error-analytics/',
data=data)
except requests.ConnectionError:
pass # do not push analytics if no network
if self.verbose:
print("\n----------")
print(
"Validation failed, likely due to incompatible model output and post-processing."
"See below:\n"
)
print(traceback.format_exc())
break
else: # This means if a break was not explicitly called
self.validate_flag = True
if self.verbose:
print("\n\nValidation passed successfully!")
return
raise RuntimeError("Validation did not pass")
def close(self):
if self.simple_server and not(self.simple_server.fileno() == -1): # checks to see if server is running
print("Closing Gradio server on port {}...".format(self.server_port))
networking.close_server(self.simple_server)
def launch(self, inline=None, inbrowser=None, share=False, validate=True, debug=False):
def launch(self, inline=None, inbrowser=None, share=False, debug=False):
"""
Parameters
share (bool): whether to create a publicly shareable link from your computer for the interface.
inline (bool): whether to display in the interface inline on python
notebooks.
inbrowser (bool): whether to automatically launch the interface in a
new tab on the default browser.
share (bool): whether to create a publicly shareable link from
your computer for the interface.
debug (bool): if True, and the interface was launched from Google
Colab, prints the errors in the cell output.
:returns
httpd (str): HTTPServer object
path_to_local_server (str): Locally accessible link
share_url (str): Publicly accessible link (if share=True)
"""
# if validate and not self.validate_flag:
# self.validate()
output_directory = tempfile.mkdtemp()
# Set up a port to serve the directory containing the static files with interface.
@ -282,20 +273,6 @@ class Interface:
self.status = "RUNNING"
self.simple_server = httpd
is_colab = False
try: # Check if running interactively using ipython.
from_ipynb = get_ipython()
if "google.colab" in str(from_ipynb):
is_colab = True
except NameError:
data = {'error': 'NameError in launch method'}
try:
requests.post(analytics_url + 'gradio-error-analytics/',
data=data)
except requests.ConnectionError:
pass # do not push analytics if no network
pass
try:
current_pkg_version = pkg_resources.require("gradio")[0].version
latest_pkg_version = requests.get(url=PKG_VERSION_URL).json()["version"]
@ -308,6 +285,7 @@ class Interface:
except: # TODO(abidlabs): don't catch all exceptions
pass
is_colab = utils.colab_check()
if not is_colab:
print(strings.en["RUNNING_LOCALLY"].format(path_to_local_server))
else:
@ -322,19 +300,13 @@ class Interface:
share_url = networking.setup_tunnel(server_port)
print("Running on External URL:", share_url)
except RuntimeError:
data = {'error': 'RuntimeError in launch method'}
try:
requests.post(analytics_url + 'gradio-error-analytics/',
data=data)
except requests.ConnectionError:
pass # do not push analytics if no network
utils.error_analytics("RuntimeError")
share_url = None
if self.verbose:
print(strings.en["NGROK_NO_INTERNET"])
else:
if (
is_colab
): # For a colab notebook, create a public link even if share is False.
if is_colab: # For a colab notebook, create a public link even if
# share is False.
share_url = networking.setup_tunnel(server_port)
print("Running on External URL:", share_url)
if self.verbose:
@ -345,29 +317,22 @@ class Interface:
share_url = None
if inline is None:
try: # Check if running interactively using ipython.
get_ipython()
inline = True
inline = utils.ipython_check()
if inbrowser is None:
inbrowser = False
except NameError:
inline = False
if inbrowser is None:
inbrowser = True
# if interface won't appear inline, open it in new tab,
# otherwise keep it inline
inbrowser = not inline
else:
if inbrowser is None:
inbrowser = False
if inbrowser and not is_colab:
webbrowser.open(
path_to_local_server
) # Open a browser tab with the interface.
webbrowser.open(path_to_local_server) # Open a browser tab
# with the interface.
if inline:
from IPython.display import IFrame, display
if (
is_colab
): # Embed the remote interface page if on google colab;
if (is_colab):
# Embed the remote interface page if on google colab;
# otherwise, embed the local page.
print("Interface loading below...")
while not networking.url_ok(share_url):
@ -410,10 +375,6 @@ class Interface:
pass # do not push analytics if no network
return httpd, path_to_local_server, share_url
@classmethod
def get_instances(cls):
return list(Interface.instances) # Returns list of all current instances.
def reset_all():
for io in Interface.get_instances():

View File

@ -17,7 +17,6 @@ import requests
import sys
import analytics
INITIAL_PORT_VALUE = int(os.getenv(
'GRADIO_SERVER_PORT', "7860")) # The http server will try to open on port 7860. If not available, 7861, 7862, etc.
TRY_NUM_PORTS = int(os.getenv(
@ -36,8 +35,6 @@ CONFIG_FILE = "static/config.json"
ASSOCIATION_PATH_IN_STATIC = "static/apple-app-site-association"
ASSOCIATION_PATH_IN_ROOT = "apple-app-site-association"
FLAGGING_DIRECTORY = 'static/flagged/'
FLAGGING_FILENAME = 'data.txt'
analytics.write_key = "uxIFddIEuuUcFLf9VgH2teTEtPlWdkNy"
analytics_url = 'https://api.gradio.app/'
@ -172,20 +169,6 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
prediction, durations = interface.process(raw_input)
output = {"data": prediction, "durations": durations}
if interface.saliency is not None:
saliency = interface.saliency(raw_input, prediction)
output['saliency'] = saliency.tolist()
# if interface.always_flag:
# msg = json.loads(data_string)
# flag_dir = os.path.join(FLAGGING_DIRECTORY, str(interface.hash))
# os.makedirs(flag_dir, exist_ok=True)
# output_flag = {'input': interface.input_interface.rebuild_flagged(flag_dir, msg['data']),
# 'output': interface.output_interface.rebuild_flagged(flag_dir, processed_output),
# }
# with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
# f.write(json.dumps(output_flag))
# f.write("\n")
self.wfile.write(json.dumps(output).encode())
analytics_thread = threading.Thread(
@ -197,20 +180,18 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
data_string = self.rfile.read(
int(self.headers["Content-Length"]))
msg = json.loads(data_string)
flag_dir = os.path.join(FLAGGING_DIRECTORY,
str(interface.flag_hash))
os.makedirs(flag_dir, exist_ok=True)
os.makedirs(interface.flagging_dir, exist_ok=True)
output = {'inputs': [interface.input_interfaces[
i].rebuild_flagged(
flag_dir, msg['data']['input_data']) for i
i].rebuild(
interface.flagging_dir, msg['data']['input_data']) for i
in range(len(interface.input_interfaces))],
'outputs': [interface.output_interfaces[
i].rebuild_flagged(
flag_dir, msg['data']['output_data']) for i
in range(len(interface.output_interfaces))],
'message': msg['data']['message']}
i].rebuild(
interface.flagging_dir, msg['data']['output_data']) for i
in range(len(interface.output_interfaces))]}
with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
with open("{}/log.txt".format(interface.flagging_dir),
'a+') as f:
f.write(json.dumps(output))
f.write("\n")

View File

@ -44,6 +44,12 @@ class AbstractOutput(ABC):
"""
return {}
def rebuild(self, dir, data):
"""
All interfaces should define a method that rebuilds the flagged input when it's passed back (i.e. rebuilds image from base64)
"""
return data
class Textbox(AbstractOutput):
'''
@ -130,6 +136,11 @@ class Label(AbstractOutput):
"label": {},
}
def rebuild(self, dir, data):
"""
Default rebuild method for label
"""
return json.loads(data)
class Image(AbstractOutput):
'''
@ -169,11 +180,11 @@ class Image(AbstractOutput):
raise ValueError(
"The `Image` output interface (with plt=False) expects a numpy array.")
def rebuild_flagged(self, dir, msg):
def rebuild(self, dir, data):
"""
Default rebuild method to decode a base64 image
"""
im = preprocessing_utils.decode_base64_to_image(msg)
im = preprocessing_utils.decode_base64_to_image(data)
timestamp = datetime.datetime.now()
filename = 'output_{}.png'.format(timestamp.
strftime("%Y-%m-%d-%H-%M-%S"))
@ -184,7 +195,7 @@ class Image(AbstractOutput):
class KeyValues(AbstractOutput):
'''
Component displays a table representing values for multiple fields.
Output type: List[Tuple[str, value]]
Output type: Dict[str, value]
'''
def __init__(self, label=None):
@ -238,7 +249,7 @@ class HighlightedText(AbstractOutput):
if isinstance(prediction, str) or isinstance(prediction, int) or isinstance(prediction, float):
return str(prediction)
else:
raise ValueError("The `Textbox` output interface expects an output that is one of: a string, or"
raise ValueError("The `HighlightedText` output interface expects an output that is one of: a string, or"
"an int/float that can be converted to a string.")

View File

@ -75,6 +75,12 @@ input.submit {
input.submit:hover {
background-color: #f39c12;
}
.flag {
visibility: hidden;
}
.flagged {
background-color: pink !important;
}
/* label:hover {
background-color: lightgray;
} */

View File

@ -56,12 +56,11 @@ var io_master_template = {
this.target.find(".output_interfaces").css("opacity", 1);
}
},
flag: function(message) {
flag: function() {
var post_data = {
'data': {
'input_data' : toStringIfObject(this.last_input) ,
'output_data' : toStringIfObject(this.last_output),
'message' : message
'output_data' : toStringIfObject(this.last_output)
}
}
$.ajax({type: "POST",

View File

@ -22,7 +22,7 @@ function gradio(config, fn, target) {
<div class="screenshot_logo">
<img src="static/img/logo_inline.png">
</div>
</div>
<input class="flag panel_button" type="button" value="FLAG"/>
</div>
</div>`);
let io_master = Object.create(io_master_template);
@ -117,6 +117,7 @@ function gradio(config, fn, target) {
output_interface.clear();
}
target.find(".flag").removeClass("flagged");
target.find(".flag").val("FLAG");
target.find(".flag_message").empty();
target.find(".loading").addClass("invisible");
target.find(".loading_time").text("");
@ -124,9 +125,20 @@ function gradio(config, fn, target) {
io_master.last_input = null;
io_master.last_output = null;
});
if (config["allow_screenshot"]) {
if (config["allow_screenshot"] && !config["allow_flagging"]) {
target.find(".screenshot").css("visibility", "visible");
target.find(".flag").css("display", "none")
}
if (!config["allow_screenshot"] && config["allow_flagging"]) {
target.find(".flag").css("visibility", "visible");
target.find(".screenshot").css("display", "none")
}
if (config["allow_screenshot"] && config["allow_flagging"]) {
target.find(".screenshot").css("visibility", "visible");
target.find(".flag").css("visibility", "visible")
}
target.find(".screenshot").click(function() {
$(".screenshot").hide();
$(".screenshot_logo").show();
@ -146,12 +158,23 @@ function gradio(config, fn, target) {
target.find(".submit").click(function() {
io_master.gather();
target.find(".flag").removeClass("flagged");
target.find(".flag").val("FLAG");
})
}
if (!config.show_input) {
target.find(".input_panel").hide();
}
target.find(".flag").click(function() {
if (io_master.last_output) {
target.find(".flag").addClass("flagged");
target.find(".flag").val("FLAGGED");
io_master.flag();
// io_master.flag($(".flag_message").val());
}
})
return io_master;
}
function gradio_url(config, url, target) {

View File

@ -11,10 +11,10 @@ const key_values = {
init: function(opts) {},
output: function(data) {
let html = ""
for (let row of data) {
for (const [key, value] of Object.entries(data)) {
html += `<tr>
<td>${row[0]}</td>
<td>${row[1]}</td>
<td>${key}</td>
<td>${value}</td>
</tr>`;
}
this.target.find("tbody").html(html);

44
build/lib/gradio/utils.py Normal file
View File

@ -0,0 +1,44 @@
import requests
from IPython import get_ipython
analytics_url = 'https://api.gradio.app/'
def error_analytics(type):
"""
Send error analytics if there is network
:param type: RuntimeError or NameError
"""
data = {'error': '{} in launch method'.format(type)}
try:
requests.post(analytics_url + 'gradio-error-analytics/',
data=data)
except requests.ConnectionError:
pass # do not push analytics if no network
def colab_check():
"""
Check if interface is launching from Google Colab
:return is_colab (bool): True or False
"""
is_colab = False
try: # Check if running interactively using ipython.
from_ipynb = get_ipython()
if "google.colab" in str(from_ipynb):
is_colab = True
except NameError:
error_analytics("NameError", analytics_url)
return is_colab
def ipython_check():
"""
Check if interface is launching from iPython (not colab)
:return is_ipython (bool): True or False
"""
try: # Check if running interactively using ipython.
get_ipython()
is_ipython = True
except NameError:
is_ipython = False
return is_ipython

View File

@ -10,6 +10,7 @@ gradio/outputs.py
gradio/preprocessing_utils.py
gradio/strings.py
gradio/tunneling.py
gradio/utils.py
gradio.egg-info/PKG-INFO
gradio.egg-info/SOURCES.txt
gradio.egg-info/dependency_links.txt

View File

@ -6266,9 +6266,6 @@
var source = container.bounds;
var destination = box;
source = {top: 0, left: 0, width: container.intrinsicWidth, height: container.intrinsicHeight}
console.log(image)
console.log(container)
console.log(box)
var newWidth = 30;
var newHeight = 30;
var newX = destination.left;
@ -6283,9 +6280,6 @@
newHeight = destination.height;
newX = destination.left + (destination.width - newWidth) / 2;
}
console.log(destination.left, destination.top, destination.width, destination.height);
console.log(newX, newY, newWidth, newHeight);
console.log("---");
this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, newX, newY, newWidth, newHeight);
this.ctx.restore();
}