pyxllib 0.0.43__py3-none-any.whl → 0.3.197__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. pyxllib/__init__.py +9 -2
  2. pyxllib/algo/__init__.py +8 -0
  3. pyxllib/algo/disjoint.py +54 -0
  4. pyxllib/algo/geo.py +541 -0
  5. pyxllib/{util/mathlib.py → algo/intervals.py} +172 -36
  6. pyxllib/algo/matcher.py +389 -0
  7. pyxllib/algo/newbie.py +166 -0
  8. pyxllib/algo/pupil.py +629 -0
  9. pyxllib/algo/shapelylib.py +67 -0
  10. pyxllib/algo/specialist.py +241 -0
  11. pyxllib/algo/stat.py +494 -0
  12. pyxllib/algo/treelib.py +149 -0
  13. pyxllib/algo/unitlib.py +66 -0
  14. pyxllib/autogui/__init__.py +5 -0
  15. pyxllib/autogui/activewin.py +246 -0
  16. pyxllib/autogui/all.py +9 -0
  17. pyxllib/autogui/autogui.py +852 -0
  18. pyxllib/autogui/uiautolib.py +362 -0
  19. pyxllib/autogui/virtualkey.py +102 -0
  20. pyxllib/autogui/wechat.py +827 -0
  21. pyxllib/autogui/wechat_msg.py +421 -0
  22. pyxllib/autogui/wxautolib.py +84 -0
  23. pyxllib/cv/__init__.py +1 -11
  24. pyxllib/cv/expert.py +267 -0
  25. pyxllib/cv/{imlib.py → imfile.py} +18 -83
  26. pyxllib/cv/imhash.py +39 -0
  27. pyxllib/cv/pupil.py +9 -0
  28. pyxllib/cv/rgbfmt.py +1525 -0
  29. pyxllib/cv/slidercaptcha.py +137 -0
  30. pyxllib/cv/trackbartools.py +163 -49
  31. pyxllib/cv/xlcvlib.py +1040 -0
  32. pyxllib/cv/xlpillib.py +423 -0
  33. pyxllib/data/__init__.py +0 -0
  34. pyxllib/data/echarts.py +240 -0
  35. pyxllib/data/jsonlib.py +89 -0
  36. pyxllib/{util/oss2_.py → data/oss.py} +11 -9
  37. pyxllib/data/pglib.py +1127 -0
  38. pyxllib/data/sqlite.py +568 -0
  39. pyxllib/{util → data}/sqllib.py +13 -31
  40. pyxllib/ext/JLineViewer.py +505 -0
  41. pyxllib/ext/__init__.py +6 -0
  42. pyxllib/{util → ext}/demolib.py +119 -35
  43. pyxllib/ext/drissionlib.py +277 -0
  44. pyxllib/ext/kq5034lib.py +12 -0
  45. pyxllib/{util/main.py → ext/old.py} +122 -284
  46. pyxllib/ext/qt.py +449 -0
  47. pyxllib/ext/robustprocfile.py +497 -0
  48. pyxllib/ext/seleniumlib.py +76 -0
  49. pyxllib/{util/tklib.py → ext/tk.py} +10 -11
  50. pyxllib/ext/unixlib.py +827 -0
  51. pyxllib/ext/utools.py +351 -0
  52. pyxllib/{util/webhooklib.py → ext/webhook.py} +45 -17
  53. pyxllib/ext/win32lib.py +40 -0
  54. pyxllib/ext/wjxlib.py +88 -0
  55. pyxllib/ext/wpsapi.py +124 -0
  56. pyxllib/ext/xlwork.py +9 -0
  57. pyxllib/ext/yuquelib.py +1105 -0
  58. pyxllib/file/__init__.py +17 -0
  59. pyxllib/file/docxlib.py +761 -0
  60. pyxllib/{util → file}/gitlib.py +40 -27
  61. pyxllib/file/libreoffice.py +165 -0
  62. pyxllib/file/movielib.py +148 -0
  63. pyxllib/file/newbie.py +10 -0
  64. pyxllib/file/onenotelib.py +1469 -0
  65. pyxllib/file/packlib/__init__.py +330 -0
  66. pyxllib/{util → file/packlib}/zipfile.py +598 -195
  67. pyxllib/file/pdflib.py +426 -0
  68. pyxllib/file/pupil.py +185 -0
  69. pyxllib/file/specialist/__init__.py +685 -0
  70. pyxllib/{basic/_5_dirlib.py → file/specialist/dirlib.py} +364 -93
  71. pyxllib/file/specialist/download.py +193 -0
  72. pyxllib/file/specialist/filelib.py +2829 -0
  73. pyxllib/file/xlsxlib.py +3131 -0
  74. pyxllib/file/xlsyncfile.py +341 -0
  75. pyxllib/prog/__init__.py +5 -0
  76. pyxllib/prog/cachetools.py +64 -0
  77. pyxllib/prog/deprecatedlib.py +233 -0
  78. pyxllib/prog/filelock.py +42 -0
  79. pyxllib/prog/ipyexec.py +253 -0
  80. pyxllib/prog/multiprogs.py +940 -0
  81. pyxllib/prog/newbie.py +451 -0
  82. pyxllib/prog/pupil.py +1197 -0
  83. pyxllib/{sitepackages.py → prog/sitepackages.py} +5 -3
  84. pyxllib/prog/specialist/__init__.py +391 -0
  85. pyxllib/prog/specialist/bc.py +203 -0
  86. pyxllib/prog/specialist/browser.py +497 -0
  87. pyxllib/prog/specialist/common.py +347 -0
  88. pyxllib/prog/specialist/datetime.py +199 -0
  89. pyxllib/prog/specialist/tictoc.py +240 -0
  90. pyxllib/prog/specialist/xllog.py +180 -0
  91. pyxllib/prog/xlosenv.py +108 -0
  92. pyxllib/stdlib/__init__.py +17 -0
  93. pyxllib/{util → stdlib}/tablepyxl/__init__.py +1 -3
  94. pyxllib/{util → stdlib}/tablepyxl/style.py +1 -1
  95. pyxllib/{util → stdlib}/tablepyxl/tablepyxl.py +2 -4
  96. pyxllib/text/__init__.py +8 -0
  97. pyxllib/text/ahocorasick.py +39 -0
  98. pyxllib/text/airscript.js +744 -0
  99. pyxllib/text/charclasslib.py +121 -0
  100. pyxllib/text/jiebalib.py +267 -0
  101. pyxllib/text/jinjalib.py +32 -0
  102. pyxllib/text/jsa_ai_prompt.md +271 -0
  103. pyxllib/text/jscode.py +922 -0
  104. pyxllib/text/latex/__init__.py +158 -0
  105. pyxllib/text/levenshtein.py +303 -0
  106. pyxllib/text/nestenv.py +1215 -0
  107. pyxllib/text/newbie.py +300 -0
  108. pyxllib/text/pupil/__init__.py +8 -0
  109. pyxllib/text/pupil/common.py +1121 -0
  110. pyxllib/text/pupil/xlalign.py +326 -0
  111. pyxllib/text/pycode.py +47 -0
  112. pyxllib/text/specialist/__init__.py +8 -0
  113. pyxllib/text/specialist/common.py +112 -0
  114. pyxllib/text/specialist/ptag.py +186 -0
  115. pyxllib/text/spellchecker.py +172 -0
  116. pyxllib/text/templates/echart_base.html +11 -0
  117. pyxllib/text/templates/highlight_code.html +17 -0
  118. pyxllib/text/templates/latex_editor.html +103 -0
  119. pyxllib/text/vbacode.py +17 -0
  120. pyxllib/text/xmllib.py +747 -0
  121. pyxllib/xl.py +39 -0
  122. pyxllib/xlcv.py +17 -0
  123. pyxllib-0.3.197.dist-info/METADATA +48 -0
  124. pyxllib-0.3.197.dist-info/RECORD +126 -0
  125. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info}/WHEEL +4 -5
  126. pyxllib/basic/_1_strlib.py +0 -945
  127. pyxllib/basic/_2_timelib.py +0 -488
  128. pyxllib/basic/_3_pathlib.py +0 -916
  129. pyxllib/basic/_4_loglib.py +0 -419
  130. pyxllib/basic/__init__.py +0 -54
  131. pyxllib/basic/arrow_.py +0 -250
  132. pyxllib/basic/chardet_.py +0 -66
  133. pyxllib/basic/dirlib.py +0 -529
  134. pyxllib/basic/dprint.py +0 -202
  135. pyxllib/basic/extension.py +0 -12
  136. pyxllib/basic/judge.py +0 -31
  137. pyxllib/basic/log.py +0 -204
  138. pyxllib/basic/pathlib_.py +0 -705
  139. pyxllib/basic/pytictoc.py +0 -102
  140. pyxllib/basic/qiniu_.py +0 -61
  141. pyxllib/basic/strlib.py +0 -761
  142. pyxllib/basic/timer.py +0 -132
  143. pyxllib/cv/cv.py +0 -834
  144. pyxllib/cv/cvlib/_1_geo.py +0 -543
  145. pyxllib/cv/cvlib/_2_cvprcs.py +0 -309
  146. pyxllib/cv/cvlib/_2_imgproc.py +0 -594
  147. pyxllib/cv/cvlib/_3_pilprcs.py +0 -80
  148. pyxllib/cv/cvlib/_4_cvimg.py +0 -211
  149. pyxllib/cv/cvlib/__init__.py +0 -10
  150. pyxllib/cv/debugtools.py +0 -82
  151. pyxllib/cv/fitz_.py +0 -300
  152. pyxllib/cv/installer.py +0 -42
  153. pyxllib/debug/_0_installer.py +0 -38
  154. pyxllib/debug/_1_typelib.py +0 -277
  155. pyxllib/debug/_2_chrome.py +0 -198
  156. pyxllib/debug/_3_showdir.py +0 -161
  157. pyxllib/debug/_4_bcompare.py +0 -140
  158. pyxllib/debug/__init__.py +0 -49
  159. pyxllib/debug/bcompare.py +0 -132
  160. pyxllib/debug/chrome.py +0 -198
  161. pyxllib/debug/installer.py +0 -38
  162. pyxllib/debug/showdir.py +0 -158
  163. pyxllib/debug/typelib.py +0 -278
  164. pyxllib/image/__init__.py +0 -12
  165. pyxllib/torch/__init__.py +0 -20
  166. pyxllib/torch/modellib.py +0 -37
  167. pyxllib/torch/trainlib.py +0 -344
  168. pyxllib/util/__init__.py +0 -20
  169. pyxllib/util/aip_.py +0 -141
  170. pyxllib/util/casiadb.py +0 -59
  171. pyxllib/util/excellib.py +0 -495
  172. pyxllib/util/filelib.py +0 -612
  173. pyxllib/util/jsondata.py +0 -27
  174. pyxllib/util/jsondata2.py +0 -92
  175. pyxllib/util/labelmelib.py +0 -139
  176. pyxllib/util/onepy/__init__.py +0 -29
  177. pyxllib/util/onepy/onepy.py +0 -574
  178. pyxllib/util/onepy/onmanager.py +0 -170
  179. pyxllib/util/pyautogui_.py +0 -219
  180. pyxllib/util/textlib.py +0 -1305
  181. pyxllib/util/unorder.py +0 -22
  182. pyxllib/util/xmllib.py +0 -639
  183. pyxllib-0.0.43.dist-info/METADATA +0 -39
  184. pyxllib-0.0.43.dist-info/RECORD +0 -80
  185. pyxllib-0.0.43.dist-info/top_level.txt +0 -1
  186. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info/licenses}/LICENSE +0 -0
