Esempio n. 1
0
def distribute_package(root, version=None, repository=None, *, upload=True):
    """ 发布包的工具函数

    :param root: 项目的根目录,例如 'D:/slns/pyxllib'
        根目录下有对应的 setup.py 等文件
    :param repository: 比如我配置了 [xlpr],就可以传入 'xlpr'
    """
    from pyxllib.file.specialist import File, Dir

    # 1 切换工作目录
    os.chdir(str(root))

    # 2 改版本号
    if version:
        f = File('setup.py', root)
        s = re.sub(r"(version\s*=\s*)(['\"])(.+?)(\2)", fr'\1\g<2>{version}\4', f.read())
        f.write(s)

    # 3 打包
    subprocess.run('python setup.py sdist')

    # 4 上传
    if upload:
        # 上传
        cmd = 'twine upload dist/*'
        if repository:
            cmd += f' -r {repository}'
        subprocess.run(cmd)
        # 删除打包生成的中间文件
        Dir('dist').delete()
        Dir('build').delete()
Esempio n. 2
0
 def browser(_self, opt='html'):
     if opt == 'html':
         data = _self.get_text('html')  # html、xhtml 可以转网页,虽然排版相对来说还是会乱一点
         data = ''.join(data)
         etag = get_etag(data)
         f = File(etag, Dir.TEMP, suffix='.html')
         f.write(data)
         browser(f)
     else:
         raise ValueError
Esempio n. 3
0
    def to_image(_self, outfile, *, scale=1, if_exists=None):
        """ 转成为文件 """
        f = File(outfile)
        suffix = f.suffix.lower()

        if suffix == '.svg':
            content = _self.get_svg_image()
            f.write(content, if_exists=if_exists)
        else:
            im = _self.get_cv_image(scale)
            xlcv.write(im, if_exists=if_exists)
Esempio n. 4
0
    def bcompare(self):
        """ 可以通过subinput设置文件后缀类型 """
        from pyxllib.debug.specialist import bcompare

        suffix = self.cmds.get('subinput', None)
        try:
            f1 = File('left', Dir.TEMP, suffix=suffix)
            f2 = File('right', Dir.TEMP, suffix=suffix)
        except OSError:  # 忽略错误的扩展名
            f1 = File('left', Dir.TEMP)
            f2 = File('right', Dir.TEMP)
        f1.write(suffix)
        f2.write(self.cmds['ClipText'])
        bcompare(f1, f2, wait=False)
Esempio n. 5
0
 def write(self, loc):
     f = File(loc, self.root, suffix='.json')
     imfile = self.imfiles[loc]
     lmdict = LabelmeDict.gen_data(imfile)
     for label, ann in self.data[loc].items():
         a = ann.copy()
         DictTool.isub(a, ['img'])
         shape = LabelmeDict.gen_shape(json.dumps(a, ensure_ascii=False),
                                       a['points'],
                                       a['shape_type'],
                                       group_id=a['group_id'],
                                       flags=a['flags'])
         lmdict['shapes'].append(shape)
     f.write(lmdict, indent=2)
Esempio n. 6
0
 def write(self, relpath, **kwargs):
     """
     :param relpath: 必须是斜杠表示的相对路径 'a/1.txt'、'b/2.json'
     """
     data = self.rp2data[relpath]
     file = File(relpath, self.root)
     if file:  # 如果文件存在,要遵循原有的编码规则
         with open(str(file), 'rb') as f:
             bstr = f.read()
         encoding = get_encoding(bstr)
         kwargs['encoding'] = encoding
         kwargs['if_exists'] = 'replace'
         file.write(data, **kwargs)
     else:  # 否则直接写入
         file.write(data, **kwargs)
Esempio n. 7
0
 def browser(self, opt='pdf'):
     if opt == 'pdf':
         f = self.src_file
         browser(self.src_file)
     elif opt == 'html':
         ls = []
         for i in range(self.page_count):
             page = self.load_page(i)
             ls.append(page.get_text('html'))
         data = '\n'.join(ls)
         etag = get_etag(data)
         f = File(etag, Dir.TEMP, suffix='.html')
         f.write(data)
         browser(f)
     else:
         raise ValueError(f'{opt}')
     return f
