code: def names_to_ott_ids_perfect(self, names, **kwargs):
          
          results = self.TNRS(names, **kwargs)['results']
          d = {}
          for blob in results:
              query_name = blob["id"]
              m = blob["matches"]
              perf_ind = None
              for i, poss_m in enumerate(m):
                  if (not poss_m['is_approximate_match']) and (not poss_m['is_dubious']):
                      if perf_ind is None:
                          perf_ind = i
                      else:
                          raise ValueError('Multiple matches for "{q}"'.format(q=query_name))
              if perf_ind is None:
                  raise ValueError('No matches for "{q}"'.format(q=query_name))
              d[query_name] = m[perf_ind]['ot:ottId']
          ret = []
          for query_name in names:
              ni = d.get(query_name)
              if ni is None:
                  raise ValueError('No matches for "{q}"'.format(q=query_name))
              ret.append(ni)
          return ret
docs: delegates a call to TNRS (same arguments as that function).
  
          Returns a list of (non-dubious) OTT IDs in the same order as the original names.
          Raises a ValueError if each name does not have exactly one perfect, non-dubious
          (score = 1.0) match in the TNRS results.