clean_skipfails.py (4482B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import logging 6 import os 7 import sys 8 from pathlib import Path 9 from typing import Optional 10 11 from manifestparser.manifestparser import ManifestParser 12 from manifestparser.toml import alphabetize_toml_str, remove_skip_if 13 from moztest.resolve import TestResolver 14 from tomlkit.toml_document import TOMLDocument 15 16 ERROR = "error" 17 18 19 class CleanSkipfails: 20 def __init__( 21 self, 22 command_context=None, 23 manifest_search_path: str = "", 24 os_name: Optional[str] = None, 25 os_version: Optional[str] = None, 26 processor: Optional[str] = None, 27 ) -> None: 28 self.command_context = command_context 29 if self.command_context is not None: 30 self.topsrcdir = self.command_context.topsrcdir 31 else: 32 self.topsrcdir = Path(__file__).parent.parent 33 self.topsrcdir = os.path.normpath(self.topsrcdir) 34 self.component = "clean-skip-fails" 35 36 self.manifest_search_path = manifest_search_path 37 self.os_name = os_name 38 self.os_version = os_version 39 self.processor = processor 40 41 def error(self, e): 42 if self.command_context is not None: 43 self.command_context.log( 44 logging.ERROR, self.component, {ERROR: str(e)}, "ERROR: {error}" 45 ) 46 else: 47 print(f"ERROR: {e}", file=sys.stderr, flush=True) 48 49 def info(self, e): 50 if self.command_context is not None: 51 self.command_context.log( 52 logging.INFO, self.component, {ERROR: str(e)}, "INFO: {error}" 53 ) 54 else: 55 print(f"INFO: {e}", file=sys.stderr, flush=True) 56 57 def full_path(self, filename: str): 58 """Returns full path for the relative filename""" 59 60 return os.path.join(self.topsrcdir, os.path.normpath(filename.split(":")[-1])) 61 62 def isdir(self, filename: str): 63 """Returns True if filename is a directory""" 64 65 return os.path.isdir(self.full_path(filename)) 66 67 def run(self): 68 if self.os_name is None and self.os_version is None and self.processor is None: 69 self.error("Needs at least --os, --os_version or --processor to be set.") 70 return 71 72 manifest_path_set = self.get_manifest_paths() 73 parser = ManifestParser(use_toml=True, document=True) 74 for manifest_path in manifest_path_set: 75 parser.read(manifest_path) 76 manifest: TOMLDocument = parser.source_documents[ 77 os.path.abspath(manifest_path) 78 ] 79 has_removed_items = remove_skip_if( 80 manifest, self.os_name, self.os_version, self.processor 81 ) 82 manifest_str = alphabetize_toml_str(manifest) 83 if len(manifest_str) > 0: 84 fp = open(manifest_path, "w", encoding="utf-8", newline="\n") 85 fp.write(manifest_str) 86 fp.close() 87 removed_condition: list[str] = [] 88 if self.os_name is not None: 89 removed_condition.append(f"'os == {self.os_name}'") 90 if self.os_version is not None: 91 removed_condition.append(f"'os_version == {self.os_version}'") 92 if self.processor is not None: 93 removed_condition.append(f"'processor == {self.processor}'") 94 if has_removed_items: 95 self.info( 96 f'Removed skip-if conditions for {", ".join(removed_condition)} in manifest: "{manifest_path}"' 97 ) 98 else: 99 self.info( 100 f'Did not find skip-if conditions to remove for {", ".join(removed_condition)} in manifest: "{manifest_path}"' 101 ) 102 103 def get_manifest_paths(self) -> set[str]: 104 resolver = TestResolver.from_environment(cwd=self.manifest_search_path) 105 if self.isdir(self.manifest_search_path): 106 tests = list(resolver.resolve_tests(paths=[self.manifest_search_path])) 107 manifest_paths = set(t["manifest"] for t in tests) 108 else: 109 myPath = Path(".").parent 110 manifest_paths = set([ 111 str(x).replace("\\", "/") 112 for x in myPath.glob(self.manifest_search_path) 113 ]) 114 return manifest_paths