Esempio n. 8
0
class PairContent:
    """ 配对文本类,主要用于bc差异比较 """
    def __init__(self, left_file_name=None, right_file_name=None):
        self.left_file = File(
            left_file_name) if left_file_name else left_file_name
        self.right_file = File(
            right_file_name) if right_file_name else right_file_name
        self.left, self.right = [], []

    def add(self, lt, rt=None):
        """ rt不加,默认本轮内容是同lt """
        lt = str(lt)
        self.left.append(lt)
        rt = lt if rt is None else str(rt)
        self.right.append(rt)

    def bcompare(self, **kwargs):
        left, right = '\n'.join(self.left), '\n'.join(self.right)
        if self.left_file is not None:
            left = self.left_file.write(left)
        if self.right_file is not None:
            right = self.right_file.write(right)
        bcompare(left, right, **kwargs)
Esempio n. 9
0
def browser_jsons_kv(fd,
                     files='**/*.json',
                     encoding=None,
                     max_items=10,
                     max_value_length=100):
    """ demo_keyvaluescounter,查看目录下json数据的键值对信息

    :param fd: 目录
    :param files: 匹配的文件格式
    :param encoding: 文件编码
    :param max_items: 项目显示上限,有些数据项目太多了,要精简下
            设为假值则不设上限
    :param max_value_length: 添加的值,进行截断,防止有些值太长
    :return:
    """
    kvc = KeyValuesCounter()
    d = Dir(fd)
    for p in d.select_files(files):
        # print(p)
        data = p.read(encoding=encoding, mode='.json')
        kvc.add(data, max_value_length=max_value_length)
    p = File(r'demo_keyvaluescounter.html', Dir.TEMP)
    p.write(kvc.to_html_table(max_items=max_items), if_exists='replace')
    browser(p.to_str())
Esempio n. 10
0
def modify_file(file, func, *, outfile=None, file_mode=None, debug=0):
    """ 对单个文件就行优化的功能函数

    这样一些底层函数功能可以写成数据级的接口,然后由这个函数负责文件的读写操作,并且支持debug比较前后内容差异

    :param outfile: 默认是对file原地操作,如果使用该参数,则将处理后的内容写入outfile文件
    :param file_mode: 指定文件读取类型格式,例如'.json'是json文件,读取为字典
    :param debug: 这个功能可以对照refine分级轮理解
        无outfile参数时,原地操作
            0,【直接原地操作】关闭调试,直接运行 (根据outfile=None选择原地操作,或者指定生成新文件)
            1,【进行审核】打开BC比较差异,左边原始内容,右边参考内容  (打开前后差异内容对比)
            -1,【先斩后奏】介于完全不调试和全部人工检查之间,特殊的差异比较。左边放原始文件修改后的结果,右边对照原内容。
        有outfile参数时
            0 | False,直接生成目标文件,如果outfile已存在会被覆盖
            1 | True,直接生成目标文件,但是会弹出bc比较前后内容差异 (相同内容不会弹出)
    """
    infile = File(file)
    enc = get_encoding(infile.read(mode='b'))
    data = infile.read(mode=file_mode, encoding=enc)
    origin_content = str(data)
    new_data = func(data)

    isdiff = origin_content != str(new_data)
    if outfile is None:  # 原地操作
        if isdiff:  # 内容不同才会有相关debug功能,否则静默跳过就好
            if debug == 0:
                infile.write(new_data, mode=file_mode)  # 直接处理
            elif debug == 1:
                temp_file = File('refine_content',
                                 Dir.TEMP,
                                 suffix=infile.suffix).write(new_data)
                bcompare(infile, temp_file)  # 使用beyond compare软件打开对比查看
            elif debug == -1:
                temp_file = File('origin_content',
                                 Dir.TEMP,
                                 suffix=infile.suffix)
                infile.copy(temp_file)
                infile.write(new_data, mode=file_mode,
                             encoding=enc)  # 把原文件内容替换了
                bcompare(infile, temp_file)  # 然后显示与旧内容进行对比
            else:
                raise ValueError(f'{debug}')
    else:
        outfile = File(outfile)
        outfile.write(new_data, mode=file_mode, encoding=enc)  # 直接处理
        if debug and isdiff:
            bcompare(infile, outfile)

    return isdiff
