parameters: (app, exception)
docstring: Compare backed up frozen RST files from ``backup_frozen()`` with 
      newly frozen RST. If they don't match within accepted tolerances, 
      raise an exception to fail the current CI job. This implies that 
      the OCIO API changed without building with CMake option 
      ``-DOCIO_BUILD_FROZEN_DOCS=ON``; needed to update frozen RST in the 
      source tree.
docstring_summary: Compare backed up frozen RST files from ``backup_frozen()`` with 
      newly frozen RST. If they don't match within accepted tolerances, 
      raise an exception to fail the current CI job. This implies that 
      the OCIO API changed without building with CMake option 
      ``-DOCIO_BUILD_FROZEN_DOCS=ON``; needed to update frozen RST in the 
      source tree.
docstring_tokens: Compare backed up frozen RST files from backup_frozen () with newly frozen RST . If they don t match within accepted tolerances raise an exception to fail the current CI job . This implies that the OCIO API changed without building with CMake option - DOCIO_BUILD_FROZEN_DOCS = ON ; needed to update frozen RST in the source tree .
function: def compare_frozen(app, exception):
      """
      Compare backed up frozen RST files from ``backup_frozen()`` with 
      newly frozen RST. If they don't match within accepted tolerances, 
      raise an exception to fail the current CI job. This implies that 
      the OCIO API changed without building with CMake option 
      ``-DOCIO_BUILD_FROZEN_DOCS=ON``; needed to update frozen RST in the 
      source tree.
      """
      # Raise Sphinx exceptions for debugging
      if exception:
          raise ExtensionError(str(exception))
  
      if not app.config.frozendoc_compare:
          return
  
      logger.info("Comparing frozen RST: {src} <-> {dst}\n".format(
          src=PYTHON_FROZEN_DIR, 
          dst=PYTHON_BACKUP_DIR
      ))
  
      frozen_files = set(os.listdir(PYTHON_FROZEN_DIR))
      backup_files = set(os.listdir(PYTHON_BACKUP_DIR))
  
      # Find any files which are different, or only present in one of the two 
      # directories.
      match, mismatch, errors = filecmp.cmpfiles(
          PYTHON_FROZEN_DIR, 
          PYTHON_BACKUP_DIR,
          list(frozen_files | backup_files),
          shallow=False
      )
  
      # Different OSs or compilers may result in slightly different signatures
      # or types. Test each mismatched file for the ratio of how different 
      # their contents are. If they have a difference ratio at or above 0.6 (the 
      # recommended ratio to determine close matches), assume the differences are
      # ok. This is certainly not a water tight assumption, but deemed (at the 
      # moment) preferrable to failing on every mior difference. Keep track of 
      # these ignored differences and report them for transparency in CI logs.
      ignored = []
  
      for i in reversed(range(len(mismatch))):
          filename = mismatch[i]
          logger.info("Difference found in: {}".format(filename))
  
          frozen_path = os.path.join(PYTHON_FROZEN_DIR, filename)
          with open(frozen_path, "r") as frozen_file:
              frozen_data = frozen_file.read()
  
          backup_path = os.path.join(PYTHON_BACKUP_DIR, filename)
          with open(backup_path, "r") as backup_file:
              backup_data = backup_file.read()
  
          for line in difflib.unified_diff(
              frozen_data.splitlines(), 
              backup_data.splitlines(), 
              fromfile=frozen_path, 
              tofile=backup_path
          ):
              logger.info(line)
  
          # Based on difflib's caution of argument order playing a role in the 
          # results of ratio(), check the ratio in both directions and use the
          # better of the two as our heuristic.
          match_ab = difflib.SequenceMatcher(None, frozen_data, backup_data)
          match_ba = difflib.SequenceMatcher(None, backup_data, frozen_data)
          max_ratio = max(match_ab.ratio(), match_ba.ratio())
  
          if max_ratio >= 0.6:
              ignored.append(mismatch.pop(i))
              logger.info(
                  "Difference ratio {} is within error tolerances\n".format(
                      max_ratio
                  )
              )
          else:
              logger.error(
                  "Difference ratio {} exceeds error tolerances\n".format(
                      max_ratio
                  )
              )
  
      if os.path.exists(PYTHON_BACKUP_DIR):
          shutil.rmtree(PYTHON_BACKUP_DIR)
  
      if mismatch or errors:
          raise ExtensionError(
              "Frozen RST is out of date! Build OpenColorIO with CMake option "
              "'-DOCIO_BUILD_FROZEN_DOCS=ON' to update required frozen "
              "documentation source files in: {dir}\n\n"
              "    Changed files: {changed}\n\n"
              "      Added files: {added}\n\n"
              "    Removed files: {removed}\n\n"
              "See log for changed file differences.\n".format(
                  dir=PYTHON_FROZEN_DIR,
                  changed=", ".join(mismatch),
                  added=", ".join(f for f in errors if f in frozen_files),
                  removed=", ".join(f for f in errors if f in backup_files),
              )
          )
  
      # Report ignored differences
      if ignored:
          logger.warning(
              "Some differences were found and ignored when comparing frozen "
              "RST to current documentation source in: {dir}\n\n"
              "    Changed files: {changed}\n\n"
              "See log for changed file differences.\n".format(
                  dir=PYTHON_FROZEN_DIR,
                  changed=", ".join(ignored),
              )
          )
  
      logger.info("Frozen RST matches within error tolerances.")