@@ -2,10 +2,11 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  # @Author : 陈坤泽
4
4
  # @Email : 877362867@qq.com
5
- # @Data : 2018/07/12 09:32
5
+ # @Date : 2018/07/12 09:32
6
6
 
7
7
 
8
- """
8
+ """ 一系列还未整理的旧代码
9
+
9
10
  任何模块代码的第一个字符串用来写文档注释
10
11
 
11
12
  因为util下的debuglib、textlib、filelib的功能拆分并不是特别精确,所以一般不对外开放接口
@@ -14,45 +15,20 @@
14
15
 
15
16
  import filecmp
16
17
  import shutil
17
- import sys, json
18
+ import sys
18
19
  import textwrap
19
- from os.path import getmtime
20
20
  from os.path import join as pathjoin
21
- from collections import OrderedDict, Counter, defaultdict
21
+ from collections import OrderedDict, Counter
22
+ import base64
23
+ import requests
22
24
 
23
25
  from bs4 import BeautifulSoup
24
26
 
25
- from pyxllib.debug import *
26
- from pyxllib.image import *
27
- from pyxllib.util.filelib import *
28
-
29
-
30
- def ________B_数据结构________():
31
- pass
32
-
33
-
34
- def dict__sub__(d1, d2):
35
- """在d1中删除d2存在Keys的方法"""
36
- d = {}
37
- for k in [k for k in d1 if k not in d2]:
38
- d[k] = d1[k]
39
- return d
40
-
41
27
 
