docstr: Generates primitives_with_limited_support.md.
  
  See the doc for instructions.
docstr_tok: ["Generates","primitives_with_limited_support.md",".","See","the","doc","for","instructions","."]
code: def test_generate_limitations_doc(self):
      """Generates primitives_with_limited_support.md.
  
      See the doc for instructions.
      """
  
      harnesses = [
          h
          for h in test_harnesses.all_harnesses
          if h.filter(h, include_jax_unimpl=True)
      ]
      print(f"Found {len(harnesses)} test harnesses that work in JAX")
  
      def unique_hash(h: test_harnesses.Harness, l: Jax2TfLimitation):
          return (
              h.group_name,
              l.description,
              l.devices,
              tuple(np.dtype(d).name for d in l.dtypes),
              l.modes,
          )
  
      unique_limitations: dict[
          Any, tuple[test_harnesses.Harness, Jax2TfLimitation]
      ] = {}
      for h in harnesses:
          for l in h.jax_unimplemented:
              if l.enabled:
                  # Fake a Jax2TFLimitation from the Limitation
                  tfl = Jax2TfLimitation(
                      description="Not implemented in JAX: "
                      + l.description,
                      devices=l.devices,
                      dtypes=l.dtypes,
                      expect_tf_error=False,
                      skip_tf_run=True,
                  )
                  unique_limitations[hash(unique_hash(h, tfl))] = (
                      h,
                      tfl,
                  )
      for h in harnesses:
          for l in Jax2TfLimitation.limitations_for_harness(h):
              unique_limitations[hash(unique_hash(h, l))] = (h, l)
  
      print(f"Found {len(unique_limitations)} unique limitations")
      tf_error_table = [
          """
  | Affected primitive | Description of limitation | Affected dtypes | Affected devices | Affected compilation modes |
  | --- | --- | --- | --- | --- |"""
      ]
      tf_numerical_discrepancies_table = list(tf_error_table)  # a copy
      for h, l in sorted(
          unique_limitations.values(),
          key=lambda pair: unique_hash(*pair),
      ):
          devices = ", ".join(sorted(l.devices))
          modes = ", ".join(sorted(l.modes))
          description = l.description
          if l.skip_comparison:
              description = (
                  "Numeric comparison disabled: " + description
              )
          if l.expect_tf_error:
              description = "TF error: " + description
          if l.skip_tf_run:
              description = "TF test skipped: " + description
  
          if l.skip_tf_run or l.expect_tf_error:
              to_table = tf_error_table
          elif l.skip_comparison or l.custom_assert:
              to_table = tf_numerical_discrepancies_table
          else:
              continue
  
          to_table.append(
              f"| {h.group_name} | {description} | "
              f"{test_harnesses.dtypes_to_str(l.dtypes, empty_means_all=True)} | {devices} | {modes} |"
          )
  
      if not os.environ.get("JAX_OUTPUT_LIMITATIONS_DOC"):
          raise unittest.SkipTest(
              "Set JAX_OUTPUT_LIMITATIONS_DOC=1 to enable the generation of the documentation"
          )
      # The CPU has more supported types, and harnesses
      self.assertEqual("cpu", jtu.device_under_test())
      self.assertTrue(
          config.enable_x64.value,
          "Documentation generation must be run with JAX_ENABLE_X64=1",
      )
  
      with open(
          os.path.join(
              os.path.dirname(__file__),
              "../g3doc/primitives_with_limited_support.md.template",
          )
      ) as f:
          template = f.read()
      output_file = os.path.join(
          os.path.dirname(__file__),
          "../g3doc/primitives_with_limited_support.md",
      )
  
      with open(output_file, "w") as f:
          f.write(
              template.replace(
                  "{{generation_date}}", str(datetime.date.today())
              )
              .replace("{{tf_error_table}}", "\n".join(tf_error_table))
              .replace(
                  "{{tf_numerical_discrepancies_table}}",
                  "\n".join(tf_numerical_discrepancies_table),
              )
          )
  
imports: import datetime
  import os
  from typing import Any
  import unittest
  from absl import logging
  from absl.testing import absltest
  from absl.testing import parameterized
  import jax
  from jax import dtypes
  from jax import numpy
  from jax._src import config
  from jax._src import test_util
  from jax.experimental import jax2tf
  from jax.interpreters import mlir
  from jax._src.interpreters import xla
  import numpy
  import tensorflow
  from jax.experimental.jax2tf.tests import tf_test_util
  from jax.experimental.jax2tf.tests.jax2tf_limitations import Jax2TfLimitation
  from jax._src.internal_test_util import test_harnesses
label_desc: Use image node_id 3 for calling the JaxPrimitiveTest obj's underlying member method code with example usage: obj.test_generate_limitations_doc() and returns: h,  l,  l,  tuple,  l