code: def _udf_cell(args, cell_body):
    
    udf_name = args['name']
    if not udf_name:
      raise Exception('Declaration must be of the form %%bq udf --name <variable name>')
  
    # Parse out parameters, return type, and imports
    param_pattern = r'^\s*\/\/\s*@param\s+([<>\w]+)\s+([<>\w,\s]+)\s*$'
    returns_pattern = r'^\s*\/\/\s*@returns\s+([<>\w,\s]+)\s*$'
    import_pattern = r'^\s*\/\/\s*@import\s+(\S+)\s*$'
  
    params = re.findall(param_pattern, cell_body, re.MULTILINE)
    return_type = re.findall(returns_pattern, cell_body, re.MULTILINE)
    imports = re.findall(import_pattern, cell_body, re.MULTILINE)
  
    if len(return_type) < 1:
      raise Exception('UDF return type must be defined using // @returns <type>')
    if len(return_type) > 1:
      raise Exception('Found more than one return type definition')
  
    return_type = return_type[0]
  
    # Finally build the UDF object
    udf = bigquery.UDF(udf_name, cell_body, return_type, params, args['language'], imports)
    google.datalab.utils.commands.notebook_environment()[udf_name] = udf
docs: Implements the Bigquery udf cell magic for ipython notebooks.
  
    The supported syntax is:
    %%bq udf --name <var> --language <lang>
    // @param <name> <type>
    // @returns <type>
    // @import <gcs_path>
    <js function>
  
    Args:
      args: the optional arguments following '%%bq udf'.
      cell_body: the UDF declaration (inputs and outputs) and implementation in javascript.