docs: def process_needtables(app, doctree, fromdocname):
      """
      Replace all needtables nodes with a tale of filtered noded.
  
      :param app:
      :param doctree:
      :param fromdocname:
      :return:
      """
      env = app.builder.env
  
      for node in doctree.traverse(Needtable):
          if not app.config.needs_include_needs:
              # Ok, this is really dirty.
              # If we replace a node, docutils checks, if it will not lose any attributes.
              # But this is here the case, because we are using the attribute "ids" of a node.
              # However, I do not understand, why losing an attribute is such a big deal, so we delete everything
              # before docutils claims about it.
              for att in ('ids', 'names', 'classes', 'dupnames'):
                  node[att] = []
              node.replace_self([])
              continue
  
          id = node.attributes["ids"][0]
          current_needtable = env.need_all_needtables[id]
          all_needs = env.needs_all_needs
  
          if current_needtable["style"] == "" or current_needtable["style"].upper() not in ["TABLE", "DATATABLES"]:
              if app.config.needs_table_style == "":
                  style = "DATATABLES"
              else:
                  style = app.config.needs_table_style.upper()
          else:
              style = current_needtable["style"].upper()
  
          # Prepare table
          classes = ["NEEDS_{style}".format(style=style)]
          content = nodes.table(classes=classes)
          tgroup = nodes.tgroup()
  
          # Define Table column width
          # ToDo: Find a way to chosen to perfect width automatically.
          for col in current_needtable["columns"]:
              if col == "TITLE":
                  tgroup += nodes.colspec(colwidth=15)
              else:
                  tgroup += nodes.colspec(colwidth=5)
  
          node_columns = []
          for col in current_needtable["columns"]:
              header_name = col.title() if col != "ID" else col
              header_name = header_name.replace("_", " ")
              node_columns.append(nodes.entry('', nodes.paragraph('', header_name)))
  
          tgroup += nodes.thead('', nodes.row(
              '', *node_columns))
          tbody = nodes.tbody()
          tgroup += tbody
          content += tgroup
  
          all_needs = list(all_needs.values())
  
          if current_needtable["sort_by"] is not None:
              if current_needtable["sort_by"] == "id":
                  all_needs = sorted(all_needs, key=lambda node: node["id"])
              elif current_needtable["sort_by"] == "status":
                  all_needs = sorted(all_needs, key=status_sorter)
  
          # Perform filtering of needs
          found_needs = procces_filters(all_needs, current_needtable)
  
          for need_info in found_needs:
              temp_need = need_info.copy()
              if temp_need['is_need']:
                  row = nodes.row(classes=['need'])
                  prefix = ''
              else:
                  row = nodes.row(classes=['need_part'])
                  temp_need['id'] = temp_need['id_complete']
                  prefix = app.config.needs_part_prefix
                  temp_need['title'] = temp_need['content']
  
              for col in current_needtable["columns"]:
                  if col == "ID":
                      row += row_col_maker(app, fromdocname, env.needs_all_needs, temp_need, "id", make_ref=True,
                                           prefix=prefix)
                  elif col == "TITLE":
                      row += row_col_maker(
                          app, fromdocname, env.needs_all_needs, temp_need, "title",
                          prefix=app.config.needs_part_prefix)
                  elif col == "INCOMING":
                      row += row_col_maker(app, fromdocname, env.needs_all_needs, temp_need,
                                           "links_back", ref_lookup=True)
                  elif col == "OUTGOING":
                      row += row_col_maker(app, fromdocname, env.needs_all_needs, temp_need, "links", ref_lookup=True)
                  else:
                      row += row_col_maker(app, fromdocname, env.needs_all_needs, temp_need, col.lower())
              tbody += row
  
              # Need part rows
              if current_needtable["show_parts"] and need_info['is_need']:
                  for key, part in need_info["parts"].items():
                      row = nodes.row(classes=['need_part'])
                      temp_part = part.copy()  # The dict needs to be manipulated, so that row_col_maker() can be used
                      temp_part['docname'] = need_info['docname']
  
                      for col in current_needtable["columns"]:
                          if col == "ID":
                              temp_part['id'] = '.'.join([need_info['id'], part['id']])
                              row += row_col_maker(
                                  app, fromdocname, env.needs_all_needs, temp_part, "id",
                                  make_ref=True, prefix=app.config.needs_part_prefix)
                          elif col == "TITLE":
                              row += row_col_maker(
                                  app, fromdocname, env.needs_all_needs, temp_part, "content",
                                  prefix=app.config.needs_part_prefix)
                          elif col == "INCOMING":
                              row += row_col_maker(
                                  app, fromdocname, env.needs_all_needs, temp_part, "links_back", ref_lookup=True)
                          else:
                              row += row_col_maker(
                                  app, fromdocname, env.needs_all_needs, temp_part, col.lower())
  
                      tbody += row
  
          if len(found_needs) == 0:
              content.append(no_needs_found_paragraph())
  
          # add filter information to output
          if current_needtable["show_filters"]:
              content.append(used_filter_paragraph(current_needtable))
  
          node.replace_self(content)