Esempio n. 11
0
    def from_content(cls,
                     html_content,
                     title='temphtml',
                     *,
                     encoding=None,
                     number=True,
                     text_catalogue=True):
        """
        :param html_content: 原始网页的完整内容
        :param title: 页面标题,默认会先找head/title,如果没有,则取一个随机名称(TODO 未实装,目前固定名称)
        :param encoding: 保存的几个文件编码,默认是utf8,但windows平台有些特殊场合也可能要存储gbk
        :param number: 是否对每节启用自动编号的css

        算法基本原理:读取原网页,找出所有h标签,并增设a锚点
            另外生成一个导航html文件
            然后再生成一个主文件,让用户通过主文件来浏览页面

        # 读取csdn博客并展示目录 (不过因为这个存在跳级,效果不是那么好)
        >> file = 自动制作网页标题的导航栏(requests.get(r'https://blog.csdn.net/code4101/article/details/83009000').content.decode('utf8'))
        >> browser(str(file))
        http://i2.tiimg.com/582188/64f40d235705de69.png
        """
        from humanfriendly import format_size

        # 1 对原html,设置锚点,生成一个新的文件f2
        cnt = 0

        # 这个refs是可以用py算法生成的,目前是存储在github上引用
        refs = [
            '<html><head>', '<link rel=Stylesheet type="text/css" media=all '
            f'href="https://code4101.github.io/css/navigation{int(number)}.css">',
            '</head><body>'
        ]

        f2 = File(title + '_content', Dir.TEMP, suffix='.html')

        def func(m):
            nonlocal cnt
            cnt += 1
            name, content = m.group('name'), m.group('inner')
            content = BeautifulSoup(content, 'lxml').get_text()
            # 要写<h><a></a></h>,不能写<a><h></h></a>,否则css中设置的计数器重置不会起作用
            refs.append(
                f'<{name}><a href="{f2}#navigation{cnt}" target="showframe">{content}</a></{name}>'
            )
            return f'<a name="navigation{cnt}"/>' + m.group()

        html_content = re.sub(
            r'<(?P<name>h\d+)(?:>|\s.*?>)(?P<body>\s*(?P<inner>.*?)\s*)</\1>',
            func,
            html_content,
            flags=re.DOTALL)
        f2 = f2.write(html_content, encoding=encoding, if_exists='replace')

        # 2 f1除了导航栏,可以多附带一些有用的参考信息
        # 2.1 前文的refs已经存储了超链接的导航

        # 2.2 文本版的目录
        bs = BeautifulSoup(html_content, 'lxml')
        text = bs.get_text()
        if text_catalogue:
            # 目录
            refs.append(f'<br/>【文本版的目录】')
            catalogue = bs.get_catalogue(indent='\t',
                                         start_level=-1,
                                         jump=True,
                                         size=True)
            refs.append(f'<pre>{catalogue}</pre>')
            # 全文长度
            n = strwidth(text)
            refs.append('<br/>【Total Bytes】' + format_size(n))

        # 2.3 文中使用的高频词
        # 英文可以直接按空格切开统计,区分大小写
        text2 = re.sub(grp_chinese_char(), '', text)  # 删除中文,先不做中文的功能~~
        text2 = re.sub(r'[,\.,。\(\)();;??"]', ' ', text2)  # 标点符号按空格处理
        words = Counter(text2.split())
        msg = '\n'.join([(x[0] if x[1] == 1 else f'{x[0]},{x[1]}')
                         for x in words.most_common()])
        msg += f'<br/>共{len(words)}个词汇,用词数{sum(words.values())}。'
        refs.append(f'<br/>【词汇表】<pre>{msg}</pre>')

        # 2.5 收尾,写入f1
        refs.append('</body>\n</html>')
        f1 = File(title + '_catalogue', Dir.TEMP,
                  suffix='.html').write('\n'.join(refs),
                                        encoding=encoding,
                                        if_exists='replace')

        # 3 生成主页 f0
        main_content = f"""<html>
        <frameset cols="20%,80%">
        	<frame src="{f1}">
        	<frame src="{f2}" name="showframe">
        </frameset></html>"""

        f0 = File(title + '_index', Dir.TEMP,
                  suffix='.html').write(main_content,
                                        encoding=encoding,
                                        if_exists='replace')
        return f0
