code: def parse_fn_docstring(fn):
      
      doc = fn.__doc__
      params, return_ = {}, {}
      param_order = []
      for line in doc.split("\n"):
          line = line.strip()
          if line.startswith(":param"):
              _, name, desc = line.split(":", 2)
              name = name[6:].strip()  # skip 'param '
              params[name] = {'desc': desc.strip()}
              param_order.append(name)
          elif line.startswith(":type"):
              _, name, desc = line.split(":", 2)
              name = name[5:].strip()  # skip 'type '
              if not name in params:
                  raise ValueError("'type' without 'param' for {}".format(name))
              params[name]['type'] = desc.strip()
          elif line.startswith(":return"):
              _1, _2, desc = line.split(":", 2)
              return_['desc'] = desc
          elif line.startswith(":rtype"):
              _1, _2, desc = line.split(":", 2)
              return_['type'] = desc.strip()
      return params
docs: Get parameter and return types from function's docstring.
  
      Docstrings must use this format::
  
         :param foo: What is foo
         :type foo: int
         :return: What is returned
         :rtype: double
  
      :return: A map of names, each with keys 'type' and 'desc'.
      :rtype: tuple(dict)