Exemplo n.º 1
0
def _chart_cell(args, cell):
    source = args['data']
    ipy = IPython.get_ipython()
    chart_options = _utils.parse_config(cell, ipy.user_ns)
    if chart_options is None:
        chart_options = {}
    fields = args['fields'] if args['fields'] else '*'

    _HTML_TEMPLATE = u"""
    <div class="bqgc" id="%s">
    </div>
    <script>
      require(['extensions/charting', 'element!%s', 'style!/static/extensions/charting.css'],
        function(charts, dom) {
          charts.render(dom, {chartStyle:'%s', dataName:'%s', fields:'%s'}, %s, %s);
        }
      );
    </script>
  """
    div_id = _html.Html.next_id()
    chart_type = args['chart']
    count = 25 if chart_type == 'paged_table' else -1
    data, _ = _utils.get_data(source, fields, 0, count)

    return IPython.core.display.HTML(
        _HTML_TEMPLATE %
        (div_id, div_id, chart_type, _utils.get_data_source_index(source),
         fields, json.dumps(chart_options, cls=gcp._util.JSONEncoder),
         json.dumps(data, cls=gcp._util.JSONEncoder)))
Exemplo n.º 2
0
def _chart_cell(args, cell):
  source = args['data']
  ipy = IPython.get_ipython()
  chart_options = _utils.parse_config(cell, ipy.user_ns)
  if chart_options is None:
    chart_options = {}
  fields = args['fields'] if args['fields'] else '*'

  _HTML_TEMPLATE = """
    <div class="bqgc" id="%s">
    </div>
    <script>
      require(['extensions/charting', 'element!%s', 'style!/static/extensions/charting.css'],
        function(charts, dom) {
          charts.render(dom, {chartStyle:'%s', dataName:'%s', fields:'%s'}, %s, %s);
        }
      );
    </script>
  """
  div_id = _html.Html.next_id()
  chart_type = args['chart']
  count = 25 if chart_type == 'paged_table' else -1
  data, _ = _utils.get_data(source, fields, 0, count)

  return IPython.core.display.HTML(
    _HTML_TEMPLATE % (div_id, div_id, chart_type, _utils.get_data_source_index(source), fields,
                      json.dumps(chart_options, cls=gcp._util.JSONEncoder),
                      json.dumps(data, ensure_ascii=False, cls=gcp._util.JSONEncoder)))
Exemplo n.º 3
0
def _table_viewer(table, rows_per_page=25, fields=None):
  """  Return a table viewer.

    This includes a static rendering of the first page of the table, that gets replaced
    by the charting code in environments where Javascript is executable and BQ is available.

  Args:
    table: the table to view.
    rows_per_page: how many rows to display at one time.
    fields: an array of field names to display; default is None which uses the full schema.
  Returns:
    A string containing the HTML for the table viewer.
  """
  if not table.exists():
    raise Exception('Table %s does not exist' % str(table))

  _HTML_TEMPLATE = u"""
    <div class="bqtv" id="{div_id}">{static_table}</div>
    <br />{meta_data}<br />
    <script>
      require(['extensions/charting', 'element!{div_id}', 'style!/static/extensions/charting.css'],
        function(charts, dom) {{
          charts.render(dom,
            {{
              chartStyle:"{chart_style}",
              dataName:"{data_name}",
              fields:"{fields}",
              totalRows:{total_rows},
              rowsPerPage:{rows_per_page},
            }}, {{}}, {data});
        }}
      );
    </script>
  """

  if fields is None:
    fields = _utils.get_field_list(fields, table.schema)
  div_id = _html.Html.next_id()
  meta_count = ('rows: %d' % table.length) if table.length >= 0 else ''
  meta_name = str(table) if table.job is None else ('job: %s' % table.job.id)
  if table.job:
    if table.job.cache_hit:
      meta_cost = 'cached'
    else:
      bytes = gcp.bigquery._query_stats.QueryStats._size_formatter(table.job.bytes_processed)
      meta_cost = '%s processed' % bytes
    meta_time = 'time: %.1fs' % table.job.total_time
  else:
    meta_cost = ''
    meta_time = ''

  data, total_count = _utils.get_data(table, fields, 0, rows_per_page)

  if total_count < 0:
    # The table doesn't have a length metadata property but may still be small if we fetched less
    # rows than we asked for.
    fetched_count = len(data['rows'])
    if fetched_count < rows_per_page:
      total_count = fetched_count

  chart = 'table' if 0 <= total_count <= rows_per_page else 'paged_table'
  meta_entries = [meta_count, meta_time, meta_cost, meta_name]
  meta_data = '(%s)' % (', '.join([entry for entry in meta_entries if len(entry)]))

  return _HTML_TEMPLATE.format(div_id=div_id,
                               static_table=_html.HtmlBuilder.render_chart_data(data),
                               meta_data=meta_data,
                               chart_style=chart,
                               data_name=_utils.get_data_source_index(str(table)),
                               fields=','.join(fields),
                               total_rows=total_count,
                               rows_per_page=rows_per_page,
                               data=json.dumps(data, cls=gcp._util.JSONEncoder))
