• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) 2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17
18import itertools
19import os
20import re
21import glob
22from typing import *
23
24
25def do_nothing(x: Any) -> Any:
26    return x
27
28
29class BasicTool:
30    @classmethod
31    def find_files_with_pattern(cls, folder: str, pattern: str = "/**", recursive: bool = True, apply_abs: bool = True,
32                                real_path: bool = True, de_duplicate: bool = True, is_sort: bool = True,
33                                post_handler: Callable[[List[str]], List[str]] = None) -> list:
34        """
35        根据指定paatern匹配folder下的所有文件,默认递归地查找所有文件
36        folder:要查找的目录,会先经过cls.abspath处理(结尾不带/)
37        pattern:要查找的模式,需要以/开头,因为会和folder拼接
38        recursive:是否递归查找
39        apply_abs:是否将路径转换为绝对路径
40        real_path:如果是软链接,是否转换为真正的路径
41        de_duplicate:是否去重
42        is_sort:是否排序
43        post_handler: 对文件进行额外处理的方法,参数为文件名的List,返回值为字符串列表
44        FIXME 有可能会卡住,可能原因为符号链接
45        """
46        file_list = glob.glob(cls.abspath(folder)+pattern, recursive=recursive)
47        if apply_abs:
48            file_list = list(map(lambda x: cls.abspath(x), file_list))
49        if real_path:
50            file_list = list(map(lambda x: os.path.realpath(x), file_list))
51        if de_duplicate:
52            file_list = list(set(file_list))
53        if is_sort:
54            file_list = sorted(file_list, key=str.lower)
55        if post_handler:
56            file_list = post_handler(file_list)
57        if folder in file_list:
58            file_list.remove(folder)
59        return file_list
60
61    @classmethod
62    def match_paragraph(cls, content: str, start_pattern: str = r"\w+\(\".*?\"\) *{", end_pattern: str = "\}") -> \
63            Iterator[re.Match]:
64        """
65        匹配代码段,支持单行
66        注意:ptrn中已经包含前面的空格,所以start_pattern中可以省略
67        :param content: 被匹配的字符串
68        :param start_pattern: 模式的开头
69        :param end_pattern: 模式的结尾
70        :return: 匹配到的段落的迭代器
71        """
72        ptrn = r'^( *){s}(?#匹配开头).*?(?#中间非贪婪)\1(?#如果开头前面有空格,则结尾的前面应该有相同数量的空格)?{e}$(?#匹配结尾)'.format(
73            s=start_pattern, e=end_pattern)
74        ptrn = re.compile(ptrn, re.M | re.S)
75        result = re.finditer(ptrn, content)
76        return result
77
78    @classmethod
79    def re_group_1(cls, content: str, pattern: str, **kwargs) -> str:
80        """
81        匹配正则表达式,如果有匹配到内容,返回group(1)的内容
82        :param content: 要被匹配的内容
83        :param pattern: 进行匹配的模式
84        :return: 匹配到的结果(group(1))
85        TODO 对()的检查应该更严格
86        """
87        if not (r'(' in pattern and r')' in pattern):
88            raise ValueError("parentheses'()' must in the pattern")
89        result = re.search(pattern, content, **kwargs)
90        if result:
91            return result.group(1)
92        return str()
93
94    @classmethod
95    def abspath(cls, path: str) -> str:
96        """
97        将路径转换为绝对路径,如果有~,展开
98        :param path: 要被转换的路径
99        :return: 绝对路径
100        """
101        return os.path.abspath(os.path.expanduser(path))
102
103    @classmethod
104    def grep_ern(cls, pattern: str, path: str, include: str = str(), exclude: tuple = tuple(),
105                 post_handler: Callable[[Text], Any] = do_nothing) -> Any:
106        """
107        执行grep命令来查找内容
108        :param exclude: 不搜索path下的的exclude目录
109        :param include: 指定要搜索的文件
110        :param pattern: 使用pattern进行grep
111        :param path: 搜索路径
112        :param post_handler: 对grep的结果进行后处理
113        :return: post_handler对grep结果进行处理后的结果
114        TODO 将cls.execute用subprocess代替
115        """
116        cmd = f"grep -Ern '{pattern}' '{cls.abspath(path)}'"
117        # E:启用正则表达式  r:递归搜索  n:显示行号
118        if include:
119            cmd += f" --include='{include}'"
120        for e in exclude:
121            cmd += f" --exclude-dir='{e}'"
122        o = cls.execute(cmd)
123        if post_handler:
124            o = post_handler(o)
125        return o
126
127    @classmethod
128    def execute(cls, cmd: str, post_processor: Callable[[Text], Text] = do_nothing) -> Any:
129        """
130        封装popen,返回标准输出的列表
131        :param post_processor: 对执行结果进行处理
132        :param cmd: 待执行的命令
133        :return: 经处理过后的字符串列表
134
135        """
136        output = os.popen(cmd).read()
137        output = post_processor(output)
138        return output
139
140
141if __name__ == '__main__':
142    res = BasicTool.grep_ern("^( *)ohos_prebuilt_shared_library", "/home/aodongbiao/oh", include="BUILD.gn", exclude=("/home/aodongbiao/oh/out","doc", ".ccache"), post_handler=lambda x: x.split('\n'))
143    # print(res)
144    for i in res:
145        if "oh/out" in i:
146            print(i)
147