42
28
  def ________C_文本处理________():
43
29
  pass
44
30
 
45
31
 
46
- def read_from_ubuntu(url):
47
- """从paste.ubuntu.com获取数据"""
48
- if isinstance(url, int): # 允许输入一个数字ID来获取网页内容
49
- url = 'https://paste.ubuntu.com/' + str(url) + '/'
50
- r = requests.get(url)
51
- soup = BeautifulSoup(r.text, 'lxml')
52
- content = soup.find_all(name='div', attrs={'class': 'paste'})[2]
53
- return content.get_text()
54
-
55
-
56
32
  def 从部门Confluence获取数据(url):
57
33
  cookies = getattr(从部门Confluence获取数据, 'cookies', None)
58
34
  if cookies: # 如果存储了cookies,尝试使用
@@ -84,107 +60,6 @@ def ReadFromUrl(url):
84
60
  return soup.get_text()
85
61
 
86
62
 
87
- class CWord:
88
- def __init__(self, arg1=None, *, visible=None):
89
- """visible默认为None,代表不对现有窗口显示情况做更改
90
- 如果设为bool值true或false,
91
- """
92
- self.__dict__['app'] = win32.gencache.EnsureDispatch('Word.Application')
93
- if isinstance(visible, bool): self.app.Visible = visible
94
-
95
- if isinstance(arg1, str): # 输入的是一个文件名则打开
96
- file = arg1
97
- self.app.Documents.Open(file) # 打开文件
98
- # self.__dict__ = app.Documents(Path(file).name).__dict__
99
- self.__dict__['doc'] = self.app.Documents(Path(file).name) # 存储到doc成员变量
100
- else: # 如果输入参数不合法,新建一个空word
101
- self.app.Documents.Add()
102
- self.__dict__['doc'] = self.app.ActiveDocument
103
-
104
- def CheckAttr(self):
105
- """ 输出 self.app.Documents 的成员 """
106
- showdir(self.doc)
107
-
108
- def CntPage(self):
109
- """统计word页数"""
110
- return self.doc.ActiveWindow.Panes(1).Pages.Count
111
-
112
- def GetParagraphs(self):
113
- """以 yield 形式获得每个段落文本内容"""
114
- cntPar = self.doc.Paragraphs.Count
115
- for i in range(1, cntPar + 1):
116
- yield str(self.doc.Paragraphs(i))
117
-
118
- def Close(self):
119
- """ 关闭word文件 """
120
- self.doc.Close(False)
121
- # self.app.Quit()
122
-
123
- def __getattr__(self, item):
124
- """ 智能获取成员 """
125
- if item in self.__dict__:
126
- return self.__dict__[item]
127
- elif self.doc:
128
- return getattr(self.doc, item)
129
- else:
130
- return None
131
-
132
- def __setattr__(self, key, value):
133
- """ 智能设置成员 """
134
- if key in self.__dict__:
135
- self.__dict__[key] = value
136
- elif self.doc:
137
- setattr(self.doc, key, value)
138
- else:
139
- pass
140
-
141
- def __str__(self):
142
- """ 获得word文件的全文纯文本 """
143
- return str(self.doc.Content)
144
-
145
-
146
- class CExcel:
147
- def __init__(self, arg1=None, *, visible=None):
148
- """visible默认为None,代表不对现有窗口显示情况做更改
149
- 如果设为bool值true或false,
150
- """
151
- import win32com.client as win32
152
- import win32com
153
-
154
- self.__dict__['app'] = win32.gencache.EnsureDispatch('Excel.Application')
155
- if isinstance(visible, bool): self.app.Visible = visible
156
-
157
- if isinstance(arg1, str): # 输入的是一个文件名则打开
158
- file = arg1
159
- self.app.Workbooks.Open(file) # 打开文件
160
- # self.__dict__ = app.Documents(Path(file).name).__dict__
161
- self.__dict__['wb'] = self.app.Workbooks(Path(file).name) # 存储到doc成员变量
162
- else: # 如果输入参数不合法,新建一个空word
163
- # self.app.Workbooks.Add()
164
- # self.__dict__['wb'] = self.app.ActiveWorkbook
165
- self.__dict__['wb'] = self.app.Workbooks.Add()
166
- self.__dict__['st'] = self.wb.ActiveSheet
167
-
168
- def WriteCell(self, row=0, col=0, val='', *, fontColor=None):
169
- """往当前激活的st增加数据
170
-
171
- row可以写0,表示往新的一行加数据
172
- col可以列名,智能进行列查找
173
-
174
- color可以设置颜色
175
- """
176
- # 空表还有bug
177
- if row == 0: row = self.st.UsedRange.Count + 1
178
- dprint(row)
179
- # if col == 0: row = self.st.UsedRange.Count + 1
180
-
181
- self.st.Cells(row, col).Value = str(val)
182
-
183
- def GetVal(self, row, col):
184
- """获得指定单元格的值"""
185
- return self.st.Cells(row, col).Text
186
-
187
-
188
63
  def EnsureContent(ob=None, encoding='utf8'):