Exemplo n.º 4
0
def _table_viewer(table, rows_per_page=25, fields=None):
    """  Return a table viewer.

  Args:
    table: the table to view.
    rows_per_page: how many rows to display at one time.
    fields: an array of field names to display; default is None which uses the full schema.
  Returns:
    A string containing the HTML for the table viewer.
  """
    if not table.exists():
        raise Exception('%s does not exist' % str(table))

    _HTML_TEMPLATE = """
    <div class="bqtv" id="%s"></div>
    <br />%s<br />
    <script>
      require(['extensions/charting', 'element!%s', 'style!/static/extensions/charting.css'],
        function(charts, dom) {
          charts.render(dom,
            {
              chartStyle:"%s",
              dataName:"%s",
              fields:"%s",
              totalRows:%d,
              rowsPerPage:%d,
            }, {}, %s);
        }
      );
    </script>
  """

    if fields is None:
        fields = _utils.get_field_list(fields, table.schema)
    div_id = _html.Html.next_id()
    meta_count = ('rows: %d' % table.length) if table.length >= 0 else ''
    meta_name = str(table) if table.job is None else ('job: %s' % table.job.id)
    if table.job:
        if table.job.cache_hit:
            meta_cost = 'cached'
        else:
            bytes = gcp.bigquery._query_stats.QueryStats._size_formatter(
                table.job.bytes_processed)
            meta_cost = '%s processed' % bytes
        meta_time = 'time: %.1fs' % table.job.total_time
    else:
        meta_cost = ''
        meta_time = ''

    data, total_count = _utils.get_data(table, fields, 0, rows_per_page)

    if total_count < 0:
        # The table doesn't have a length metadata property but may still be small if we fetched less
        # rows than we asked for.
        fetched_count = len(data['rows'])
        if fetched_count < rows_per_page:
            total_count = fetched_count

    chart = 'table' if 0 <= total_count <= rows_per_page else 'paged_table'
    meta_entries = [meta_count, meta_time, meta_cost, meta_name]
    meta_data = '(%s)' % (', '.join(
        [entry for entry in meta_entries if len(entry)]))

    return _HTML_TEMPLATE %\
        (div_id, meta_data, div_id, chart,
         _utils.get_data_source_index(str(table)), ','.join(fields), total_count, rows_per_page,
         json.dumps(data, cls=gcp._util.JSONEncoder))
