code: def _extract_from_sent(doc, span, blacklist=True, debug=False):
      """
      Extract Pronouns and Noun phrases mentions from a spacy Span
      """
      keep_tags = re.compile(r"N.*|PRP.*|DT|IN")
      leave_dep = ["det", "compound", "appos"]
      keep_dep = ["nsubj", "dobj", "iobj", "pobj"]
      nsubj_or_dep = ["nsubj", "dep"]
      conj_or_prep = ["conj", "prep"]
      remove_pos = ["CCONJ", "SCONJ", "INTJ", "ADP"]
      lower_not_end = ["'s", ",", ".", "!", "?", ":", ";"]
  
      # Utility to remove bad endings
      def cleanup_endings(left, right, token):
          minchild_idx = min(left + [token.i]) if left else token.i
          maxchild_idx = max(right + [token.i]) if right else token.i
          # Clean up endings and begginging
          while maxchild_idx >= minchild_idx and (
              doc[maxchild_idx].pos_ in remove_pos
              or doc[maxchild_idx].lower_ in lower_not_end
          ):
              if debug:
                  print(
                      "Removing last token",
                      doc[maxchild_idx].lower_,
                      doc[maxchild_idx].tag_,
                  )
              maxchild_idx -= 1  # We don't want mentions finishing with 's or conjunctions/punctuation
          while minchild_idx <= maxchild_idx and (
              doc[minchild_idx].pos_ in remove_pos
              or doc[minchild_idx].lower_ in lower_not_end
          ):
              if debug:
                  print(
                      "Removing first token",
                      doc[minchild_idx].lower_,
                      doc[minchild_idx].tag_,
                  )
              minchild_idx += 1  # We don't want mentions starting with 's or conjunctions/punctuation
          return minchild_idx, maxchild_idx + 1
  
      mentions_spans = []
      for token in span:
          if debug:
              print(
                  "🚀 tok:",
                  token,
                  "tok.tag_:",
                  token.tag_,
                  "tok.pos_:",
                  token.pos_,
                  "tok.dep_:",
                  token.dep_,
              )
  
          if blacklist and token.lower_ in NO_COREF_LIST:
              if debug:
                  print("token in no_coref_list")
              continue
          if (
              not keep_tags.match(token.tag_) or token.dep_ in leave_dep
          ) and not token.dep_ in keep_dep:
              if debug:
                  print("not pronoun or no right dependency")
              continue
  
          # pronoun
          if re.match(r"PRP.*", token.tag_):
              if debug:
                  print("PRP")
              endIdx = token.i + 1
  
              span = doc[token.i : endIdx]
              if debug:
                  print("==-- PRP store:", span)
              mentions_spans.append(span)
  
              # when pronoun is a part of conjunction (e.g., you and I)
              if token.n_rights > 0 or token.n_lefts > 0:
                  span = doc[token.left_edge.i : token.right_edge.i + 1]
                  if debug:
                      print("==-- in conj store:", span)
                  mentions_spans.append(span)
              continue
  
          # Add NP mention
          if debug:
              print("NP or IN:", token.lower_)
              if token.tag_ == "IN":
                  print("IN tag")
          # Take care of 's
          if token.lower_ == "'s":
              if debug:
                  print("'s detected")
              h = token.head
              j = 0
              while h.head.i != h.i and j < MAX_ITER:
                  if debug:
                      print("token head:", h, h.dep_, "head:", h.head)
                      print(id(h.head), id(h))
                  if h.dep_ == "nsubj":
                      minchild_idx = min(
                          (
                              c.left_edge.i
                              for c in doc
                              if c.head.i == h.head.i
                              and c.dep_ in nsubj_or_dep
                          ),
                          default=token.i,
                      )
                      maxchild_idx = max(
                          (
                              c.right_edge.i
                              for c in doc
                              if c.head.i == h.head.i
                              and c.dep_ in nsubj_or_dep
                          ),
                          default=token.i,
                      )
                      if debug:
                          print(
                              "'s', i1:",
                              doc[minchild_idx],
                              " i2:",
                              doc[maxchild_idx],
                          )
                      span = doc[minchild_idx : maxchild_idx + 1]
                      if debug:
                          print("==-- 's' store:", span)
                      mentions_spans.append(span)
                      break
                  h = h.head
                  j += 1
              assert j != MAX_ITER
              continue
  
          # clean up
          for c in doc:
              if debug and c.head.i == token.i:
                  print(
                      "🚧 token in span:",
                      c,
                      "- head & dep:",
                      c.head,
                      c.dep_,
                  )
          left = list(c.left_edge.i for c in doc if c.head.i == token.i)
          right = list(
              c.right_edge.i for c in doc if c.head.i == token.i
          )
          if (
              token.tag_ == "IN"
              and token.dep_ == "mark"
              and len(left) == 0
              and len(right) == 0
          ):
              left = list(
                  c.left_edge.i for c in doc if c.head.i == token.head.i
              )
              right = list(
                  c.right_edge.i
                  for c in doc
                  if c.head.i == token.head.i
              )
          if debug:
              print("left side:", left)
              print("right side:", right)
              minchild_idx = min(left) if left else token.i
              maxchild_idx = max(right) if right else token.i
              print("full span:", doc[minchild_idx : maxchild_idx + 1])
          start, end = cleanup_endings(left, right, token)
          if start == end:
              continue
          if doc[start].lower_ == "'s":
              continue  # we probably already have stored this mention
          span = doc[start:end]
          if debug:
              print("cleaned endings span:", doc[start:end])
              print("==-- full span store:", span)
          mentions_spans.append(span)
          if debug and token.tag_ == "IN":
              print("IN tag")
          if any(tok.dep_ in conj_or_prep for tok in span):
              if debug:
                  print(
                      "Conjunction found, storing first element separately"
                  )
              for c in doc:
                  if c.head.i == token.i and c.dep_ not in conj_or_prep:
                      if debug:
                          print(
                              "left no conj:",
                              c,
                              "dep & edge:",
                              c.dep_,
                              c.left_edge,
                          )
                      if debug:
                          print(
                              "right no conj:",
                              c,
                              "dep & edge:",
                              c.dep_,
                              c.right_edge,
                          )
              left_no_conj = list(
                  c.left_edge.i
                  for c in doc
                  if c.head.i == token.i and c.dep_ not in conj_or_prep
              )
              right_no_conj = list(
                  c.right_edge.i
                  for c in doc
                  if c.head.i == token.i and c.dep_ not in conj_or_prep
              )
              if debug:
                  print(
                      "left side no conj:",
                      [doc[i] for i in left_no_conj],
                  )
              if debug:
                  print(
                      "right side no conj:",
                      [doc[i] for i in right_no_conj],
                  )
              start, end = cleanup_endings(
                  left_no_conj, right_no_conj, token
              )
              if start == end:
                  continue
              span = doc[start:end]
              if debug:
                  print("==-- full span store:", span)
              mentions_spans.append(span)
      if debug:
          print("mentions_spans inside", mentions_spans)
      return mentions_spans
  
imports: import re
  import io
  from six import string_types, integer_types
  from spacy.tokens import Span, Token
  from neuralcoref.train.compat import unicode_
  from neuralcoref.train.utils import encode_distance, parallel_process
  import spacy
  import numpy
label_desc: Use image node_id 2 for calling a global function with example usage: _extract_from_sent(doc, span, blacklist, debug) and returns: mentions_spans, minchild_idx,  unknown