Esempio n. 12
0
 def write(im, file, if_exists='replace'):
     if not isinstance(file, File):
         file = File(file)
     data = cv2.imencode(ext=file.suffix, img=im)[1]
     return file.write(data.tobytes(), if_exists=if_exists)
Esempio n. 13
0
def showdir(c, *, to_html=None, printf=True, width=200):
    """查看类信息
    会罗列出类c的所有成员方法、成员变量,并生成一个html文

    查阅一个对象的成员变量及成员方法
    为了兼容linux输出df时也能对齐,有几个中文域宽处理相关的函数

    :param c: 要处理的对象
    :param to_html:
        win32上默认True,用chrome、explorer打开
        linux上默认False,直接输出到控制台
    :param printf:
        默认是True,会输出到浏览器或控制条
        设为False则不输出
    :param width: 属性列显示值的上限字符数
    """
    # 1 输出类表头
    from humanfriendly import format_size

    res = []
    object_name = func_input_message(2)['argnames'][0]
    if to_html is None:
        to_html = sys.platform == 'win32'
    newline = '<br/>' if to_html else '\n'

    t = f'==== 对象名称:{object_name},类继承关系:{inspect.getmro(type(c))},' \
        + f'内存消耗:{format_size(sys.getsizeof(c), binary=True)}' \
        + f'(递归子类总大小:{format_size(getasizeof(c), binary=True)}) ===='

    if to_html:
        res.append('<p>')
        t = html.escape(t) + '</p>'
    res.append(t + newline)

    # 2 html的样式精调
    def df2str(df):
        if to_html:
            df = df.applymap(str)  # 不转成文本经常有些特殊函数会报错
            df.index += 1  # 编号从1开始
            # pd.options.display.max_colwidth = -1  # 如果临时需要显示完整内容
            t = df.to_html()
            table = BeautifulSoup(t, 'lxml')
            table.thead.tr['bgcolor'] = 'LightSkyBlue'  # 设置表头颜色
            # 根据pycharm的规则,命名应该是成员变量Field,成员方法Member
            ch = 'F' if '成员变量' in table.tr.contents[3].string else 'M'
            table.thead.tr.th.string = f'编号{ch}{len(df)}'
            t = table.prettify()
        else:
            # 直接转文本,遇到中文是会对不齐的,但是showdir主要用途本来就是在浏览器看的,这里就不做调整了
            t = dataframe_str(df)
        return t

    # 3 添加成员变量和成员函数
    # 成员变量
    members = getmembers(c)
    methods = filter(lambda m: not callable(getattr(c, m[0])), members)
    ls = []
    for ele in methods:
        k, v = ele
        if k.endswith(r'________'):  # 这个名称的变量是我代码里的特殊标记,不显示
            continue
        attr = getattr(c, k)
        if isinstance(attr, enum.IntFlag):  # 对re.RegexFlag等枚举类输出整数值
            v = typename(attr) + ',' + str(int(attr)) + ',' + str(v)
        else:
            try:
                text = str(v)
            except:
                text = '取不到str值'

            v = typename(attr) + ',' + shorten(text, width=width)
        ls.append([k, v])
    df = pd.DataFrame.from_records(ls, columns=['成员变量', '描述'])
    res.append(df2str(df) + newline)

    # 成员函数
    methods = filter(lambda m: callable(getattr(c, m[0])), members)
    df = pd.DataFrame.from_records(methods, columns=['成员函数', '描述'])
    res.append(df2str(df) + newline)
    res = newline.join(res)

    # 4 使用chrome.exe浏览或输出到控制台
    #   这里底层可以封装一个chrome函数来调用,但是这个chrome需要依赖太多功能,故这里暂时手动简单调用
    if to_html:
        if isinstance(to_html, str):
            # 如果是字符串,则认为是指定了输出文件的路径
            f = File(to_html, suffix='.html')
        else:
            f = File(object_name, Dir.TEMP, suffix='.html')

        filename = f.write(ensure_gbk(res), if_exists='replace').to_str()
        browser(filename)
    else:  # linux环境直接输出表格
        print(res)

    return res