class_docstr: A base class that specifies the shape and dtype of a tensor.
  
  Args:
      shape: A string representing einops notation of the shape of the tensor.
          For example, "B, C" represents a tensor with two dimensions, the first
          of which has size B and the second of which has size C. shape must
          consist of unique dimension names. For example having "B B" is invalid.
      dtype: The dtype of the tensor. If None, the dtype is not checked during
          validation. Also during Sampling the dtype is set the default dtype of
          the backend.
      framework: The framework of the tensor. If None, the framework is not
          checked during validation.
      shape_vals: An optional dictionary mapping some dimension names to their
          values. For example, if shape is "B, C" and shape_vals is {"C": 3}, then
          the shape of the tensor is (B, 3). B is to be determined during
          run-time but C is fixed to 3.
  
  .. testcode::
      :skipif: True
  
      spec = TensorSpec("b, d", d=128, dtype=tf.float32)
      spec.shape  # ('b', 128)
      spec.validate(torch.rand(32, 128, dtype=torch.float32))  # passes
      spec.validate(torch.rand(32, 64, dtype=torch.float32))   # raises ValueError
      spec.validate(torch.rand(32, 128, dtype=torch.float64))  # raises ValueError
  
  Public Methods:
      validate: Checks if the shape and dtype of the tensor matches the
          specification.
      fill: creates a tensor with the specified value that is an
          example of a tensor that matches the specification. This can only be
          called if `framework` is specified.
docstr: Creates a tensor filled with `fill_value` that matches the specs.
  
  Args:
      fill_value: The value to fill the tensor with.
  
  Returns:
      A tensor with the specified value that matches the specs.
  
  Raises:
      ValueError: If `framework` is not specified.
code: def fill(self, fill_value: Union[float, int] = 0) -> TensorType:
      """Creates a tensor filled with `fill_value` that matches the specs.
  
      Args:
          fill_value: The value to fill the tensor with.
  
      Returns:
          A tensor with the specified value that matches the specs.
  
      Raises:
          ValueError: If `framework` is not specified.
      """
  
      if self._framework == "torch":
          return torch.full(
              self.full_shape, fill_value, dtype=self.dtype
          )
  
      elif self._framework == "tf2":
          if self.dtype:
              return (
                  tf.ones(self.full_shape, dtype=self.dtype)
                  * fill_value
              )
          return tf.fill(self.full_shape, fill_value)
  
      elif self._framework == "np":
          return np.full(self.full_shape, fill_value, dtype=self.dtype)
  
      elif self._framework == "jax":
          return jax.numpy.full(
              self.full_shape, fill_value, dtype=self.dtype
          )
  
      elif self._framework is None:
          raise ValueError(
              "Cannot fill tensor without providing `framework` to TensorSpec. "
              "This TensorSpec was instantiated without `framework`."
          )
  
imports: import abc
  from copy import deepcopy
  import numpy
  from typing import Any, Optional, Dict, List, Tuple, Union, Type
  from ray.rllib.utils import try_import_jax, try_import_tf, try_import_torch
  from ray.rllib.utils.annotations import OverrideToImplementCustomLogic
  from ray.rllib.utils.annotations import DeveloperAPI, override
  from ray.rllib.utils.typing import TensorType
label_desc: Use image node_id 12 for calling the TensorSpec obj's underlying member method code with example usage: obj.fill(fill_value) and returns: torch, tf, unknown, np, jax