class_docstr: Base class for creating message passing layers of the form
  
  .. math::
      \mathbf{x}_i^{\prime} = \gamma_{\mathbf{\Theta}} \left( \mathbf{x}_i,
      \square_{j \in \mathcal{N}(i)} \, \phi_{\mathbf{\Theta}}
      \left(\mathbf{x}_i, \mathbf{x}_j,\mathbf{e}_{j,i}\right) \right),
  
  where :math:`\square` denotes a differentiable, permutation invariant
  function, *e.g.*, sum, mean or max, and :math:`\gamma_{\mathbf{\Theta}}`
  and :math:`\phi_{\mathbf{\Theta}}` denote differentiable functions such as
  MLPs.
  See `here <https://pytorch-geometric.readthedocs.io/en/latest/notes/
  create_gnn.html>`__ for the accompanying tutorial.
  
  Args:
      aggr (string, optional): The aggregation scheme to use
          (:obj:`"add"`, :obj:`"mean"`, :obj:`"max"` or :obj:`None`).
          (default: :obj:`"add"`)
      flow (string, optional): The flow direction of message passing
          (:obj:`"source_to_target"` or :obj:`"target_to_source"`).
          (default: :obj:`"source_to_target"`)
      node_dim (int, optional): The axis along which to propagate.
          (default: :obj:`-2`)
docstr: Fuses computations of :func:`message` and :func:`aggregate` into a
  single function.
  If applicable, this saves both time and memory since messages do not
  explicitly need to be materialized.
  This function will only gets called in case it is implemented and
  propagation takes place based on a :obj:`torch_sparse.SparseTensor`.
docstr_tok: ["Fuses","computations","of",":","func",":","`","message","`","and",":","func",":","`","aggregate","`","into","a","single","function",".","If","applicable",",","this","saves","both","time","and","memory","since","messages","do","not","explicitly","need","to","be","materialized",".","This","function","will","only","gets","called","in","case","it","is","implemented","and","propagation","takes","place","based","on","a",":","obj",":","`","torch_sparse.SparseTensor","`","."]
code: def message_and_aggregate(self, adj_t: SparseTensor) -> Tensor:
      r"""Fuses computations of :func:`message` and :func:`aggregate` into a
      single function.
      If applicable, this saves both time and memory since messages do not
      explicitly need to be materialized.
      This function will only gets called in case it is implemented and
      propagation takes place based on a :obj:`torch_sparse.SparseTensor`.
      """
      raise NotImplementedError
  
imports: import os
  import re
  import inspect
  import os.path
  from uuid import uuid1
  from itertools import chain
  from inspect import Parameter
  from typing import List, Optional, Set
  from torch_geometric.typing import Adj, Size
  import torch
  from torch import Tensor
  from jinja2 import Template
  from torch_sparse import SparseTensor
  from torch_scatter import gather_csr, scatter, segment_csr
  from .utils.helpers import expand_left
  from .utils.jit import class_from_module_repr
  from .utils.typing import sanitize, split_types_repr, parse_types, resolve_types
  from .utils.inspector import Inspector, func_header_repr, func_body_repr
label_desc: Use image node_id 9 for calling the MessagePassing obj's underlying member method code with example usage: obj.message_and_aggregate(adj_t) without return types