function_tokens: def compare_frozen ( app , exception ) : # Raise Sphinx exceptions for debugging if exception : raise ExtensionError ( str ( exception ) ) if not app . config . frozendoc_compare : return logger . info ( "Comparing frozen RST: {src} <-> {dst}\n" . format ( src = PYTHON_FROZEN_DIR , dst = PYTHON_BACKUP_DIR ) ) frozen_files = set ( os . listdir ( PYTHON_FROZEN_DIR ) ) backup_files = set ( os . listdir ( PYTHON_BACKUP_DIR ) ) # Find any files which are different, or only present in one of the two  # directories. match , mismatch , errors = filecmp . cmpfiles ( PYTHON_FROZEN_DIR , PYTHON_BACKUP_DIR , list ( frozen_files | backup_files ) , shallow = False ) # Different OSs or compilers may result in slightly different signatures # or types. Test each mismatched file for the ratio of how different  # their contents are. If they have a difference ratio at or above 0.6 (the  # recommended ratio to determine close matches), assume the differences are # ok. This is certainly not a water tight assumption, but deemed (at the  # moment) preferrable to failing on every mior difference. Keep track of  # these ignored differences and report them for transparency in CI logs. ignored = [ ] for i in reversed ( range ( len ( mismatch ) ) ) : filename = mismatch [ i ] logger . info ( "Difference found in: {}" . format ( filename ) ) frozen_path = os . path . join ( PYTHON_FROZEN_DIR , filename ) with open ( frozen_path , "r" ) as frozen_file : frozen_data = frozen_file . read ( ) backup_path = os . path . join ( PYTHON_BACKUP_DIR , filename ) with open ( backup_path , "r" ) as backup_file : backup_data = backup_file . read ( ) for line in difflib . unified_diff ( frozen_data . splitlines ( ) , backup_data . splitlines ( ) , fromfile = frozen_path , tofile = backup_path ) : logger . info ( line ) # Based on difflib's caution of argument order playing a role in the  # results of ratio(), check the ratio in both directions and use the # better of the two as our heuristic. match_ab = difflib . SequenceMatcher ( None , frozen_data , backup_data ) match_ba = difflib . SequenceMatcher ( None , backup_data , frozen_data ) max_ratio = max ( match_ab . ratio ( ) , match_ba . ratio ( ) ) if max_ratio >= 0.6 : ignored . append ( mismatch . pop ( i ) ) logger . info ( "Difference ratio {} is within error tolerances\n" . format ( max_ratio ) ) else : logger . error ( "Difference ratio {} exceeds error tolerances\n" . format ( max_ratio ) ) if os . path . exists ( PYTHON_BACKUP_DIR ) : shutil . rmtree ( PYTHON_BACKUP_DIR ) if mismatch or errors : raise ExtensionError ( "Frozen RST is out of date! Build OpenColorIO with CMake option " "'-DOCIO_BUILD_FROZEN_DOCS=ON' to update required frozen " "documentation source files in: {dir}\n\n" "    Changed files: {changed}\n\n" "      Added files: {added}\n\n" "    Removed files: {removed}\n\n" "See log for changed file differences.\n" . format ( dir = PYTHON_FROZEN_DIR , changed = ", " . join ( mismatch ) , added = ", " . join ( f for f in errors if f in frozen_files ) , removed = ", " . join ( f for f in errors if f in backup_files ) , ) ) # Report ignored differences if ignored : logger . warning ( "Some differences were found and ignored when comparing frozen " "RST to current documentation source in: {dir}\n\n" "    Changed files: {changed}\n\n" "See log for changed file differences.\n" . format ( dir = PYTHON_FROZEN_DIR , changed = ", " . join ( ignored ) , ) ) logger . info ( "Frozen RST matches within error tolerances." )