Exemplo n.º 5
0
def _chart_cell(args, cell):
  source = args['data']
  ipy = IPython.get_ipython()
  chart_options = _utils.parse_config(cell, ipy.user_ns)
  if chart_options is None:
    chart_options = {}
  elif not isinstance(chart_options, dict):
    raise Exception("Could not parse chart options")
  fields = args['fields'] if args['fields'] else '*'
  div_id = _html.Html.next_id()
  env = {}
  controls_html = ''
  controls_ids = []
  if 'variables' in chart_options:
    variables = chart_options['variables']
    del chart_options['variables']  # Just to make sure GCharts doesn't see them.
    try:
      item = _utils.get_notebook_item(source)
      _, defaults = gcp.data.SqlModule.get_sql_statement_with_environment(item, '')
    except Exception:
      defaults = {}
    for varname, control in variables.items():
      label = control.get('label', varname)
      control_id = div_id + '__' + varname
      controls_ids.append(control_id)
      value = control.get('value', defaults.get(varname, None))
      # The user should usually specify the type but we will default to 'textbox' for strings
      # and 'set' for lists.
      if isinstance(value, basestring):
        type = 'textbox'
      elif isinstance(value, list):
        type = 'set'
      else:
        type = None
      type = control.get('type', type)

      if type == 'picker':
        choices = control.get('choices', value)
        if not isinstance(choices, list) or len(choices) == 0:
          raise Exception('picker control must specify a nonempty set of choices')
        if value is None:
          value = choices[0]
        choices_html = ''
        for i, choice in enumerate(choices):
          choices_html += "<option value=\"%s\" %s>%s</option>" % \
              (choice, ("selected=\"selected\"" if choice == value else ''), choice)
        control_html = "{label}<select disabled id=\"{id}\">{choices}</select>"\
            .format(label=label, id=control_id, choices=choices_html)
      elif type == 'set':  # Multi-picker; implemented as checkboxes.
        # TODO(gram): consider using "name" property of the control to group checkboxes. That
        # way we can save the code of constructing and parsing control Ids with sequential
        #  numbers in it. Multiple checkboxes can share the same name.
        choices = control.get('choices', value)
        if not isinstance(choices, list) or len(choices) == 0:
          raise Exception('set control must specify a nonempty set of choices')
        if value is None:
          value = choices
        choices_html = ''
        controls_ids[-1] = '%s:%d' % (control_id, len(choices))  # replace ID to include count.
        for i, choice in enumerate(choices):
          checked = choice in value
          choice_id = '%s:%d' % (control_id, i)
          # TODO(gram): we may want a 'Submit/Refresh button as we may not want to rerun
          # query on each checkbox change.
          choices_html += """
            <div>
              <label>
                <input type="checkbox" id="{id}" value="{choice}" {checked} disabled>
                {choice}
              </label>
            </div>
          """.format(id=choice_id, choice=choice, checked="checked" if checked else '')
        control_html = "{label}<div>{choices}</div>".format(label=label, choices=choices_html)
      elif type == 'checkbox':
        control_html = """
              <label>
                <input type="checkbox" id="{id}" {checked} disabled>
                {label}
              </label>
          """.format(label=label, id=control_id, checked="checked" if value else '')
      elif type == 'slider':
        min = control.get('min', None)
        max = control.get('max', None)
        if min is None or max is None:
          raise Exception('slider control must specify a min and max value')
        if max <= min:
          raise Exception('slider control must specify a min value less than max value')
        step = control.get('step', 1 if isinstance(min, int) and isinstance(max, int)
            else (max - min) / 10.0)
        if value is None:
          value = min
        control_html = """
          {label}
          <input type="text" class="gchart-slider_value" id="{id}_value" value="{value}" disabled/>
          <input type="range" class="gchart-slider" id="{id}" min="{min}" max="{max}" step="{step}"
              value="{value}" disabled/>
        """.format(label=label, id=control_id, value=value, min=min, max=max, step=step)
      elif type == 'textbox':
        if value is None:
          value = ''
        control_html = "{label}<input type=\"text\" value=\"{value}\" id=\"{id}\" disabled/>"\
            .format(label=label, value=value, id=control_id)
      else:
        raise Exception(
            'Unknown control type %s (expected picker, slider, checkbox, textbox or set)' % type)

      env[varname] = value
      controls_html += "<div class=\"gchart-control\">{control}</div>\n"\
          .format(control=control_html)

    controls_html = "<div class=\"gchart-controls\">{controls}</div>".format(controls=controls_html)

  _HTML_TEMPLATE = """
    <div class="bqgc-container">
      {controls}
      <div class="bqgc{extra_class}" id="{id}">
      </div>
    </div>
    <script>
      require(['extensions/charting', 'element!{id}', 'style!/static/extensions/charting.css'],
        function(charts, dom) {{
          charts.render(dom, {{chartStyle:'{chart_type}', dataName:'{source}', fields:'{fields}'}},
            {options}, {data}, {control_ids});
        }}
      );
    </script>
  """

  chart_type = args['chart']
  count = 25 if chart_type == 'paged_table' else -1
  data, _ = _utils.get_data(source, fields, env, 0, count)

  # TODO(gram): check if we need to augment env with user_ns
  return IPython.core.display.HTML(
    _HTML_TEMPLATE.format(controls=controls_html,
                      id=div_id,
                      chart_type=chart_type,
                      extra_class=" bqgc-controlled" if len(controls_html) else '',
                      source=_utils.get_data_source_index(source),
                      fields=fields,
                      options=json.dumps(chart_options, cls=gcp._util.JSONEncoder),
                      data=json.dumps(data, cls=gcp._util.JSONEncoder),
                      control_ids=str(controls_ids)))