189
64
  """
190
65
  未输入ob参数时,自动从控制台获取文本
@@ -209,8 +84,10 @@ def EnsureContent(ob=None, encoding='utf8'):
209
84
  text = textract.process(ob)
210
85
  return text.decode(encoding, errors='ignore')
211
86
  elif ob.endswith('.doc'):
212
- a = CWord(ob)
213
- s = str(a)
87
+ from pyxllib.ex.win32lib import XlWin32WordApplication
88
+ app = XlWin32WordApplication.get_app()
89
+ a = app.open_doc(ob)
90
+ s = a.content
214
91
  a.Close()
215
92
  return s
216
93
  else: # 其他按文本格式处理
@@ -338,8 +215,8 @@ def SetWkDir(wkDir=None, key=None):
338
215
 
339
216
  def SmartCopyFiles(files, inFolder, outFolder):
340
217
  """将files里的文件移到folder目录里,如果folder里已经存在对应文件则自动进行备份"""
341
- inFd = Path(inFolder)
342
- outFd = Path(outFolder)
218
+ inFd = File(inFolder)
219
+ outFd = File(outFolder)
343
220
 
344
221
  for file in files:
345
222
  inFile = inFd / file
@@ -350,9 +227,9 @@ def SmartCopyFiles(files, inFolder, outFolder):
350
227
  if filecmp.cmp(inFile, outFile):
351
228
  continue # 如果两个文件是相同的,不用操作,可以直接处理下一个
352
229
  else:
353
- Path(outFile).backup() # 如果不相同,则对outFile进行备份
230
+ File(outFile).backup() # 如果不相同,则对outFile进行备份
354
231
  shutil.copy2(inFile, outFile)
355
- Path(outFile).backup() # 对拷贝过来的文件也提前做好备份
232
+ File(outFile).backup() # 对拷贝过来的文件也提前做好备份
356
233
 
357
234
 
358
235
  def MyMove(folder1, folder2):
@@ -363,7 +240,7 @@ def MyMove(folder1, folder2):
363
240
  def 多规则字符串筛选(列表, glob筛选=None, *, 正则筛选=None, 指定名筛选=None, 去除备份文件=False):
364
241
  """该函数主要供文件处理使用,其它字符串算法慎用"""
365
242
  if glob筛选:
366
- 列表 = list(filter(lambda x: Path(x).match(glob筛选), 列表))
243
+ 列表 = list(filter(lambda x: File(x).match(glob筛选), 列表))
367
244
 
368
245
  # 只挑选出满足正则条件的文件名(目录名)
369
246
  if 正则筛选:
@@ -373,7 +250,7 @@ def 多规则字符串筛选(列表, glob筛选=None, *, 正则筛选=None, 指
373
250
  列表 = list(filter(lambda x: x in 指定名筛选, 列表))
374
251
 
375
252
  if 去除备份文件:
376
- 列表 = list(filter(lambda x: not Path(x).backup_time, 列表))
253
+ 列表 = list(filter(lambda x: not File(x).backup_time, 列表))
377
254
 
378
255
  return 列表
379
256
 
@@ -443,7 +320,7 @@ class CBaseFolder(object):
443
320
  if not 目标目录: # 如果没有设置目标目录,则以该类所在目录为准
444
321
  目标目录 = self.name
445
322
  for fn in files:
446
- f = Path(os.path.join(self.name, fn))
323
+ f = File(os.path.join(self.name, fn))
447
324
  目标名称 = re.sub(origin, target, fn, flags=re.IGNORECASE)
448
325
  f.rename(os.path.join(目标目录, 目标名称))
449
326
 
@@ -462,7 +339,7 @@ class CBaseFolder(object):
462
339
  continue
463
340
 
464
341
  def 大小(self):
465
- return Path(self.name).size
342
+ return File(self.name).size
466
343
 
467
344
  def 删除(self):
468
345
  shutil.rmtree(self.name, ignore_errors=True)
@@ -486,7 +363,7 @@ def 文件搜索匹配(源目录, 自定义正则规则, *, 目标类型=('文
486
363
  正则规则 = 自定义正则规则转为标准正则表达式(自定义正则规则)
487
364
  所有目录 = tuple(os.walk(源目录))
488
365
  for 当前目录名, 包含目录, 包含文件 in 所有目录:
489
- parts = Path(当前目录名).parts
366
+ parts = File(当前目录名).parts
490
367
  if '.git' in parts or '$RECYCLE.BIN' in parts: # 去掉'.git'这个备份目录,'$RECYCLE.BIN'这个不知啥鬼目录
491
368
  continue
492
369
  相对目录 = 当前目录名[源目录前缀长度 + 1:]
@@ -523,8 +400,8 @@ def 文件重命名(源目录, 自定义正则规则, 新正则名称, *, 目标
523
400
  ls.append([f, f2])
524
401
  if not 调试:
525
402
  targetName = os.path.join(目标目录, f2)
526
- f3 = Path(targetName)
527
- if f3.is_file():
403
+ f3 = File(targetName)
404
+ if f3:
528
405
  print('文件已存在:', f3.name)
529
406
  if 覆盖操作:
530
407
  f3.delete()
@@ -565,7 +442,7 @@ def 目录下查找文本(目录, 文件名筛选, 目标文本, *, 模式='表
565
442
  行文本模式:显示所有匹配的行文本
566
443
  """
