py2ls 0.1.10.24__py3-none-any.whl → 0.1.10.25__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.
py2ls/batman.py
CHANGED
@@ -3,33 +3,75 @@ from email.mime.text import MIMEText
|
|
3
3
|
from email.mime.multipart import MIMEMultipart
|
4
4
|
from email.mime.base import MIMEBase
|
5
5
|
from email import encoders
|
6
|
-
import schedule
|
7
6
|
import time
|
8
7
|
from datetime import datetime
|
9
8
|
import os
|
10
9
|
from pprint import pp
|
11
10
|
import json
|
11
|
+
import mimetypes
|
12
|
+
import sys
|
12
13
|
|
13
14
|
|
14
|
-
|
15
|
-
def convert_to_html(text_list):
|
15
|
+
def convert_to_html(text_list, strict=False):
|
16
16
|
if not isinstance(text_list, list):
|
17
17
|
text_list = [text_list]
|
18
18
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
# Define a mapping for escape sequences to their HTML representations
|
20
|
+
escape_mapping = {
|
21
|
+
"\\": "\", # Backslash
|
22
|
+
"'": "'", # Single quote
|
23
|
+
'"': """, # Double quote
|
24
|
+
"\n": "<br>", # Newline
|
25
|
+
"\r": "", # Carriage return (not represented in HTML)
|
26
|
+
"\t": " ", # Tab (4 spaces)
|
27
|
+
"\b": "", # Backspace (not typically represented)
|
28
|
+
"\f": "", # Form feed (not typically represented)
|
29
|
+
"\v": "", # Vertical tab (not typically represented)
|
30
|
+
"\a": "", # Bell/alert sound (not typically represented)
|
31
|
+
"\0": "", # Null character (not typically represented)
|
32
|
+
}
|
33
|
+
# Convert text by replacing escape sequences with their HTML equivalents
|
34
|
+
html_content = ""
|
35
|
+
for text in text_list:
|
36
|
+
for escape_seq, html_rep in escape_mapping.items():
|
37
|
+
text = text.replace(escape_seq, html_rep)
|
38
|
+
html_content += text.replace("\n", "<br>") # Add line breaks for newlines
|
39
|
+
if strict:
|
40
|
+
html_content = "<html><body>\n" + html_content + "\n</body></html>"
|
26
41
|
return html_content
|
27
42
|
|
28
43
|
|
44
|
+
def get_name(email_str, by="@"):
|
45
|
+
if "num" in by:
|
46
|
+
for i, char in enumerate(email_str):
|
47
|
+
if char.isdigit():
|
48
|
+
break
|
49
|
+
else:
|
50
|
+
return email_str
|
51
|
+
return email_str[:i]
|
52
|
+
|
53
|
+
# Handle the case where '@' is the criteria
|
54
|
+
elif "@" in by:
|
55
|
+
name = email_str.split("@")[0]
|
56
|
+
name = get_name(name, by="num")
|
57
|
+
name = " ".join([part.capitalize() for part in name.split(".")])
|
58
|
+
return name
|
59
|
+
|
60
|
+
|
29
61
|
def extract_kv(
|
30
|
-
dir_data=
|
62
|
+
dir_data=None,
|
31
63
|
idx=0,
|
32
64
|
): # select the index
|
65
|
+
if dir_data is None:
|
66
|
+
if "dar" in sys.platform:
|
67
|
+
dir_data = "/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
68
|
+
else:
|
69
|
+
if "win" in sys.platform:
|
70
|
+
dir_data = (
|
71
|
+
"Z:\\Jianfeng\\Apps\settings\\confidential_data\\gmail_login.json"
|
72
|
+
)
|
73
|
+
elif "lin" in sys.platform:
|
74
|
+
dir_data = "/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
33
75
|
with open(dir_data, "r") as file:
|
34
76
|
email_login = json.load(file)
|
35
77
|
for i, (user, pd) in enumerate(email_login.items()):
|
@@ -38,6 +80,10 @@ def extract_kv(
|
|
38
80
|
|
39
81
|
|
40
82
|
def email_to(**kwargs):
|
83
|
+
return email(**kwargs)
|
84
|
+
|
85
|
+
|
86
|
+
def email(**kwargs):
|
41
87
|
"""
|
42
88
|
usage:
|
43
89
|
email_to(who="example@gmail.com",
|
@@ -106,7 +152,14 @@ def email_to(**kwargs):
|
|
106
152
|
what = ""
|
107
153
|
if isinstance(what, list):
|
108
154
|
what = convert_to_html(what)
|
109
|
-
if 'class="
|
155
|
+
if 'class="' in str(what):
|
156
|
+
# Combine HTML content correctly
|
157
|
+
html_content = "<html><body>\n"
|
158
|
+
html_content += f"{what}"
|
159
|
+
html_content += f"<br><br>{convert_to_html([signature])}"
|
160
|
+
html_content += "\n</body></html>"
|
161
|
+
message.attach(MIMEText(html_content, "html"))
|
162
|
+
elif 'class="' in str(attachments):
|
110
163
|
# Combine HTML content correctly
|
111
164
|
html_content = "<html><body>\n"
|
112
165
|
html_content += f"{convert_to_html(what)}<br>{attachments}"
|
@@ -124,15 +177,24 @@ def email_to(**kwargs):
|
|
124
177
|
if isinstance(attachments, str):
|
125
178
|
attachments = [attachments]
|
126
179
|
for file in attachments:
|
127
|
-
|
180
|
+
# 有时候一些不常用的文件类型, 无法自动识别
|
181
|
+
mime_type, _ = mimetypes.guess_type(file)
|
182
|
+
if mime_type is None:
|
183
|
+
if file.endswith(".xlsx"):
|
184
|
+
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
185
|
+
else:
|
186
|
+
mime_type = "application/octet-stream"
|
187
|
+
|
188
|
+
main_type, sub_type = mime_type.split("/", 1)
|
189
|
+
# part = MIMEBase("application", "octet-stream") # 旧的版本
|
190
|
+
part = MIMEBase(main_type, sub_type)
|
128
191
|
try:
|
129
192
|
with open(file, "rb") as attachment:
|
130
193
|
part.set_payload(attachment.read())
|
131
194
|
encoders.encode_base64(part)
|
132
|
-
|
195
|
+
filename = os.path.basename(file)
|
133
196
|
part.add_header(
|
134
|
-
"Content-Disposition",
|
135
|
-
f'attachment; filename= "{os.path.basename(file)}"',
|
197
|
+
"Content-Disposition", f'attachment; filename="{filename}"'
|
136
198
|
)
|
137
199
|
message.attach(part)
|
138
200
|
except FileNotFoundError:
|
py2ls/ips.py
CHANGED
@@ -58,6 +58,18 @@ except NameError:
|
|
58
58
|
pass
|
59
59
|
|
60
60
|
|
61
|
+
|
62
|
+
|
63
|
+
# set 'dir_save'
|
64
|
+
if 'dar' in sys.platform:
|
65
|
+
dir_save = "/Users/macjianfeng/Dropbox/Downloads/"
|
66
|
+
else:
|
67
|
+
if 'win' in sys.platform:
|
68
|
+
dir_save= "Z:\\Jianfeng\\temp\\"
|
69
|
+
elif 'lin' in sys.platform:
|
70
|
+
dir_data="/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
71
|
+
|
72
|
+
|
61
73
|
def unique(lst, ascending=None):
|
62
74
|
"""
|
63
75
|
移除列表中的重复元素,同时可以选择按升序或降序排序。
|
@@ -260,10 +272,6 @@ def upgrade(module="py2ls"):
|
|
260
272
|
except subprocess.CalledProcessError as e:
|
261
273
|
print(f"An error occurred while upgrading py2ls: {e}")
|
262
274
|
|
263
|
-
|
264
|
-
dir_save = "/Users/macjianfeng/Dropbox/Downloads/"
|
265
|
-
|
266
|
-
|
267
275
|
def get_version(pkg):
|
268
276
|
import importlib.metadata
|
269
277
|
|
@@ -749,6 +757,41 @@ def num2str(num, *args, **kwargs):
|
|
749
757
|
# num2str(12345333.6789, sep=","), type(num2str(12345.6789, ","))
|
750
758
|
# ) # Output: "12,345.6789"
|
751
759
|
# print(num2str(7000.00, sep=","), type(num2str(7000.00, ","))) # Output: "7,000.00"
|
760
|
+
|
761
|
+
|
762
|
+
# Helper to convert text or list of text to HTML
|
763
|
+
def str2html(text_list, strict=False):
|
764
|
+
if not isinstance(text_list, list):
|
765
|
+
text_list = [text_list]
|
766
|
+
|
767
|
+
# Define a mapping for escape sequences to their HTML representations
|
768
|
+
escape_mapping = {
|
769
|
+
"\\": "\", # Backslash
|
770
|
+
"'": "'", # Single quote
|
771
|
+
'"': """, # Double quote
|
772
|
+
"\n": "<br>", # Newline
|
773
|
+
"\r": "", # Carriage return (not represented in HTML)
|
774
|
+
"\t": " ", # Tab (4 spaces)
|
775
|
+
"\b": "", # Backspace (not typically represented)
|
776
|
+
"\f": "", # Form feed (not typically represented)
|
777
|
+
"\v": "", # Vertical tab (not typically represented)
|
778
|
+
"\a": "", # Bell/alert sound (not typically represented)
|
779
|
+
"\0": "", # Null character (not typically represented)
|
780
|
+
}
|
781
|
+
|
782
|
+
# Convert text by replacing escape sequences with their HTML equivalents
|
783
|
+
html_content = ""
|
784
|
+
for text in text_list:
|
785
|
+
for escape_seq, html_rep in escape_mapping.items():
|
786
|
+
text = text.replace(escape_seq, html_rep)
|
787
|
+
html_content += text.replace("\n", "<br>") # Add line breaks for newlines
|
788
|
+
|
789
|
+
if strict:
|
790
|
+
html_content = "<html><body>\n" + html_content + "\n</body></html>"
|
791
|
+
|
792
|
+
return html_content
|
793
|
+
|
794
|
+
|
752
795
|
def sreplace(*args, **kwargs):
|
753
796
|
"""
|
754
797
|
sreplace(text, by=None, robust=True)
|
@@ -1769,46 +1812,66 @@ def sort_kind(df, by="name", ascending=True):
|
|
1769
1812
|
sorted_df = df.iloc[sorted_index].reset_index(drop=True)
|
1770
1813
|
return sorted_df
|
1771
1814
|
|
1772
|
-
|
1773
|
-
def isa(*args, **kwargs):
|
1815
|
+
def isa(content, kind):
|
1774
1816
|
"""
|
1775
|
-
|
1776
|
-
|
1817
|
+
content, kind='img'
|
1818
|
+
kinds file paths based on the specified kind.
|
1777
1819
|
Args:
|
1778
|
-
|
1779
|
-
|
1820
|
+
content (str): Path to the file.
|
1821
|
+
kind (str): kind of file to kind. Default is 'img' for images. Other options include 'doc' for documents,
|
1780
1822
|
'zip' for ZIP archives, and 'other' for other types of files.
|
1781
1823
|
Returns:
|
1782
|
-
bool: True if the file matches the
|
1824
|
+
bool: True if the file matches the kind, False otherwise.
|
1783
1825
|
"""
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
return
|
1792
|
-
elif "
|
1793
|
-
return
|
1794
|
-
elif "
|
1795
|
-
return
|
1796
|
-
elif "
|
1797
|
-
|
1798
|
-
):
|
1799
|
-
return
|
1800
|
-
elif "
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1826
|
+
if "img" in kind.lower() or "image" in kind.lower():
|
1827
|
+
return is_image(content)
|
1828
|
+
elif "doc" in kind.lower():
|
1829
|
+
return is_document(content)
|
1830
|
+
elif "zip" in kind.lower():
|
1831
|
+
return is_zip(content)
|
1832
|
+
elif "dir" in kind.lower() or ("f" in kind.lower() and "d" in kind.lower()):
|
1833
|
+
return os.path.isdir(content)
|
1834
|
+
elif "fi" in kind.lower(): # file
|
1835
|
+
return os.path.isfile(content)
|
1836
|
+
elif "num" in kind.lower(): # file
|
1837
|
+
return os.path.isfile(content)
|
1838
|
+
elif "text" in kind.lower() or "txt" in kind.lower(): # file
|
1839
|
+
return is_text(content)
|
1840
|
+
elif "color" in kind.lower(): # file
|
1841
|
+
return is_str_color(content)
|
1842
|
+
elif "html" in kind.lower():
|
1843
|
+
# Remove leading and trailing whitespace
|
1844
|
+
content = content.strip()
|
1845
|
+
# Check for common HTML tags using regex
|
1846
|
+
# This pattern matches anything that looks like an HTML tag
|
1847
|
+
tag_pattern = r"<[a-zA-Z][^>]*>(.*?)</[a-zA-Z][^>]*>"
|
1848
|
+
# Check for any opening and closing tags
|
1849
|
+
if re.search(tag_pattern, content):
|
1850
|
+
return True
|
1851
|
+
# Additional checks for self-closing tags
|
1852
|
+
self_closing_tags = ["img", "br", "hr", "input", "meta", "link"]
|
1853
|
+
for tag in self_closing_tags:
|
1854
|
+
if f"<{tag}" in content:
|
1855
|
+
return True
|
1856
|
+
return False
|
1808
1857
|
else:
|
1809
|
-
print(f"{
|
1858
|
+
print(f"{kind} was not set up correctly")
|
1810
1859
|
return False
|
1811
1860
|
|
1861
|
+
import sys
|
1862
|
+
def get_os():
|
1863
|
+
os_name = sys.platform
|
1864
|
+
if "dar" in os_name:
|
1865
|
+
return "macOS"
|
1866
|
+
else:
|
1867
|
+
if "win" in os_name:
|
1868
|
+
return "Windows"
|
1869
|
+
elif "linux" in os_name:
|
1870
|
+
return "Linux"
|
1871
|
+
else:
|
1872
|
+
print(f"{os_name}, returned 'None'")
|
1873
|
+
return None
|
1874
|
+
|
1812
1875
|
|
1813
1876
|
def listdir(
|
1814
1877
|
rootdir,
|
@@ -3925,3 +3988,52 @@ format_excel(
|
|
3925
3988
|
# Save the workbook
|
3926
3989
|
wb.save(filename)
|
3927
3990
|
print(f"Formatted Excel file saved as:\n{filename}")
|
3991
|
+
|
3992
|
+
|
3993
|
+
from IPython.display import display, HTML, Markdown, Image
|
3994
|
+
|
3995
|
+
def preview(var):
|
3996
|
+
"""Master function to preview formatted variables in Jupyter."""
|
3997
|
+
|
3998
|
+
if isinstance(var, str):
|
3999
|
+
if isa(var,'html'):
|
4000
|
+
display(HTML(var)) # Render as HTML
|
4001
|
+
# Check if it's a valid markdown
|
4002
|
+
elif var.startswith("#"):
|
4003
|
+
display(Markdown(var))
|
4004
|
+
else:
|
4005
|
+
# Otherwise, display as plain text
|
4006
|
+
print(var)
|
4007
|
+
|
4008
|
+
elif isinstance(var, pd.DataFrame):
|
4009
|
+
# Display pandas DataFrame
|
4010
|
+
display(var)
|
4011
|
+
|
4012
|
+
elif isinstance(var, list) or isinstance(var, dict):
|
4013
|
+
# Display JSON
|
4014
|
+
json_str = json.dumps(var, indent=4)
|
4015
|
+
display(Markdown(f"```json\n{json_str}\n```"))
|
4016
|
+
|
4017
|
+
elif isinstance(var, bytes):
|
4018
|
+
# Display image if it's in bytes format
|
4019
|
+
display(Image(data=var))
|
4020
|
+
|
4021
|
+
elif isinstance(var, str) and (var.endswith(".png") or var.endswith(".jpg")):
|
4022
|
+
# Display image from file path
|
4023
|
+
display(Image(filename=var))
|
4024
|
+
|
4025
|
+
elif isinstance(var, dict):
|
4026
|
+
# Handle dictionary formatting
|
4027
|
+
json_str = json.dumps(var, indent=4)
|
4028
|
+
display(Markdown(f"```json\n{json_str}\n```"))
|
4029
|
+
|
4030
|
+
else:
|
4031
|
+
# If the format is not recognized, print a message
|
4032
|
+
print("Format not recognized or unsupported.")
|
4033
|
+
|
4034
|
+
|
4035
|
+
# # Example usages:
|
4036
|
+
# preview("This is a plain text message.")
|
4037
|
+
# preview("# This is a Markdown header")
|
4038
|
+
# preview(pd.DataFrame({"Name": ["Alice", "Bob"], "Age": [25, 30]}))
|
4039
|
+
# preview({"key": "value", "numbers": [1, 2, 3]})
|
@@ -172,7 +172,7 @@ py2ls/.gitignore,sha256=y7GvbD_zZkjPVVIue8AyiuFkDMuUbvMaV65Lgu89To8,2763
|
|
172
172
|
py2ls/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
|
173
173
|
py2ls/README.md,sha256=CwvJWAnSXnCnrVHlnEbrxxi6MbjbE_MT6DH2D53S818,11572
|
174
174
|
py2ls/__init__.py,sha256=Nn8jTIvySX7t7DMJ8VNRVctTStgXGjHldOIdZ35PdW8,165
|
175
|
-
py2ls/batman.py,sha256=
|
175
|
+
py2ls/batman.py,sha256=HsZuB_NspZ8CysEY8lLy78zSqd_mg0LOGBofDwQjfKQ,10101
|
176
176
|
py2ls/brain_atlas.py,sha256=w1o5EelRjq89zuFJUNSz4Da8HnTCwAwDAZ4NU4a-bAY,5486
|
177
177
|
py2ls/chat.py,sha256=Yr22GoIvoWhpV3m4fdwV_I0Mn77La346_ymSinR-ORA,3793
|
178
178
|
py2ls/correlators.py,sha256=RbOaJIPLCHJtUm5SFi_4dCJ7VFUPWR0PErfK3K26ad4,18243
|
@@ -206,7 +206,7 @@ py2ls/doc.py,sha256=xN3g1OWfoaGUhikbJ0NqbN5eKy1VZVvWwRlhHMgyVEc,4243
|
|
206
206
|
py2ls/export_requirements.py,sha256=x2WgUF0jYKz9GfA1MVKN-MdsM-oQ8yUeC6Ua8oCymio,2325
|
207
207
|
py2ls/freqanalysis.py,sha256=F4218VSPbgL5tnngh6xNCYuNnfR-F_QjECUUxrPYZss,32594
|
208
208
|
py2ls/ich2ls.py,sha256=3E9R8oVpyYZXH5PiIQgT3CN5NxLe4Dwtm2LwaeacE6I,21381
|
209
|
-
py2ls/ips.py,sha256=
|
209
|
+
py2ls/ips.py,sha256=yJHpxn0EQIPk0Xhh_tb7VMWkL9Eh9Hw5XzzY7TfhQOE,147612
|
210
210
|
py2ls/netfinder.py,sha256=vgOOMhzwbjRuLWMAPyf_kh3HoOhsJ9dlA-tCkMf7kNU,55371
|
211
211
|
py2ls/ocr.py,sha256=5lhUbJufIKRSOL6wAWVLEo8TqMYSjoI_Q-IO-_4u3DE,31419
|
212
212
|
py2ls/plot.py,sha256=yj-AfnYNr1ha_Y5EimTsUVSooFc36nE0KCQ8cP9_Trs,97601
|
@@ -215,6 +215,6 @@ py2ls/sleep_events_detectors.py,sha256=bQA3HJqv5qnYKJJEIhCyhlDtkXQfIzqksnD0YRXso
|
|
215
215
|
py2ls/stats.py,sha256=fJmXQ9Lq460StOn-kfEljE97cySq7876HUPTnpB5hLs,38123
|
216
216
|
py2ls/translator.py,sha256=zBeq4pYZeroqw3DT-5g7uHfVqKd-EQptT6LJ-Adi8JY,34244
|
217
217
|
py2ls/wb_detector.py,sha256=7y6TmBUj9exCZeIgBAJ_9hwuhkDh1x_-yg4dvNY1_GQ,6284
|
218
|
-
py2ls-0.1.10.
|
219
|
-
py2ls-0.1.10.
|
220
|
-
py2ls-0.1.10.
|
218
|
+
py2ls-0.1.10.25.dist-info/METADATA,sha256=LN1qZZRz26ZuwKH1RSRFFpxTR5TeIElPhveOyOaXTHA,19791
|
219
|
+
py2ls-0.1.10.25.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
220
|
+
py2ls-0.1.10.25.dist-info/RECORD,,
|
File without changes
|