docs: def resolve_container_id_or_name(raw_string, is_error=False, multi=False):
      '''
      :param raw_string: A potential project or container ID or name
      :type raw_string: string
      :param is_error: Whether to raise an exception if the project or
              container ID cannot be resolved
      :type is_error: boolean
      :returns: Project or container ID if found or else None
      :rtype: string or None
      :raises: :exc:`ResolutionError` if *is_error* is True and the
              project or container could not be resolved
  
      Unescapes and attempts to resolve *raw_string* to a project or
      container ID.
  
      '''
      string = unescape_name_str(raw_string)
      if is_container_id(string):
          return ([string] if multi else string)
  
      if string in cached_project_names:
          return ([cached_project_names[string]] if multi else cached_project_names[string])
  
      try:
          results = list(dxpy.find_projects(name=string, describe=True, level='VIEW'))
      except Exception as details:
          raise ResolutionError(str(details))
  
      if len(results) == 1:
          cached_project_names[string] = results[0]['id']
          return ([results[0]['id']] if multi else results[0]['id'])
      elif len(results) == 0:
          if is_error:
              raise ResolutionError('Could not find a project named "' + string + '"')
          return ([] if multi else None)
      elif not multi:
          if INTERACTIVE_CLI:
              print('Found multiple projects with name "' + string + '"')
              choice = pick(['{id} ({level})'.format(id=result['id'], level=result['level'])
                             for result in results])
              return results[choice]['id']
          else:
              raise ResolutionError('Found multiple projects with name "' + string + '"; please use a project ID to specify the desired project')
      else:
          # len(results) > 1 and multi
          return [result['id'] for result in results]