errorlist.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #!/usr/bin/env python3
  2. # this script automatically generates the error list for the docs by
  3. # looking at the "Error" class and its subclasses.
  4. from textwrap import indent
  5. import borg.archiver # noqa: F401 - need import to get Error subclasses.
  6. from borg.constants import * # NOQA
  7. from borg.helpers import Error, BackupError, BorgWarning
  8. def subclasses(cls):
  9. direct_subclasses = cls.__subclasses__()
  10. return set(direct_subclasses) | {s for c in direct_subclasses for s in subclasses(c)}
  11. # 0, 1, 2 are used for success, generic warning, generic error
  12. # 3..99 are available for specific errors
  13. # 100..127 are available for specific warnings
  14. # 128+ are reserved for signals
  15. free_error_rcs = set(range(EXIT_ERROR_BASE, EXIT_WARNING_BASE)) # 3 .. 99
  16. free_warning_rcs = set(range(EXIT_WARNING_BASE, EXIT_SIGNAL_BASE)) # 100 .. 127
  17. # these classes map to rc 2
  18. generic_error_rc_classes = set()
  19. generic_warning_rc_classes = set()
  20. error_classes = {Error} | subclasses(Error)
  21. for cls in sorted(error_classes, key=lambda cls: (cls.__module__, cls.__qualname__)):
  22. traceback = "yes" if cls.traceback else "no"
  23. rc = cls.exit_mcode
  24. print(" ", cls.__qualname__, "rc:", rc, "traceback:", traceback)
  25. print(indent(cls.__doc__, " " * 8))
  26. if rc in free_error_rcs:
  27. free_error_rcs.remove(rc)
  28. elif rc == 2:
  29. generic_error_rc_classes.add(cls.__qualname__)
  30. else: # rc != 2
  31. # if we did not intentionally map this to the generic error rc, this might be an issue:
  32. print(f"ERROR: {rc} is not a free/available RC, but either duplicate or invalid")
  33. print()
  34. print("free error RCs:", sorted(free_error_rcs))
  35. print("generic errors:", sorted(generic_error_rc_classes))
  36. warning_classes = {BorgWarning} | subclasses(BorgWarning) | {BackupError} | subclasses(BackupError)
  37. for cls in sorted(warning_classes, key=lambda cls: (cls.__module__, cls.__qualname__)):
  38. rc = cls.exit_mcode
  39. print(" ", cls.__qualname__, "rc:", rc)
  40. print(indent(cls.__doc__, " " * 8))
  41. if rc in free_warning_rcs:
  42. free_warning_rcs.remove(rc)
  43. elif rc == 1:
  44. generic_warning_rc_classes.add(cls.__qualname__)
  45. else: # rc != 1
  46. # if we did not intentionally map this to the generic warning rc, this might be an issue:
  47. print(f"ERROR: {rc} is not a free/available RC, but either duplicate or invalid")
  48. print("\n")
  49. print("free warning RCs:", sorted(free_warning_rcs))
  50. print("generic warnings:", sorted(generic_warning_rc_classes))