code: def py_to_nb(py_path, nb_path, fill_outputs=True):
      f = open(py_path)
      py = f.read()
      f.close()
      # validate(py)
  
      # header, _, py, tag = _get_next_script_element(py)
      # attributes = _parse_header(header)
      cells = []
      loc = 0
      # Write first header cell
      # header_cell = {
      # "cell_type": "markdown",
      # "source": [
      # "# " + attributes["title"] + "\n",
      # "\n",
      # "**" + attributes["auth_field"] + ":** " + attributes["author"] + "<br>\n",
      # "**Date created:** " + attributes["date_created"] + "<br>\n",
      # "**Last modified:** " + attributes["last_modified"] + "<br>\n",
      # "**Description:** " + attributes["description"],
      # ],
      # "metadata": {"colab_type": "text"},
      # }
      # cells.append(header_cell)
      while py:
          e, cell_type, py, tag = _get_next_script_element(py)
          lines = e.split("\n")
  
          if all(l == "" for l in lines):
              continue
  
          if lines and not lines[0]:
              lines = lines[1:]
          source = [l + "\n" for l in lines]
          # Drop last newline char
          if source and not source[-1].strip():
              source = source[:-1]
          if tag == "shell":
              source = ["!" + l for l in source]
              cell_type = "code"
          if tag != "invisible" and source:
              cell = {"cell_type": cell_type, "source": source}
              if cell_type == "code":
                  cell["outputs"] = []
                  cell["metadata"] = {"colab_type": "code"}
                  cell["execution_count"] = 0
                  loc += _count_locs(source)
              else:
                  cell["metadata"] = {"colab_type": "text"}
              cells.append(cell)
      notebook = {}
      for key in NB_BASE.keys():
          notebook[key] = NB_BASE[key]
      notebook["metadata"]["colab"]["name"] = str(py_path).split("/")[
          -1
      ][:-3]
      notebook["cells"] = cells
      if loc > MAX_LOC:
          raise ValueError(
              "Found %d lines of code, but expected fewer than %d"
              % (loc, MAX_LOC)
          )
  
      f = open(nb_path, "w")
      f.write(json.dumps(notebook, indent=1, sort_keys=True))
      f.close()
      if fill_outputs:
          print("Generating ipynb")
          parent_dir = Path(nb_path).parent
          current_files = os.listdir(parent_dir)
          try:
              os.system(
                  "jupyter nbconvert --to notebook --execute --debug "
                  + str(nb_path)
                  + " --inplace"
                  + " --ExecutePreprocessor.timeout="
                  + str(TIMEOUT)
              )
          finally:
              new_files = os.listdir(parent_dir)
              for fname in new_files:
                  if fname not in current_files:
                      fpath = parent_dir / fname
                      if os.path.isdir(fpath):
                          print("Removing created folder:", fname)
                          shutil.rmtree(fpath)
                      else:
                          print("Removing created file:", fname)
                          os.remove(fpath)
  
file_path: icevision/docs/tutobooks.py
imports: import json
  import os
  import random
  import shutil
  import sys
  from pathlib import Path
label_desc: Use image node_id 2 for calling a global function with example usage: py_to_nb(py_path, nb_path, fill_outputs) without return types