class_docstr: This class manages the querying of DBpedia and attaches the found entities to the document
class_docstr_tok: ["This","class","manages","the","querying","of","DBpedia","and","attaches","the","found","entities","to","the","document"]
docstr: Adds the entities from the response data to the doc.ents.
  
  :param doc: The document to process
  :type doc: Doc
  :param data: The JSON data from the server
  :return: The return value is a Doc object.
docstr_tok: ["Adds","the","entities","from","the","response","data","to","the","doc.ents",".",":","param","doc",":","The","document","to","process",":","type","doc",":","Doc",":","param","data",":","The","JSON","data","from","the","server",":","return",":","The","return","value","is","a","Doc","object","."]
code: def process_single_doc_after_call(self, doc: Doc, data) -> Doc:
      """
      Adds the entities from the response data to the doc.ents.
  
      :param doc: The document to process
      :type doc: Doc
      :param data: The JSON data from the server
      :return: The return value is a Doc object.
      """
  
      if not data:
          logger.log("DEBUG", "No data returned from DBpedia Spotlight")
          return doc
  
      doc._.dbpedia_raw_result = data
  
      ents_data = []
      # fields have different names depending on the process
      text_key = "@name"
  
      def get_uri(el):
          return None
  
      # get_offset
      if self.process == "annotate":
  
          def get_ents_list(json):
              return json.get("Resources", [])
  
          text_key = "@surfaceForm"
  
          def get_uri(el):
              return el["@URI"]
  
      elif self.process == "spot":
  
          def get_ents_list(json):
              return json.get("annotation", {}).get("surfaceForm", [])
  
      elif self.process == "candidates":
  
          def get_ents_list(json):
              surface_form = json.get("annotation", {}).get(
                  "surfaceForm", []
              )
              if isinstance(surface_form, dict):
                  # if only one candidate
                  surface_form = [surface_form]
              return surface_form
  
          def get_uri(el):
              return f"http://dbpedia.org/resource/{el['resource']['@uri']}"
  
      for ent in get_ents_list(data):
          logger.debug(ent)
          start_ch = int(ent["@offset"])
          end_ch = int(start_ch + len(ent[text_key]))
          ent_kb_id = get_uri(ent)
          # TODO look at '@types' and choose most relevant?
          if ent_kb_id:
              span = doc.char_span(
                  start_ch, end_ch, "DBPEDIA_ENT", ent_kb_id
              )
          else:
              span = doc.char_span(start_ch, end_ch, "DBPEDIA_ENT")
          if not span:
              # something strange like "something@bbc.co.uk" where the match is only part of a SpaCy token
              # 1. find the token to split
              logger.debug(f"{start_ch}, {end_ch}, {ent}")
              # tokens also wider than start_ch, end_ch
              tokens_to_split = [
                  t
                  for t in doc
                  if t.idx >= start_ch or t.idx + len(t) <= end_ch
              ]
              span = doc.char_span(
                  min(t.idx for t in tokens_to_split),
                  max(t.idx + len(t) for t in tokens_to_split),
              )
              # with doc.retokenize() as retokenizer:
              #     for t in tokens_to_split:
              #         retokenizer.split(t, ['a', 't'], [t.head, t.head])
              # raise ValueError()
          span._.dbpedia_raw_result = ent
          ents_data.append(span)
  
      # try to add results to doc.ents
      try:
          doc.ents = list(doc.ents) + ents_data
          logger.debug("The entities are in doc.ents")
      except Exception as e:
          logger.debug(str(e))
          if self.overwrite_ents:
              # overwrite ok
              doc.spans["ents_original"] = doc.ents
              try:
                  doc.ents = ents_data
              except (
                  ValueError
              ):  # if there are overlapping spans in the dbpedia_spotlight entities
                  doc.ents = spacy.util.filter_spans(ents_data)
              logger.debug(
                  'doc.ents has been overwritten. The original entities are in doc.spans["ents_original"]'
              )
          else:
              # don't overwrite
              logger.debug(
                  'doc.ents not overwritten. You can find the dbpedia ents in doc.spans["dbpedia_spotlight"]'
              )
      # doc.spans['dbpedia_raw_result'] = data
      doc.spans[self.span_group] = ents_data
      return doc
  
file_path: spacy-dbpedia-spotlight/spacy_dbpedia_spotlight/entity_linker.py
imports: import concurrent.futures
  import sys
  import requests
  import spacy
  from multiprocessing.pool import ThreadPool
  from loguru import logger
  from requests import HTTPError
  from spacy import util
  from spacy.language import Language
  from spacy.tokens import Doc, Span
label_desc: Use image node_id 2 for calling the EntityLinker obj's underlying member method code with example usage: obj.process_single_doc_after_call(doc, data) and returns: doc, doc, None, json, el, json, surface_form, str, el