567
444
  ls = 文件搜索匹配(目录, 文件名筛选, 目标类型=('文件',))
568
- ls = list(filter(lambda x: Path(x).backup_time == '', ls)) # 去除备份文件
445
+ ls = list(filter(lambda x: File(x).backup_time == '', ls)) # 去除备份文件
569
446
  ls = natural_sort(ls)
570
447
  if 模式 == '表格':
571
448
  table = list()
@@ -598,8 +475,8 @@ def 目录下统计单词出现频数(目录, 文件名筛选, 目标文本=r'(\
598
475
  """默认会找所有单词,以及tex命令"""
599
476
  ls = 文件搜索匹配(目录, 文件名筛选, 目标类型=('文件',))
600
477
  s = list()
601
- for fileName in [f for f in ls if not Path(f).backup_time]: # 去除备份文件
602
- c = Path(pathjoin(目录, fileName)).read()
478
+ for fileName in [f for f in ls if not File(f).backup_time]: # 去除备份文件
479
+ c = File(pathjoin(目录, fileName)).read()
603
480
  s.append(c)
604
481
  s = '\n'.join(s)
605
482
 
@@ -616,70 +493,91 @@ def 目录下统计单词出现频数(目录, 文件名筛选, 目标文本=r'(\
616
493
  def GetFullPathClass(s):
617
494
  """如果输入的是相对路径,会解析为绝对路径"""
618
495
  # p = Path(s).resolve() # 奕本的电脑这句话运行不了
619
- p = Path(s)
496
+ p = File(s)
620
497
  if not s.startswith('\\') and not p.drive:
621
- p = Path.cwd() / p
498
+ p = File.cwd() / p
622
499
  return p
623
500
 
624
501
 
625
- def ________E_图像处理________():
626
- pass
502
+ ____other = """"""
627
503
 
504
+ mydecrypt = base64.b64decode
628
505
 
629
- ################################################################################
630
- ### 图 像 处 理 操 作
631
- ################################################################################
632
- import PIL
633
- import PIL.ExifTags
634
- from PIL import Image
635
506
 
507
+ class LengthFormatter:
508
+ """ 长度换算类,可以在允许浮点小误差的场景使用
509
+ TODO 需要精确运算也是可以的,那就要用分数类来存储底层值了
510
+
511
+ # 默认标准长度是mm,所以初始化一个233数字,就等于用233mm初始化
512
+ >>> LengthFormatter(233).cm # 然后可以转化为cm,计算厘米单位下的长度值
513
+ 23.3
514
+ >>> LengthFormatter('233pt') # 可以用带单位的字符串
515
+ 81.78mm
516
+ >>> LengthFormatter('233.45 pt') # 支持小数、有空格等格式
517
+ 81.94mm
636
518
 
637
- def 图像实际视图(img):
638
- """Image.open读取图片时,是手机严格正放时拍到的图片效果,
639
- 但手机拍照时是会记录旋转位置的,即可以判断是物理空间中,实际朝上、朝下的方向,
640
- 从而识别出正拍(代号1),顺时针旋转90度拍摄(代号8),顺时针180度拍摄(代号3),顺时针270度拍摄(代号6)。
641
- windows上的图片查阅软件能识别方向代号后正确摆放;
642
- 为了让python处理图片的时候能增加这个属性的考虑,这个函数能修正识别角度返回新的图片。
519
+ 应用举例:把长度超过12cm的hspace都限制在12cm以内
520
+ >> s = NestEnv(s).latexcmd1('hspace').bracket('{', inner=True).\
521
+ replace(lambda x: '12cm' if LengthFormatter(x).cm > 12 else x)
643
522
  """
644
- exif_data = img._getexif()
645
- if exif_data:
646
- exif = {
647
- PIL.ExifTags.TAGS[k]: v
648
- for k, v in exif_data.items()
649
- if k in PIL.ExifTags.TAGS
650
- }
651
- 方向 = exif['Orientation']
652
- if 方向 == 8:
653
- img = img.transpose(PIL.Image.ROTATE_90)
654
- elif 方向 == 3:
655
- img = img.transpose(PIL.Image.ROTATE_180)
656
- elif 方向 == 6:
657
- img = img.transpose(PIL.Image.ROTATE_270)
658
- return img
659
-
660
-
661
- def 查看图片的Exif信息(img):
662
- exif_data = img._getexif()
663
- if exif_data:
664
- exif = {
665
- PIL.ExifTags.TAGS[k]: v
666
- for k, v in exif_data.items()
667
- if k in PIL.ExifTags.TAGS
668
- }
669
- else:
670
- exif = None
671
- return exif
523
+
524
+ # 所有其他单位长度与参照长度mm之间比例关系
525
+ ratio = {'pt': 0.351, # 点
526
+ 'bp': 0.353, # 大点,≈1pt
527
+ 'dd': 0.376, # 迪多,=1.07pt
528
+ 'pc': 4.218, # 派卡,=12pt
529
+ 'sp': 1 / 65536, # 定标点,65536sp=1pt
530
+ 'cm': 10, # 厘米
531
+ 'cc': 4.513, # 西塞罗
532
+ 'in': 25.4, # 英寸,=72.27pt
533
+ 'em': 18, # 1em≈当前字体中M的宽度,在正文12pt情况下,一般为18pt
534
+ 'ex': 12, # 1ex≈当前字体中x的高度,暂按12pt处理
535
+ }
536
+
537
+ def __init__(self, v=0):
538
+ if isinstance(v, (int, float)):
539
+ self.__dict__['mm'] = v
540
+ elif isinstance(v, str):
541
+ m = re.match(r'(-?\d+(?:\.\d*)?)\s*(' + '|'.join(list(self.ratio.keys()) + ['mm']) + ')$', v)
542
+ if not m: raise ValueError(f'不存在的长度单位类型:{v}')
543
+ self.__dict__['mm'] = 0
544
+ self.__setitem__(m.group(2), float(m.group(1)))
545
+ else:
546
+ raise ValueError(f'不存在的长度单位类型:{v}')
547
+
548
+ def __repr__(self):
549
+ return '{:.2f}mm'.format(self.__dict__['mm'])
550
+
551
+ def __getattr__(self, key):
552
+ if key in self.ratio.keys():
553
+ return self.__dict__['mm'] / self.ratio[key]
554
+ else:
555
+ raise ValueError(f'不存在的长度单位类型:{key}')
556
+
557
+ def __setitem__(self, key, value):
558
+ if key == 'mm':
559
+ self.__dict__['mm'] = value
560
+ elif key in self.ratio.keys():
561
+ self.__dict__['mm'] = value * self.ratio[key]
562
+ else:
563
+ raise ValueError(f'不存在的长度单位类型:{key}')
564
+
565
+
566
+ ____image = """
567
+ 暂时还没空整理的一些图片功能
568
+ """
672
569
 
673
570
 
674
571
  def 缩放目录下所有png图片(folder, rate=120):
675
572
  """rate可以控制缩放比例,正常是100
676
573
  再乘120是不想缩放太多,理论上乘100是正常比例
574
+
575
+ 旧函数名:缩放目录下所有png图片
677
576
  """
678
- fd = CBaseFolder(folder)
679
- for imgFile in fd.Files('*.png'):
680
- files = pathjoin(fd.name, imgFile)
577
+ fd = Dir(folder)
578
+ for f in fd.select_files('*.png'):
681
579
  try:
682
- im = Image.open(files)
580
+ im = Image.open(str(f))
683
581
  if 'dpi' in im.info:
684
582
  if im.info['dpi'][0] in (305, 610): # 这个是magick转换过来的特殊值,不能缩放
685
583
  continue # 180920周四,610是为欧龙加的,欧龙双师需要设置-density 240
@@ -689,137 +587,77 @@ def 缩放目录下所有png图片(folder, rate=120):
689
587
  s[0] = int(s[0] / im.info['dpi'][0] * rate)
690
588
  s[1] = int(s[1] / im.info['dpi'][1] * rate)
691
589
  im = im.resize(s, Image.ANTIALIAS)
692
- im.save(files)
590
+ im.save(str(f))
693
591
  except:
694
- print('无法处理图片:', files)
592
+ print('无法处理图片:', f)
695
593
  continue
696
594
 
697
595
 
698
596
  def 缩放目录下所有png图片2(folder, scale=1.0):
699
597
  """rate可以控制缩放比例,正常是100
700
598
  再乘120是不想缩放太多,理论上乘100是正常比例
599
+
600
+ 旧函数名:缩放目录下所有png图片2
701
601
  """
702
- fd = CBaseFolder(folder)
703
- for imgFile in fd.Files('*.png'):
704
- files = pathjoin(fd.name, imgFile)
705
- im = Image.open(files)
602
+ fd = Dir(folder)
603
+ for f in fd.select_files('*.png'):
604
+ im = Image.open(str(f))
706
605
  s = list(im.size)
707
606
  s[0] = int(s[0] * scale)
708
607
  s[1] = int(s[1] * scale)
709
608
  im = im.resize(s, Image.ANTIALIAS)
710
- im.save(files)
609
+ im.save(str(f))
711
610
 
712
611
 
713
612
  def 查看目录下png图片信息(folder):
714
- fd = CBaseFolder(folder)
613
+ """
614
+ 旧函数名:查看目录下png图片信息
615
+ """
616
+ fd = Dir(folder)
715
617
  ls = list()
716
- for imgFile in fd.Files('*.png'):
717
- file = Path(pathjoin(fd.name, imgFile))
718
- im = Image.open(file.name)
618
+ for f in fd.select_files('*.png'):
619
+ im = Image.open(str(f))
719
620
  d0, d1 = im.info['dpi'] if 'dpi' in im.info else ('', '')
720
621
  # 处理eps格式
721
- epsFile = file.with_suffix('.eps')
622
+ epsFile = f.with_suffix('.eps')
722
623
  if epsFile:
723
624
  epsSize, epsIm = epsFile.大小(), Image.open(epsFile.name)
724
625
  boundingBox = epsIm.info['BoundingBox'].replace(' ', ',') if 'BoundingBox' in epsIm.info else ''
725
626
  else:
726
627
  epsSize, boundingBox = '', ''
727
628
  # 处理pdf格式
728
- pdfFile = Path(file.name[:-4] + '-eps-converted-to.pdf')
629
+ pdfFile = File(f.name[:-4] + '-eps-converted-to.pdf')
729
630
  pdfSize = pdfFile.size if pdfFile else ''
730
631
  # 存储到列表
731
- ls.append((imgFile, im.size[0], im.size[1], d0, d1,
732
- file.size, file.mtime.strftime(' %y%m%d-%H%M%S'),
632
+ ls.append((f, im.size[0], im.size[1], d0, d1,
633
+ f.size, f.mtime.strftime(' %y%m%d-%H%M%S'),
733
634
  epsSize, boundingBox, pdfSize))
734
635
  df = pd.DataFrame.from_records(ls,
735
636
  columns=('fileName', 'width', 'height', 'dpi_w', 'dpi_h', 'size', 'time', 'epsSize',
736
637
  'boundingBox', 'pdfSize'))
737
- PrintFullTable(df)
638
+ with pd.option_context('display.max_colwidth', -1, 'display.max_columns', 20,
639
+ 'display.width', 200): # 上下文控制格式
640
+ print(df)
738
641
  return df
739
642
 
740
643
 
741
- def MakeColorTransparent(image, color, thresh2=0):
742
- """
743
- 将指定颜色转为透明
644
+ def make_color_transparent(image, color, thresh2=0):
645
+ """ 将指定颜色转为透明
646
+ https://stackoverflow.com/questions/765736/using-pil-to-make-all-white-pixels-transparent/765829
744
647
 
745
- https://stackoverflow.com/questions/765736/using-pil-to-make-all-white-pixels-transparent/765829"""
648
+ 旧函数名:MakeColorTransparent
649
+ """
746
650
  from PIL import ImageMath
747
651
 
748
- def Distance2(a, b):
652
+ def distance2(a, b):
749
653
  return (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2])
750
654
 
751
655
  image = image.convert("RGBA")
752
656
  red, green, blue, alpha = image.split()
753
657
  image.putalpha(ImageMath.eval("""convert(((((t - d(c, (r, g, b))) >> 31) + 1) ^ 1) * a, 'L')""",
754
- t=thresh2, d=Distance2, c=color, r=red, g=green, b=blue, a=alpha))
658
+ t=thresh2, d=distance2, c=color, r=red, g=green, b=blue, a=alpha))
755
659
  return image
756
660
 
757
661
 
758
- ____other = """"""
759
-
760
- mydecrypt = base64.b64decode
761
-
762
-
763
- class LengthFormatter:
764
- """ 长度换算类,可以在允许浮点小误差的场景使用
765
- TODO 需要精确运算也是可以的,那就要用分数类来存储底层值了
766
-
767
- # 默认标准长度是mm,所以初始化一个233数字,就等于用233mm初始化
768
- >>> LengthFormatter(233).cm # 然后可以转化为cm,计算厘米单位下的长度值
769
- 23.3
770
- >>> LengthFormatter('233pt') # 可以用带单位的字符串
771
- 81.78mm
772
- >>> LengthFormatter('233.45 pt') # 支持小数、有空格等格式
773
- 81.94mm
774
-
775
- 应用举例:把长度超过12cm的hspace都限制在12cm以内
776
- >> s = NestEnv(s).latexcmd1('hspace').bracket('{', inner=True).\
777
- replace(lambda x: '12cm' if LengthFormatter(x).cm > 12 else x)
778
- """
779
-
780
- # 所有其他单位长度与参照长度mm之间比例关系
781
- ratio = {'pt': 0.351, # 点
782
- 'bp': 0.353, # 大点,≈1pt
783
- 'dd': 0.376, # 迪多,=1.07pt
784
- 'pc': 4.218, # 派卡,=12pt
785
- 'sp': 1 / 65536, # 定标点,65536sp=1pt
786
- 'cm': 10, # 厘米
787
- 'cc': 4.513, # 西塞罗
788
- 'in': 25.4, # 英寸,=72.27pt
789
- 'em': 18, # 1em≈当前字体中M的宽度,在正文12pt情况下,一般为18pt
790
- 'ex': 12, # 1ex≈当前字体中x的高度,暂按12pt处理
791
- }
792
-
793
- def __init__(self, v=0):
794
- if isinstance(v, (int, float)):
795
- self.__dict__['mm'] = v
796
- elif isinstance(v, str):
797
- m = re.match(r'(-?\d+(?:\.\d*)?)\s*(' + '|'.join(list(self.ratio.keys()) + ['mm']) + ')$', v)
798
- if not m: raise ValueError(f'不存在的长度单位类型:{v}')
799
- self.__dict__['mm'] = 0
800
- self.__setitem__(m.group(2), float(m.group(1)))
801
- else:
802
- raise ValueError(f'不存在的长度单位类型:{v}')
803
-
804
- def __repr__(self):
805
- return '{:.2f}mm'.format(self.__dict__['mm'])
806
-
807
- def __getattr__(self, key):
808
- if key == 'mm':
809
- return self.__dict__['mm']
810
- elif key in self.ratio.keys():
811
- return self.__dict__['mm'] / self.ratio[key]
812
- else:
813
- raise ValueError(f'不存在的长度单位类型:{key}')
814
-
815
- def __setitem__(self, key, value):
816
- if key == 'mm':
817
- self.__dict__['mm'] = value
818
- elif key in self.ratio.keys():
819
- self.__dict__['mm'] = value * self.ratio[key]
820
- else:
821
- raise ValueError(f'不存在的长度单位类型:{key}')
822
-
823
-
824
662
  if __name__ == '__main__':
825
663
  print('测试')