docs: def get_handler(id_or_link, project=None):
      '''
      :param id_or_link: String containing an object ID or dict containing a DXLink
      :type id_or_link: string or dict
      :param project: String project ID to use as the context if the the object is a data object
      :type project: string
      :rtype: :class:`~dxpy.bindings.DXObject`, :class:`~dxpy.bindings.DXApp`, or :class:`~dxpy.bindings.DXGlobalWorkflow`
  
      Parses a string or DXLink dict. Creates and returns an object handler for it.
  
      Example::
  
          get_handler("file-1234")
      '''
      try:
          cls = _guess_link_target_type(id_or_link)
      except Exception as e:
          raise DXError("Could not parse link {}: {}".format(id_or_link, e))
  
      if cls in [dxpy.DXApp, dxpy.DXGlobalWorkflow]:
          # This special case should translate identifiers of the form
          # "app-name" or "app-name/version_or_tag" to the appropriate
          # arguments
          if dxpy.utils.resolver.is_hashid(id_or_link):
              return cls(id_or_link)
          else:
              slash_pos = id_or_link.find('/')
              dash_pos = id_or_link.find('-')
              if slash_pos == -1:
                  return cls(name=id_or_link[dash_pos+1:])
              else:
                  return cls(name=id_or_link[dash_pos+1:slash_pos],
                             alias=id_or_link[slash_pos + 1:])
      elif project is None or cls in [dxpy.DXJob, dxpy.DXAnalysis, dxpy.DXProject, dxpy.DXContainer]:
          # This case is important for the handlers which do not
          # take a project field
          return cls(id_or_link)
      else:
          return cls(id_or_link, project=project)