class FontmakeError(Exception):
    """Base class for all fontmake exceptions."""

    pass


class TTFAError(FontmakeError):
    def __init__(self, exitcode):
        self.exitcode = exitcode

    def __str__(self):
        return "ttfautohint command failed: error " + str(self.exitcode)

import os


class FontmakeError(Exception):
    """Base class for all fontmake exceptions.

    This exception is intended to be chained to the original exception. The
    main purpose is to provide a source file trail that points to where the
    explosion came from.
    """

    def __init__(self, msg, source_file):
        self.msg = msg
        self.source_trail = [source_file]

    def __str__(self):
        trail = " -> ".join(
            f"'{str(os.path.relpath(s))}'"
            for s in reversed(self.source_trail)
            if s is not None
        )
        cause = str(self.__cause__) if self.__cause__ is not None else None

        message = ""
        if trail:
            message = f"In {trail}: "
        message += f"{self.msg}"
        if cause:
            message += f": {cause}"

        return message


class TTFAError(FontmakeError):
    def __init__(self, exitcode, source_file):
        self.exitcode = exitcode
        self.source_trail = source_file

    def __str__(self):
        return (
            f"ttfautohint failed for '{str(os.path.relpath(self.source_trail))}': "
            f"error code {str(self.exitcode)}."
        )

Add source trail logic to FontmakeError and partly TTFAError
Add source trail logic to FontmakeError and partly TTFAError

+ import os
+ 
+ 
  class FontmakeError(Exception):
-     """Base class for all fontmake exceptions."""
+     """Base class for all fontmake exceptions.
  
-     pass
+     This exception is intended to be chained to the original exception. The
+     main purpose is to provide a source file trail that points to where the
+     explosion came from.
+     """
+ 
+     def __init__(self, msg, source_file):
+         self.msg = msg
+         self.source_trail = [source_file]
+ 
+     def __str__(self):
+         trail = " -> ".join(
+             f"'{str(os.path.relpath(s))}'"
+             for s in reversed(self.source_trail)
+             if s is not None
+         )
+         cause = str(self.__cause__) if self.__cause__ is not None else None
+ 
+         message = ""
+         if trail:
+             message = f"In {trail}: "
+         message += f"{self.msg}"
+         if cause:
+             message += f": {cause}"
+ 
+         return message
  
  
  class TTFAError(FontmakeError):
-     def __init__(self, exitcode):
+     def __init__(self, exitcode, source_file):
          self.exitcode = exitcode
+         self.source_trail = source_file
  
      def __str__(self):
-         return "ttfautohint command failed: error " + str(self.exitcode)
+         return (
+             f"ttfautohint failed for '{str(os.path.relpath(self.source_trail))}': "
+             f"error code {str(self.exitcode)}."
+         )
  
Add source trail logic to FontmakeError and partly TTFAError
## Code Before:
class FontmakeError(Exception):
    """Base class for all fontmake exceptions."""

    pass


class TTFAError(FontmakeError):
    def __init__(self, exitcode):
        self.exitcode = exitcode

    def __str__(self):
        return "ttfautohint command failed: error " + str(self.exitcode)

## Instruction:
Add source trail logic to FontmakeError and partly TTFAError
## Code After:
import os


class FontmakeError(Exception):
    """Base class for all fontmake exceptions.

    This exception is intended to be chained to the original exception. The
    main purpose is to provide a source file trail that points to where the
    explosion came from.
    """

    def __init__(self, msg, source_file):
        self.msg = msg
        self.source_trail = [source_file]

    def __str__(self):
        trail = " -> ".join(
            f"'{str(os.path.relpath(s))}'"
            for s in reversed(self.source_trail)
            if s is not None
        )
        cause = str(self.__cause__) if self.__cause__ is not None else None

        message = ""
        if trail:
            message = f"In {trail}: "
        message += f"{self.msg}"
        if cause:
            message += f": {cause}"

        return message


class TTFAError(FontmakeError):
    def __init__(self, exitcode, source_file):
        self.exitcode = exitcode
        self.source_trail = source_file

    def __str__(self):
        return (
            f"ttfautohint failed for '{str(os.path.relpath(self.source_trail))}': "
            f"error code {str(self.exitcode)}."
        )
