from typing import List, Pattern, Dict, Match from typing import Union, Any, Optional, Iterable, TypeVar import re import functools import operator import json import logging logger = logging.getLogger("desktopenv.metric.thunderbird") V = TypeVar("Value") def _match_pref(value: Any, rule: Dict[str, Union[str, Any]]) -> bool: # function _match_pref {{{ # if rule["method"].startswith("re"): flags: List[str] = rule["method"].split(".")[1:] flags: Iterable[re.RegexFlag] = (getattr(re, fl) for fl in flags) flag: re.RegexFlag = functools.reduce(operator.or_, flags, re.RegexFlag(0)) logger.debug("REFLAG: %s", repr(flag)) match_: Optional[Match[str]] = re.search(rule["ref"], value, flag) return match_ is not None if rule["method"] in { "eq", "ne" , "le", "lt" , "ge", "gt" }: return getattr(operator, rule["method"])(value, rule["ref"]) raise NotImplementedError() # }}} function _match_pref # _pref_pattern: Pattern[str] = re.compile(r'^user_pref\("(?P(?:[^"]|\\")+)\", (?P.+)\);$'); def check_thunderbird_prefs(result: str, rule: Dict[str, Dict[str, Dict[str, Any]]]): """ Args: result (str): path to result file rule (Dict[str, Dict[str, Dict[str, Any]]]): dict like { "expect": { str: { "method": str "ref": something } } "unexpect": { str: { "method": str "ref": something } } } Returns: float """ if result is None: return 0. expect_rules = rule.get("expect", {}) unexpect_rules = rule.get("unexpect", {}) expect_metrics = {k: False for k in expect_rules} unexpect_metric = True with open(result) as f: for l in f: match_: Match[str] = _pref_pattern.match(l.strip()) if match_ is None: continue key: str = match_.group("key") #value: str = match_.group("val") #if value in {"true", "false"}: #value = value.title() #value: V = eval(value) value = json.loads(match_.group("val")) if key in expect_rules: logger.debug("K: %s, V: %s", key, repr(value)) expect_metrics[key] = _match_pref(value, expect_rules[key]) elif key in unexpect_rules: unexpect_metric = unexpect_metric and not _match_pref(value, unexpect_rules[key]) return float(all(expect_metrics.values()) and unexpect_metric) if __name__ == "__main__": import lxml.etree from lxml.cssselect import CSSSelector from lxml.etree import _Element #xml = "../../任务数据/Thunderbird/vertical-card-view.xml" xml = "../../任务数据/Thunderbird/vertical-table-view.xml" at: _Element = lxml.etree.parse(xml) #elements: List[_Element] = CSSSelector('application[name=Thunderbird] page-tab-list')(at) # page tab tags #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]')(at) # email tag page #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section:nth-child(3)')(at) # email tag page #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section[attr|id=threadPane]>section[attr|id="threadTree"]>table[attr|class="tree-table"]>section[attr|class~="tree-table-header"]>table-row>column-header[name=Subject]>push-button', namespaces={"attr": "uri:deskat:attributes.at-spi.gnome.org"})(at) # table view, column header elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section[attr|id=threadPane]>section[attr|id="threadTree"]>table[attr|class="tree-table"]>tree>tree-item>section[name="Subject"]>section>section', namespaces={"attr": "uri:deskat:attributes.at-spi.gnome.org"})(at) # table view, column header print(len(elements)) for elm in elements: print(lxml.etree.tostring(elm, encoding="unicode", pretty_print=True))