class_docstr: Abstract subclass of NodeProvider meant for use with external cluster managers.
  
  Batches reads of cluster state into a single method, get_node_data, called at the
  start of an autoscaling update.
  
  Batches modifications to cluster state into a single method, submit_scale_request,
  called at the end of an autoscaling update.
  
  Implementing a concrete subclass of BatchingNodeProvider only requires overriding
  get_node_data() and submit_scale_request().
  
  See the method docstrings for more information.
  
  Note that an autoscaling update may be conditionally
  cancelled using the optional method safe_to_scale()
  of the root NodeProvider.
docstr: Queries cluster manager for node info. Returns a mapping from node id to
  NodeData.
  
  Each NodeData value must adhere to the semantics of the NodeData docstring.
  (Note in particular the requirements for NodeData.status.)
  
  Consistency requirement:
  If a node id was present in ScaleRequest.workers_to_delete of a previously
  submitted scale request, it should no longer be present as a key in
  get_node_data.
  (Node termination must be registered immediately when submit_scale_request
  returns.)
docstr_tok: ["Queries","cluster","manager","for","node","info",".","Returns","a","mapping","from","node","id","to","NodeData",".","Each","NodeData","value","must","adhere","to","the","semantics","of","the","NodeData","docstring",".","(","Note","in","particular","the","requirements","for","NodeData.status",".",")","Consistency","requirement",":","If","a","node","id","was","present","in","ScaleRequest.workers_to_delete","of","a","previously","submitted","scale","request",",","it","should","no","longer","be","present","as","a","key","in","get_node_data",".","(","Node","termination","must","be","registered","immediately","when","submit_scale_request","returns",".",")"]
code: def get_node_data(self) -> Dict[NodeID, NodeData]:
      """Queries cluster manager for node info. Returns a mapping from node id to
      NodeData.
  
      Each NodeData value must adhere to the semantics of the NodeData docstring.
      (Note in particular the requirements for NodeData.status.)
  
      Consistency requirement:
      If a node id was present in ScaleRequest.workers_to_delete of a previously
      submitted scale request, it should no longer be present as a key in
      get_node_data.
      (Node termination must be registered immediately when submit_scale_request
      returns.)
      """
      raise NotImplementedError
  
imports: import logging
  from collections import defaultdict
  from dataclasses import dataclass, field
  from typing import Any, Dict, List, Optional, Set
  from ray.autoscaler._private.constants import DISABLE_LAUNCH_CONFIG_CHECK_KEY, DISABLE_NODE_UPDATERS_KEY, FOREGROUND_NODE_LAUNCH_KEY
  from ray.autoscaler._private.util import NodeID, NodeIP, NodeKind, NodeStatus, NodeType
  from ray.autoscaler.node_provider import NodeProvider
  from ray.autoscaler.tags import NODE_KIND_HEAD, TAG_RAY_NODE_KIND, TAG_RAY_NODE_STATUS, TAG_RAY_USER_NODE_TYPE
label_desc: Use image node_id 2 for calling the BatchingNodeProvider obj's underlying member method code with example usage: obj.get_node_data() without return types