Exemplo n.º 6
0
def _table_viewer(table, rows_per_page=25, fields=None):
  """  Return a table viewer.

  Args:
    table: the table to view.
    rows_per_page: how many rows to display at one time.
    fields: an array of field names to display; default is None which uses the full schema.
  Returns:
    A string containing the HTML for the table viewer.
  """
  if not table.exists():
    raise Exception('%s does not exist' % str(table))

  _HTML_TEMPLATE = """
    <div class="bqtv" id="%s"></div>
    <br />%s<br />
    <script>
      require(['extensions/charting', 'element!%s', 'style!/static/extensions/charting.css'],
        function(charts, dom) {
          charts.render(dom,
            {
              chartStyle:"%s",
              dataName:"%s",
              fields:"%s",
              totalRows:%d,
              rowsPerPage:%d,
            }, {}, %s);
        }
      );
    </script>
  """

  if fields is None:
    fields = _utils.get_field_list(fields, table.schema)
  div_id = _html.Html.next_id()
  meta_count = ('rows: %d' % table.length) if table.length >= 0 else ''
  meta_name = str(table) if table.job is None else ('job: %s' % table.job.id)
  if table.job:
    if table.job.cache_hit:
      meta_cost = 'cached'
    else:
      bytes = gcp.bigquery._query_stats.QueryStats._size_formatter(table.job.bytes_processed)
      meta_cost = '%s processed' % bytes
    meta_time = 'time: %.1fs' % table.job.total_time
  else:
    meta_cost = ''
    meta_time = ''

  data, total_count = _utils.get_data(table, fields, 0, rows_per_page)

  if total_count < 0:
    # The table doesn't have a length metadata property but may still be small if we fetched less
    # rows than we asked for.
    fetched_count = len(data['rows'])
    if fetched_count < rows_per_page:
      total_count = fetched_count

  chart = 'table' if 0 <= total_count <= rows_per_page else 'paged_table'
  meta_entries = [meta_count, meta_time, meta_cost, meta_name]
  meta_data = '(%s)' % (', '.join([entry for entry in meta_entries if len(entry)]))

  return _HTML_TEMPLATE %\
      (div_id, meta_data, div_id, chart,
       _utils.get_data_source_index(str(table)), ','.join(fields), total_count, rows_per_page,
       json.dumps(data, cls=gcp._util.JSONEncoder))
Exemplo n.º 7
0
def _table_viewer(table, rows_per_page=25, fields=None):
    """  Return a table viewer.

    This includes a static rendering of the first page of the table, that gets replaced
    by the charting code in environments where Javascript is executable and BQ is available.

  Args:
    table: the table to view.
    rows_per_page: how many rows to display at one time.
    fields: an array of field names to display; default is None which uses the full schema.
  Returns:
    A string containing the HTML for the table viewer.
  """
    if not table.exists():
        raise Exception('%s does not exist' % str(table))

    _HTML_TEMPLATE = """
    <div class="bqtv" id="{div_id}">{static_table}</div>
    <br />{meta_data}<br />
    <script>
      require(['extensions/charting', 'element!{div_id}', 'style!/static/extensions/charting.css'],
        function(charts, dom) {{
          charts.render(dom,
            {{
              chartStyle:"{chart_style}",
              dataName:"{data_name}",
              fields:"{fields}",
              totalRows:{total_rows},
              rowsPerPage:{rows_per_page},
            }}, {{}}, {data});
        }}
      );
    </script>
  """

    if fields is None:
        fields = _utils.get_field_list(fields, table.schema)
    div_id = _html.Html.next_id()
    meta_count = ('rows: %d' % table.length) if table.length >= 0 else ''
    meta_name = str(table) if table.job is None else ('job: %s' % table.job.id)
    if table.job:
        if table.job.cache_hit:
            meta_cost = 'cached'
        else:
            bytes = gcp.bigquery._query_stats.QueryStats._size_formatter(
                table.job.bytes_processed)
            meta_cost = '%s processed' % bytes
        meta_time = 'time: %.1fs' % table.job.total_time
    else:
        meta_cost = ''
        meta_time = ''

    data, total_count = _utils.get_data(table, fields, 0, rows_per_page)

    if total_count < 0:
        # The table doesn't have a length metadata property but may still be small if we fetched less
        # rows than we asked for.
        fetched_count = len(data['rows'])
        if fetched_count < rows_per_page:
            total_count = fetched_count

    chart = 'table' if 0 <= total_count <= rows_per_page else 'paged_table'
    meta_entries = [meta_count, meta_time, meta_cost, meta_name]
    meta_data = '(%s)' % (', '.join(
        [entry for entry in meta_entries if len(entry)]))

    return _HTML_TEMPLATE.format(
        div_id=div_id,
        static_table=_html.HtmlBuilder.render_chart_data(data),
        meta_data=meta_data,
        chart_style=chart,
        data_name=_utils.get_data_source_index(str(table)),
        fields=','.join(fields),
        total_rows=total_count,
        rows_per_page=rows_per_page,
        data=json.dumps(data, ensure_ascii=False, cls=gcp._util.JSONEncoder))