terminal.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from argparse import ArgumentParser
  2. from os import getcwd
  3. from os import path
  4. from pathlib import Path
  5. from typing import List
  6. import yaml
  7. from printerlinter import factory
  8. from printerlinter.diagnostic import Diagnostic
  9. from printerlinter.formatters.def_json_formatter import DefJsonFormatter
  10. from printerlinter.formatters.inst_cfg_formatter import InstCfgFormatter
  11. def main() -> None:
  12. parser = ArgumentParser(
  13. description="UltiMaker Cura printer linting, static analysis and formatting of Cura printer definitions and other resources")
  14. parser.add_argument("--setting", required=False, type=Path, help="Path to the `.printer-linter` setting file")
  15. parser.add_argument("--report", required=False, type=Path, help="Path where the diagnostic report should be stored")
  16. parser.add_argument("--format", action="store_true", help="Format the files")
  17. parser.add_argument("--diagnose", action="store_true", help="Diagnose the files")
  18. parser.add_argument("--deleted", action="store_true", help="Check for deleted files")
  19. parser.add_argument("--fix", action="store_true", help="Attempt to apply the suggested fixes on the files")
  20. parser.add_argument("Files", metavar="F", type=Path, nargs="+", help="Files or directories to format")
  21. args = parser.parse_args()
  22. files = extractFilePaths(args.Files)
  23. setting_path = args.setting
  24. to_format = args.format
  25. to_fix = args.fix
  26. to_diagnose = args.diagnose
  27. report = args.report
  28. if not setting_path:
  29. setting_path = Path(getcwd(), ".printer-linter")
  30. if not setting_path.exists():
  31. print(f"Can't find the settings: {setting_path}")
  32. return
  33. with open(setting_path, "r") as f:
  34. settings = yaml.load(f, yaml.FullLoader)
  35. full_body_check = {"Diagnostics": []}
  36. comments_check = {"Error Files": []}
  37. for file in files:
  38. if not path.exists(file):
  39. print(f"Can't find the file: {file}")
  40. return
  41. if args.deleted:
  42. for file in args.Files:
  43. if file not in files:
  44. deletedFiles = diagnoseIssuesWithFile(file, settings)
  45. comments_check["Error Files"].extend([d.toDict() for d in deletedFiles])
  46. results = yaml.dump(comments_check, default_flow_style=False, indent=4, width=240)
  47. if report:
  48. report.write_text(results)
  49. else:
  50. print(results)
  51. if to_fix or to_diagnose:
  52. for file in files:
  53. diagnostics = diagnoseIssuesWithFile(file, settings)
  54. full_body_check["Diagnostics"].extend([d.toDict() for d in diagnostics])
  55. results = yaml.dump(full_body_check, default_flow_style=False, indent=4, width=240)
  56. if report:
  57. report.write_text(results)
  58. else:
  59. print(results)
  60. if to_fix:
  61. for file in files:
  62. if f"{file.as_posix()}" in full_body_check:
  63. applyFixesToFile(file, settings, full_body_check)
  64. if to_format:
  65. for file in files:
  66. applyFormattingToFile(file, settings)
  67. def diagnoseIssuesWithFile(file: Path, settings: dict) -> List[Diagnostic]:
  68. """ For file, runs all diagnostic checks in settings and returns a list of diagnostics """
  69. linters = factory.getLinter(file, settings)
  70. if not linters:
  71. return []
  72. linter_results = []
  73. for linter in linters:
  74. linter_results.extend(list(filter(lambda d: d is not None, linter.check())))
  75. return linter_results
  76. def applyFixesToFile(file, settings, full_body_check) -> None:
  77. if not file.exists():
  78. return
  79. ext = ".".join(file.name.split(".")[-2:])
  80. if ext == "def.json":
  81. issues = full_body_check[f"{file.as_posix()}"]
  82. for issue in issues:
  83. if issue["diagnostic"] == "diagnostic-definition-redundant-override" and settings["fixes"].get(
  84. "diagnostic-definition-redundant-override", True):
  85. pass
  86. def applyFormattingToFile(file: Path, settings) -> None:
  87. if not file.exists():
  88. return
  89. ext = ".".join(file.name.split(".")[-2:])
  90. if ext == "def.json":
  91. formatter = DefJsonFormatter(settings)
  92. formatter.formatFile(file)
  93. if ext == "inst.cfg":
  94. formatter = InstCfgFormatter(settings)
  95. formatter.formatFile(file)
  96. def extractFilePaths(paths: List[Path]) -> List[Path]:
  97. """ Takes list of files and directories, returns the files as well as all files within directories as a List """
  98. file_paths = []
  99. for path in paths:
  100. if path.is_dir():
  101. file_paths.extend(path.rglob("**/*"))
  102. if not path.match("*"):
  103. file_paths.append(path)
  104. else:
  105. file_paths.extend(Path(*path.parts[:-1]).glob(path.parts[-1]))
  106. continue
  107. return file_paths
  108. if __name__ == "__main__":
  109. main()